]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_eng.c
gost_grasshopper_cipher: Rework cipher registration
[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 *reg;
113 } gost_cipher_array[] = {
114     {
115         NID_id_Gost28147_89,
116         NULL,
117         &Gost28147_89_cipher,
118     },
119     {
120         NID_gost89_cnt,
121         NULL,
122         &Gost28147_89_cnt_cipher,
123     },
124     {
125         NID_gost89_cnt_12,
126         NULL,
127         &Gost28147_89_cnt_12_cipher,
128     },
129     {
130         NID_gost89_cbc,
131         NULL,
132         &Gost28147_89_cbc_cipher,
133     },
134     {
135         NID_grasshopper_ecb,
136         NULL,
137         &grasshopper_ecb_cipher,
138     },
139     {
140         NID_grasshopper_cbc,
141         NULL,
142         &grasshopper_cbc_cipher,
143     },
144     {
145         NID_grasshopper_cfb,
146         NULL,
147         &grasshopper_cfb_cipher,
148     },
149     {
150         NID_grasshopper_ofb,
151         NULL,
152         &grasshopper_ofb_cipher,
153     },
154     {
155         NID_grasshopper_ctr,
156         NULL,
157         &grasshopper_ctr_cipher,
158     },
159     {
160         NID_magma_cbc,
161         NULL,
162         &magma_cbc_cipher,
163     },
164     {
165         NID_magma_ctr,
166         NULL,
167         &magma_ctr_cipher,
168     },
169     {
170         NID_magma_ctr_acpkm,
171         NULL,
172         &magma_ctr_acpkm_cipher,
173     },
174     {
175         NID_magma_ctr_acpkm_omac,
176         NULL,
177         &magma_ctr_acpkm_omac_cipher,
178     },
179     {
180         NID_kuznyechik_ctr_acpkm,
181         NULL,
182         &grasshopper_ctr_acpkm_cipher,
183     },
184     {
185         NID_kuznyechik_ctr_acpkm_omac,
186         NULL,
187         &grasshopper_ctr_acpkm_omac_cipher,
188     },
189     {
190         NID_magma_kexp15,
191         cipher_magma_wrap,
192     },
193     {
194         NID_kuznyechik_kexp15,
195         cipher_kuznyechik_wrap,
196     },
197     { 0 },
198 };
199
200 static struct gost_meth_minfo {
201     int nid;
202     EVP_PKEY_METHOD **pmeth;
203     EVP_PKEY_ASN1_METHOD **ameth;
204     const char *pemstr;
205     const char *info;
206 } gost_meth_array[] = {
207     {
208         NID_id_GostR3410_2001,
209         &pmeth_GostR3410_2001,
210         &ameth_GostR3410_2001,
211         "GOST2001",
212         "GOST R 34.10-2001",
213     },
214     {
215         NID_id_Gost28147_89_MAC,
216         &pmeth_Gost28147_MAC,
217         &ameth_Gost28147_MAC,
218         "GOST-MAC",
219         "GOST 28147-89 MAC",
220     },
221     {
222         NID_id_GostR3410_2012_256,
223         &pmeth_GostR3410_2012_256,
224         &ameth_GostR3410_2012_256,
225         "GOST2012_256",
226         "GOST R 34.10-2012 with 256 bit key",
227     },
228     {
229         NID_id_GostR3410_2012_512,
230         &pmeth_GostR3410_2012_512,
231         &ameth_GostR3410_2012_512,
232         "GOST2012_512",
233         "GOST R 34.10-2012 with 512 bit key",
234     },
235     {
236         NID_gost_mac_12,
237         &pmeth_Gost28147_MAC_12,
238         &ameth_Gost28147_MAC_12,
239         "GOST-MAC-12",
240         "GOST 28147-89 MAC with 2012 params",
241     },
242     {
243         NID_magma_mac,
244         &pmeth_magma_mac,
245         &ameth_magma_mac,
246         "MAGMA-MAC",
247         "GOST R 34.13-2015 Magma MAC",
248     },
249     {
250         NID_grasshopper_mac,
251         &pmeth_grasshopper_mac,
252         &ameth_grasshopper_mac,
253         "KUZNYECHIK-MAC",
254         "GOST R 34.13-2015 Grasshopper MAC",
255     },
256     {
257         NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac,
258         &pmeth_magma_mac_acpkm,
259         &ameth_magma_mac_acpkm,
260         "ID-TC26-CIPHER-GOSTR3412-2015-MAGMA-CTRACPKM-OMAC",
261         "GOST R 34.13-2015 Magma MAC ACPKM",
262     },
263     {
264         NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac,
265         &pmeth_grasshopper_mac_acpkm,
266         &ameth_grasshopper_mac_acpkm,
267         "ID-TC26-CIPHER-GOSTR3412-2015-KUZNYECHIK-CTRACPKM-OMAC",
268         "GOST R 34.13-2015 Grasshopper MAC ACPKM",
269     },
270     { 0 },
271 };
272
273 #ifndef OSSL_NELEM
274 # define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0]))
275 #endif
276
277 /* `- 1' because of terminating zero element */
278 static int known_digest_nids[OSSL_NELEM(gost_digest_array) - 1];
279 static int known_cipher_nids[OSSL_NELEM(gost_cipher_array) - 1];
280 static int known_meths_nids[OSSL_NELEM(gost_meth_array) - 1];
281
282 static int gost_engine_init(ENGINE* e) {
283     return 1;
284 }
285
286 static int gost_engine_finish(ENGINE* e) {
287     return 1;
288 }
289
290 static int gost_engine_destroy(ENGINE* e) {
291     struct gost_digest_minfo *dinfo = gost_digest_array;
292     for (; dinfo->nid; dinfo++) {
293         if (dinfo->alias)
294             EVP_delete_digest_alias(dinfo->alias);
295         dinfo->destroy();
296     }
297
298     struct gost_cipher_minfo *cinfo = gost_cipher_array;
299     for (; cinfo->nid; cinfo++) {
300         if (cinfo->reg)
301             GOST_deinit_cipher(cinfo->reg);
302         else
303             EVP_CIPHER_meth_free((EVP_CIPHER *)cinfo->cipher());
304     }
305
306     //cipher_gost_grasshopper_destroy();
307     //wrap_ciphers_destroy();
308
309     gost_param_free();
310
311     struct gost_meth_minfo *minfo = gost_meth_array;
312     for (; minfo->nid; minfo++) {
313         *minfo->pmeth = NULL;
314         *minfo->ameth = NULL;
315     }
316
317     ERR_unload_GOST_strings();
318
319     return 1;
320 }
321
322 static int bind_gost(ENGINE* e, const char* id) {
323     int ret = 0;
324     if (id != NULL && strcmp(id, engine_gost_id) != 0)
325         return 0;
326     if (ameth_GostR3410_2001) {
327         printf("GOST engine already loaded\n");
328         goto end;
329     }
330     if (!ENGINE_set_id(e, engine_gost_id)) {
331         printf("ENGINE_set_id failed\n");
332         goto end;
333     }
334     if (!ENGINE_set_name(e, engine_gost_name)) {
335         printf("ENGINE_set_name failed\n");
336         goto end;
337     }
338     if (!ENGINE_set_digests(e, gost_digests)) {
339         printf("ENGINE_set_digests failed\n");
340         goto end;
341     }
342     if (!ENGINE_set_ciphers(e, gost_ciphers)) {
343         printf("ENGINE_set_ciphers failed\n");
344         goto end;
345     }
346     if (!ENGINE_set_pkey_meths(e, gost_pkey_meths)) {
347         printf("ENGINE_set_pkey_meths failed\n");
348         goto end;
349     }
350     if (!ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) {
351         printf("ENGINE_set_pkey_asn1_meths failed\n");
352         goto end;
353     }
354     /* Control function and commands */
355     if (!ENGINE_set_cmd_defns(e, gost_cmds)) {
356         fprintf(stderr, "ENGINE_set_cmd_defns failed\n");
357         goto end;
358     }
359     if (!ENGINE_set_ctrl_function(e, gost_control_func)) {
360         fprintf(stderr, "ENGINE_set_ctrl_func failed\n");
361         goto end;
362     }
363     if (!ENGINE_set_destroy_function(e, gost_engine_destroy)
364         || !ENGINE_set_init_function(e, gost_engine_init)
365         || !ENGINE_set_finish_function(e, gost_engine_finish)) {
366         goto end;
367     }
368
369     struct gost_meth_minfo *minfo = gost_meth_array;
370     for (; minfo->nid; minfo++) {
371
372         /* This skip looks temporary. */
373         if (minfo->nid == NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac)
374             continue;
375
376         if (!register_ameth_gost(minfo->nid, minfo->ameth, minfo->pemstr,
377                 minfo->info))
378             goto end;
379         if (!register_pmeth_gost(minfo->nid, minfo->pmeth, 0))
380             goto end;
381     }
382
383     if (!ENGINE_register_ciphers(e)
384         || !ENGINE_register_digests(e)
385         || !ENGINE_register_pkey_meths(e))
386         goto end;
387
388     struct gost_cipher_minfo *cinfo = gost_cipher_array;
389     for (; cinfo->nid; cinfo++) {
390         const EVP_CIPHER *cipher;
391
392         if (cinfo->reg)
393             cipher = GOST_init_cipher(cinfo->reg);
394         else
395             cipher = cinfo->cipher();
396         if (!EVP_add_cipher(cipher))
397             goto end;
398     }
399
400     struct gost_digest_minfo *dinfo = gost_digest_array;
401     for (; dinfo->nid; dinfo++) {
402         if (!EVP_add_digest(dinfo->digest()))
403             goto end;
404         if (dinfo->alias &&
405             !EVP_add_digest_alias(dinfo->sn, dinfo->alias))
406             goto end;
407     }
408
409     ENGINE_register_all_complete();
410
411     ERR_load_GOST_strings();
412     ret = 1;
413     end:
414     return ret;
415 }
416
417 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
418 IMPLEMENT_DYNAMIC_BIND_FN(bind_gost)
419     IMPLEMENT_DYNAMIC_CHECK_FN()
420 #endif                          /* ndef OPENSSL_NO_DYNAMIC_ENGINE */
421
422 /* ENGINE_DIGESTS_PTR callback installed by ENGINE_set_digests */
423 static int gost_digests(ENGINE *e, const EVP_MD **digest,
424                         const int **nids, int nid)
425 {
426     struct gost_digest_minfo *info = gost_digest_array;
427
428     if (!digest) {
429         int *n = known_digest_nids;
430
431         *nids = n;
432         for (; info->nid; info++)
433             *n++ = info->nid;
434         return OSSL_NELEM(known_digest_nids);
435     }
436
437     for (; info->nid; info++)
438         if (nid == info->nid) {
439             *digest = info->digest();
440             return 1;
441         }
442     *digest = NULL;
443     return 0;
444 }
445
446 /* ENGINE_CIPHERS_PTR callback installed by ENGINE_set_ciphers */
447 static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
448                         const int **nids, int nid)
449 {
450     struct gost_cipher_minfo *info = gost_cipher_array;
451
452     if (!cipher) {
453         int *n = known_cipher_nids;
454
455         *nids = n;
456         for (; info->nid; info++)
457             *n++ = info->nid;
458         return OSSL_NELEM(known_cipher_nids);
459     }
460
461     for (; info->nid; info++)
462         if (nid == info->nid) {
463             if (info->reg)
464                 *cipher = GOST_init_cipher(info->reg);
465             else
466                 *cipher = info->cipher();
467             return 1;
468         }
469     *cipher = NULL;
470     return 0;
471 }
472
473 static int gost_meth_nids(const int **nids)
474 {
475     struct gost_meth_minfo *info = gost_meth_array;
476     int *n = known_meths_nids;
477
478     *nids = n;
479     for (; info->nid; info++)
480         *n++ = info->nid;
481     return OSSL_NELEM(known_meths_nids);
482 }
483
484 /* ENGINE_PKEY_METHS_PTR installed by ENGINE_set_pkey_meths */
485 static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
486                            const int **nids, int nid)
487 {
488     struct gost_meth_minfo *info;
489
490     if (!pmeth)
491         return gost_meth_nids(nids);
492
493     for (info = gost_meth_array; info->nid; info++)
494         if (nid == info->nid) {
495             *pmeth = *info->pmeth;
496             return 1;
497         }
498     *pmeth = NULL;
499     return 0;
500 }
501
502 /* ENGINE_PKEY_ASN1_METHS_PTR installed by ENGINE_set_pkey_asn1_meths */
503 static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
504                                 const int **nids, int nid)
505 {
506     struct gost_meth_minfo *info;
507
508     if (!ameth)
509         return gost_meth_nids(nids);
510
511     for (info = gost_meth_array; info->nid; info++)
512         if (nid == info->nid) {
513             *ameth = *info->ameth;
514             return 1;
515         }
516     *ameth = NULL;
517     return 0;
518 }
519
520 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
521
522 static ENGINE* engine_gost(void) {
523     ENGINE* ret = ENGINE_new();
524     if (!ret)
525         return NULL;
526     if (!bind_gost(ret, engine_gost_id)) {
527         ENGINE_free(ret);
528         return NULL;
529     }
530     return ret;
531 }
532
533 void ENGINE_load_gost(void) {
534     ENGINE* toadd;
535     if (pmeth_GostR3410_2001)
536         return;
537     toadd = engine_gost();
538     if (!toadd)
539         return;
540     ENGINE_add(toadd);
541     ENGINE_free(toadd);
542     ERR_clear_error();
543 }
544
545 #endif