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