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