]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_prov_mac.c
tcl_tests: ca.try: Ignore openssl crl exit status for 'corrupted CRL' test
[openssl-gost/engine.git] / gost_prov_mac.c
1 /**********************************************************************
2  *               gost_prov_mac.c - Initialize all macs                *
3  *                                                                    *
4  *      Copyright (c) 2021 Richard Levitte <richard@levitte.org>      *
5  *     This file is distributed under the same license as OpenSSL     *
6  *                                                                    *
7  *          OpenSSL provider interface to GOST mac functions          *
8  *                Requires OpenSSL 3.0 for compilation                *
9  **********************************************************************/
10
11 #include <openssl/core.h>
12 #include <openssl/core_dispatch.h>
13 #include "gost_prov.h"
14 #include "gost_lcl.h"
15
16 /*
17  * Forward declarations of all generic OSSL_DISPATCH functions, to make sure
18  * they are correctly defined further down.  For the algorithm specific ones
19  * MAKE_FUNCTIONS() does it for us.
20  */
21
22 static OSSL_FUNC_mac_dupctx_fn mac_dupctx;
23 static OSSL_FUNC_mac_freectx_fn mac_freectx;
24 static OSSL_FUNC_mac_init_fn mac_init;
25 static OSSL_FUNC_mac_update_fn mac_update;
26 static OSSL_FUNC_mac_final_fn mac_final;
27 static OSSL_FUNC_mac_get_ctx_params_fn mac_get_ctx_params;
28 static OSSL_FUNC_mac_set_ctx_params_fn mac_set_ctx_params;
29
30 struct gost_prov_mac_desc_st {
31     /*
32      * In the GOST engine, the MAC implementation bases itself heavily on
33      * digests with the same name.  We can re-use that part.
34      */
35     GOST_digest *digest_desc;
36     size_t initial_mac_size;
37 };
38 typedef struct gost_prov_mac_desc_st GOST_DESC;
39
40 struct gost_prov_mac_ctx_st {
41     /* Provider context */
42     PROV_CTX *provctx;
43     const GOST_DESC *descriptor;
44
45     /* Output MAC size */
46     size_t mac_size;
47     /* XOF mode, where applicable */
48     int xof_mode;
49
50     /*
51      * Since existing functionality is mainly designed as EVP_MDs for
52      * ENGINEs, the functions in this file are accomodated and are simply
53      * wrappers that use a local EVP_MD and EVP_MD_CTX.
54      * Future development should take a more direct approach and have the
55      * appropriate digest functions and digest data directly in this context.
56      */
57
58     /* The EVP_MD created from |descriptor| */
59     EVP_MD *digest;
60     /* The context for the EVP_MD functions */
61     EVP_MD_CTX *dctx;
62 };
63 typedef struct gost_prov_mac_ctx_st GOST_CTX;
64
65 static void mac_freectx(void *vgctx)
66 {
67     GOST_CTX *gctx = vgctx;
68
69     /*
70      * We don't free gctx->digest here.
71      * That will be done by the provider teardown, via
72      * GOST_prov_deinit_digests() (defined at the bottom of this file).
73      */
74     EVP_MD_CTX_free(gctx->dctx);
75     OPENSSL_free(gctx);
76 }
77
78 static GOST_CTX *mac_newctx(void *provctx, const GOST_DESC *descriptor)
79 {
80     GOST_CTX *gctx = NULL;
81
82     if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
83         gctx->provctx = provctx;
84         gctx->descriptor = descriptor;
85         gctx->mac_size = descriptor->initial_mac_size;
86         gctx->digest = GOST_init_digest(descriptor->digest_desc);
87         gctx->dctx = EVP_MD_CTX_new();
88
89         if (gctx->digest == NULL
90             || gctx->dctx == NULL
91             || EVP_DigestInit_ex(gctx->dctx, gctx->digest,
92                                  gctx->provctx->e) <= 0) {
93             mac_freectx(gctx);
94             gctx = NULL;
95         }
96     }
97     return gctx;
98 }
99
100 static void *mac_dupctx(void *vsrc)
101 {
102     GOST_CTX *src = vsrc;
103     GOST_CTX *dst =
104         mac_newctx(src->provctx, src->descriptor);
105
106     if (dst != NULL)
107         EVP_MD_CTX_copy(dst->dctx, src->dctx);
108     return dst;
109 }
110
111 static int mac_init(void *mctx, const unsigned char *key,
112                     size_t keylen, const OSSL_PARAM params[])
113 {
114     GOST_CTX *gctx = mctx;
115
116     return mac_set_ctx_params(gctx, params)
117         && (key == NULL
118             || EVP_MD_CTX_ctrl(gctx->dctx, EVP_MD_CTRL_SET_KEY,
119                                (int)keylen, (void *)key) > 0);
120 }
121
122 static int mac_update(void *mctx, const unsigned char *in, size_t inl)
123 {
124     GOST_CTX *gctx = mctx;
125
126     return EVP_DigestUpdate(gctx->dctx, in, inl) > 0;
127 }
128
129 static int mac_final(void *mctx, unsigned char *out, size_t *outl,
130                      size_t outsize)
131 {
132     GOST_CTX *gctx = mctx;
133     unsigned int tmpoutl;
134     int ret = 0;
135
136     /* This is strange code...  but it duplicates pkey_gost_mac_signctx() */
137
138     if (outl == NULL)
139         return 0;
140
141     /* for platforms where sizeof(int) != * sizeof(size_t) */
142     tmpoutl = *outl;
143
144     if (out != NULL) {
145         /* We ignore the error for GOST MDs that don't support setting
146            the size */
147         EVP_MD_CTX_ctrl(gctx->dctx, EVP_MD_CTRL_XOF_LEN, gctx->mac_size, NULL);
148         ret = EVP_DigestFinal_ex(gctx->dctx, out, &tmpoutl);
149     }
150     if (outl != NULL)
151         *outl = (size_t)gctx->mac_size;
152     return ret;
153 }
154
155 static const OSSL_PARAM *mac_gettable_params(void *provctx,
156                                              const GOST_DESC * descriptor)
157 {
158     static const OSSL_PARAM params[] = {
159         OSSL_PARAM_size_t("size", NULL),
160         OSSL_PARAM_size_t("keylen", NULL),
161         OSSL_PARAM_END
162     };
163
164     return params;
165 }
166
167 static const OSSL_PARAM *mac_gettable_ctx_params(void *mctx, void *provctx)
168 {
169     static const OSSL_PARAM params[] = {
170         OSSL_PARAM_size_t("size", NULL),
171         OSSL_PARAM_size_t("keylen", NULL),
172         OSSL_PARAM_END
173     };
174
175     return params;
176 }
177
178 static const OSSL_PARAM *mac_settable_ctx_params(void *mctx, void *provctx)
179 {
180     static const OSSL_PARAM params[] = {
181         OSSL_PARAM_size_t("size", NULL),
182         OSSL_PARAM_octet_string("key", NULL, 0),
183         OSSL_PARAM_END
184     };
185
186     return params;
187 }
188
189 static int mac_get_params(const GOST_DESC * descriptor, OSSL_PARAM params[])
190 {
191     OSSL_PARAM *p = NULL;
192
193     if (((p = OSSL_PARAM_locate(params, "size")) != NULL
194          && !OSSL_PARAM_set_size_t(p, descriptor->initial_mac_size))
195         || ((p = OSSL_PARAM_locate(params, "keylen")) != NULL
196             && !OSSL_PARAM_set_size_t(p, 32)))
197         return 0;
198     return 1;
199 }
200
201 static int mac_get_ctx_params(void *mctx, OSSL_PARAM params[])
202 {
203     GOST_CTX *gctx = mctx;
204     OSSL_PARAM *p = NULL;
205
206     if ((p = OSSL_PARAM_locate(params, "size")) != NULL
207         && !OSSL_PARAM_set_size_t(p, gctx->mac_size))
208         return 0;
209
210     if ((p = OSSL_PARAM_locate(params, "keylen")) != NULL) {
211         unsigned int len = 0;
212
213         if (EVP_MD_CTX_ctrl(gctx->dctx, EVP_MD_CTRL_KEY_LEN, 0, &len) <= 0
214             || !OSSL_PARAM_set_size_t(p, len))
215             return 0;
216     }
217
218     if ((p = OSSL_PARAM_locate(params, "xof")) != NULL
219         && (!(EVP_MD_flags(EVP_MD_CTX_md(gctx->dctx)) & EVP_MD_FLAG_XOF)
220             || !OSSL_PARAM_set_int(p, gctx->xof_mode)))
221         return 0;
222
223     return 1;
224 }
225
226 static int mac_set_ctx_params(void *mctx, const OSSL_PARAM params[])
227 {
228     GOST_CTX *gctx = mctx;
229     const OSSL_PARAM *p = NULL;
230
231     if ((p = OSSL_PARAM_locate_const(params, "size")) != NULL
232         && !OSSL_PARAM_get_size_t(p, &gctx->mac_size))
233         return 0;
234     if ((p = OSSL_PARAM_locate_const(params, "key")) != NULL) {
235         const unsigned char *key = NULL;
236         size_t keylen = 0;
237         int ret;
238
239         if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&key, &keylen))
240             return 0;
241
242         ret = EVP_MD_CTX_ctrl(gctx->dctx, EVP_MD_CTRL_SET_KEY,
243                               (int)keylen, (void *)key);
244         if (ret <= 0 && ret != -2)
245             return 0;
246     }
247     if ((p = OSSL_PARAM_locate_const(params, "xof")) != NULL
248         && (!(EVP_MD_flags(EVP_MD_CTX_md(gctx->dctx)) & EVP_MD_FLAG_XOF)
249             || !OSSL_PARAM_get_int(p, &gctx->xof_mode)))
250         return 0;
251     if ((p = OSSL_PARAM_locate_const(params, "key-mesh")) != NULL) {
252         size_t key_mesh = 0;
253         int i_cipher_key_mesh = 0, *p_cipher_key_mesh = NULL;
254
255         if (!OSSL_PARAM_get_size_t(p, &key_mesh))
256             return 0;
257
258         if ((p = OSSL_PARAM_locate_const(params, "cipher-key-mesh")) != NULL) {
259             size_t cipher_key_mesh = 0;
260
261             if (!OSSL_PARAM_get_size_t(p, &cipher_key_mesh)) {
262                 return 0;
263             } else {
264                 i_cipher_key_mesh = (int)cipher_key_mesh;
265                 p_cipher_key_mesh = &i_cipher_key_mesh;
266             }
267         }
268
269         if (EVP_MD_CTX_ctrl(gctx->dctx, EVP_CTRL_KEY_MESH,
270                             key_mesh, p_cipher_key_mesh) <= 0)
271             return 0;
272     }
273     return 1;
274 }
275
276 /*
277  * Macros to map the MAC algorithms to their respective GOST_digest
278  * implementation where necessary.  Not needed for magma and grasshopper, as
279  * they already have fitting names.
280  */
281 #define id_Gost28147_89_MAC_digest      Gost28147_89_MAC_digest
282 #define gost_mac_12_digest              Gost28147_89_mac_12_digest
283 #define id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac_digest \
284     kuznyechik_ctracpkm_omac_digest
285
286 typedef void (*fptr_t)(void);
287 #define MAKE_FUNCTIONS(name, macsize)                                   \
288     const GOST_DESC name##_desc = {                                     \
289         &name##_digest,                                                 \
290         macsize,                                                        \
291     };                                                                  \
292     static OSSL_FUNC_mac_newctx_fn name##_newctx;                       \
293     static void *name##_newctx(void *provctx)                           \
294     {                                                                   \
295         return mac_newctx(provctx, &name##_desc);                       \
296     }                                                                   \
297     static OSSL_FUNC_mac_gettable_params_fn name##_gettable_params;     \
298     static const OSSL_PARAM *name##_gettable_params(void *provctx)      \
299     {                                                                   \
300         return mac_gettable_params(provctx, &name##_desc);              \
301     }                                                                   \
302     static OSSL_FUNC_mac_get_params_fn name##_get_params;               \
303     static int name##_get_params(OSSL_PARAM *params)                    \
304     {                                                                   \
305         return mac_get_params(&name##_desc, params);                    \
306     }                                                                   \
307     static const OSSL_DISPATCH name##_functions[] = {                   \
308         { OSSL_FUNC_MAC_GETTABLE_PARAMS,                                \
309           (fptr_t)name##_gettable_params },                             \
310         { OSSL_FUNC_MAC_GET_PARAMS, (fptr_t)name##_get_params },        \
311         { OSSL_FUNC_MAC_NEWCTX, (fptr_t)name##_newctx },                \
312         { OSSL_FUNC_MAC_DUPCTX, (fptr_t)mac_dupctx },                   \
313         { OSSL_FUNC_MAC_FREECTX, (fptr_t)mac_freectx },                 \
314         { OSSL_FUNC_MAC_INIT, (fptr_t)mac_init },                       \
315         { OSSL_FUNC_MAC_UPDATE, (fptr_t)mac_update },                   \
316         { OSSL_FUNC_MAC_FINAL, (fptr_t)mac_final },                     \
317         { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,                            \
318           (fptr_t)mac_gettable_ctx_params },                            \
319         { OSSL_FUNC_MAC_GET_CTX_PARAMS, (fptr_t)mac_get_ctx_params },   \
320         { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,                            \
321           (fptr_t)mac_settable_ctx_params },                            \
322         { OSSL_FUNC_MAC_SET_CTX_PARAMS, (fptr_t)mac_set_ctx_params },   \
323     }
324
325 /*
326  * The name used here is the same as the NID name.  Some of the names are
327  * horribly long, but that can't be helped...
328  */
329 MAKE_FUNCTIONS(id_Gost28147_89_MAC, 4);
330 MAKE_FUNCTIONS(gost_mac_12, 4);
331 MAKE_FUNCTIONS(magma_mac, 8);
332 MAKE_FUNCTIONS(grasshopper_mac, 16);
333 MAKE_FUNCTIONS(id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac, 16);
334
335 /* The OSSL_ALGORITHM for the provider's operation query function */
336 const OSSL_ALGORITHM GOST_prov_macs[] = {
337     { SN_id_Gost28147_89_MAC ":1.2.643.2.2.22", NULL,
338       id_Gost28147_89_MAC_functions, "GOST 28147-89 MAC" },
339     { SN_gost_mac_12, NULL, gost_mac_12_functions },
340     { SN_magma_mac, NULL, magma_mac_functions },
341     { SN_grasshopper_mac, NULL, grasshopper_mac_functions },
342     { SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac
343       ":1.2.643.7.1.1.5.2.2", NULL,
344       id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac_functions },
345     { NULL , NULL, NULL }
346 };
347
348 void GOST_prov_deinit_mac_digests(void) {
349     static GOST_digest *list[] = {
350         &Gost28147_89_MAC_digest,
351         &Gost28147_89_mac_12_digest,
352         &magma_mac_digest,
353         &grasshopper_mac_digest,
354         &kuznyechik_ctracpkm_omac_digest
355     };
356     size_t i;
357 #define elems(l) (sizeof(l) / sizeof(l[0]))
358
359     for (i = 0; i < elems(list); i++)
360         GOST_deinit_digest(list[i]);
361 }