]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_ameth.c
ameth: fill digestParamSet for the sake of backwards compatibility
[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 = hashsum2bn(buf, len);
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 = hashsum2bn(p, len);
332             BN_CTX *ctx = BN_CTX_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 = hashsum2bn(s->data, s->length);
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, NULL);
393         ASN1_INTEGER_free(priv_key);
394     } else if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == *p) {
395         MASKED_GOST_KEY *mgk = NULL;
396         mgk = d2i_MASKED_GOST_KEY(NULL, &p, priv_len);
397
398         if (!mgk) {
399             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
400             return 0;
401         }
402
403         priv_len = mgk->masked_priv_key->length;
404         if (priv_len % expected_key_len) {
405             MASKED_GOST_KEY_free(mgk);
406             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
407             return 0;
408         }
409
410         pk_num = unmask_priv_key(pk, mgk->masked_priv_key->data,
411                                  expected_key_len,
412                                  priv_len / expected_key_len - 1);
413         MASKED_GOST_KEY_free(mgk);
414     } else {
415         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
416         return 0;
417     }
418
419     if (pk_num == NULL) {
420         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
421         return 0;
422     }
423
424     ret = gost_set_priv_key(pk, pk_num);
425     BN_free(pk_num);
426     return ret;
427 }
428
429 /* ----------------------------------------------------------------------*/
430 static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
431 {
432     ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
433     ASN1_STRING *params = NULL;
434     unsigned char *buf = NULL;
435     int key_len = pkey_bits_gost(pk), i = 0;
436     /* unmasked private key */
437     const char *pk_format = get_gost_engine_param(GOST_PARAM_PK_FORMAT);
438
439     key_len = (key_len < 0) ? 0 : key_len / 8;
440     if (key_len == 0 || !(buf = OPENSSL_malloc(key_len))) {
441         return 0;
442     }
443
444     if (!store_bignum(gost_get0_priv_key(pk), buf, key_len)) {
445         OPENSSL_free(buf);
446         return 0;
447     }
448
449     params = encode_gost_algor_params(pk);
450     if (!params) {
451         OPENSSL_free(buf);
452         return 0;
453     }
454
455     /* Convert buf to Little-endian */
456     for (i = 0; i < key_len / 2; i++) {
457         unsigned char tmp = buf[i];
458         buf[i] = buf[key_len - 1 - i];
459         buf[key_len - 1 - i] = tmp;
460     }
461
462     if (pk_format != NULL && strcmp(pk_format, PK_WRAP_PARAM) == 0) {
463         ASN1_STRING *octet = NULL;
464         int priv_len = 0;
465         unsigned char *priv_buf = NULL;
466         octet = ASN1_STRING_new();        
467         if (!octet || !ASN1_OCTET_STRING_set(octet, buf, key_len)) {
468             ASN1_STRING_free(octet);
469             ASN1_STRING_free(params);
470             OPENSSL_free(buf);
471             return 0;
472         }
473         priv_len = i2d_ASN1_OCTET_STRING(octet, &priv_buf);
474         ASN1_STRING_free(octet);
475         OPENSSL_free(buf);
476
477         return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
478                                priv_buf, priv_len);
479     }
480
481     return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
482                            buf, key_len);
483 }
484
485 /* --------- printing keys --------------------------------*/
486 static int print_gost_priv(BIO *out, const EVP_PKEY *pkey, int indent)
487 {
488     BIGNUM *key;
489
490     if (!BIO_indent(out, indent, 128))
491         return 0;
492     BIO_printf(out, "Private key: ");
493     key = gost_get0_priv_key(pkey);
494     if (!key)
495         BIO_printf(out, "<undefined>");
496     else
497         BN_print(out, key);
498     BIO_printf(out, "\n");
499
500     return 1;
501 }
502
503 static int print_gost_ec_pub(BIO *out, const EVP_PKEY *pkey, int indent)
504 {
505     BN_CTX *ctx;
506     BIGNUM *X, *Y;
507     const EC_POINT *pubkey;
508     const EC_GROUP *group;
509     EC_KEY *key = (EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey);
510     int ok = 0;
511
512     ctx = BN_CTX_new();
513     if (!ctx) {
514         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_MALLOC_FAILURE);
515         return 0;
516     }
517
518     BN_CTX_start(ctx);
519     X = BN_CTX_get(ctx);
520     Y = BN_CTX_get(ctx);
521     pubkey = (key) ? EC_KEY_get0_public_key(key) : NULL;
522     group = (key) ? EC_KEY_get0_group(key) : NULL;
523     if (!pubkey || !group)
524         goto err;
525
526     if (!EC_POINT_get_affine_coordinates(group, pubkey, X, Y, ctx)) {
527         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_EC_LIB);
528         goto err;
529     }
530     if (!BIO_indent(out, indent, 128))
531         goto err;
532     BIO_printf(out, "Public key:\n");
533     if (!BIO_indent(out, indent + 3, 128))
534         goto err;
535     BIO_printf(out, "X:");
536     BN_print(out, X);
537     BIO_printf(out, "\n");
538     if (!BIO_indent(out, indent + 3, 128))
539         goto err;
540     BIO_printf(out, "Y:");
541     BN_print(out, Y);
542     BIO_printf(out, "\n");
543     ok = 1;
544  err:
545     BN_CTX_end(ctx);
546     BN_CTX_free(ctx);
547
548     return ok;
549 }
550
551 static int print_gost_ec_param(BIO *out, const EVP_PKEY *pkey, int indent)
552 {
553     EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
554     const EC_GROUP *group = (ec) ? EC_KEY_get0_group(ec) : NULL;
555     int param_nid;
556
557     if (!group)
558         return 0;
559
560     param_nid = EC_GROUP_get_curve_name(group);
561     if (!BIO_indent(out, indent, 128))
562         return 0;
563     BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
564
565     return 1;
566 }
567
568 static int print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
569                          ASN1_PCTX *pctx, int type)
570 {
571     if (type == 2) {
572         if (print_gost_priv(out, pkey, indent) == 0)
573             return 0;
574     }
575     if (type >= 1) {
576         if (print_gost_ec_pub(out, pkey, indent) == 0)
577             return 0;
578     }
579
580     return print_gost_ec_param(out, pkey, indent);
581 }
582
583 static int param_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, 0);
587 }
588
589 static int pub_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, 1);
593 }
594
595 static int priv_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
596                               ASN1_PCTX *pctx)
597 {
598     return print_gost_ec(out, pkey, indent, pctx, 2);
599 }
600
601 /* ---------------------------------------------------------------------*/
602 static int param_missing_gost_ec(const EVP_PKEY *pk)
603 {
604     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
605     if (!ec)
606         return 1;
607     if (!EC_KEY_get0_group(ec))
608         return 1;
609     return 0;
610 }
611
612 static int param_copy_gost_ec(EVP_PKEY *to, const EVP_PKEY *from)
613 {
614     EC_KEY *eto = EVP_PKEY_get0(to);
615     const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
616     if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
617         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_INCOMPATIBLE_ALGORITHMS);
618         return 0;
619     }
620     if (!efrom) {
621         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_KEY_PARAMETERS_MISSING);
622         return 0;
623     }
624     if (!eto) {
625         eto = EC_KEY_new();
626         if (!eto) {
627             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_MALLOC_FAILURE);
628             return 0;
629         }
630         if (!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
631             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
632             EC_KEY_free(eto);
633             return 0;
634         }
635     }
636     if (!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
637         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
638         return 0;
639     }
640     if (EC_KEY_get0_private_key(eto)) {
641         return gost_ec_compute_public(eto);
642     }
643     return 1;
644 }
645
646 static int param_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
647 {
648     const EC_GROUP *group_a, *group_b;
649     EC_KEY *ec_a = EVP_PKEY_get0((EVP_PKEY *)a);
650     EC_KEY *ec_b = EVP_PKEY_get0((EVP_PKEY *)b);
651     if (!ec_a || !ec_b)
652         return 0;
653
654     group_a = EC_KEY_get0_group(ec_a);
655     group_b = EC_KEY_get0_group(ec_b);
656     if (!group_a || !group_b)
657         return 0;
658
659     if (EC_GROUP_get_curve_name(group_a) == EC_GROUP_get_curve_name(group_b)) {
660         return 1;
661     }
662     return 0;
663 }
664
665 /* ---------- Public key functions * --------------------------------------*/
666 static int pub_decode_gost_ec(EVP_PKEY *pk, X509_PUBKEY *pub)
667 {
668     X509_ALGOR *palg = NULL;
669     const unsigned char *pubkey_buf = NULL;
670     unsigned char *databuf;
671     ASN1_OBJECT *palgobj = NULL;
672     int pub_len;
673     EC_POINT *pub_key;
674     BIGNUM *X, *Y;
675     ASN1_OCTET_STRING *octet = NULL;
676     size_t len;
677     const EC_GROUP *group;
678
679     if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
680         return 0;
681     EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
682     if (!decode_gost_algor_params(pk, palg))
683         return 0;
684     group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
685     octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
686     if (!octet) {
687         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
688         return 0;
689     }
690     databuf = OPENSSL_malloc(octet->length);
691     if (databuf == NULL) {
692         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
693         ASN1_OCTET_STRING_free(octet);
694         return 0;
695     }
696
697     BUF_reverse(databuf, octet->data, octet->length);
698     len = octet->length / 2;
699     ASN1_OCTET_STRING_free(octet);
700
701     Y = BN_bin2bn(databuf, len, NULL);
702     X = BN_bin2bn(databuf + len, len, NULL);
703     OPENSSL_free(databuf);
704     pub_key = EC_POINT_new(group);
705     if (!EC_POINT_set_affine_coordinates(group, pub_key, X, Y, NULL)) {
706         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
707         EC_POINT_free(pub_key);
708         BN_free(X);
709         BN_free(Y);
710         return 0;
711     }
712     BN_free(X);
713     BN_free(Y);
714     if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
715         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
716         EC_POINT_free(pub_key);
717         return 0;
718     }
719     EC_POINT_free(pub_key);
720     return 1;
721
722 }
723
724 static int pub_encode_gost_ec(X509_PUBKEY *pub, const EVP_PKEY *pk)
725 {
726     ASN1_OBJECT *algobj = NULL;
727     ASN1_OCTET_STRING *octet = NULL;
728     void *pval = NULL;
729     unsigned char *buf = NULL, *databuf = NULL;
730     int data_len, ret = -1;
731     const EC_POINT *pub_key;
732     BIGNUM *X = NULL, *Y = NULL, *order = NULL;
733     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
734     int ptype = V_ASN1_SEQUENCE;
735     ASN1_STRING *params;
736
737     algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
738
739     params = encode_gost_algor_params(pk);
740     pval = params;
741
742     order = BN_new();
743     if (!order) {
744         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
745         goto err;
746     }
747     EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
748     pub_key = EC_KEY_get0_public_key(ec);
749     if (!pub_key) {
750         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, GOST_R_PUBLIC_KEY_UNDEFINED);
751         goto err;
752     }
753     X = BN_new();
754     Y = BN_new();
755     if (!X || !Y) {
756         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
757         goto err;
758     }
759     if (!EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
760                                              pub_key, X, Y, NULL)) {
761         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_INTERNAL_ERROR);
762         goto err;
763     }
764     data_len = 2 * BN_num_bytes(order);
765     databuf = OPENSSL_zalloc(data_len);
766     if (databuf == NULL) {
767         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
768         goto err;
769     }
770
771     store_bignum(X, databuf + data_len / 2, data_len / 2);
772     store_bignum(Y, databuf, data_len / 2);
773
774     BUF_reverse(databuf, NULL, data_len);
775
776     octet = ASN1_OCTET_STRING_new();
777     if (octet == NULL) {
778         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
779         goto err;
780     }
781
782     if (0 == ASN1_STRING_set(octet, databuf, data_len)) {
783         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
784         goto err;
785     }
786
787     ret = i2d_ASN1_OCTET_STRING(octet, &buf);
788  err:
789     ASN1_BIT_STRING_free(octet);
790     if (X)
791         BN_free(X);
792     if (Y)
793         BN_free(Y);
794     if (order)
795         BN_free(order);
796     if (databuf)
797         OPENSSL_free(databuf);
798
799     if (ret < 0)
800         return 0;
801     return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
802 }
803
804 static int pub_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
805 {
806     const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
807     const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
808     const EC_POINT *ka, *kb;
809     if (!ea || !eb)
810         return 0;
811     ka = EC_KEY_get0_public_key(ea);
812     kb = EC_KEY_get0_public_key(eb);
813     if (!ka || !kb)
814         return 0;
815     return (0 == EC_POINT_cmp(EC_KEY_get0_group(ea), ka, kb, NULL));
816 }
817
818 static int pkey_size_gost(const EVP_PKEY *pk)
819 {
820     if (!pk)
821         return -1;
822
823     switch (EVP_PKEY_base_id(pk)) {
824     case NID_id_GostR3410_94:
825     case NID_id_GostR3410_2001:
826     case NID_id_GostR3410_2012_256:
827         return 64;
828     case NID_id_GostR3410_2012_512:
829         return 128;
830     }
831
832     return -1;
833 }
834
835 /* ---------------------- ASN1 METHOD for GOST MAC  -------------------*/
836 static void mackey_free_gost(EVP_PKEY *pk)
837 {
838     OPENSSL_free(EVP_PKEY_get0(pk));
839 }
840
841 static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
842 {
843     switch (op) {
844     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
845         if (arg2) {
846             *(int *)arg2 = NID_id_Gost28147_89_MAC;
847             return 2;
848         }
849     }
850     return -2;
851 }
852
853 static int mac_ctrl_gost_12(EVP_PKEY *pkey, int op, long arg1, void *arg2)
854 {
855     switch (op) {
856     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
857         if (arg2) {
858             *(int *)arg2 = NID_gost_mac_12;
859             return 2;
860         }
861     }
862     return -2;
863 }
864
865 static int mac_ctrl_magma(EVP_PKEY *pkey, int op, long arg1, void *arg2)
866 {
867     switch (op) {
868     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
869         if (arg2) {
870             *(int *)arg2 = NID_magma_mac;
871             return 2;
872         }
873     }
874     return -2;
875 }
876
877 static int mac_ctrl_grasshopper(EVP_PKEY *pkey, int op, long arg1, void *arg2)
878 {
879     switch (op) {
880     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
881         if (arg2) {
882             *(int *)arg2 = NID_grasshopper_mac;
883             return 2;
884         }
885     }
886     return -2;
887 }
888
889 static int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
890 {
891     int nid =
892         EC_GROUP_get_curve_name(EC_KEY_get0_group
893                                 (EVP_PKEY_get0((EVP_PKEY *)pkey)));
894     return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
895 }
896
897 static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
898                                  int derlen)
899 {
900     ASN1_OBJECT *obj = NULL;
901     int nid;
902     if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
903         return 0;
904     }
905     nid = OBJ_obj2nid(obj);
906     ASN1_OBJECT_free(obj);
907
908     return gost_decode_nid_params(pkey, NID_id_GostR3410_2001, nid);
909 }
910
911 /* ----------------------------------------------------------------------*/
912 int register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
913                         const char *pemstr, const char *info)
914 {
915     *ameth = EVP_PKEY_asn1_new(nid, ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
916     if (!*ameth)
917         return 0;
918     switch (nid) {
919     case NID_id_GostR3410_2001:
920         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
921         EVP_PKEY_asn1_set_private(*ameth,
922                                   priv_decode_gost, priv_encode_gost,
923                                   priv_print_gost_ec);
924
925         EVP_PKEY_asn1_set_param(*ameth,
926                                 gost2001_param_decode, gost2001_param_encode,
927                                 param_missing_gost_ec, param_copy_gost_ec,
928                                 param_cmp_gost_ec, param_print_gost_ec);
929         EVP_PKEY_asn1_set_public(*ameth,
930                                  pub_decode_gost_ec, pub_encode_gost_ec,
931                                  pub_cmp_gost_ec, pub_print_gost_ec,
932                                  pkey_size_gost, pkey_bits_gost);
933
934         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
935         EVP_PKEY_asn1_set_security_bits(*ameth, pkey_bits_gost);
936         break;
937     case NID_id_GostR3410_2012_256:
938     case NID_id_GostR3410_2012_512:
939         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
940         EVP_PKEY_asn1_set_private(*ameth,
941                                   priv_decode_gost, priv_encode_gost,
942                                   priv_print_gost_ec);
943
944         EVP_PKEY_asn1_set_param(*ameth,
945                                 NULL, NULL,
946                                 param_missing_gost_ec, param_copy_gost_ec,
947                                 param_cmp_gost_ec, NULL);
948
949         EVP_PKEY_asn1_set_public(*ameth,
950                                  pub_decode_gost_ec, pub_encode_gost_ec,
951                                  pub_cmp_gost_ec, pub_print_gost_ec,
952                                  pkey_size_gost, pkey_bits_gost);
953
954         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
955         EVP_PKEY_asn1_set_security_bits(*ameth, pkey_bits_gost);
956         break;
957     case NID_id_Gost28147_89_MAC:
958         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
959         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost);
960         break;
961     case NID_gost_mac_12:
962         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
963         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost_12);
964         break;
965     case NID_magma_mac:
966         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
967         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_magma);
968         break;
969     case NID_grasshopper_mac:
970         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
971         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_grasshopper);
972         break;
973     }
974     return 1;
975 }