]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_eng.c
Add explicit support for NID_id_GostR3410_2001DH (GOST R 34.10-2001 DH)
[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 GOST_digest *gost_digest_array[] = {
58     &GostR3411_94_digest,
59     &Gost28147_89_MAC_digest,
60     &GostR3411_2012_256_digest,
61     &GostR3411_2012_512_digest,
62     &Gost28147_89_mac_12_digest,
63     &magma_mac_digest,
64     &grasshopper_mac_digest,
65     &kuznyechik_ctracpkm_omac_digest,
66 };
67
68 GOST_cipher *gost_cipher_array[] = {
69     &Gost28147_89_cipher,
70     &Gost28147_89_cnt_cipher,
71     &Gost28147_89_cnt_12_cipher,
72     &Gost28147_89_cbc_cipher,
73     &grasshopper_ecb_cipher,
74     &grasshopper_cbc_cipher,
75     &grasshopper_cfb_cipher,
76     &grasshopper_ofb_cipher,
77     &grasshopper_ctr_cipher,
78     &magma_cbc_cipher,
79     &magma_ctr_cipher,
80     &magma_ctr_acpkm_cipher,
81     &magma_ctr_acpkm_omac_cipher,
82     &grasshopper_ctr_acpkm_cipher,
83     &grasshopper_ctr_acpkm_omac_cipher,
84     &magma_kexp15_cipher,
85     &kuznyechik_kexp15_cipher,
86 };
87
88 static struct gost_meth_minfo {
89     int nid;
90     EVP_PKEY_METHOD **pmeth;
91     EVP_PKEY_ASN1_METHOD **ameth;
92     const char *pemstr;
93     const char *info;
94 } gost_meth_array[] = {
95     {
96         NID_id_GostR3410_2001,
97         &pmeth_GostR3410_2001,
98         &ameth_GostR3410_2001,
99         "GOST2001",
100         "GOST R 34.10-2001",
101     },
102     {
103         NID_id_GostR3410_2001DH,
104         &pmeth_GostR3410_2001DH,
105         &ameth_GostR3410_2001DH,
106         "GOST2001 DH",
107         "GOST R 34.10-2001 DH",
108     },
109     {
110         NID_id_Gost28147_89_MAC,
111         &pmeth_Gost28147_MAC,
112         &ameth_Gost28147_MAC,
113         "GOST-MAC",
114         "GOST 28147-89 MAC",
115     },
116     {
117         NID_id_GostR3410_2012_256,
118         &pmeth_GostR3410_2012_256,
119         &ameth_GostR3410_2012_256,
120         "GOST2012_256",
121         "GOST R 34.10-2012 with 256 bit key",
122     },
123     {
124         NID_id_GostR3410_2012_512,
125         &pmeth_GostR3410_2012_512,
126         &ameth_GostR3410_2012_512,
127         "GOST2012_512",
128         "GOST R 34.10-2012 with 512 bit key",
129     },
130     {
131         NID_gost_mac_12,
132         &pmeth_Gost28147_MAC_12,
133         &ameth_Gost28147_MAC_12,
134         "GOST-MAC-12",
135         "GOST 28147-89 MAC with 2012 params",
136     },
137     {
138         NID_magma_mac,
139         &pmeth_magma_mac,
140         &ameth_magma_mac,
141         "MAGMA-MAC",
142         "GOST R 34.13-2015 Magma MAC",
143     },
144     {
145         NID_grasshopper_mac,
146         &pmeth_grasshopper_mac,
147         &ameth_grasshopper_mac,
148         "KUZNYECHIK-MAC",
149         "GOST R 34.13-2015 Grasshopper MAC",
150     },
151     {
152         NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac,
153         &pmeth_magma_mac_acpkm,
154         &ameth_magma_mac_acpkm,
155         "ID-TC26-CIPHER-GOSTR3412-2015-MAGMA-CTRACPKM-OMAC",
156         "GOST R 34.13-2015 Magma MAC ACPKM",
157     },
158     {
159         NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac,
160         &pmeth_grasshopper_mac_acpkm,
161         &ameth_grasshopper_mac_acpkm,
162         "ID-TC26-CIPHER-GOSTR3412-2015-KUZNYECHIK-CTRACPKM-OMAC",
163         "GOST R 34.13-2015 Grasshopper MAC ACPKM",
164     },
165     { 0 },
166 };
167
168 #ifndef OSSL_NELEM
169 # define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0]))
170 #endif
171
172 static int known_digest_nids[OSSL_NELEM(gost_digest_array)];
173 static int known_cipher_nids[OSSL_NELEM(gost_cipher_array)];
174 /* `- 1' because of terminating zero element */
175 static int known_meths_nids[OSSL_NELEM(gost_meth_array) - 1];
176
177 static int gost_engine_init(ENGINE* e) {
178     return 1;
179 }
180
181 static int gost_engine_finish(ENGINE* e) {
182     return 1;
183 }
184
185 static int gost_engine_destroy(ENGINE* e) {
186     int i;
187
188     for (i = 0; i < OSSL_NELEM(gost_digest_array); i++)
189         GOST_deinit_digest(gost_digest_array[i]);
190     for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++)
191         GOST_deinit_cipher(gost_cipher_array[i]);
192
193     gost_param_free();
194
195     struct gost_meth_minfo *minfo = gost_meth_array;
196     for (; minfo->nid; minfo++) {
197         *minfo->pmeth = NULL;
198         *minfo->ameth = NULL;
199     }
200
201     ERR_unload_GOST_strings();
202
203     return 1;
204 }
205
206 static int bind_gost(ENGINE* e, const char* id) {
207     int ret = 0;
208     if (id != NULL && strcmp(id, engine_gost_id) != 0)
209         return 0;
210     if (ameth_GostR3410_2001) {
211         printf("GOST engine already loaded\n");
212         goto end;
213     }
214     if (!ENGINE_set_id(e, engine_gost_id)) {
215         printf("ENGINE_set_id failed\n");
216         goto end;
217     }
218     if (!ENGINE_set_name(e, engine_gost_name)) {
219         printf("ENGINE_set_name failed\n");
220         goto end;
221     }
222     if (!ENGINE_set_digests(e, gost_digests)) {
223         printf("ENGINE_set_digests failed\n");
224         goto end;
225     }
226     if (!ENGINE_set_ciphers(e, gost_ciphers)) {
227         printf("ENGINE_set_ciphers failed\n");
228         goto end;
229     }
230     if (!ENGINE_set_pkey_meths(e, gost_pkey_meths)) {
231         printf("ENGINE_set_pkey_meths failed\n");
232         goto end;
233     }
234     if (!ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) {
235         printf("ENGINE_set_pkey_asn1_meths failed\n");
236         goto end;
237     }
238     /* Control function and commands */
239     if (!ENGINE_set_cmd_defns(e, gost_cmds)) {
240         fprintf(stderr, "ENGINE_set_cmd_defns failed\n");
241         goto end;
242     }
243     if (!ENGINE_set_ctrl_function(e, gost_control_func)) {
244         fprintf(stderr, "ENGINE_set_ctrl_func failed\n");
245         goto end;
246     }
247     if (!ENGINE_set_destroy_function(e, gost_engine_destroy)
248         || !ENGINE_set_init_function(e, gost_engine_init)
249         || !ENGINE_set_finish_function(e, gost_engine_finish)) {
250         goto end;
251     }
252
253     struct gost_meth_minfo *minfo = gost_meth_array;
254     for (; minfo->nid; minfo++) {
255
256         /* This skip looks temporary. */
257         if (minfo->nid == NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac)
258             continue;
259
260         if (!register_ameth_gost(minfo->nid, minfo->ameth, minfo->pemstr,
261                 minfo->info))
262             goto end;
263         if (!register_pmeth_gost(minfo->nid, minfo->pmeth, 0))
264             goto end;
265     }
266
267     if (!ENGINE_register_ciphers(e)
268         || !ENGINE_register_digests(e)
269         || !ENGINE_register_pkey_meths(e))
270         goto end;
271
272     int i;
273     for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++) {
274         if (!EVP_add_cipher(GOST_init_cipher(gost_cipher_array[i])))
275             goto end;
276     }
277
278     for (i = 0; i < OSSL_NELEM(gost_digest_array); i++) {
279         if (!EVP_add_digest(GOST_init_digest(gost_digest_array[i])))
280             goto end;
281     }
282
283     ENGINE_register_all_complete();
284
285     ERR_load_GOST_strings();
286     ret = 1;
287     end:
288     return ret;
289 }
290
291 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
292 IMPLEMENT_DYNAMIC_BIND_FN(bind_gost)
293     IMPLEMENT_DYNAMIC_CHECK_FN()
294 #endif                          /* ndef OPENSSL_NO_DYNAMIC_ENGINE */
295
296 /* ENGINE_DIGESTS_PTR callback installed by ENGINE_set_digests */
297 static int gost_digests(ENGINE *e, const EVP_MD **digest,
298                         const int **nids, int nid)
299 {
300     int i;
301
302     if (!digest) {
303         int *n = known_digest_nids;
304
305         *nids = n;
306         for (i = 0; i < OSSL_NELEM(gost_digest_array); i++)
307             *n++ = gost_digest_array[i]->nid;
308         return i;
309     }
310
311     for (i = 0; i < OSSL_NELEM(gost_digest_array); i++)
312         if (nid == gost_digest_array[i]->nid) {
313             *digest = GOST_init_digest(gost_digest_array[i]);
314             return 1;
315         }
316     *digest = NULL;
317     return 0;
318 }
319
320 /* ENGINE_CIPHERS_PTR callback installed by ENGINE_set_ciphers */
321 static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
322                         const int **nids, int nid)
323 {
324     int i;
325
326     if (!cipher) {
327         int *n = known_cipher_nids;
328
329         *nids = n;
330         for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++)
331             *n++ = gost_cipher_array[i]->nid;
332         return i;
333     }
334
335     for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++)
336         if (nid == gost_cipher_array[i]->nid) {
337             *cipher = GOST_init_cipher(gost_cipher_array[i]);
338             return 1;
339         }
340     *cipher = NULL;
341     return 0;
342 }
343
344 static int gost_meth_nids(const int **nids)
345 {
346     struct gost_meth_minfo *info = gost_meth_array;
347     int *n = known_meths_nids;
348
349     *nids = n;
350     for (; info->nid; info++)
351         *n++ = info->nid;
352     return OSSL_NELEM(known_meths_nids);
353 }
354
355 /* ENGINE_PKEY_METHS_PTR installed by ENGINE_set_pkey_meths */
356 static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
357                            const int **nids, int nid)
358 {
359     struct gost_meth_minfo *info;
360
361     if (!pmeth)
362         return gost_meth_nids(nids);
363
364     for (info = gost_meth_array; info->nid; info++)
365         if (nid == info->nid) {
366             *pmeth = *info->pmeth;
367             return 1;
368         }
369     *pmeth = NULL;
370     return 0;
371 }
372
373 /* ENGINE_PKEY_ASN1_METHS_PTR installed by ENGINE_set_pkey_asn1_meths */
374 static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
375                                 const int **nids, int nid)
376 {
377     struct gost_meth_minfo *info;
378
379     if (!ameth)
380         return gost_meth_nids(nids);
381
382     for (info = gost_meth_array; info->nid; info++)
383         if (nid == info->nid) {
384             *ameth = *info->ameth;
385             return 1;
386         }
387     *ameth = NULL;
388     return 0;
389 }
390
391 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
392
393 static ENGINE* engine_gost(void) {
394     ENGINE* ret = ENGINE_new();
395     if (!ret)
396         return NULL;
397     if (!bind_gost(ret, engine_gost_id)) {
398         ENGINE_free(ret);
399         return NULL;
400     }
401     return ret;
402 }
403
404 void ENGINE_load_gost(void) {
405     ENGINE* toadd;
406     if (pmeth_GostR3410_2001)
407         return;
408     toadd = engine_gost();
409     if (!toadd)
410         return;
411     ENGINE_add(toadd);
412     ENGINE_free(toadd);
413     ERR_clear_error();
414 }
415
416 #endif
417 /* vim: set expandtab cinoptions=\:0,l1,t0,g0,(0 sw=4 : */