]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_pmeth.c
Let's wrap old and new key enncryption together
[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, s->r);
452     fprintf(stderr, "\nS=");
453     BN_print_fp(stderr, 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, 4);
525 }
526
527 static int pkey_gost_grasshopper_mac_init(EVP_PKEY_CTX *ctx)
528 {
529         return pkey_gost_omac_init(ctx, 8);
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                 GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL,
702                         GOST_R_INVALID_DIGEST_TYPE);
703                 return 0;
704             }
705             data->md = (EVP_MD *)p2;
706             return 1;
707         }
708
709     case EVP_PKEY_CTRL_GET_MD:
710         *(const EVP_MD **)p2 = data->md;
711         return 1;
712
713     case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
714     case EVP_PKEY_CTRL_PKCS7_DECRYPT:
715     case EVP_PKEY_CTRL_PKCS7_SIGN:
716         return 1;
717     case EVP_PKEY_CTRL_SET_MAC_KEY:
718         if (p1 != 32) {
719             GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH);
720             return 0;
721         }
722
723         memcpy(data->key, p2, 32);
724         data->key_set = 1;
725         return 1;
726     case EVP_PKEY_CTRL_DIGESTINIT:
727         {
728             EVP_MD_CTX *mctx = p2;
729             struct gost_mac_key *key;
730             if (!data->key_set) {
731                 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
732                 if (!pkey) {
733                     GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL,
734                             GOST_R_MAC_KEY_NOT_SET);
735                     return 0;
736                 }
737                 key = EVP_PKEY_get0(pkey);
738                 if (!key) {
739                     GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL,
740                             GOST_R_MAC_KEY_NOT_SET);
741                     return 0;
742                 }
743                 return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
744                     (mctx, EVP_MD_CTRL_SET_KEY, 0, key);
745             } else {
746                 return EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
747                     (mctx, EVP_MD_CTRL_SET_KEY, 32, &(data->key));
748             }
749         }
750     case EVP_PKEY_CTRL_MAC_LEN:
751         {
752             if (p1 < 1 || p1 > max_size) {
753
754                 GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL, GOST_R_INVALID_MAC_SIZE);
755                 return 0;
756             }
757             data->mac_size = p1;
758             return 1;
759         }
760     }
761     return -2;
762 }
763
764 static int pkey_gost_magma_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
765 {
766         return pkey_gost_omac_ctrl(ctx, type, p1, p2, 8);
767 }
768
769 static int pkey_gost_grasshopper_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
770 {
771         return pkey_gost_omac_ctrl(ctx, type, p1, p2, 16);
772 }
773
774 static int pkey_gost_omac_ctrl_str(EVP_PKEY_CTX *ctx,
775                                   const char *type, const char *value, size_t max_size)
776 {
777     if (strcmp(type, key_ctrl_string) == 0) {
778         if (strlen(value) != 32) {
779             GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL_STR,
780                     GOST_R_INVALID_MAC_KEY_LENGTH);
781             return 0;
782         }
783         return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
784                                   32, (char *)value);
785     }
786     if (strcmp(type, hexkey_ctrl_string) == 0) {
787         long keylen;
788         int ret;
789         unsigned char *keybuf = string_to_hex(value, &keylen);
790         if (!keybuf || keylen != 32) {
791             GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL_STR,
792                     GOST_R_INVALID_MAC_KEY_LENGTH);
793             OPENSSL_free(keybuf);
794             return 0;
795         }
796         ret = pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 32, keybuf);
797         OPENSSL_free(keybuf);
798         return ret;
799
800     }
801     if (!strcmp(type, maclen_ctrl_string)) {
802         char *endptr;
803         long size = strtol(value, &endptr, 10);
804         if (*endptr != '\0') {
805             GOSTerr(GOST_F_PKEY_GOST_OMAC_CTRL_STR, GOST_R_INVALID_MAC_SIZE);
806             return 0;
807         }
808         return pkey_gost_omac_ctrl(ctx, EVP_PKEY_CTRL_MAC_LEN, size, NULL, max_size);
809     }
810     return -2;
811 }
812
813 static int pkey_gost_magma_mac_ctrl_str(EVP_PKEY_CTX *ctx,
814                                   const char *type, const char *value)
815 {
816         return pkey_gost_omac_ctrl_str(ctx, type, value, 8);
817 }
818
819 static int pkey_gost_grasshopper_mac_ctrl_str(EVP_PKEY_CTX *ctx,
820                                   const char *type, const char *value)
821 {
822         return pkey_gost_omac_ctrl_str(ctx, type, value, 8);
823 }
824
825 static int pkey_gost_mac_keygen_base(EVP_PKEY_CTX *ctx,
826                                      EVP_PKEY *pkey, int mac_nid)
827 {
828     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
829     struct gost_mac_key *keydata;
830     if (!data || !data->key_set) {
831         GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN_BASE, GOST_R_MAC_KEY_NOT_SET);
832         return 0;
833     }
834     keydata = OPENSSL_malloc(sizeof(struct gost_mac_key));
835     if (keydata == NULL)
836         return 0;
837     memcpy(keydata->key, data->key, 32);
838     keydata->mac_param_nid = data->mac_param_nid;
839     keydata->mac_size = data->mac_size;
840     EVP_PKEY_assign(pkey, mac_nid, keydata);
841     return 1;
842 }
843
844 static int pkey_gost_mac_keygen_12(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
845 {
846     return pkey_gost_mac_keygen_base(ctx, pkey, NID_gost_mac_12);
847 }
848
849 static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
850 {
851     return pkey_gost_mac_keygen_base(ctx, pkey, NID_id_Gost28147_89_MAC);
852 }
853
854 static int pkey_gost_magma_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
855 {
856     return pkey_gost_mac_keygen_base(ctx, pkey, NID_magma_mac);
857 }
858
859 static int pkey_gost_grasshopper_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
860 {
861     return pkey_gost_mac_keygen_base(ctx, pkey, NID_grasshopper_mac);
862 }
863
864 static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
865 {
866     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
867
868     if (data == NULL) {
869         pkey_gost_mac_init(ctx);
870     }
871
872     data = EVP_PKEY_CTX_get_data(ctx);
873     if (!data) {
874         GOSTerr(GOST_F_PKEY_GOST_MAC_SIGNCTX_INIT, GOST_R_MAC_KEY_NOT_SET);
875         return 0;
876     }
877
878     return 1;
879 }
880
881 static int pkey_gost_magma_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
882 {
883     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
884
885     if (data == NULL) {
886         pkey_gost_omac_init(ctx, 4);
887     }
888
889     data = EVP_PKEY_CTX_get_data(ctx);
890     if (!data) {
891         GOSTerr(GOST_F_PKEY_GOST_MAGMA_MAC_SIGNCTX_INIT, GOST_R_MAC_KEY_NOT_SET);
892         return 0;
893     }
894
895     return 1;
896 }
897
898 static int pkey_gost_grasshopper_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
899 {
900     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
901
902     if (data == NULL) {
903         pkey_gost_omac_init(ctx, 8);
904     }
905
906     data = EVP_PKEY_CTX_get_data(ctx);
907     if (!data) {
908         GOSTerr(GOST_F_PKEY_GOST_GRASSHOPPER_MAC_SIGNCTX_INIT, GOST_R_MAC_KEY_NOT_SET);
909         return 0;
910     }
911
912     return 1;
913 }
914
915 static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
916                                  size_t *siglen, EVP_MD_CTX *mctx)
917 {
918     unsigned int tmpsiglen;
919     int ret;
920     struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
921
922     if (!siglen)
923         return 0;
924     tmpsiglen = *siglen;        /* for platforms where sizeof(int) !=
925                                  * sizeof(size_t) */
926
927     if (!sig) {
928         *siglen = data->mac_size;
929         return 1;
930     }
931
932     EVP_MD_meth_get_ctrl(EVP_MD_CTX_md(mctx))
933         (mctx, EVP_MD_CTRL_MAC_LEN, data->mac_size, NULL);
934     ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen);
935     *siglen = data->mac_size;
936     return ret;
937 }
938
939 /* ----------------------------------------------------------------*/
940 int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth, int flags)
941 {
942     *pmeth = EVP_PKEY_meth_new(id, flags);
943     if (!*pmeth)
944         return 0;
945
946     switch (id) {
947     case NID_id_GostR3410_2001:
948         EVP_PKEY_meth_set_ctrl(*pmeth,
949                                pkey_gost_ctrl, pkey_gost_ec_ctrl_str_256);
950         EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost_ec_cp_sign);
951         EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost_ec_cp_verify);
952
953         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost2001cp_keygen);
954
955         EVP_PKEY_meth_set_encrypt(*pmeth,
956                                   pkey_gost_encrypt_init,
957                                   pkey_gost_encrypt);
958         EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_gost_decrypt);
959         EVP_PKEY_meth_set_derive(*pmeth,
960                                  pkey_gost_derive_init, pkey_gost_ec_derive);
961         EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,
962                                    pkey_gost2001_paramgen);
963         break;
964     case NID_id_GostR3410_2012_256:
965         EVP_PKEY_meth_set_ctrl(*pmeth,
966                                pkey_gost_ctrl, pkey_gost_ec_ctrl_str_256);
967         EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost_ec_cp_sign);
968         EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost_ec_cp_verify);
969
970         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost2012cp_keygen);
971
972         EVP_PKEY_meth_set_encrypt(*pmeth,
973                                   pkey_gost_encrypt_init,
974                                   pkey_gost_encrypt);
975         EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_gost_decrypt);
976         EVP_PKEY_meth_set_derive(*pmeth,
977                                  pkey_gost_derive_init, pkey_gost_ec_derive);
978         EVP_PKEY_meth_set_paramgen(*pmeth,
979                                    pkey_gost_paramgen_init,
980                                    pkey_gost2012_paramgen);
981         break;
982     case NID_id_GostR3410_2012_512:
983         EVP_PKEY_meth_set_ctrl(*pmeth,
984                                pkey_gost_ctrl, pkey_gost_ec_ctrl_str_512);
985         EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost_ec_cp_sign);
986         EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost_ec_cp_verify);
987
988         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost2012cp_keygen);
989
990         EVP_PKEY_meth_set_encrypt(*pmeth,
991                                   pkey_gost_encrypt_init,
992                                   pkey_gost_encrypt);
993         EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_gost_decrypt);
994         EVP_PKEY_meth_set_derive(*pmeth,
995                                  pkey_gost_derive_init, pkey_gost_ec_derive);
996         EVP_PKEY_meth_set_paramgen(*pmeth,
997                                    pkey_gost_paramgen_init,
998                                    pkey_gost2012_paramgen);
999         break;
1000     case NID_id_Gost28147_89_MAC:
1001         EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_mac_ctrl,
1002                                pkey_gost_mac_ctrl_str);
1003         EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_mac_signctx_init,
1004                                   pkey_gost_mac_signctx);
1005         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_mac_keygen);
1006         EVP_PKEY_meth_set_init(*pmeth, pkey_gost_mac_init);
1007         EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
1008         EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
1009         return 1;
1010     case NID_gost_mac_12:
1011         EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_mac_ctrl,
1012                                pkey_gost_mac_ctrl_str);
1013         EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_mac_signctx_init,
1014                                   pkey_gost_mac_signctx);
1015         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_mac_keygen_12);
1016         EVP_PKEY_meth_set_init(*pmeth, pkey_gost_mac_init);
1017         EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
1018         EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
1019         return 1;
1020     case NID_magma_mac:
1021         EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_magma_mac_ctrl,
1022                                pkey_gost_magma_mac_ctrl_str);
1023         EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_magma_mac_signctx_init,
1024                                   pkey_gost_mac_signctx);
1025         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_magma_mac_keygen);
1026         EVP_PKEY_meth_set_init(*pmeth, pkey_gost_magma_mac_init);
1027         EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
1028         EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
1029         return 1;
1030     case NID_grasshopper_mac:
1031         EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_grasshopper_mac_ctrl,
1032                                pkey_gost_grasshopper_mac_ctrl_str);
1033         EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_grasshopper_mac_signctx_init,
1034                                   pkey_gost_mac_signctx);
1035         EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_grasshopper_mac_keygen);
1036         EVP_PKEY_meth_set_init(*pmeth, pkey_gost_grasshopper_mac_init);
1037         EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup);
1038         EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy);
1039         return 1;
1040     default:                   /* Unsupported method */
1041         return 0;
1042     }
1043     EVP_PKEY_meth_set_init(*pmeth, pkey_gost_init);
1044     EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_cleanup);
1045
1046     EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_copy);
1047     /*
1048      * FIXME derive etc...
1049      */
1050
1051     return 1;
1052 }