]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_ameth.c
Merge pull request #182 from outspace/master
[openssl-gost/engine.git] / gost_ameth.c
1 /**********************************************************************
2  *                          gost_ameth.c                              *
3  *             Copyright (c) 2005-2006 Cryptocom LTD                  *
4  *         This file is distributed under the same license as OpenSSL *
5  *                                                                    *
6  *       Implementation of RFC 4490/4491 ASN1 method                  *
7  *       for OpenSSL                                                  *
8  *          Requires OpenSSL 0.9.9 for compilation                    *
9  **********************************************************************/
10 #include <string.h>
11 #include <openssl/crypto.h>
12 #include <openssl/err.h>
13 #include <openssl/engine.h>
14 #include <openssl/evp.h>
15 #include <openssl/asn1.h>
16 #ifndef OPENSSL_NO_CMS
17 # include <openssl/cms.h>
18 #endif
19 #include "gost_lcl.h"
20 #include "e_gost_err.h"
21
22 #define PK_WRAP_PARAM "LEGACY_PK_WRAP"
23
24 /*
25  * Pack bignum into byte buffer of given size, filling all leading bytes by
26  * zeros
27  */
28 int store_bignum(const BIGNUM *bn, unsigned char *buf, int len)
29 {
30     int bytes = BN_num_bytes(bn);
31
32     if (bytes > len)
33         return 0;
34     memset(buf, 0, len);
35     BN_bn2bin(bn, buf + len - bytes);
36     return 1;
37 }
38
39 static int pkey_bits_gost(const EVP_PKEY *pk)
40 {
41     if (!pk)
42         return -1;
43
44     switch (EVP_PKEY_base_id(pk)) {
45     case NID_id_GostR3410_2001:
46     case NID_id_GostR3410_2012_256:
47         return 256;
48     case NID_id_GostR3410_2012_512:
49         return 512;
50     }
51
52     return -1;
53 }
54
55 static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
56 {
57     ASN1_STRING *params = ASN1_STRING_new();
58     GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
59     int pkey_param_nid = NID_undef;
60     void *key_ptr = EVP_PKEY_get0((EVP_PKEY *)key);
61     int result = 0;
62
63     if (!params || !gkp) {
64         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
65         goto err;
66     }
67     switch (EVP_PKEY_base_id(key)) {
68     case NID_id_GostR3410_2012_256:
69         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
70         switch (pkey_param_nid) {
71             case NID_id_GostR3410_2001_TestParamSet:
72             case NID_id_GostR3410_2001_CryptoPro_A_ParamSet:
73             case NID_id_GostR3410_2001_CryptoPro_B_ParamSet:
74             case NID_id_GostR3410_2001_CryptoPro_C_ParamSet:
75             case NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet:
76             case NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet:
77                 gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_2012_256);
78         }
79         break;
80     case NID_id_GostR3410_2012_512:
81         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
82         break;
83     case NID_id_GostR3410_2001:
84         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
85         gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
86         break;
87     }
88
89     if (pkey_param_nid == NID_undef) {
90         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, GOST_R_INVALID_PARAMSET);
91         goto err;
92     }
93
94     gkp->key_params = OBJ_nid2obj(pkey_param_nid);
95     /*
96      * gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);
97      */
98     params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
99     if (params->length <= 0) {
100         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
101         goto err;
102     }
103     params->type = V_ASN1_SEQUENCE;
104     result = 1;
105  err:
106     if (gkp)
107         GOST_KEY_PARAMS_free(gkp);
108     if (result == 0) {          /* if error */
109         if (params)
110             ASN1_STRING_free(params);
111         return NULL;
112     }
113     return params;
114 }
115
116 static int gost_decode_nid_params(EVP_PKEY *pkey, int pkey_nid, int param_nid)
117 {
118     void *key_ptr = EVP_PKEY_get0(pkey);
119
120     switch (pkey_nid) {
121     case NID_id_GostR3410_2012_256:
122     case NID_id_GostR3410_2012_512:
123     case NID_id_GostR3410_2001:
124         if (!key_ptr) {
125             key_ptr = EC_KEY_new();
126             if (!EVP_PKEY_assign(pkey, pkey_nid, key_ptr)) {
127                 EC_KEY_free(key_ptr);
128                 break;
129             }
130         }
131         return fill_GOST_EC_params(key_ptr, param_nid);
132     }
133
134     return 0;
135 }
136
137 /*
138  * Parses GOST algorithm parameters from X509_ALGOR and modifies pkey setting
139  * NID and parameters
140  */
141 static int decode_gost_algor_params(EVP_PKEY *pkey,
142                                     const X509_ALGOR *palg)
143 {
144     const ASN1_OBJECT *palg_obj = NULL;
145     int ptype = V_ASN1_UNDEF;
146     int pkey_nid = NID_undef, param_nid = NID_undef;
147     ASN1_STRING *pval = NULL;
148     const unsigned char *p;
149     GOST_KEY_PARAMS *gkp = NULL;
150
151     if (!pkey || !palg)
152         return 0;
153     X509_ALGOR_get0(&palg_obj, &ptype, (const void **)&pval, palg);
154     if (ptype != V_ASN1_SEQUENCE) {
155         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
156                 GOST_R_BAD_KEY_PARAMETERS_FORMAT);
157         return 0;
158     }
159     p = pval->data;
160     pkey_nid = OBJ_obj2nid(palg_obj);
161
162     gkp = d2i_GOST_KEY_PARAMS(NULL, &p, pval->length);
163     if (!gkp) {
164         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
165                 GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
166         return 0;
167     }
168     param_nid = OBJ_obj2nid(gkp->key_params);
169     GOST_KEY_PARAMS_free(gkp);
170     if (!EVP_PKEY_set_type(pkey, pkey_nid)) {
171         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR);
172         return 0;
173     }
174     return gost_decode_nid_params(pkey, pkey_nid, param_nid);
175 }
176
177 static int gost_set_priv_key(EVP_PKEY *pkey, BIGNUM *priv)
178 {
179     switch (EVP_PKEY_base_id(pkey)) {
180     case NID_id_GostR3410_2012_512:
181     case NID_id_GostR3410_2012_256:
182     case NID_id_GostR3410_2001:
183         {
184             EC_KEY *ec = EVP_PKEY_get0(pkey);
185             if (!ec) {
186                 ec = EC_KEY_new();
187                 EVP_PKEY_assign(pkey, EVP_PKEY_base_id(pkey), ec);
188             }
189             if (!EC_KEY_set_private_key(ec, priv))
190                 return 0;
191             if (!EVP_PKEY_missing_parameters(pkey))
192                 return gost_ec_compute_public(ec);
193             break;
194         }
195     default:
196         return 0;
197     }
198     return 1;
199 }
200
201 BIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey)
202 {
203     switch (EVP_PKEY_base_id(pkey)) {
204     case NID_id_GostR3410_2012_512:
205     case NID_id_GostR3410_2012_256:
206     case NID_id_GostR3410_2001:
207         {
208             EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
209             if (ec)
210                 return (BIGNUM *)EC_KEY_get0_private_key(ec);
211             break;
212         }
213     }
214     return NULL;
215 }
216
217 /*
218  * Control function
219  */
220 static int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
221 {
222     int nid = EVP_PKEY_base_id(pkey), md_nid = NID_undef;
223     X509_ALGOR *alg1 = NULL, *alg2 = NULL;
224
225     switch (nid) {
226     case NID_id_GostR3410_2012_512:
227         md_nid = NID_id_GostR3411_2012_512;
228         break;
229     case NID_id_GostR3410_2012_256:
230         md_nid = NID_id_GostR3411_2012_256;
231         break;
232     case NID_id_GostR3410_2001:
233     case NID_id_GostR3410_94:
234         md_nid = NID_id_GostR3411_94;
235         break;
236     default:
237         return -1;
238     }
239
240     switch (op) {
241     case ASN1_PKEY_CTRL_PKCS7_SIGN:
242         if (arg1 == 0) {
243             PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO *)arg2, NULL,
244                                         &alg1, &alg2);
245             X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid), V_ASN1_NULL, 0);
246             X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
247         }
248         return 1;
249 #ifndef OPENSSL_NO_CMS
250     case ASN1_PKEY_CTRL_CMS_SIGN:
251         if (arg1 == 0) {
252             CMS_SignerInfo_get0_algs((CMS_SignerInfo *)arg2, NULL, NULL,
253                                      &alg1, &alg2);
254             X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid), V_ASN1_NULL, 0);
255             X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
256         }
257         return 1;
258 #endif
259     case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
260         if (arg1 == 0) {
261             ASN1_STRING *params = encode_gost_algor_params(pkey);
262             if (!params) {
263                 return -1;
264             }
265             PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO *)arg2, &alg1);
266             X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_id(pkey)),
267                             V_ASN1_SEQUENCE, params);
268         }
269         return 1;
270 #ifndef OPENSSL_NO_CMS
271     case ASN1_PKEY_CTRL_CMS_ENVELOPE:
272         if (arg1 == 0) {
273             ASN1_STRING *params = encode_gost_algor_params(pkey);
274             if (!params) {
275                 return -1;
276             }
277             CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL,
278                                              NULL, &alg1);
279             X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_id(pkey)),
280                             V_ASN1_SEQUENCE, params);
281         }
282         return 1;
283 #endif
284     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
285         *(int *)arg2 = md_nid;
286         return 2;
287     }
288
289     return -2;
290 }
291
292 /* --------------------- free functions * ------------------------------*/
293 static void pkey_free_gost_ec(EVP_PKEY *key)
294 {
295     EC_KEY_free((EC_KEY *)EVP_PKEY_get0(key));
296 }
297
298 /* ------------------ private key functions  -----------------------------*/
299
300 static BIGNUM *unmask_priv_key(EVP_PKEY *pk,
301                                const unsigned char *buf, int len, int num_masks)
302 {
303     BIGNUM *pknum_masked = NULL, *q = NULL;
304     const EC_KEY *key_ptr = (pk) ? EVP_PKEY_get0(pk) : NULL;
305     const EC_GROUP *group = (key_ptr) ? EC_KEY_get0_group(key_ptr) : NULL;
306
307     pknum_masked = hashsum2bn(buf, len);
308     if (!pknum_masked)
309         return NULL;
310
311     if (num_masks > 0) {
312         /*
313          * XXX Remove sign by gost94
314          */
315         const unsigned char *p = buf + num_masks * len;
316
317         q = BN_new();
318         if (!q || !group || EC_GROUP_get_order(group, q, NULL) <= 0) {
319             BN_free(pknum_masked);
320             pknum_masked = NULL;
321             goto end;
322         }
323
324         for (; p != buf; p -= len) {
325             BIGNUM *mask = hashsum2bn(p, len);
326             BN_CTX *ctx = BN_CTX_new();
327
328             BN_mod_mul(pknum_masked, pknum_masked, mask, q, ctx);
329
330             BN_CTX_free(ctx);
331             BN_free(mask);
332         }
333     }
334
335  end:
336     if (q)
337         BN_free(q);
338     return pknum_masked;
339 }
340
341 static int priv_decode_gost(EVP_PKEY *pk,
342                             const PKCS8_PRIV_KEY_INFO *p8inf)
343 {
344     const unsigned char *pkey_buf = NULL, *p = NULL;
345     int priv_len = 0;
346     BIGNUM *pk_num = NULL;
347     int ret = 0;
348     const X509_ALGOR *palg = NULL;
349     const ASN1_OBJECT *palg_obj = NULL;
350     ASN1_INTEGER *priv_key = NULL;
351     int expected_key_len;
352
353     if (!PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf))
354         return 0;
355     p = pkey_buf;
356     if (!decode_gost_algor_params(pk, palg)) {
357         return 0;
358     }
359
360     expected_key_len = pkey_bits_gost(pk) > 0 ? pkey_bits_gost(pk) / 8 : 0;
361     if (expected_key_len == 0) {
362         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
363         return 0;
364     }
365
366     if (priv_len % expected_key_len == 0) {
367         /* Key is not wrapped but masked */
368         pk_num = unmask_priv_key(pk, pkey_buf, expected_key_len,
369                                  priv_len / expected_key_len - 1);
370     } else if (V_ASN1_OCTET_STRING == *p) {
371         /* New format - Little endian octet string */
372         ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
373         if (!s || ((s->length != 32) && (s->length != 64))) {
374             ASN1_STRING_free(s);
375             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
376             return 0;
377         }
378         pk_num = hashsum2bn(s->data, s->length);
379         ASN1_STRING_free(s);
380     } else if (V_ASN1_INTEGER == *p) {
381         priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
382         if (!priv_key) {
383             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
384             return 0;
385         }
386         pk_num = ASN1_INTEGER_to_BN(priv_key, NULL);
387         ASN1_INTEGER_free(priv_key);
388     } else if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == *p) {
389         MASKED_GOST_KEY *mgk = NULL;
390         mgk = d2i_MASKED_GOST_KEY(NULL, &p, priv_len);
391
392         if (!mgk) {
393             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
394             return 0;
395         }
396
397         priv_len = mgk->masked_priv_key->length;
398         if (priv_len % expected_key_len) {
399             MASKED_GOST_KEY_free(mgk);
400             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
401             return 0;
402         }
403
404         pk_num = unmask_priv_key(pk, mgk->masked_priv_key->data,
405                                  expected_key_len,
406                                  priv_len / expected_key_len - 1);
407         MASKED_GOST_KEY_free(mgk);
408     } else {
409         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
410         return 0;
411     }
412
413     if (pk_num == NULL) {
414         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
415         return 0;
416     }
417
418     ret = gost_set_priv_key(pk, pk_num);
419     BN_free(pk_num);
420     return ret;
421 }
422
423 /* ----------------------------------------------------------------------*/
424 static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
425 {
426     ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
427     ASN1_STRING *params = NULL;
428     unsigned char *buf = NULL;
429     int key_len = pkey_bits_gost(pk), i = 0;
430     /* unmasked private key */
431     const char *pk_format = get_gost_engine_param(GOST_PARAM_PK_FORMAT);
432
433     key_len = (key_len < 0) ? 0 : key_len / 8;
434     if (key_len == 0 || !(buf = OPENSSL_malloc(key_len))) {
435         return 0;
436     }
437
438     if (!store_bignum(gost_get0_priv_key(pk), buf, key_len)) {
439         OPENSSL_free(buf);
440         return 0;
441     }
442
443     params = encode_gost_algor_params(pk);
444     if (!params) {
445         OPENSSL_free(buf);
446         return 0;
447     }
448
449     /* Convert buf to Little-endian */
450     for (i = 0; i < key_len / 2; i++) {
451         unsigned char tmp = buf[i];
452         buf[i] = buf[key_len - 1 - i];
453         buf[key_len - 1 - i] = tmp;
454     }
455
456     if (pk_format != NULL && strcmp(pk_format, PK_WRAP_PARAM) == 0) {
457         ASN1_STRING *octet = NULL;
458         int priv_len = 0;
459         unsigned char *priv_buf = NULL;
460         octet = ASN1_STRING_new();        
461         if (!octet || !ASN1_OCTET_STRING_set(octet, buf, key_len)) {
462             ASN1_STRING_free(octet);
463             ASN1_STRING_free(params);
464             OPENSSL_free(buf);
465             return 0;
466         }
467         priv_len = i2d_ASN1_OCTET_STRING(octet, &priv_buf);
468         ASN1_STRING_free(octet);
469         OPENSSL_free(buf);
470
471         return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
472                                priv_buf, priv_len);
473     }
474
475     return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
476                            buf, key_len);
477 }
478
479 /* --------- printing keys --------------------------------*/
480 static int print_gost_priv(BIO *out, const EVP_PKEY *pkey, int indent)
481 {
482     BIGNUM *key;
483
484     if (!BIO_indent(out, indent, 128))
485         return 0;
486     BIO_printf(out, "Private key: ");
487     key = gost_get0_priv_key(pkey);
488     if (!key)
489         BIO_printf(out, "<undefined>");
490     else
491         BN_print(out, key);
492     BIO_printf(out, "\n");
493
494     return 1;
495 }
496
497 static int print_gost_ec_pub(BIO *out, const EVP_PKEY *pkey, int indent)
498 {
499     BN_CTX *ctx;
500     BIGNUM *X, *Y;
501     const EC_POINT *pubkey;
502     const EC_GROUP *group;
503     EC_KEY *key = (EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey);
504     int ok = 0;
505
506     ctx = BN_CTX_new();
507     if (!ctx) {
508         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_MALLOC_FAILURE);
509         return 0;
510     }
511
512     BN_CTX_start(ctx);
513     X = BN_CTX_get(ctx);
514     Y = BN_CTX_get(ctx);
515     pubkey = (key) ? EC_KEY_get0_public_key(key) : NULL;
516     group = (key) ? EC_KEY_get0_group(key) : NULL;
517     if (!pubkey || !group)
518         goto err;
519
520     if (!EC_POINT_get_affine_coordinates(group, pubkey, X, Y, ctx)) {
521         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_EC_LIB);
522         goto err;
523     }
524     if (!BIO_indent(out, indent, 128))
525         goto err;
526     BIO_printf(out, "Public key:\n");
527     if (!BIO_indent(out, indent + 3, 128))
528         goto err;
529     BIO_printf(out, "X:");
530     BN_print(out, X);
531     BIO_printf(out, "\n");
532     if (!BIO_indent(out, indent + 3, 128))
533         goto err;
534     BIO_printf(out, "Y:");
535     BN_print(out, Y);
536     BIO_printf(out, "\n");
537     ok = 1;
538  err:
539     BN_CTX_end(ctx);
540     BN_CTX_free(ctx);
541
542     return ok;
543 }
544
545 static int print_gost_ec_param(BIO *out, const EVP_PKEY *pkey, int indent)
546 {
547     EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
548     const EC_GROUP *group = (ec) ? EC_KEY_get0_group(ec) : NULL;
549     int param_nid;
550
551     if (!group)
552         return 0;
553
554     param_nid = EC_GROUP_get_curve_name(group);
555     if (!BIO_indent(out, indent, 128))
556         return 0;
557     BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
558
559     return 1;
560 }
561
562 static int print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
563                          ASN1_PCTX *pctx, int type)
564 {
565     if (type == 2) {
566         if (print_gost_priv(out, pkey, indent) == 0)
567             return 0;
568     }
569     if (type >= 1) {
570         if (print_gost_ec_pub(out, pkey, indent) == 0)
571             return 0;
572     }
573
574     return print_gost_ec_param(out, pkey, indent);
575 }
576
577 static int param_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
578                                ASN1_PCTX *pctx)
579 {
580     return print_gost_ec(out, pkey, indent, pctx, 0);
581 }
582
583 static int pub_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
584                              ASN1_PCTX *pctx)
585 {
586     return print_gost_ec(out, pkey, indent, pctx, 1);
587 }
588
589 static int priv_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
590                               ASN1_PCTX *pctx)
591 {
592     return print_gost_ec(out, pkey, indent, pctx, 2);
593 }
594
595 /* ---------------------------------------------------------------------*/
596 static int param_missing_gost_ec(const EVP_PKEY *pk)
597 {
598     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
599     if (!ec)
600         return 1;
601     if (!EC_KEY_get0_group(ec))
602         return 1;
603     return 0;
604 }
605
606 static int param_copy_gost_ec(EVP_PKEY *to, const EVP_PKEY *from)
607 {
608     EC_KEY *eto = EVP_PKEY_get0(to);
609     const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
610     if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
611         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_INCOMPATIBLE_ALGORITHMS);
612         return 0;
613     }
614     if (!efrom) {
615         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_KEY_PARAMETERS_MISSING);
616         return 0;
617     }
618     if (!eto) {
619         eto = EC_KEY_new();
620         if (!eto) {
621             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_MALLOC_FAILURE);
622             return 0;
623         }
624         if (!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
625             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
626             EC_KEY_free(eto);
627             return 0;
628         }
629     }
630     if (!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
631         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
632         return 0;
633     }
634     if (EC_KEY_get0_private_key(eto)) {
635         return gost_ec_compute_public(eto);
636     }
637     return 1;
638 }
639
640 static int param_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
641 {
642     const EC_GROUP *group_a, *group_b;
643     EC_KEY *ec_a = EVP_PKEY_get0((EVP_PKEY *)a);
644     EC_KEY *ec_b = EVP_PKEY_get0((EVP_PKEY *)b);
645     if (!ec_a || !ec_b)
646         return 0;
647
648     group_a = EC_KEY_get0_group(ec_a);
649     group_b = EC_KEY_get0_group(ec_b);
650     if (!group_a || !group_b)
651         return 0;
652
653     if (EC_GROUP_get_curve_name(group_a) == EC_GROUP_get_curve_name(group_b)) {
654         return 1;
655     }
656     return 0;
657 }
658
659 /* ---------- Public key functions * --------------------------------------*/
660 static int pub_decode_gost_ec(EVP_PKEY *pk, X509_PUBKEY *pub)
661 {
662     X509_ALGOR *palg = NULL;
663     const unsigned char *pubkey_buf = NULL;
664     unsigned char *databuf;
665     ASN1_OBJECT *palgobj = NULL;
666     int pub_len;
667     EC_POINT *pub_key;
668     BIGNUM *X, *Y;
669     ASN1_OCTET_STRING *octet = NULL;
670     size_t len;
671     const EC_GROUP *group;
672
673     if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
674         return 0;
675     EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
676     if (!decode_gost_algor_params(pk, palg))
677         return 0;
678     group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
679     octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
680     if (!octet) {
681         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
682         return 0;
683     }
684     databuf = OPENSSL_malloc(octet->length);
685     if (databuf == NULL) {
686         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
687         ASN1_OCTET_STRING_free(octet);
688         return 0;
689     }
690
691     BUF_reverse(databuf, octet->data, octet->length);
692     len = octet->length / 2;
693     ASN1_OCTET_STRING_free(octet);
694
695     Y = BN_bin2bn(databuf, len, NULL);
696     X = BN_bin2bn(databuf + len, len, NULL);
697     OPENSSL_free(databuf);
698     pub_key = EC_POINT_new(group);
699     if (!EC_POINT_set_affine_coordinates(group, pub_key, X, Y, NULL)) {
700         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
701         EC_POINT_free(pub_key);
702         BN_free(X);
703         BN_free(Y);
704         return 0;
705     }
706     BN_free(X);
707     BN_free(Y);
708     if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
709         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
710         EC_POINT_free(pub_key);
711         return 0;
712     }
713     EC_POINT_free(pub_key);
714     return 1;
715
716 }
717
718 static int pub_encode_gost_ec(X509_PUBKEY *pub, const EVP_PKEY *pk)
719 {
720     ASN1_OBJECT *algobj = NULL;
721     ASN1_OCTET_STRING *octet = NULL;
722     void *pval = NULL;
723     unsigned char *buf = NULL, *databuf = NULL;
724     int data_len, ret = -1;
725     const EC_POINT *pub_key;
726     BIGNUM *X = NULL, *Y = NULL, *order = NULL;
727     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
728     int ptype = V_ASN1_SEQUENCE;
729     ASN1_STRING *params;
730
731     algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
732
733     params = encode_gost_algor_params(pk);
734     pval = params;
735
736     order = BN_new();
737     if (!order) {
738         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
739         goto err;
740     }
741     EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
742     pub_key = EC_KEY_get0_public_key(ec);
743     if (!pub_key) {
744         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, GOST_R_PUBLIC_KEY_UNDEFINED);
745         goto err;
746     }
747     X = BN_new();
748     Y = BN_new();
749     if (!X || !Y) {
750         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
751         goto err;
752     }
753     if (!EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
754                                              pub_key, X, Y, NULL)) {
755         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_INTERNAL_ERROR);
756         goto err;
757     }
758     data_len = 2 * BN_num_bytes(order);
759     databuf = OPENSSL_zalloc(data_len);
760     if (databuf == NULL) {
761         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
762         goto err;
763     }
764
765     store_bignum(X, databuf + data_len / 2, data_len / 2);
766     store_bignum(Y, databuf, data_len / 2);
767
768     BUF_reverse(databuf, NULL, data_len);
769
770     octet = ASN1_OCTET_STRING_new();
771     if (octet == NULL) {
772         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
773         goto err;
774     }
775
776     if (0 == ASN1_STRING_set(octet, databuf, data_len)) {
777         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
778         goto err;
779     }
780
781     ret = i2d_ASN1_OCTET_STRING(octet, &buf);
782  err:
783     ASN1_BIT_STRING_free(octet);
784     if (X)
785         BN_free(X);
786     if (Y)
787         BN_free(Y);
788     if (order)
789         BN_free(order);
790     if (databuf)
791         OPENSSL_free(databuf);
792
793     if (ret < 0)
794         return 0;
795     return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
796 }
797
798 static int pub_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
799 {
800     const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
801     const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
802     const EC_POINT *ka, *kb;
803     if (!ea || !eb)
804         return 0;
805     ka = EC_KEY_get0_public_key(ea);
806     kb = EC_KEY_get0_public_key(eb);
807     if (!ka || !kb)
808         return 0;
809     return (0 == EC_POINT_cmp(EC_KEY_get0_group(ea), ka, kb, NULL));
810 }
811
812 static int pkey_size_gost(const EVP_PKEY *pk)
813 {
814     if (!pk)
815         return -1;
816
817     switch (EVP_PKEY_base_id(pk)) {
818     case NID_id_GostR3410_94:
819     case NID_id_GostR3410_2001:
820     case NID_id_GostR3410_2012_256:
821         return 64;
822     case NID_id_GostR3410_2012_512:
823         return 128;
824     }
825
826     return -1;
827 }
828
829 /* ---------------------- ASN1 METHOD for GOST MAC  -------------------*/
830 static void mackey_free_gost(EVP_PKEY *pk)
831 {
832     OPENSSL_free(EVP_PKEY_get0(pk));
833 }
834
835 static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
836 {
837     switch (op) {
838     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
839         if (arg2) {
840             *(int *)arg2 = NID_id_Gost28147_89_MAC;
841             return 2;
842         }
843     }
844     return -2;
845 }
846
847 static int mac_ctrl_gost_12(EVP_PKEY *pkey, int op, long arg1, void *arg2)
848 {
849     switch (op) {
850     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
851         if (arg2) {
852             *(int *)arg2 = NID_gost_mac_12;
853             return 2;
854         }
855     }
856     return -2;
857 }
858
859 static int mac_ctrl_magma(EVP_PKEY *pkey, int op, long arg1, void *arg2)
860 {
861     switch (op) {
862     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
863         if (arg2) {
864             *(int *)arg2 = NID_magma_mac;
865             return 2;
866         }
867     }
868     return -2;
869 }
870
871 static int mac_ctrl_grasshopper(EVP_PKEY *pkey, int op, long arg1, void *arg2)
872 {
873     switch (op) {
874     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
875         if (arg2) {
876             *(int *)arg2 = NID_grasshopper_mac;
877             return 2;
878         }
879     }
880     return -2;
881 }
882
883 static int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
884 {
885     int nid =
886         EC_GROUP_get_curve_name(EC_KEY_get0_group
887                                 (EVP_PKEY_get0((EVP_PKEY *)pkey)));
888     return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
889 }
890
891 static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
892                                  int derlen)
893 {
894     ASN1_OBJECT *obj = NULL;
895     int nid;
896     if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
897         return 0;
898     }
899     nid = OBJ_obj2nid(obj);
900     ASN1_OBJECT_free(obj);
901
902     return gost_decode_nid_params(pkey, NID_id_GostR3410_2001, nid);
903 }
904
905 /* ----------------------------------------------------------------------*/
906 int register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
907                         const char *pemstr, const char *info)
908 {
909     *ameth = EVP_PKEY_asn1_new(nid, ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
910     if (!*ameth)
911         return 0;
912     switch (nid) {
913     case NID_id_GostR3410_2001:
914         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
915         EVP_PKEY_asn1_set_private(*ameth,
916                                   priv_decode_gost, priv_encode_gost,
917                                   priv_print_gost_ec);
918
919         EVP_PKEY_asn1_set_param(*ameth,
920                                 gost2001_param_decode, gost2001_param_encode,
921                                 param_missing_gost_ec, param_copy_gost_ec,
922                                 param_cmp_gost_ec, param_print_gost_ec);
923         EVP_PKEY_asn1_set_public(*ameth,
924                                  pub_decode_gost_ec, pub_encode_gost_ec,
925                                  pub_cmp_gost_ec, pub_print_gost_ec,
926                                  pkey_size_gost, pkey_bits_gost);
927
928         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
929         EVP_PKEY_asn1_set_security_bits(*ameth, pkey_bits_gost);
930         break;
931     case NID_id_GostR3410_2012_256:
932     case NID_id_GostR3410_2012_512:
933         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
934         EVP_PKEY_asn1_set_private(*ameth,
935                                   priv_decode_gost, priv_encode_gost,
936                                   priv_print_gost_ec);
937
938         EVP_PKEY_asn1_set_param(*ameth,
939                                 NULL, NULL,
940                                 param_missing_gost_ec, param_copy_gost_ec,
941                                 param_cmp_gost_ec, NULL);
942
943         EVP_PKEY_asn1_set_public(*ameth,
944                                  pub_decode_gost_ec, pub_encode_gost_ec,
945                                  pub_cmp_gost_ec, pub_print_gost_ec,
946                                  pkey_size_gost, pkey_bits_gost);
947
948         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
949         EVP_PKEY_asn1_set_security_bits(*ameth, pkey_bits_gost);
950         break;
951     case NID_id_Gost28147_89_MAC:
952         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
953         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost);
954         break;
955     case NID_gost_mac_12:
956         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
957         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost_12);
958         break;
959     case NID_magma_mac:
960         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
961         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_magma);
962         break;
963     case NID_grasshopper_mac:
964         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
965         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_grasshopper);
966         break;
967     }
968     return 1;
969 }