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