]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_pmeth.c
tcl_tests: ca.try: Ignore openssl crl exit status for 'corrupted CRL' test
[openssl-gost/engine.git] / gost_pmeth.c
1 /**********************************************************************
2  *                          gost_pmeth.c                              *
3  *             Copyright (c) 2005-2013 Cryptocom LTD                  *
4  *         This file is distributed under the same license as OpenSSL *
5  *                                                                    *
6  *   Implementation of RFC 4357 (GOST R 34.10) Publick key method     *
7  *       for OpenSSL                                                  *
8  *          Requires OpenSSL 1.0.0+ for compilation                   *
9  **********************************************************************/
10 #include <openssl/evp.h>
11 #include <openssl/objects.h>
12 #include <openssl/ec.h>
13 #include <openssl/err.h>
14 #include <openssl/x509v3.h>     /* For string_to_hex */
15 #include <openssl/opensslv.h>   /* For OPENSSL_VERSION_MAJOR */
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include "gost_lcl.h"
20 #include "e_gost_err.h"
21
22 #define ossl3_const
23 #ifdef OPENSSL_VERSION_MAJOR
24 #undef ossl3_const
25 #define ossl3_const const
26 #endif
27
28 /* -----init, cleanup, copy - uniform for all algs  --------------*/
29 /* Allocates new gost_pmeth_data structure and assigns it as data */
30 static int pkey_gost_init(EVP_PKEY_CTX *ctx)
31 {
32     struct gost_pmeth_data *data;
33     EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
34
35     data = OPENSSL_malloc(sizeof(*data));
36     if (!data)
37         return 0;
38     memset(data, 0, sizeof(*data));
39     if (pkey && EVP_PKEY_get0(pkey)) {
40         switch (EVP_PKEY_base_id(pkey)) {
41         case NID_id_GostR3410_2001:
42         case NID_id_GostR3410_2001DH:
43         case NID_id_GostR3410_2012_256:
44         case NID_id_GostR3410_2012_512:
45             {
46                 const EC_GROUP *group =
47                     EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey));
48                 if (group != NULL) {
49                     data->sign_param_nid = EC_GROUP_get_curve_name(group);
50                     break;
51                 }
52                 /* else */
53             }
54         default:
55             OPENSSL_free(data);
56             return 0;
57         }
58     }
59     EVP_PKEY_CTX_set_data(ctx, data);
60     return 1;
61 }
62
63 /* Copies contents of gost_pmeth_data structure */
64 static int pkey_gost_copy(EVP_PKEY_CTX *dst, ossl3_const EVP_PKEY_CTX *src)
65 {
66     struct gost_pmeth_data *dst_data, *src_data;
67     if (!pkey_gost_init(dst)) {
68         return 0;
69     }
70     src_data = EVP_PKEY_CTX_get_data(src);
71     dst_data = EVP_PKEY_CTX_get_data(dst);
72     if (!src_data || !dst_data)
73         return 0;
74
75     *dst_data = *src_data;
76
77     return 1;
78 }
79
80 /* Frees up gost_pmeth_data structure */
81 static void pkey_gost_cleanup(EVP_PKEY_CTX *ctx)
82 {
83     struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
84     if (!data)
85         return;
86     OPENSSL_free(data);
87 }
88
89 /* --------------------- control functions  ------------------------------*/
90 static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
91 {
92     struct gost_pmeth_data *pctx =
93         (struct gost_pmeth_data *)EVP_PKEY_CTX_get_data(ctx);
94     if (pctx == NULL)
95         return 0;
96
97     switch (type) {
98     case EVP_PKEY_CTRL_MD:
99         {
100             EVP_PKEY *key = EVP_PKEY_CTX_get0_pkey(ctx);
101             int pkey_nid = (key == NULL) ? NID_undef : EVP_PKEY_base_id(key);
102
103             OPENSSL_assert(p2 != NULL);
104
105             switch (EVP_MD_type((const EVP_MD *)p2)) {
106             case NID_id_GostR3411_94:
107                 if (pkey_nid == NID_id_GostR3410_2001
108                     || pkey_nid == NID_id_GostR3410_2001DH
109                     || pkey_nid == NID_id_GostR3410_94) {
110                     pctx->md = (EVP_MD *)p2;
111                     return 1;
112                 }
113                 break;
114
115             case NID_id_GostR3411_2012_256:
116                 if (pkey_nid == NID_id_GostR3410_2012_256) {
117                     pctx->md = (EVP_MD *)p2;
118                     return 1;
119                 }
120                 break;
121
122             case NID_id_GostR3411_2012_512:
123                 if (pkey_nid == NID_id_GostR3410_2012_512) {
124                     pctx->md = (EVP_MD *)p2;
125                     return 1;
126                 }
127                 break;
128             }
129
130             GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE);
131             return 0;
132         }
133
134     case EVP_PKEY_CTRL_GET_MD:
135         *(const EVP_MD **)p2 = pctx->md;
136         return 1;
137
138     case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
139     case EVP_PKEY_CTRL_PKCS7_DECRYPT:
140     case EVP_PKEY_CTRL_PKCS7_SIGN:
141     case EVP_PKEY_CTRL_DIGESTINIT:
142 #ifndef OPENSSL_NO_CMS
143     case EVP_PKEY_CTRL_CMS_ENCRYPT:
144     case EVP_PKEY_CTRL_CMS_DECRYPT:
145     case EVP_PKEY_CTRL_CMS_SIGN:
146 #endif
147         return 1;
148
149     case EVP_PKEY_CTRL_GOST_PARAMSET:
150         pctx->sign_param_nid = (int)p1;
151         return 1;
152     case EVP_PKEY_CTRL_SET_IV:
153         if (p1 > sizeof(pctx->shared_ukm) || !p2) {
154             GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_UKM_NOT_SET);
155             return 0;
156         }
157         memcpy(pctx->shared_ukm, p2, (int)p1);
158         pctx->shared_ukm_size = p1;
159         return 1;
160     case EVP_PKEY_CTRL_SET_VKO:
161         switch (p1) {
162             case 0: /* switch to KEG */
163             case NID_id_GostR3411_2012_256:
164             case NID_id_GostR3411_2012_512:
165                 break;
166             default:
167                 GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE);
168                 return 0;
169         }
170         pctx->vko_dgst_nid = p1;
171         return 1;
172   case EVP_PKEY_CTRL_CIPHER:
173         switch (p1) {
174           case NID_magma_ctr_acpkm:
175           case NID_magma_ctr_acpkm_omac:
176           case NID_magma_ctr:
177             pctx->cipher_nid = NID_magma_ctr;
178             return 1;
179           case NID_kuznyechik_ctr_acpkm:
180           case NID_kuznyechik_ctr_acpkm_omac:
181           case NID_kuznyechik_ctr:
182             pctx->cipher_nid = NID_kuznyechik_ctr;
183             return 1;
184           default:
185             pctx->cipher_nid = p1;
186             return 1;
187         }
188     case EVP_PKEY_CTRL_PEER_KEY:
189         if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */
190             return 1;
191         if (p1 == 2)            /* TLS: peer key used? */
192             return pctx->peer_key_used;
193         if (p1 == 3)            /* TLS: peer key used! */
194             return (pctx->peer_key_used = 1);
195         break;
196     }
197
198     GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_CTRL_CALL_FAILED);
199     return -2;
200 }
201
202 static int pkey_gost_ec_ctrl_str_common(EVP_PKEY_CTX *ctx,
203                                      const char *type, const char *value)
204 {
205   if (0 == strcmp(type, ukm_ctrl_string)) {
206     unsigned char ukm_buf[32], *tmp = NULL;
207     long len = 0;
208     tmp = OPENSSL_hexstr2buf(value, &len);
209     if (tmp == NULL)
210       return 0;
211
212     if (len > 32) {
213       OPENSSL_free(tmp);
214       GOSTerr(GOST_F_PKEY_GOST_EC_CTRL_STR_COMMON, GOST_R_CTRL_CALL_FAILED);
215       return 0;
216     }
217     memcpy(ukm_buf, tmp, len);
218     OPENSSL_free(tmp);
219
220     return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_SET_IV, len, ukm_buf);
221   } else if (strcmp(type, vko_ctrl_string) == 0) {
222       int bits = atoi(value);
223       int vko_dgst_nid = 0;
224
225       if (bits == 256)
226           vko_dgst_nid = NID_id_GostR3411_2012_256;
227       else if (bits == 512)
228           vko_dgst_nid = NID_id_GostR3411_2012_512;
229       else if (bits != 0) {
230           GOSTerr(GOST_F_PKEY_GOST_EC_CTRL_STR_COMMON, GOST_R_INVALID_DIGEST_TYPE);
231           return 0;
232       }
233       return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_SET_VKO, vko_dgst_nid, NULL);
234   }
235   return -2;
236 }
237
238 static int pkey_gost_ec_ctrl_str_256(EVP_PKEY_CTX *ctx,
239                                      const char *type, const char *value)
240 {
241     if (strcmp(type, param_ctrl_string) == 0) {
242         int param_nid = 0;
243
244         if (!value) {
245             return 0;
246         }
247         if (strlen(value) == 1) {
248             switch (toupper((unsigned char)value[0])) {
249             case 'A':
250                 param_nid = NID_id_GostR3410_2001_CryptoPro_A_ParamSet;
251                 break;
252             case 'B':
253                 param_nid = NID_id_GostR3410_2001_CryptoPro_B_ParamSet;
254                 break;
255             case 'C':
256                 param_nid = NID_id_GostR3410_2001_CryptoPro_C_ParamSet;
257                 break;
258             case '0':
259                 param_nid = NID_id_GostR3410_2001_TestParamSet;
260                 break;
261             default:
262                 return 0;
263             }
264         } else if ((strlen(value) == 2)
265                    && (toupper((unsigned char)value[0]) == 'X')) {
266             switch (toupper((unsigned char)value[1])) {
267             case 'A':
268                 param_nid = NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet;
269                 break;
270             case 'B':
271                 param_nid = NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet;
272                 break;
273             default:
274                 return 0;
275             }
276     } else if ((strlen(value) == 3)
277         && (toupper((unsigned char)value[0]) == 'T')
278         && (toupper((unsigned char)value[1]) == 'C')) {
279             switch (toupper((unsigned char)value[2])) {
280             case 'A':
281                 param_nid = NID_id_tc26_gost_3410_2012_256_paramSetA;
282                 break;
283             case 'B':
284                 param_nid = NID_id_tc26_gost_3410_2012_256_paramSetB;
285                 break;
286             case 'C':
287                 param_nid = NID_id_tc26_gost_3410_2012_256_paramSetC;
288                 break;
289             case 'D':
290                 param_nid = NID_id_tc26_gost_3410_2012_256_paramSetD;
291                 break;
292             default:
293                 return 0;
294             }
295         } else {
296             R3410_ec_params *p = R3410_2001_paramset;
297             param_nid = OBJ_txt2nid(value);
298             if (param_nid == NID_undef) {
299                 return 0;
300             }
301             for (; p->nid != NID_undef; p++) {
302                 if (p->nid == param_nid)
303                     break;
304             }
305             if (p->nid == NID_undef) {
306                 GOSTerr(GOST_F_PKEY_GOST_EC_CTRL_STR_256,
307                         GOST_R_INVALID_PARAMSET);
308                 return 0;
309             }
310         }
311
312         return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
313                               param_nid, NULL);
314     }
315
316     return pkey_gost_ec_ctrl_str_common(ctx, type, value);
317 }
318
319 static int pkey_gost_ec_ctrl_str_512(EVP_PKEY_CTX *ctx,
320                                      const char *type, const char *value)
321 {
322     int param_nid = NID_undef;
323
324     if (strcmp(type, param_ctrl_string))
325       return pkey_gost_ec_ctrl_str_common(ctx, type, value);
326
327     if (!value)
328         return 0;
329
330     if (strlen(value) == 1) {
331         switch (toupper((unsigned char)value[0])) {
332         case 'A':
333             param_nid = NID_id_tc26_gost_3410_2012_512_paramSetA;
334             break;
335
336         case 'B':
337             param_nid = NID_id_tc26_gost_3410_2012_512_paramSetB;
338             break;
339
340         case 'C':
341             param_nid = NID_id_tc26_gost_3410_2012_512_paramSetC;
342             break;
343
344         default:
345             return 0;
346         }
347     } else {
348         R3410_ec_params *p = R3410_2012_512_paramset;
349         param_nid = OBJ_txt2nid(value);
350         if (param_nid == NID_undef)
351             return 0;
352
353         while (p->nid != NID_undef && p->nid != param_nid)
354             p++;
355
356         if (p->nid == NID_undef) {
357             GOSTerr(GOST_F_PKEY_GOST_EC_CTRL_STR_512,
358                     GOST_R_INVALID_PARAMSET);
359             return 0;
360         }
361     }
362
363     return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, param_nid, NULL);
364 }
365
366 /* --------------------- key generation  --------------------------------*/
367
368 static int pkey_gost_paramgen_init(EVP_PKEY_CTX *ctx)
369 {
370     return 1;
371 }
372
373 static int pkey_gost2001_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
374 {
375     struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
376     EC_KEY *ec = NULL;
377
378     if (!data || data->sign_param_nid == NID_undef) {
379         GOSTerr(GOST_F_PKEY_GOST2001_PARAMGEN, GOST_R_NO_PARAMETERS_SET);
380         return 0;
381     }
382
383     ec = EC_KEY_new();
384     if (!fill_GOST_EC_params(ec, data->sign_param_nid)
385         || !EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec)) {
386         EC_KEY_free(ec);
387         return 0;
388     }
389     return 1;
390 }
391
392 static int pkey_gost2012_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
393 {
394     struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
395     EC_KEY *ec;
396     int result = 0;
397
398     if (!data || data->sign_param_nid == NID_undef) {
399         GOSTerr(GOST_F_PKEY_GOST2012_PARAMGEN, GOST_R_NO_PARAMETERS_SET);
400         return 0;
401     }
402
403     ec = EC_KEY_new();
404     if (!fill_GOST_EC_params(ec, data->sign_param_nid)) {
405         EC_KEY_free(ec);
406         return 0;
407     }
408
409     switch (data->sign_param_nid) {
410     case NID_id_tc26_gost_3410_2012_512_paramSetA:
411     case NID_id_tc26_gost_3410_2012_512_paramSetB:
412     case NID_id_tc26_gost_3410_2012_512_paramSetC:
413     case NID_id_tc26_gost_3410_2012_512_paramSetTest:
414         result =
415             (EVP_PKEY_assign(pkey, NID_id_GostR3410_2012_512, ec)) ? 1 : 0;
416         break;
417
418     case NID_id_GostR3410_2001_CryptoPro_A_ParamSet:
419     case NID_id_GostR3410_2001_CryptoPro_B_ParamSet:
420     case NID_id_GostR3410_2001_CryptoPro_C_ParamSet:
421     case NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet:
422     case NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet:
423     case NID_id_GostR3410_2001_TestParamSet:
424     case NID_id_tc26_gost_3410_2012_256_paramSetA:
425     case NID_id_tc26_gost_3410_2012_256_paramSetB:
426     case NID_id_tc26_gost_3410_2012_256_paramSetC:
427     case NID_id_tc26_gost_3410_2012_256_paramSetD:
428         result =
429             (EVP_PKEY_assign(pkey, NID_id_GostR3410_2012_256, ec)) ? 1 : 0;
430         break;
431     default:
432         result = 0;
433         break;
434     }
435
436     if (result == 0)
437         EC_KEY_free(ec);
438
439     return result;
440 }
441
442 /* ----------- keygen callbacks --------------------------------------*/
443 /* Generates GOST_R3410 2001 key and assigns it using specified type */
444 static int pkey_gost2001cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
445 {
446     EC_KEY *ec;
447     if (!pkey_gost2001_paramgen(ctx, pkey))
448         return 0;
449     ec = EVP_PKEY_get0(pkey);
450     gost_ec_keygen(ec);
451     return 1;
452 }
453
454 /* Generates GOST_R3410 2012 key and assigns it using specified type */
455 static int pkey_gost2012cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
456 {
457     if (!pkey_gost2012_paramgen(ctx, pkey))
458         return 0;
459
460     gost_ec_keygen(EVP_PKEY_get0(pkey));
461     return 1;
462 }
463
464 /* ----------- sign callbacks --------------------------------------*/
465 /*
466  * Packs signature according to Cryptopro rules
467  * and frees up ECDSA_SIG structure
468  */
469 int pack_sign_cp(ECDSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
470 {
471     const BIGNUM *sig_r = NULL, *sig_s = NULL;
472     ECDSA_SIG_get0(s, &sig_r, &sig_s);
473     *siglen = 2 * order;
474     memset(sig, 0, *siglen);
475     store_bignum(sig_s, sig, order);
476     store_bignum(sig_r, sig + order, order);
477     ECDSA_SIG_free(s);
478     return 1;
479 }
480
481 static int pkey_gost_ec_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
482                                 size_t *siglen, const unsigned char *tbs,
483                                 size_t tbs_len)
484 {
485     ECDSA_SIG *unpacked_sig = NULL;
486     EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
487     int order = 0;
488
489     if (!siglen)
490         return 0;
491     if (!pkey)
492         return 0;
493
494     switch (EVP_PKEY_base_id(pkey)) {
495     case NID_id_GostR3410_2001:
496     case NID_id_GostR3410_2001DH:
497     case NID_id_GostR3410_2012_256:
498         order = 64;
499         break;
500     case NID_id_GostR3410_2012_512:
501         order = 128;
502         break;
503     default:
504         return 0;
505     }
506
507     if (!sig) {
508         *siglen = order;
509         return 1;
510     }
511     unpacked_sig = gost_ec_sign(tbs, tbs_len, EVP_PKEY_get0(pkey));
512     if (!unpacked_sig) {
513         return 0;
514     }
515     return pack_sign_cp(unpacked_sig, order / 2, sig, siglen);
516 }
517
518 /* ------------------- verify callbacks ---------------------------*/
519 /* Unpack signature according to cryptopro rules  */
520 ECDSA_SIG *unpack_cp_signature(const unsigned char *sigbuf, size_t siglen)
521 {
522     ECDSA_SIG *sig;
523     BIGNUM *r = NULL, *s = NULL;
524
525     sig = ECDSA_SIG_new();
526     if (sig == NULL) {
527         GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, ERR_R_MALLOC_FAILURE);
528         return NULL;
529     }
530     s = BN_bin2bn(sigbuf, siglen / 2, NULL);
531     r = BN_bin2bn(sigbuf + siglen / 2, siglen / 2, NULL);
532     ECDSA_SIG_set0(sig, r, s);
533     return sig;
534 }
535
536 static int pkey_gost_ec_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
537                                   size_t siglen, const unsigned char *tbs,
538                                   size_t tbs_len)
539 {
540     int ok = 0;
541     EVP_PKEY *pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
542     ECDSA_SIG *s = (sig) ? unpack_cp_signature(sig, siglen) : NULL;
543     if (!s)
544         return 0;
545 #ifdef DEBUG_SIGN
546     fprintf(stderr, "R=");
547     BN_print_fp(stderr, ECDSA_SIG_get0_r(s));
548     fprintf(stderr, "\nS=");
549     BN_print_fp(stderr, ECDSA_SIG_get0_s(s));
550     fprintf(stderr, "\n");
551 #endif
552     if (pub_key)
553         ok = gost_ec_verify(tbs, tbs_len, s, EVP_PKEY_get0(pub_key));
554     ECDSA_SIG_free(s);
555     return ok;
556 }
557
558 /* ------------- encrypt init -------------------------------------*/
559 /* Generates ephermeral key */
560 static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx)
561 {
562     return 1;
563 }
564
565 /* --------------- Derive init ------------------------------------*/
566 static int pkey_gost_derive_init(EVP_PKEY_CTX *ctx)
567 {
568     return 1;
569 }
570
571 /* -------- PKEY_METHOD for GOST MAC algorithm --------------------*/
572 static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx)
573 {
574     struct gost_mac_pmeth_data *data = OPENSSL_malloc(sizeof(*data));
575     EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
576
577     if (!data)
578         return 0;
579     memset(data, 0, sizeof(*data));
580     data->mac_size = 4;
581     data->mac_param_nid = NID_undef;
582
583     if (pkey) {
584         struct gost_mac_key *key = EVP_PKEY_get0(pkey);
585         if (key) {
586             data->mac_param_nid = key->mac_param_nid;
587             data->mac_size = key->mac_size;
588         }
589     }
590
591     EVP_PKEY_CTX_set_data(ctx, data);
592     return 1;
593 }
594
595 static int pkey_gost_omac_init(EVP_PKEY_CTX *ctx, size_t mac_size)
596 {
597     struct gost_mac_pmeth_data *data = OPENSSL_malloc(sizeof(*data));
598     EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
599
600     if (!data)
601         return 0;
602     memset(data, 0, sizeof(*data));
603     data->mac_size = mac_size;
604     data->mac_param_nid = NID_undef;
605
606     if (pkey) {
607         struct gost_mac_key *key = EVP_PKEY_get0(pkey);
608         if (key) {
609             data->mac_param_nid = key->mac_param_nid;
610             data->mac_size = key->mac_size;
611         }
612     }
613
614     EVP_PKEY_CTX_set_data(ctx, data);
615     return 1;
616 }
617
618 static int pkey_gost_magma_mac_init(EVP_PKEY_CTX *ctx)
619 {
620     return pkey_gost_omac_init(ctx, 8);
621 }
622
623 static int pkey_gost_grasshopper_mac_init(EVP_PKEY_CTX *ctx)
624 {
625     return pkey_gost_omac_init(ctx, 16);
626 }
627
628 static void pkey_gost_mac_cleanup(EVP_PKEY_CTX *ctx)
629 {
630     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
631     if (data)
632         OPENSSL_free(data);
633 }
634
635 static int pkey_gost_mac_copy(EVP_PKEY_CTX *dst, ossl3_const EVP_PKEY_CTX *src)
636 {
637     struct gost_mac_pmeth_data *dst_data, *src_data;
638     if (!pkey_gost_mac_init(dst)) {
639         return 0;
640     }
641     src_data = EVP_PKEY_CTX_get_data(src);
642     dst_data = EVP_PKEY_CTX_get_data(dst);
643     if (!src_data || !dst_data)
644         return 0;
645
646     *dst_data = *src_data;
647     return 1;
648 }
649
650 static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
651 {
652     struct gost_mac_pmeth_data *data =
653         (struct gost_mac_pmeth_data *)EVP_PKEY_CTX_get_data(ctx);
654
655     switch (type) {
656     case EVP_PKEY_CTRL_MD:
657         {
658             int nid = EVP_MD_type((const EVP_MD *)p2);
659             if (nid != NID_id_Gost28147_89_MAC && nid != NID_gost_mac_12) {
660                 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,
661                         GOST_R_INVALID_DIGEST_TYPE);
662                 return 0;
663             }
664             data->md = (EVP_MD *)p2;
665             return 1;
666         }
667
668     case EVP_PKEY_CTRL_GET_MD:
669         *(const EVP_MD **)p2 = data->md;
670         return 1;
671
672     case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
673     case EVP_PKEY_CTRL_PKCS7_DECRYPT:
674     case EVP_PKEY_CTRL_PKCS7_SIGN:
675         return 1;
676     case EVP_PKEY_CTRL_SET_MAC_KEY:
677         if (p1 != 32) {
678             GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH);
679             return 0;
680         }
681
682         memcpy(data->key, p2, 32);
683         data->key_set = 1;
684         return 1;
685     case EVP_PKEY_CTRL_GOST_PARAMSET:
686         {
687             struct gost_cipher_info *param = p2;
688             data->mac_param_nid = param->nid;
689             return 1;
690         }
691     case EVP_PKEY_CTRL_DIGESTINIT:
692         {
693             EVP_MD_CTX *mctx = p2;
694             if (!data->key_set) {
695                 struct gost_mac_key *key;
696                 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
697                 if (!pkey) {
698                     GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,
699                             GOST_R_MAC_KEY_NOT_SET);
700                     return 0;
701                 }
702                 key = EVP_PKEY_get0(pkey);
703                 if (!key) {
704                     GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,
705                             GOST_R_MAC_KEY_NOT_SET);
706                     return 0;
707                 }
708                 return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
709                     (mctx, EVP_MD_CTRL_SET_KEY, 0, key);
710             } else {
711                 return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
712                     (mctx, EVP_MD_CTRL_SET_KEY, 32, &(data->key));
713             }
714         }
715     case EVP_PKEY_CTRL_MAC_LEN:
716         {
717             if (p1 < 1 || p1 > 8) {
718
719                 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_MAC_SIZE);
720                 return 0;
721             }
722             data->mac_size = p1;
723             return 1;
724         }
725     }
726     return -2;
727 }
728
729 static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx,
730                                   const char *type, const char *value)
731 {
732     if (strcmp(type, key_ctrl_string) == 0) {
733         if (strlen(value) != 32) {
734             GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR,
735                     GOST_R_INVALID_MAC_KEY_LENGTH);
736             return 0;
737         }
738         return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
739                                   32, (char *)value);
740     }
741     if (strcmp(type, hexkey_ctrl_string) == 0) {
742         long keylen;
743         int ret;
744         unsigned char *keybuf = string_to_hex(value, &keylen);
745         if (!keybuf || keylen != 32) {
746             GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR,
747                     GOST_R_INVALID_MAC_KEY_LENGTH);
748             OPENSSL_free(keybuf);
749             return 0;
750         }
751         ret = pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 32, keybuf);
752         OPENSSL_free(keybuf);
753         return ret;
754
755     }
756     if (!strcmp(type, maclen_ctrl_string)) {
757         char *endptr;
758         long size = strtol(value, &endptr, 10);
759         if (*endptr != '\0') {
760             GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, GOST_R_INVALID_MAC_SIZE);
761             return 0;
762         }
763         return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_MAC_LEN, size, NULL);
764     }
765     if (strcmp(type, param_ctrl_string) == 0) {
766         ASN1_OBJECT *obj = OBJ_txt2obj(value, 0);
767         const struct gost_cipher_info *param = NULL;
768         if (obj == NULL) {
769             GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, GOST_R_INVALID_MAC_PARAMS);
770             return 0;
771         }
772
773         param = get_encryption_params(obj);
774         ASN1_OBJECT_free(obj);
775         if (param == NULL) {
776             GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, GOST_R_INVALID_MAC_PARAMS);
777             return 0;
778         }
779
780
781         return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, 0,
782                                   (void *)param);
783     }
784     return -2;
785 }
786
787 static int pkey_gost_omac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2, size_t max_size)
788 {
789     struct gost_mac_pmeth_data *data =
790         (struct gost_mac_pmeth_data *)EVP_PKEY_CTX_get_data(ctx);
791
792     switch (type) {
793     case EVP_PKEY_CTRL_MD:
794         {
795             int nid = EVP_MD_type((const EVP_MD *)p2);
796             if (nid != NID_magma_mac && nid != NID_grasshopper_mac
797                 && nid != NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac /* FIXME beldmit */
798                 && nid != NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac) {
799                 GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL,
800                         GOST_R_INVALID_DIGEST_TYPE);
801                 return 0;
802             }
803             data->md = (EVP_MD *)p2;
804             return 1;
805         }
806
807     case EVP_PKEY_CTRL_GET_MD:
808         *(const EVP_MD **)p2 = data->md;
809         return 1;
810
811     case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
812     case EVP_PKEY_CTRL_PKCS7_DECRYPT:
813     case EVP_PKEY_CTRL_PKCS7_SIGN:
814         return 1;
815     case EVP_PKEY_CTRL_SET_MAC_KEY:
816         if (p1 != 32) {
817             GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH);
818             return 0;
819         }
820
821         memcpy(data->key, p2, 32);
822         data->key_set = 1;
823         return 1;
824     case EVP_PKEY_CTRL_DIGESTINIT:
825         {
826             EVP_MD_CTX *mctx = p2;
827             if (!data->key_set) {
828                 struct gost_mac_key *key;
829                 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
830                 if (!pkey) {
831                     GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL,
832                             GOST_R_MAC_KEY_NOT_SET);
833                     return 0;
834                 }
835                 key = EVP_PKEY_get0(pkey);
836                 if (!key) {
837                     GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL,
838                             GOST_R_MAC_KEY_NOT_SET);
839                     return 0;
840                 }
841                 return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
842                     (mctx, EVP_MD_CTRL_SET_KEY, 0, key);
843             } else {
844                 return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
845                     (mctx, EVP_MD_CTRL_SET_KEY, 32, &(data->key));
846             }
847         }
848     case EVP_PKEY_CTRL_MAC_LEN:
849         {
850             if (p1 < 1 || p1 > max_size) {
851
852                 GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL, GOST_R_INVALID_MAC_SIZE);
853                 return 0;
854             }
855             data->mac_size = p1;
856             return 1;
857         }
858     }
859     return -2;
860 }
861
862 static int pkey_gost_magma_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
863 {
864     return pkey_gost_omac_ctrl(ctx, type, p1, p2, 8);
865 }
866
867 static int pkey_gost_grasshopper_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
868 {
869     return pkey_gost_omac_ctrl(ctx, type, p1, p2, 16);
870 }
871
872 static int pkey_gost_omac_ctrl_str(EVP_PKEY_CTX *ctx,
873                                   const char *type, const char *value, size_t max_size)
874 {
875     if (strcmp(type, key_ctrl_string) == 0) {
876         if (strlen(value) != 32) {
877             GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL_STR,
878                     GOST_R_INVALID_MAC_KEY_LENGTH);
879             return 0;
880         }
881         return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
882                                   32, (char *)value);
883     }
884     if (strcmp(type, hexkey_ctrl_string) == 0) {
885         long keylen;
886         int ret;
887         unsigned char *keybuf = string_to_hex(value, &keylen);
888         if (!keybuf || keylen != 32) {
889             GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL_STR,
890                     GOST_R_INVALID_MAC_KEY_LENGTH);
891             OPENSSL_free(keybuf);
892             return 0;
893         }
894         ret = pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 32, keybuf);
895         OPENSSL_free(keybuf);
896         return ret;
897
898     }
899     if (!strcmp(type, maclen_ctrl_string)) {
900         char *endptr;
901         long size = strtol(value, &endptr, 10);
902         if (*endptr != '\0') {
903             GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL_STR, GOST_R_INVALID_MAC_SIZE);
904             return 0;
905         }
906         return pkey_gost_omac_ctrl(ctx, EVP_PKEY_CTRL_MAC_LEN, size, NULL, max_size);
907     }
908     return -2;
909 }
910
911 static int pkey_gost_magma_mac_ctrl_str(EVP_PKEY_CTX *ctx,
912                                   const char *type, const char *value)
913 {
914     return pkey_gost_omac_ctrl_str(ctx, type, value, 8);
915 }
916
917 static int pkey_gost_grasshopper_mac_ctrl_str(EVP_PKEY_CTX *ctx,
918                                   const char *type, const char *value)
919 {
920     return pkey_gost_omac_ctrl_str(ctx, type, value, 8);
921 }
922
923 static int pkey_gost_mac_keygen_base(EVP_PKEY_CTX *ctx,
924                                      EVP_PKEY *pkey, int mac_nid)
925 {
926     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
927     struct gost_mac_key *keydata;
928     if (!data || !data->key_set) {
929         GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN_BASE, GOST_R_MAC_KEY_NOT_SET);
930         return 0;
931     }
932     keydata = OPENSSL_malloc(sizeof(struct gost_mac_key));
933     if (keydata == NULL)
934         return 0;
935     memcpy(keydata->key, data->key, 32);
936     keydata->mac_param_nid = data->mac_param_nid;
937     keydata->mac_size = data->mac_size;
938     EVP_PKEY_assign(pkey, mac_nid, keydata);
939     return 1;
940 }
941
942 static int pkey_gost_mac_keygen_12(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
943 {
944     return pkey_gost_mac_keygen_base(ctx, pkey, NID_gost_mac_12);
945 }
946
947 static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
948 {
949     return pkey_gost_mac_keygen_base(ctx, pkey, NID_id_Gost28147_89_MAC);
950 }
951
952 static int pkey_gost_magma_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
953 {
954     return pkey_gost_mac_keygen_base(ctx, pkey, NID_magma_mac);
955 }
956
957 static int pkey_gost_grasshopper_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
958 {
959     return pkey_gost_mac_keygen_base(ctx, pkey, NID_grasshopper_mac);
960 }
961
962 static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
963 {
964     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
965
966     if (data == NULL) {
967         pkey_gost_mac_init(ctx);
968     }
969
970     data = EVP_PKEY_CTX_get_data(ctx);
971     if (!data) {
972         GOSTerr(GOST_F_PKEY_GOST_MAC_SIGNCTX_INIT, GOST_R_MAC_KEY_NOT_SET);
973         return 0;
974     }
975
976     return 1;
977 }
978
979 static int pkey_gost_magma_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
980 {
981     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
982
983     if (data == NULL) {
984         pkey_gost_omac_init(ctx, 4);
985     }
986
987     data = EVP_PKEY_CTX_get_data(ctx);
988     if (!data) {
989         GOSTerr(GOST_F_PKEY_GOST_MAGMA_MAC_SIGNCTX_INIT, GOST_R_MAC_KEY_NOT_SET);
990         return 0;
991     }
992
993     return 1;
994 }
995
996 static int pkey_gost_grasshopper_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
997 {
998     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
999
1000     if (data == NULL) {
1001         pkey_gost_omac_init(ctx, 8);
1002     }
1003
1004     data = EVP_PKEY_CTX_get_data(ctx);
1005     if (!data) {
1006         GOSTerr(GOST_F_PKEY_GOST_GRASSHOPPER_MAC_SIGNCTX_INIT, GOST_R_MAC_KEY_NOT_SET);
1007         return 0;
1008     }
1009
1010     return 1;
1011 }
1012
1013 static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
1014                                  size_t *siglen, EVP_MD_CTX *mctx)
1015 {
1016     unsigned int tmpsiglen;
1017     int ret;
1018     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
1019
1020     if (!siglen)
1021         return 0;
1022     tmpsiglen = *siglen;        /* for platforms where sizeof(int) !=
1023                                  * sizeof(size_t) */
1024
1025     if (!sig) {
1026         *siglen = data->mac_size;
1027         return 1;
1028     }
1029
1030     EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
1031         (mctx, EVP_MD_CTRL_XOF_LEN, data->mac_size, NULL);
1032     ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen);
1033     *siglen = data->mac_size;
1034     return ret;
1035 }
1036
1037 /* ----------- misc callbacks -------------------------------------*/
1038
1039 /* Callback for both EVP_PKEY_check() and EVP_PKEY_public_check. */
1040 static int pkey_gost_check(EVP_PKEY *pkey)
1041 {
1042     return EC_KEY_check_key(EVP_PKEY_get0(pkey));
1043 }
1044
1045 /* ----------------------------------------------------------------*/
1046 int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth, int flags)
1047 {
1048     *pmeth = EVP_PKEY_meth_new(id, flags);
1049     if (!*pmeth)
1050         return 0;
1051
1052     switch (id) {
1053     case NID_id_GostR3410_2001:
1054     case NID_id_GostR3410_2001DH:
1055         EVP_PKEY_meth_set_ctrl(*pmeth,
1056                                pkey_gost_ctrl, pkey_gost_ec_ctrl_str_256);
1057         EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost_ec_cp_sign);
1058         EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost_ec_cp_verify);
1059
1060         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost2001cp_keygen);
1061
1062         EVP_PKEY_meth_set_encrypt(*pmeth,
1063                                   pkey_gost_encrypt_init,
1064                                   pkey_gost_encrypt);
1065         EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_gost_decrypt);
1066         EVP_PKEY_meth_set_derive(*pmeth,
1067                                  pkey_gost_derive_init, pkey_gost_ec_derive);
1068         EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,
1069                                    pkey_gost2001_paramgen);
1070     EVP_PKEY_meth_set_check(*pmeth, pkey_gost_check);
1071     EVP_PKEY_meth_set_public_check(*pmeth, pkey_gost_check);
1072         break;
1073     case NID_id_GostR3410_2012_256:
1074         EVP_PKEY_meth_set_ctrl(*pmeth,
1075                                pkey_gost_ctrl, pkey_gost_ec_ctrl_str_256);
1076         EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost_ec_cp_sign);
1077         EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost_ec_cp_verify);
1078
1079         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost2012cp_keygen);
1080
1081         EVP_PKEY_meth_set_encrypt(*pmeth,
1082                                   pkey_gost_encrypt_init,
1083                                   pkey_gost_encrypt);
1084         EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_gost_decrypt);
1085         EVP_PKEY_meth_set_derive(*pmeth,
1086                                  pkey_gost_derive_init, pkey_gost_ec_derive);
1087         EVP_PKEY_meth_set_paramgen(*pmeth,
1088                                    pkey_gost_paramgen_init,
1089                                    pkey_gost2012_paramgen);
1090     EVP_PKEY_meth_set_check(*pmeth, pkey_gost_check);
1091     EVP_PKEY_meth_set_public_check(*pmeth, pkey_gost_check);
1092         break;
1093     case NID_id_GostR3410_2012_512:
1094         EVP_PKEY_meth_set_ctrl(*pmeth,
1095                                pkey_gost_ctrl, pkey_gost_ec_ctrl_str_512);
1096         EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost_ec_cp_sign);
1097         EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost_ec_cp_verify);
1098
1099         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost2012cp_keygen);
1100
1101         EVP_PKEY_meth_set_encrypt(*pmeth,
1102                                   pkey_gost_encrypt_init,
1103                                   pkey_gost_encrypt);
1104         EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_gost_decrypt);
1105         EVP_PKEY_meth_set_derive(*pmeth,
1106                                  pkey_gost_derive_init, pkey_gost_ec_derive);
1107         EVP_PKEY_meth_set_paramgen(*pmeth,
1108                                    pkey_gost_paramgen_init,
1109                                    pkey_gost2012_paramgen);
1110     EVP_PKEY_meth_set_check(*pmeth, pkey_gost_check);
1111     EVP_PKEY_meth_set_public_check(*pmeth, pkey_gost_check);
1112         break;
1113     case NID_id_Gost28147_89_MAC:
1114         EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_mac_ctrl,
1115                                pkey_gost_mac_ctrl_str);
1116         EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_mac_signctx_init,
1117                                   pkey_gost_mac_signctx);
1118         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_mac_keygen);
1119         EVP_PKEY_meth_set_init(*pmeth, pkey_gost_mac_init);
1120         EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
1121         EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
1122         return 1;
1123     case NID_gost_mac_12:
1124         EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_mac_ctrl,
1125                                pkey_gost_mac_ctrl_str);
1126         EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_mac_signctx_init,
1127                                   pkey_gost_mac_signctx);
1128         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_mac_keygen_12);
1129         EVP_PKEY_meth_set_init(*pmeth, pkey_gost_mac_init);
1130         EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
1131         EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
1132         return 1;
1133     case NID_magma_mac:
1134         EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_magma_mac_ctrl,
1135                                pkey_gost_magma_mac_ctrl_str);
1136         EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_magma_mac_signctx_init,
1137                                   pkey_gost_mac_signctx);
1138         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_magma_mac_keygen);
1139         EVP_PKEY_meth_set_init(*pmeth, pkey_gost_magma_mac_init);
1140         EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
1141         EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
1142         return 1;
1143     case NID_grasshopper_mac:
1144     case NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac: /* FIXME beldmit */
1145         EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_grasshopper_mac_ctrl,
1146                                pkey_gost_grasshopper_mac_ctrl_str);
1147         EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_grasshopper_mac_signctx_init,
1148                                   pkey_gost_mac_signctx);
1149         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_grasshopper_mac_keygen);
1150         EVP_PKEY_meth_set_init(*pmeth, pkey_gost_grasshopper_mac_init);
1151         EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
1152         EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
1153         return 1;
1154     default:                   /* Unsupported method */
1155         return 0;
1156     }
1157     EVP_PKEY_meth_set_init(*pmeth, pkey_gost_init);
1158     EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_cleanup);
1159
1160     EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_copy);
1161     /*
1162      * FIXME derive etc...
1163      */
1164
1165     return 1;
1166 }