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 /* Symmetric cipher and digest function registrar */
29 static int gost_ciphers(ENGINE* e, const EVP_CIPHER** cipher,
30 const int** nids, int nid);
32 static int gost_digests(ENGINE* e, const EVP_MD** digest,
33 const int** nids, int nid);
35 static int gost_pkey_meths(ENGINE* e, EVP_PKEY_METHOD** pmeth,
36 const int** nids, int nid);
38 static int gost_pkey_asn1_meths(ENGINE* e, EVP_PKEY_ASN1_METHOD** ameth,
39 const int** nids, int nid);
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;
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;
55 static struct gost_digest_minfo {
57 EVP_MD *(*digest)(void);
58 void (*destroy)(void);
61 } gost_digest_array[] = {
68 NID_id_Gost28147_89_MAC,
70 imit_gost_cpa_destroy,
73 NID_id_GostR3411_2012_256,
75 digest_gost2012_256_destroy,
76 SN_id_GostR3411_2012_256,
80 NID_id_GostR3411_2012_512,
82 digest_gost2012_512_destroy,
83 SN_id_GostR3411_2012_512,
89 imit_gost_cp_12_destroy,
99 grasshopper_omac_destroy,
102 NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac,
103 grasshopper_omac_acpkm,
104 grasshopper_omac_acpkm_destroy,
109 static struct gost_cipher_minfo {
111 const EVP_CIPHER *(*cipher)(void);
113 } gost_cipher_array[] = {
117 &Gost28147_89_cipher,
122 &Gost28147_89_cnt_cipher,
127 &Gost28147_89_cnt_12_cipher,
132 &Gost28147_89_cbc_cipher,
136 cipher_gost_grasshopper_ecb,
140 cipher_gost_grasshopper_cbc,
144 cipher_gost_grasshopper_cfb,
148 cipher_gost_grasshopper_ofb,
152 cipher_gost_grasshopper_ctr,
166 &magma_ctr_acpkm_cipher,
169 NID_magma_ctr_acpkm_omac,
171 &magma_ctr_acpkm_omac_cipher,
174 NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm,
175 cipher_gost_grasshopper_ctracpkm,
178 NID_kuznyechik_ctr_acpkm_omac,
179 cipher_gost_grasshopper_ctracpkm_omac,
186 NID_kuznyechik_kexp15,
187 cipher_kuznyechik_wrap,
192 static struct gost_meth_minfo {
194 EVP_PKEY_METHOD **pmeth;
195 EVP_PKEY_ASN1_METHOD **ameth;
198 } gost_meth_array[] = {
200 NID_id_GostR3410_2001,
201 &pmeth_GostR3410_2001,
202 &ameth_GostR3410_2001,
207 NID_id_Gost28147_89_MAC,
208 &pmeth_Gost28147_MAC,
209 &ameth_Gost28147_MAC,
214 NID_id_GostR3410_2012_256,
215 &pmeth_GostR3410_2012_256,
216 &ameth_GostR3410_2012_256,
218 "GOST R 34.10-2012 with 256 bit key",
221 NID_id_GostR3410_2012_512,
222 &pmeth_GostR3410_2012_512,
223 &ameth_GostR3410_2012_512,
225 "GOST R 34.10-2012 with 512 bit key",
229 &pmeth_Gost28147_MAC_12,
230 &ameth_Gost28147_MAC_12,
232 "GOST 28147-89 MAC with 2012 params",
239 "GOST R 34.13-2015 Magma MAC",
243 &pmeth_grasshopper_mac,
244 &ameth_grasshopper_mac,
246 "GOST R 34.13-2015 Grasshopper MAC",
249 NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac,
250 &pmeth_magma_mac_acpkm,
251 &ameth_magma_mac_acpkm,
252 "ID-TC26-CIPHER-GOSTR3412-2015-MAGMA-CTRACPKM-OMAC",
253 "GOST R 34.13-2015 Magma MAC ACPKM",
256 NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac,
257 &pmeth_grasshopper_mac_acpkm,
258 &ameth_grasshopper_mac_acpkm,
259 "ID-TC26-CIPHER-GOSTR3412-2015-KUZNYECHIK-CTRACPKM-OMAC",
260 "GOST R 34.13-2015 Grasshopper MAC ACPKM",
266 # define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0]))
269 /* `- 1' because of terminating zero element */
270 static int known_digest_nids[OSSL_NELEM(gost_digest_array) - 1];
271 static int known_cipher_nids[OSSL_NELEM(gost_cipher_array) - 1];
272 static int known_meths_nids[OSSL_NELEM(gost_meth_array) - 1];
274 static int gost_engine_init(ENGINE* e) {
278 static int gost_engine_finish(ENGINE* e) {
282 static int gost_engine_destroy(ENGINE* e) {
283 struct gost_digest_minfo *dinfo = gost_digest_array;
284 for (; dinfo->nid; dinfo++) {
286 EVP_delete_digest_alias(dinfo->alias);
290 struct gost_cipher_minfo *cinfo = gost_cipher_array;
291 for (; cinfo->nid; cinfo++) {
293 GOST_deinit_cipher(cinfo->reg);
295 EVP_CIPHER_meth_free((EVP_CIPHER *)cinfo->cipher());
298 //cipher_gost_grasshopper_destroy();
299 //wrap_ciphers_destroy();
303 struct gost_meth_minfo *minfo = gost_meth_array;
304 for (; minfo->nid; minfo++) {
305 *minfo->pmeth = NULL;
306 *minfo->ameth = NULL;
309 ERR_unload_GOST_strings();
314 static int bind_gost(ENGINE* e, const char* id) {
316 if (id != NULL && strcmp(id, engine_gost_id) != 0)
318 if (ameth_GostR3410_2001) {
319 printf("GOST engine already loaded\n");
322 if (!ENGINE_set_id(e, engine_gost_id)) {
323 printf("ENGINE_set_id failed\n");
326 if (!ENGINE_set_name(e, engine_gost_name)) {
327 printf("ENGINE_set_name failed\n");
330 if (!ENGINE_set_digests(e, gost_digests)) {
331 printf("ENGINE_set_digests failed\n");
334 if (!ENGINE_set_ciphers(e, gost_ciphers)) {
335 printf("ENGINE_set_ciphers failed\n");
338 if (!ENGINE_set_pkey_meths(e, gost_pkey_meths)) {
339 printf("ENGINE_set_pkey_meths failed\n");
342 if (!ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) {
343 printf("ENGINE_set_pkey_asn1_meths failed\n");
346 /* Control function and commands */
347 if (!ENGINE_set_cmd_defns(e, gost_cmds)) {
348 fprintf(stderr, "ENGINE_set_cmd_defns failed\n");
351 if (!ENGINE_set_ctrl_function(e, gost_control_func)) {
352 fprintf(stderr, "ENGINE_set_ctrl_func failed\n");
355 if (!ENGINE_set_destroy_function(e, gost_engine_destroy)
356 || !ENGINE_set_init_function(e, gost_engine_init)
357 || !ENGINE_set_finish_function(e, gost_engine_finish)) {
361 struct gost_meth_minfo *minfo = gost_meth_array;
362 for (; minfo->nid; minfo++) {
364 /* This skip looks temporary. */
365 if (minfo->nid == NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac)
368 if (!register_ameth_gost(minfo->nid, minfo->ameth, minfo->pemstr,
371 if (!register_pmeth_gost(minfo->nid, minfo->pmeth, 0))
375 if (!ENGINE_register_ciphers(e)
376 || !ENGINE_register_digests(e)
377 || !ENGINE_register_pkey_meths(e))
380 struct gost_cipher_minfo *cinfo = gost_cipher_array;
381 for (; cinfo->nid; cinfo++) {
382 const EVP_CIPHER *cipher;
385 cipher = GOST_init_cipher(cinfo->reg);
387 cipher = cinfo->cipher();
388 if (!EVP_add_cipher(cipher))
392 struct gost_digest_minfo *dinfo = gost_digest_array;
393 for (; dinfo->nid; dinfo++) {
394 if (!EVP_add_digest(dinfo->digest()))
397 !EVP_add_digest_alias(dinfo->sn, dinfo->alias))
401 ENGINE_register_all_complete();
403 ERR_load_GOST_strings();
409 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
410 IMPLEMENT_DYNAMIC_BIND_FN(bind_gost)
411 IMPLEMENT_DYNAMIC_CHECK_FN()
412 #endif /* ndef OPENSSL_NO_DYNAMIC_ENGINE */
414 /* ENGINE_DIGESTS_PTR callback installed by ENGINE_set_digests */
415 static int gost_digests(ENGINE *e, const EVP_MD **digest,
416 const int **nids, int nid)
418 struct gost_digest_minfo *info = gost_digest_array;
421 int *n = known_digest_nids;
424 for (; info->nid; info++)
426 return OSSL_NELEM(known_digest_nids);
429 for (; info->nid; info++)
430 if (nid == info->nid) {
431 *digest = info->digest();
438 /* ENGINE_CIPHERS_PTR callback installed by ENGINE_set_ciphers */
439 static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
440 const int **nids, int nid)
442 struct gost_cipher_minfo *info = gost_cipher_array;
445 int *n = known_cipher_nids;
448 for (; info->nid; info++)
450 return OSSL_NELEM(known_cipher_nids);
453 for (; info->nid; info++)
454 if (nid == info->nid) {
456 *cipher = GOST_init_cipher(info->reg);
458 *cipher = info->cipher();
465 static int gost_meth_nids(const int **nids)
467 struct gost_meth_minfo *info = gost_meth_array;
468 int *n = known_meths_nids;
471 for (; info->nid; info++)
473 return OSSL_NELEM(known_meths_nids);
476 /* ENGINE_PKEY_METHS_PTR installed by ENGINE_set_pkey_meths */
477 static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
478 const int **nids, int nid)
480 struct gost_meth_minfo *info;
483 return gost_meth_nids(nids);
485 for (info = gost_meth_array; info->nid; info++)
486 if (nid == info->nid) {
487 *pmeth = *info->pmeth;
494 /* ENGINE_PKEY_ASN1_METHS_PTR installed by ENGINE_set_pkey_asn1_meths */
495 static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
496 const int **nids, int nid)
498 struct gost_meth_minfo *info;
501 return gost_meth_nids(nids);
503 for (info = gost_meth_array; info->nid; info++)
504 if (nid == info->nid) {
505 *ameth = *info->ameth;
512 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
514 static ENGINE* engine_gost(void) {
515 ENGINE* ret = ENGINE_new();
518 if (!bind_gost(ret, engine_gost_id)) {
525 void ENGINE_load_gost(void) {
527 if (pmeth_GostR3410_2001)
529 toadd = engine_gost();