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