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