]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_eng.c
Restore kuznyechik-mac test
[openssl-gost/engine.git] / gost_eng.c
1 /**********************************************************************
2  *                          gost_eng.c                                *
3  *              Main file of GOST engine                              *
4  *                                                                    *
5  *             Copyright (c) 2005-2006 Cryptocom LTD                  *
6  *             Copyright (c) 2020 Chikunov Vitaly <vt@altlinux.org>   *
7  *                                                                    *
8  *       This file is distributed under the same license as OpenSSL   *
9  *                                                                    *
10  **********************************************************************/
11 #include <string.h>
12 #include <openssl/crypto.h>
13 #include <openssl/err.h>
14 #include <openssl/evp.h>
15 #include <openssl/engine.h>
16 #include <openssl/obj_mac.h>
17 #include "e_gost_err.h"
18 #include "gost_lcl.h"
19
20 #include "gost_grasshopper_cipher.h"
21
22 static const char* engine_gost_id = "gost";
23
24 static const char* engine_gost_name =
25         "Reference implementation of GOST engine";
26
27 /* Symmetric cipher and digest function registrar */
28
29 static int gost_ciphers(ENGINE* e, const EVP_CIPHER** cipher,
30                         const int** nids, int nid);
31
32 static int gost_digests(ENGINE* e, const EVP_MD** digest,
33                         const int** nids, int nid);
34
35 static int gost_pkey_meths(ENGINE* e, EVP_PKEY_METHOD** pmeth,
36                            const int** nids, int nid);
37
38 static int gost_pkey_asn1_meths(ENGINE* e, EVP_PKEY_ASN1_METHOD** ameth,
39                                 const int** nids, int nid);
40
41 static EVP_PKEY_METHOD* pmeth_GostR3410_2001 = NULL,
42         * pmeth_GostR3410_2012_256 = NULL,
43         * pmeth_GostR3410_2012_512 = NULL,
44         * pmeth_Gost28147_MAC = NULL, * pmeth_Gost28147_MAC_12 = NULL,
45         * pmeth_magma_mac = NULL,  * pmeth_grasshopper_mac = NULL,
46         * pmeth_magma_mac_acpkm = NULL,  * pmeth_grasshopper_mac_acpkm = NULL;
47
48 static EVP_PKEY_ASN1_METHOD* ameth_GostR3410_2001 = NULL,
49         * ameth_GostR3410_2012_256 = NULL,
50         * ameth_GostR3410_2012_512 = NULL,
51         * ameth_Gost28147_MAC = NULL, * ameth_Gost28147_MAC_12 = NULL,
52         * ameth_magma_mac = NULL,  * ameth_grasshopper_mac = NULL,
53         * ameth_magma_mac_acpkm = NULL,  * ameth_grasshopper_mac_acpkm = NULL;
54
55 static struct gost_digest_minfo {
56     int nid;
57     EVP_MD *(*digest)(void);
58     void (*destroy)(void);
59     const char *sn;
60     const char *alias;
61 } gost_digest_array[] = {
62     {
63         NID_id_GostR3411_94,
64         digest_gost,
65         digest_gost_destroy,
66     },
67     {
68         NID_id_Gost28147_89_MAC,
69         imit_gost_cpa,
70         imit_gost_cpa_destroy,
71     },
72     {
73         NID_id_GostR3411_2012_256,
74         digest_gost2012_256,
75         digest_gost2012_256_destroy,
76         SN_id_GostR3411_2012_256,
77         "streebog256",
78     },
79     {
80         NID_id_GostR3411_2012_512,
81         digest_gost2012_512,
82         digest_gost2012_512_destroy,
83         SN_id_GostR3411_2012_512,
84         "streebog512",
85     },
86     {
87         NID_gost_mac_12,
88         imit_gost_cp_12,
89         imit_gost_cp_12_destroy,
90     },
91     {
92         NID_magma_mac,
93         magma_omac,
94         magma_omac_destroy,
95     },
96     {
97         NID_grasshopper_mac,
98         grasshopper_omac,
99         grasshopper_omac_destroy,
100     },
101     {
102         NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac,
103         grasshopper_omac_acpkm,
104         grasshopper_omac_acpkm_destroy,
105     },
106     { 0 },
107 };
108
109 static struct gost_cipher_minfo {
110     int nid;
111     const EVP_CIPHER *(*cipher)(void);
112 } gost_cipher_array[] = {
113     {
114         NID_id_Gost28147_89,
115         cipher_gost,
116     },
117     {
118         NID_gost89_cnt,
119         cipher_gost_cpacnt,
120     },
121     {
122         NID_gost89_cnt_12,
123         cipher_gost_cpcnt_12,
124     },
125     {
126         NID_gost89_cbc,
127         cipher_gost_cbc,
128     },
129     {
130         NID_grasshopper_ecb,
131         cipher_gost_grasshopper_ecb,
132     },
133     {
134         NID_grasshopper_cbc,
135         cipher_gost_grasshopper_cbc,
136     },
137     {
138         NID_grasshopper_cfb,
139         cipher_gost_grasshopper_cfb,
140     },
141     {
142         NID_grasshopper_ofb,
143         cipher_gost_grasshopper_ofb,
144     },
145     {
146         NID_grasshopper_ctr,
147         cipher_gost_grasshopper_ctr,
148     },
149     {
150         NID_magma_cbc,
151         cipher_magma_cbc,
152     },
153     {
154         NID_magma_ctr,
155         cipher_magma_ctr,
156     },
157     {
158         NID_magma_ctr_acpkm,
159         cipher_magma_ctr_acpkm,
160     },
161     {
162         NID_magma_ctr_acpkm_omac,
163         cipher_magma_ctr_acpkm_omac,
164     },
165     {
166         NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm,
167         cipher_gost_grasshopper_ctracpkm,
168     },
169     {
170         NID_kuznyechik_ctr_acpkm_omac,
171         cipher_gost_grasshopper_ctracpkm_omac,
172     },
173     {
174         NID_magma_kexp15,
175         cipher_magma_wrap,
176     },
177     {
178         NID_kuznyechik_kexp15,
179         cipher_kuznyechik_wrap,
180     },
181     { 0 },
182 };
183
184 static struct gost_meth_minfo {
185     int nid;
186     EVP_PKEY_METHOD **pmeth;
187     EVP_PKEY_ASN1_METHOD **ameth;
188     const char *pemstr;
189     const char *info;
190 } gost_meth_array[] = {
191     {
192         NID_id_GostR3410_2001,
193         &pmeth_GostR3410_2001,
194         &ameth_GostR3410_2001,
195         "GOST2001",
196         "GOST R 34.10-2001",
197     },
198     {
199         NID_id_Gost28147_89_MAC,
200         &pmeth_Gost28147_MAC,
201         &ameth_Gost28147_MAC,
202         "GOST-MAC",
203         "GOST 28147-89 MAC",
204     },
205     {
206         NID_id_GostR3410_2012_256,
207         &pmeth_GostR3410_2012_256,
208         &ameth_GostR3410_2012_256,
209         "GOST2012_256",
210         "GOST R 34.10-2012 with 256 bit key",
211     },
212     {
213         NID_id_GostR3410_2012_512,
214         &pmeth_GostR3410_2012_512,
215         &ameth_GostR3410_2012_512,
216         "GOST2012_512",
217         "GOST R 34.10-2012 with 512 bit key",
218     },
219     {
220         NID_gost_mac_12,
221         &pmeth_Gost28147_MAC_12,
222         &ameth_Gost28147_MAC_12,
223         "GOST-MAC-12",
224         "GOST 28147-89 MAC with 2012 params",
225     },
226     {
227         NID_magma_mac,
228         &pmeth_magma_mac,
229         &ameth_magma_mac,
230         "MAGMA-MAC",
231         "GOST R 34.13-2015 Magma MAC",
232     },
233     {
234         NID_grasshopper_mac,
235         &pmeth_grasshopper_mac,
236         &ameth_grasshopper_mac,
237         "KUZNYECHIK-MAC",
238         "GOST R 34.13-2015 Grasshopper MAC",
239     },
240     {
241         NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac,
242         &pmeth_magma_mac_acpkm,
243         &ameth_magma_mac_acpkm,
244         "ID-TC26-CIPHER-GOSTR3412-2015-MAGMA-CTRACPKM-OMAC",
245         "GOST R 34.13-2015 Magma MAC ACPKM",
246     },
247     {
248         NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac,
249         &pmeth_grasshopper_mac_acpkm,
250         &ameth_grasshopper_mac_acpkm,
251         "ID-TC26-CIPHER-GOSTR3412-2015-KUZNYECHIK-CTRACPKM-OMAC",
252         "GOST R 34.13-2015 Grasshopper MAC ACPKM",
253     },
254     { 0 },
255 };
256
257 #ifndef OSSL_NELEM
258 # define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0]))
259 #endif
260
261 /* `- 1' because of terminating zero element */
262 static int known_digest_nids[OSSL_NELEM(gost_digest_array) - 1];
263 static int known_cipher_nids[OSSL_NELEM(gost_cipher_array) - 1];
264 static int known_meths_nids[OSSL_NELEM(gost_meth_array) - 1];
265
266 static int gost_engine_init(ENGINE* e) {
267     return 1;
268 }
269
270 static int gost_engine_finish(ENGINE* e) {
271     return 1;
272 }
273
274 static int gost_engine_destroy(ENGINE* e) {
275     struct gost_digest_minfo *dinfo = gost_digest_array;
276     for (; dinfo->nid; dinfo++) {
277         if (dinfo->alias)
278             EVP_delete_digest_alias(dinfo->alias);
279         dinfo->destroy();
280     }
281
282     cipher_gost_destroy();
283     cipher_gost_grasshopper_destroy();
284     wrap_ciphers_destroy();
285
286     gost_param_free();
287
288     struct gost_meth_minfo *minfo = gost_meth_array;
289     for (; minfo->nid; minfo++) {
290         *minfo->pmeth = NULL;
291         *minfo->ameth = NULL;
292     }
293
294     ERR_unload_GOST_strings();
295
296     return 1;
297 }
298
299 static int bind_gost(ENGINE* e, const char* id) {
300     int ret = 0;
301     if (id != NULL && strcmp(id, engine_gost_id) != 0)
302         return 0;
303     if (ameth_GostR3410_2001) {
304         printf("GOST engine already loaded\n");
305         goto end;
306     }
307     if (!ENGINE_set_id(e, engine_gost_id)) {
308         printf("ENGINE_set_id failed\n");
309         goto end;
310     }
311     if (!ENGINE_set_name(e, engine_gost_name)) {
312         printf("ENGINE_set_name failed\n");
313         goto end;
314     }
315     if (!ENGINE_set_digests(e, gost_digests)) {
316         printf("ENGINE_set_digests failed\n");
317         goto end;
318     }
319     if (!ENGINE_set_ciphers(e, gost_ciphers)) {
320         printf("ENGINE_set_ciphers failed\n");
321         goto end;
322     }
323     if (!ENGINE_set_pkey_meths(e, gost_pkey_meths)) {
324         printf("ENGINE_set_pkey_meths failed\n");
325         goto end;
326     }
327     if (!ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) {
328         printf("ENGINE_set_pkey_asn1_meths failed\n");
329         goto end;
330     }
331     /* Control function and commands */
332     if (!ENGINE_set_cmd_defns(e, gost_cmds)) {
333         fprintf(stderr, "ENGINE_set_cmd_defns failed\n");
334         goto end;
335     }
336     if (!ENGINE_set_ctrl_function(e, gost_control_func)) {
337         fprintf(stderr, "ENGINE_set_ctrl_func failed\n");
338         goto end;
339     }
340     if (!ENGINE_set_destroy_function(e, gost_engine_destroy)
341         || !ENGINE_set_init_function(e, gost_engine_init)
342         || !ENGINE_set_finish_function(e, gost_engine_finish)) {
343         goto end;
344     }
345
346     struct gost_meth_minfo *minfo = gost_meth_array;
347     for (; minfo->nid; minfo++) {
348
349         /* This skip looks temporary. */
350         if (minfo->nid == NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac)
351             continue;
352
353         if (!register_ameth_gost(minfo->nid, minfo->ameth, minfo->pemstr,
354                 minfo->info))
355             goto end;
356         if (!register_pmeth_gost(minfo->nid, minfo->pmeth, 0))
357             goto end;
358     }
359
360     if (!ENGINE_register_ciphers(e)
361         || !ENGINE_register_digests(e)
362         || !ENGINE_register_pkey_meths(e))
363         goto end;
364
365     struct gost_cipher_minfo *cinfo = gost_cipher_array;
366     for (; cinfo->nid; cinfo++)
367         if (!EVP_add_cipher(cinfo->cipher()))
368             goto end;
369
370     struct gost_digest_minfo *dinfo = gost_digest_array;
371     for (; dinfo->nid; dinfo++) {
372         if (!EVP_add_digest(dinfo->digest()))
373             goto end;
374         if (dinfo->alias &&
375             !EVP_add_digest_alias(dinfo->sn, dinfo->alias))
376             goto end;
377     }
378
379     ENGINE_register_all_complete();
380
381     ERR_load_GOST_strings();
382     ret = 1;
383     end:
384     return ret;
385 }
386
387 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
388 IMPLEMENT_DYNAMIC_BIND_FN(bind_gost)
389     IMPLEMENT_DYNAMIC_CHECK_FN()
390 #endif                          /* ndef OPENSSL_NO_DYNAMIC_ENGINE */
391
392 /* ENGINE_DIGESTS_PTR callback installed by ENGINE_set_digests */
393 static int gost_digests(ENGINE *e, const EVP_MD **digest,
394                         const int **nids, int nid)
395 {
396     struct gost_digest_minfo *info = gost_digest_array;
397
398     if (!digest) {
399         int *n = known_digest_nids;
400
401         *nids = n;
402         for (; info->nid; info++)
403             *n++ = info->nid;
404         return OSSL_NELEM(known_digest_nids);
405     }
406
407     for (; info->nid; info++)
408         if (nid == info->nid) {
409             *digest = info->digest();
410             return 1;
411         }
412     *digest = NULL;
413     return 0;
414 }
415
416 /* ENGINE_CIPHERS_PTR callback installed by ENGINE_set_ciphers */
417 static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
418                         const int **nids, int nid)
419 {
420     struct gost_cipher_minfo *info = gost_cipher_array;
421
422     if (!cipher) {
423         int *n = known_cipher_nids;
424
425         *nids = n;
426         for (; info->nid; info++)
427             *n++ = info->nid;
428         return OSSL_NELEM(known_cipher_nids);
429     }
430
431     for (; info->nid; info++)
432         if (nid == info->nid) {
433             *cipher = info->cipher();
434             return 1;
435         }
436     *cipher = NULL;
437     return 0;
438 }
439
440 static int gost_meth_nids(const int **nids)
441 {
442     struct gost_meth_minfo *info = gost_meth_array;
443     int *n = known_meths_nids;
444
445     *nids = n;
446     for (; info->nid; info++)
447         *n++ = info->nid;
448     return OSSL_NELEM(known_meths_nids);
449 }
450
451 /* ENGINE_PKEY_METHS_PTR installed by ENGINE_set_pkey_meths */
452 static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
453                            const int **nids, int nid)
454 {
455     struct gost_meth_minfo *info;
456
457     if (!pmeth)
458         return gost_meth_nids(nids);
459
460     for (info = gost_meth_array; info->nid; info++)
461         if (nid == info->nid) {
462             *pmeth = *info->pmeth;
463             return 1;
464         }
465     *pmeth = NULL;
466     return 0;
467 }
468
469 /* ENGINE_PKEY_ASN1_METHS_PTR installed by ENGINE_set_pkey_asn1_meths */
470 static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
471                                 const int **nids, int nid)
472 {
473     struct gost_meth_minfo *info;
474
475     if (!ameth)
476         return gost_meth_nids(nids);
477
478     for (info = gost_meth_array; info->nid; info++)
479         if (nid == info->nid) {
480             *ameth = *info->ameth;
481             return 1;
482         }
483     *ameth = NULL;
484     return 0;
485 }
486
487 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
488
489 static ENGINE* engine_gost(void) {
490     ENGINE* ret = ENGINE_new();
491     if (!ret)
492         return NULL;
493     if (!bind_gost(ret, engine_gost_id)) {
494         ENGINE_free(ret);
495         return NULL;
496     }
497     return ret;
498 }
499
500 void ENGINE_load_gost(void) {
501     ENGINE* toadd;
502     if (pmeth_GostR3410_2001)
503         return;
504     toadd = engine_gost();
505     if (!toadd)
506         return;
507     ENGINE_add(toadd);
508     ENGINE_free(toadd);
509     ERR_clear_error();
510 }
511
512 #endif