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