aboutsummaryrefslogtreecommitdiff
path: root/gost_prov.c
blob: eab5918ac229adffdf5a74873197f5390d0c2364 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/**********************************************************************
 *                 gost_prov.c - The provider itself                  *
 *                                                                    *
 *      Copyright (c) 2021 Richard Levitte <richard@levitte.org>      *
 *     This file is distributed under the same license as OpenSSL     *
 *                                                                    *
 *                Requires OpenSSL 3.0 for compilation                *
 **********************************************************************/

#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include "gost_prov.h"
#include "gost_lcl.h"
#include "prov/err.h"           /* libprov err functions */

/*********************************************************************
 *
 *  Errors
 *
 *****/

/*
 * Ugly hack, to get the errors generated by mkerr.pl.  This should ideally
 * be replaced with a local OSSL_ITEM list of < number, string > pairs as
 * reason strings, but for now, we will simply use GOST_str_reasons.
 * Fortunately, the ERR_STRING_DATA structure is compatible with OSSL_ITEM,
 * so we can return it directly.
 */
static struct proverr_functions_st *err_handle;
#define GOST_PROV
#include "e_gost_err.c"
void ERR_GOST_error(int function, int reason, char *file, int line)
{
    proverr_new_error(err_handle);
    proverr_set_error_debug(err_handle, file, line, NULL);
    proverr_set_error(err_handle, reason, NULL);
}

/*********************************************************************
 *
 *  Provider context
 *
 *****/

static void provider_ctx_free(PROV_CTX *ctx)
{
    if (ctx != NULL) {
        ENGINE_free(ctx->e);
        proverr_free_handle(ctx->proverr_handle);
        OSSL_LIB_CTX_free(ctx->libctx);
    }
    OPENSSL_free(ctx);
}

extern int populate_gost_engine(ENGINE *e);
static PROV_CTX *provider_ctx_new(const OSSL_CORE_HANDLE *core,
                                  const OSSL_DISPATCH *in)
{
    PROV_CTX *ctx;

    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL
        && (ctx->proverr_handle = proverr_new_handle(core, in)) != NULL
        && (ctx->libctx = OSSL_LIB_CTX_new()) != NULL
        && (ctx->e = ENGINE_new()) != NULL
        && populate_gost_engine(ctx->e)) {
        ctx->core_handle = core;

        /* Ugly hack */
        err_handle = ctx->proverr_handle;
    } else {
        provider_ctx_free(ctx);
        ctx = NULL;
    }
    return ctx;
}

/*********************************************************************
 *
 *  Setup
 *
 *****/

typedef void (*fptr_t)(void);

/* The function that returns the appropriate algorithm table per operation */
static const OSSL_ALGORITHM *gost_operation(void *vprovctx,
                                                int operation_id,
                                                const int *no_cache)
{
    switch (operation_id) {
    case OSSL_OP_CIPHER:
        return GOST_prov_ciphers;
    case OSSL_OP_DIGEST:
        return GOST_prov_digests;
    case OSSL_OP_MAC:
        return GOST_prov_macs;
    }
    return NULL;
}

static int gost_get_params(void *provctx, OSSL_PARAM *params)
{
    OSSL_PARAM *p;

    p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
    if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL GOST Provider"))
        return 0;
    p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS);
    if (p != NULL && !OSSL_PARAM_set_int(p, 1)) /* We never fail. */
        return 0;

    return 1;
}

static const OSSL_ITEM *gost_get_reason_strings(void *provctx)
{
#if 0
    return reason_strings;
#endif
    return (OSSL_ITEM *)GOST_str_reasons;
}

/* The function that tears down this provider */
static void gost_teardown(void *vprovctx)
{
    GOST_prov_deinit_ciphers();
    GOST_prov_deinit_digests();
    GOST_prov_deinit_mac_digests();
    provider_ctx_free(vprovctx);
}

/* The base dispatch table */
static const OSSL_DISPATCH provider_functions[] = {
    { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (fptr_t)gost_operation },
    { OSSL_FUNC_PROVIDER_GET_REASON_STRINGS, (fptr_t)gost_get_reason_strings },
    { OSSL_FUNC_PROVIDER_GET_PARAMS, (fptr_t)gost_get_params },
    { OSSL_FUNC_PROVIDER_TEARDOWN, (fptr_t)gost_teardown },
    { 0, NULL }
};

struct prov_ctx_st {
    void *core_handle;
    struct proverr_functions_st *err_handle;
};

#ifdef BUILDING_PROVIDER_AS_LIBRARY
/*
 * This allows the provider to be built in library form.  In this case, the
 * application must add it explicitly like this:
 *
 * OSSL_PROVIDER_add_builtin(NULL, "gost", GOST_provider_init);
 */
# define OSSL_provider_init GOST_provider_init
#endif

OPENSSL_EXPORT
int OSSL_provider_init(const OSSL_CORE_HANDLE *core,
                       const OSSL_DISPATCH *in,
                       const OSSL_DISPATCH **out,
                       void **vprovctx)
{
    if ((*vprovctx = provider_ctx_new(core, in)) == NULL)
        return 0;
    *out = provider_functions;
    return 1;
}