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