1 /**********************************************************************
3 * Main file of GOST engine *
5 * Copyright (c) 2005-2006 Cryptocom LTD *
6 * Copyright (c) 2020 Chikunov Vitaly <vt@altlinux.org> *
8 * This file is distributed under the same license as OpenSSL *
10 **********************************************************************/
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"
20 #include "gost_grasshopper_cipher.h"
22 static const char* engine_gost_id = "gost";
24 static const char* engine_gost_name =
25 "Reference implementation of GOST engine";
27 const ENGINE_CMD_DEFN gost_cmds[] = {
28 {GOST_CTRL_CRYPT_PARAMS,
30 "OID of default GOST 28147-89 parameters",
31 ENGINE_CMD_FLAG_STRING},
32 {GOST_CTRL_PBE_PARAMS,
34 "Shortname of default digest alg for PBE",
35 ENGINE_CMD_FLAG_STRING},
38 "Private key format params",
39 ENGINE_CMD_FLAG_STRING},
43 /* Symmetric cipher and digest function registrar */
45 static int gost_ciphers(ENGINE* e, const EVP_CIPHER** cipher,
46 const int** nids, int nid);
48 static int gost_digests(ENGINE* e, const EVP_MD** digest,
49 const int** nids, int nid);
51 static int gost_pkey_meths(ENGINE* e, EVP_PKEY_METHOD** pmeth,
52 const int** nids, int nid);
54 static int gost_pkey_asn1_meths(ENGINE* e, EVP_PKEY_ASN1_METHOD** ameth,
55 const int** nids, int nid);
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;
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;
73 GOST_digest *gost_digest_array[] = {
75 &Gost28147_89_MAC_digest,
76 &GostR3411_2012_256_digest,
77 &GostR3411_2012_512_digest,
78 &Gost28147_89_mac_12_digest,
80 &grasshopper_mac_digest,
81 &kuznyechik_ctracpkm_omac_digest,
84 GOST_cipher *gost_cipher_array[] = {
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,
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,
104 static struct gost_meth_minfo {
106 EVP_PKEY_METHOD **pmeth;
107 EVP_PKEY_ASN1_METHOD **ameth;
110 } gost_meth_array[] = {
112 NID_id_GostR3410_2001,
113 &pmeth_GostR3410_2001,
114 &ameth_GostR3410_2001,
119 NID_id_GostR3410_2001DH,
120 &pmeth_GostR3410_2001DH,
121 &ameth_GostR3410_2001DH,
123 "GOST R 34.10-2001 DH",
126 NID_id_Gost28147_89_MAC,
127 &pmeth_Gost28147_MAC,
128 &ameth_Gost28147_MAC,
133 NID_id_GostR3410_2012_256,
134 &pmeth_GostR3410_2012_256,
135 &ameth_GostR3410_2012_256,
137 "GOST R 34.10-2012 with 256 bit key",
140 NID_id_GostR3410_2012_512,
141 &pmeth_GostR3410_2012_512,
142 &ameth_GostR3410_2012_512,
144 "GOST R 34.10-2012 with 512 bit key",
148 &pmeth_Gost28147_MAC_12,
149 &ameth_Gost28147_MAC_12,
151 "GOST 28147-89 MAC with 2012 params",
158 "GOST R 34.13-2015 Magma MAC",
162 &pmeth_grasshopper_mac,
163 &ameth_grasshopper_mac,
165 "GOST R 34.13-2015 Grasshopper MAC",
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",
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",
185 # define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0]))
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];
193 static int gost_engine_init(ENGINE* e) {
197 static int gost_engine_finish(ENGINE* e) {
201 static int gost_engine_destroy(ENGINE* e) {
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]);
211 struct gost_meth_minfo *minfo = gost_meth_array;
212 for (; minfo->nid; minfo++) {
213 *minfo->pmeth = NULL;
214 *minfo->ameth = NULL;
217 ERR_unload_GOST_strings();
222 static int bind_gost(ENGINE* e, const char* id) {
224 if (id != NULL && strcmp(id, engine_gost_id) != 0)
226 if (ameth_GostR3410_2001) {
227 printf("GOST engine already loaded\n");
230 if (!ENGINE_set_id(e, engine_gost_id)) {
231 printf("ENGINE_set_id failed\n");
234 if (!ENGINE_set_name(e, engine_gost_name)) {
235 printf("ENGINE_set_name failed\n");
238 if (!ENGINE_set_digests(e, gost_digests)) {
239 printf("ENGINE_set_digests failed\n");
242 if (!ENGINE_set_ciphers(e, gost_ciphers)) {
243 printf("ENGINE_set_ciphers failed\n");
246 if (!ENGINE_set_pkey_meths(e, gost_pkey_meths)) {
247 printf("ENGINE_set_pkey_meths failed\n");
250 if (!ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) {
251 printf("ENGINE_set_pkey_asn1_meths failed\n");
254 /* Control function and commands */
255 if (!ENGINE_set_cmd_defns(e, gost_cmds)) {
256 fprintf(stderr, "ENGINE_set_cmd_defns failed\n");
259 if (!ENGINE_set_ctrl_function(e, gost_control_func)) {
260 fprintf(stderr, "ENGINE_set_ctrl_func failed\n");
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)) {
269 struct gost_meth_minfo *minfo = gost_meth_array;
270 for (; minfo->nid; minfo++) {
272 /* This skip looks temporary. */
273 if (minfo->nid == NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac)
276 if (!register_ameth_gost(minfo->nid, minfo->ameth, minfo->pemstr,
279 if (!register_pmeth_gost(minfo->nid, minfo->pmeth, 0))
283 if (!ENGINE_register_ciphers(e)
284 || !ENGINE_register_digests(e)
285 || !ENGINE_register_pkey_meths(e))
289 for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++) {
290 if (!EVP_add_cipher(GOST_init_cipher(gost_cipher_array[i])))
294 for (i = 0; i < OSSL_NELEM(gost_digest_array); i++) {
295 if (!EVP_add_digest(GOST_init_digest(gost_digest_array[i])))
299 ENGINE_register_all_complete();
301 ERR_load_GOST_strings();
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 */
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)
319 int *n = known_digest_nids;
322 for (i = 0; i < OSSL_NELEM(gost_digest_array); i++)
323 *n++ = gost_digest_array[i]->nid;
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]);
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)
343 int *n = known_cipher_nids;
346 for (i = 0; i < OSSL_NELEM(gost_cipher_array); i++)
347 *n++ = gost_cipher_array[i]->nid;
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]);
360 static int gost_meth_nids(const int **nids)
362 struct gost_meth_minfo *info = gost_meth_array;
363 int *n = known_meths_nids;
366 for (; info->nid; info++)
368 return OSSL_NELEM(known_meths_nids);
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)
375 struct gost_meth_minfo *info;
378 return gost_meth_nids(nids);
380 for (info = gost_meth_array; info->nid; info++)
381 if (nid == info->nid) {
382 *pmeth = *info->pmeth;
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)
393 struct gost_meth_minfo *info;
396 return gost_meth_nids(nids);
398 for (info = gost_meth_array; info->nid; info++)
399 if (nid == info->nid) {
400 *ameth = *info->ameth;
407 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
409 static ENGINE* engine_gost(void) {
410 ENGINE* ret = ENGINE_new();
413 if (!bind_gost(ret, engine_gost_id)) {
420 void ENGINE_load_gost(void) {
422 if (pmeth_GostR3410_2001)
424 toadd = engine_gost();
433 /* vim: set expandtab cinoptions=\:0,l1,t0,g0,(0 sw=4 : */