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