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