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