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