]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_ameth.c
Merge branch 'no_gost94_sig' into gost12_algs
[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 /*
23  * Pack bignum into byte buffer of given size, filling all leading bytes by
24  * zeros
25  */
26 int store_bignum(BIGNUM *bn, unsigned char *buf, int len)
27 {
28     int bytes = BN_num_bytes(bn);
29
30     if (bytes > len)
31         return 0;
32     memset(buf, 0, len);
33     BN_bn2bin(bn, buf + len - bytes);
34     return 1;
35 }
36
37 /* Convert byte buffer to bignum, skipping leading zeros*/
38 BIGNUM *getbnfrombuf(const unsigned char *buf, size_t len)
39 {
40     BIGNUM *b;
41
42     while (*buf == 0 && len > 0) {
43         buf++;
44         len--;
45     }
46     if (len)
47         return BN_bin2bn(buf, len, NULL);
48     b = BN_new();
49     BN_zero(b);
50     return b;
51 }
52
53 static int pkey_bits_gost(const EVP_PKEY *pk)
54 {
55     if (!pk)
56         return -1;
57
58     switch (EVP_PKEY_base_id(pk)) {
59     case NID_id_GostR3410_2001:
60     case NID_id_GostR3410_2012_256:
61         return 256;
62     case NID_id_GostR3410_2012_512:
63         return 512;
64     }
65
66     return -1;
67 }
68
69 static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
70 {
71     ASN1_STRING *params = ASN1_STRING_new();
72     GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
73     int pkey_param_nid = NID_undef;
74     void *key_ptr = EVP_PKEY_get0((EVP_PKEY *)key);
75     int result = 0;
76
77     if (!params || !gkp) {
78         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
79         goto err;
80     }
81     switch (EVP_PKEY_base_id(key)) {
82     case NID_id_GostR3410_2012_256:
83         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
84         gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_2012_256);
85         break;
86     case NID_id_GostR3410_2012_512:
87         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
88         gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_2012_512);
89         break;
90     case NID_id_GostR3410_2001:
91         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
92         gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
93         break;
94     }
95
96     if (pkey_param_nid == NID_undef) {
97         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, GOST_R_INVALID_PARAMSET);
98         goto err;
99     }
100
101     gkp->key_params = OBJ_nid2obj(pkey_param_nid);
102     /*
103      * gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);
104      */
105     params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
106     if (params->length <= 0) {
107         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
108         goto err;
109     }
110     params->type = V_ASN1_SEQUENCE;
111     result = 1;
112  err:
113     if (gkp)
114         GOST_KEY_PARAMS_free(gkp);
115     if (result == 0) {          /* if error */
116         if (params)
117             ASN1_STRING_free(params);
118         return NULL;
119     }
120     return params;
121 }
122
123 static int gost_decode_nid_params(EVP_PKEY *pkey, int pkey_nid, int param_nid)
124 {
125     void *key_ptr = EVP_PKEY_get0(pkey);
126
127     switch (pkey_nid) {
128     case NID_id_GostR3410_2012_256:
129     case NID_id_GostR3410_2012_512:
130     case NID_id_GostR3410_2001:
131         if (!key_ptr) {
132             key_ptr = EC_KEY_new();
133             if (!EVP_PKEY_assign(pkey, pkey_nid, key_ptr)) {
134                 EC_KEY_free(key_ptr);
135                 break;
136             }
137         }
138         return fill_GOST_EC_params(key_ptr, param_nid);
139     }
140
141     return 0;
142 }
143
144 /*
145  * Parses GOST algorithm parameters from X509_ALGOR and modifies pkey setting
146  * NID and parameters
147  */
148 static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
149 {
150     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, (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                 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(pkey->type),
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(pkey->type), V_ASN1_SEQUENCE,
286                             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(key->pkey.ec);
302 }
303
304 /* ------------------ private key functions  -----------------------------*/
305
306 static BIGNUM *unmask_priv_key(EVP_PKEY *pk,
307                                const unsigned char *buf, int len,
308                                int num_masks)
309 {
310     BIGNUM *pknum_masked = NULL, *q = NULL;
311     const EC_KEY *key_ptr = (pk) ? EVP_PKEY_get0(pk) : NULL;
312     const EC_GROUP *group = (key_ptr) ? EC_KEY_get0_group(key_ptr) : NULL;
313
314     pknum_masked = hashsum2bn(buf, len);
315     if (!pknum_masked)
316         return NULL;
317
318     if (num_masks > 0) {
319         /*
320          * XXX Remove sign by gost94
321          */
322         const unsigned char *p = buf + num_masks * len;
323
324         q = BN_new();
325         if (!q || !group || EC_GROUP_get_order(group, q, NULL) <= 0) {
326             BN_free(pknum_masked);
327             pknum_masked = NULL;
328             goto end;
329         }
330
331         for (; p != buf; p -= len) {
332             BIGNUM *mask = hashsum2bn(p, len);
333             BN_CTX *ctx = BN_CTX_new();
334
335             BN_mod_mul(pknum_masked, pknum_masked, mask, q, ctx);
336
337             BN_CTX_free(ctx);
338             BN_free(mask);
339         }
340     }
341
342  end:
343     if (q)
344         BN_free(q);
345     return pknum_masked;
346 }
347
348 static int priv_decode_gost(EVP_PKEY *pk, 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     X509_ALGOR *palg = NULL;
355     ASN1_OBJECT *palg_obj = NULL;
356     ASN1_INTEGER *priv_key = NULL;
357     int expected_key_len = 32;
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 = encode_gost_algor_params(pk);
434     unsigned char *priv_buf = NULL, *buf = NULL;
435     int key_len = pkey_bits_gost(pk), priv_len = 0, i = 0;
436
437     ASN1_STRING *octet = NULL;
438     if (!params) {
439         return 0;
440     }
441
442     key_len = (key_len < 0) ? 0 : key_len / 8;
443     if (key_len == 0 || !(buf = OPENSSL_malloc(key_len))) {
444         return 0;
445     }
446
447     if (!store_bignum(gost_get0_priv_key(pk), buf, key_len)) {
448         OPENSSL_free(buf);
449         return 0;
450     }
451
452     /* Convert buf to Little-endian */
453     for (i = 0; i < key_len / 2; i++) {
454         unsigned char tmp = buf[i];
455         buf[i] = buf[key_len - 1 - i];
456         buf[key_len - 1 - i] = tmp;
457     }
458
459     octet = ASN1_STRING_new();
460     ASN1_OCTET_STRING_set(octet, buf, key_len);
461
462     priv_len = i2d_ASN1_OCTET_STRING(octet, &priv_buf);
463     ASN1_STRING_free(octet);
464     OPENSSL_free(buf);
465
466     return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
467                            priv_buf, priv_len);
468 }
469
470 /* --------- printing keys --------------------------------*/
471 static int print_gost_priv(BIO *out, const EVP_PKEY *pkey, int indent)
472 {
473     BIGNUM *key;
474
475     if (!BIO_indent(out, indent, 128))
476         return 0;
477     BIO_printf(out, "Private key: ");
478     key = gost_get0_priv_key(pkey);
479     if (!key)
480         BIO_printf(out, "<undefined>");
481     else
482         BN_print(out, key);
483     BIO_printf(out, "\n");
484
485     return 1;
486 }
487
488 static int print_gost_ec_pub(BIO *out, const EVP_PKEY *pkey, int indent)
489 {
490     BN_CTX *ctx;
491     BIGNUM *X, *Y;
492     const EC_POINT *pubkey;
493     const EC_GROUP *group;
494     EC_KEY *key = (EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey);
495     int ok = 0;
496
497     ctx = BN_CTX_new();
498     if (!ctx) {
499         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_MALLOC_FAILURE);
500         return 0;
501     }
502
503     BN_CTX_start(ctx);
504     X = BN_CTX_get(ctx);
505     Y = BN_CTX_get(ctx);
506     pubkey = (key) ? EC_KEY_get0_public_key(key) : NULL;
507     group = (key) ? EC_KEY_get0_group(key) : NULL;
508     if (!pubkey || !group)
509         goto err;
510
511     if (!EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx)) {
512         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_EC_LIB);
513         goto err;
514     }
515     if (!BIO_indent(out, indent, 128))
516         goto err;
517     BIO_printf(out, "Public key:\n");
518     if (!BIO_indent(out, indent + 3, 128))
519         goto err;
520     BIO_printf(out, "X:");
521     BN_print(out, X);
522     BIO_printf(out, "\n");
523     if (!BIO_indent(out, indent + 3, 128))
524         goto err;
525     BIO_printf(out, "Y:");
526     BN_print(out, Y);
527     BIO_printf(out, "\n");
528     ok = 1;
529  err:
530     BN_CTX_end(ctx);
531     BN_CTX_free(ctx);
532
533     return ok;
534 }
535
536 static int print_gost_ec_param(BIO *out, const EVP_PKEY *pkey, int indent)
537 {
538     EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
539     const EC_GROUP *group = (ec) ? EC_KEY_get0_group(ec) : NULL;
540     int param_nid;
541
542     if (!group)
543         return 0;
544
545     param_nid = EC_GROUP_get_curve_name(group);
546     if (!BIO_indent(out, indent, 128))
547         return 0;
548     BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
549
550     return 1;
551 }
552
553 static int print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
554                          ASN1_PCTX *pctx, int type)
555 {
556     if (type == 2) {
557         if (print_gost_priv(out, pkey, indent) == 0)
558             return 0;
559     }
560     if (type >= 1) {
561         if (print_gost_ec_pub(out, pkey, indent) == 0)
562             return 0;
563     }
564
565     return print_gost_ec_param(out, pkey, indent);
566 }
567
568 static int param_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
569                                ASN1_PCTX *pctx)
570 {
571     return print_gost_ec(out, pkey, indent, pctx, 0);
572 }
573
574 static int pub_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
575                              ASN1_PCTX *pctx)
576 {
577     return print_gost_ec(out, pkey, indent, pctx, 1);
578 }
579
580 static int priv_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
581                               ASN1_PCTX *pctx)
582 {
583     return print_gost_ec(out, pkey, indent, pctx, 2);
584 }
585
586 /* ---------------------------------------------------------------------*/
587 static int param_missing_gost_ec(const EVP_PKEY *pk)
588 {
589     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
590     if (!ec)
591         return 1;
592     if (!EC_KEY_get0_group(ec))
593         return 1;
594     return 0;
595 }
596
597
598 static int param_copy_gost_ec(EVP_PKEY *to, const EVP_PKEY *from)
599 {
600     EC_KEY *eto = EVP_PKEY_get0(to);
601     const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
602     if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
603         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_INCOMPATIBLE_ALGORITHMS);
604         return 0;
605     }
606     if (!efrom) {
607         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_KEY_PARAMETERS_MISSING);
608         return 0;
609     }
610     if (!eto) {
611         eto = EC_KEY_new();
612         if (!eto) {
613             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_MALLOC_FAILURE);
614             return 0;
615         }
616         if (!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
617             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
618             EC_KEY_free(eto);
619             return 0;
620         }
621     }
622     if (!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
623         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
624         return 0;
625     }
626     if (EC_KEY_get0_private_key(eto)) {
627         return gost_ec_compute_public(eto);
628     }
629     return 1;
630 }
631
632 static int param_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
633 {
634     const EC_GROUP *group_a, *group_b;
635     EC_KEY *ec_a = EVP_PKEY_get0((EVP_PKEY *)a);
636     EC_KEY *ec_b = EVP_PKEY_get0((EVP_PKEY *)b);
637     if (!ec_a || !ec_b)
638         return 0;
639
640     group_a = EC_KEY_get0_group(ec_a);
641     group_b = EC_KEY_get0_group(ec_b);
642     if (!group_a || !group_b)
643         return 0;
644
645     if (EC_GROUP_get_curve_name(group_a) == EC_GROUP_get_curve_name(group_b)) {
646         return 1;
647     }
648     return 0;
649 }
650
651 /* ---------- Public key functions * --------------------------------------*/
652 static int pub_decode_gost_ec(EVP_PKEY *pk, X509_PUBKEY *pub)
653 {
654     X509_ALGOR *palg = NULL;
655     const unsigned char *pubkey_buf = NULL;
656     unsigned char *databuf;
657     ASN1_OBJECT *palgobj = NULL;
658     int pub_len, i, j;
659     EC_POINT *pub_key;
660     BIGNUM *X, *Y;
661     ASN1_OCTET_STRING *octet = NULL;
662     int len;
663     const EC_GROUP *group;
664
665     if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
666         return 0;
667     EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
668     if (!decode_gost_algor_params(pk, palg))
669         return 0;
670     group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
671     octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
672     if (!octet) {
673         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
674         return 0;
675     }
676     databuf = OPENSSL_malloc(octet->length);
677     if (databuf == NULL) {
678         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
679         ASN1_OCTET_STRING_free(octet);
680         return 0;
681     }
682     for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
683         databuf[j] = octet->data[i];
684     }
685     len = octet->length / 2;
686     ASN1_OCTET_STRING_free(octet);
687
688     Y = getbnfrombuf(databuf, len);
689     X = getbnfrombuf(databuf + len, len);
690     OPENSSL_free(databuf);
691     pub_key = EC_POINT_new(group);
692     if (!EC_POINT_set_affine_coordinates_GFp(group, pub_key, X, Y, NULL)) {
693         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
694         EC_POINT_free(pub_key);
695         BN_free(X);
696         BN_free(Y);
697         return 0;
698     }
699     BN_free(X);
700     BN_free(Y);
701     if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
702         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
703         EC_POINT_free(pub_key);
704         return 0;
705     }
706     EC_POINT_free(pub_key);
707     return 1;
708
709 }
710
711 static int pub_encode_gost_ec(X509_PUBKEY *pub, const EVP_PKEY *pk)
712 {
713     ASN1_OBJECT *algobj = NULL;
714     ASN1_OCTET_STRING *octet = NULL;
715     void *pval = NULL;
716     unsigned char *buf = NULL, *databuf = NULL, *sptr;
717     int i, j, data_len, ret = -1;
718     const EC_POINT *pub_key;
719     BIGNUM *X = NULL, *Y = NULL, *order = NULL;
720     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
721     int ptype = V_ASN1_UNDEF;
722
723     algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
724     if (pk->save_parameters) {
725         ASN1_STRING *params = encode_gost_algor_params(pk);
726         pval = params;
727         ptype = V_ASN1_SEQUENCE;
728     }
729     order = BN_new();
730     if (!order) {
731         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
732         goto err;
733     }
734     EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
735     pub_key = EC_KEY_get0_public_key(ec);
736     if (!pub_key) {
737         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, GOST_R_PUBLIC_KEY_UNDEFINED);
738         goto err;
739     }
740     X = BN_new();
741     Y = BN_new();
742     if (!X || !Y) {
743         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
744         goto err;
745     }
746     if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
747                                              pub_key, X, Y, NULL)) {
748         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_INTERNAL_ERROR);
749         goto err;
750     }
751     data_len = 2 * BN_num_bytes(order);
752     databuf = OPENSSL_malloc(data_len);
753     if (databuf == NULL) {
754         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
755         goto err;
756     }
757     memset(databuf, 0, data_len);
758
759     store_bignum(X, databuf + data_len / 2, data_len / 2);
760     store_bignum(Y, databuf, data_len / 2);
761
762     octet = ASN1_OCTET_STRING_new();
763     if (octet == NULL) {
764         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
765         goto err;
766     }
767     ASN1_STRING_set(octet, NULL, data_len);
768     sptr = ASN1_STRING_data(octet);
769     for (i = 0, j = data_len - 1; i < data_len; i++, j--) {
770         sptr[i] = databuf[j];
771     }
772
773     ret = i2d_ASN1_OCTET_STRING(octet, &buf);
774     ASN1_BIT_STRING_free(octet);
775 err:
776     if (X)
777         BN_free(X);
778     if (Y)
779         BN_free(Y);
780     if (order)
781         BN_free(order);
782     if (databuf)
783         OPENSSL_free(databuf);
784
785     if (ret < 0)
786         return 0;
787     return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
788 }
789
790 static int pub_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
791 {
792     const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
793     const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
794     const EC_POINT *ka, *kb;
795     if (!ea || !eb)
796         return 0;
797     ka = EC_KEY_get0_public_key(ea);
798     kb = EC_KEY_get0_public_key(eb);
799     if (!ka || !kb)
800         return 0;
801     return (0 == EC_POINT_cmp(EC_KEY_get0_group(ea), ka, kb, NULL));
802 }
803
804 static int pkey_size_gost(const EVP_PKEY *pk)
805 {
806     if (!pk)
807         return -1;
808
809     switch (EVP_PKEY_base_id(pk)) {
810     case NID_id_GostR3410_94:
811     case NID_id_GostR3410_2001:
812     case NID_id_GostR3410_2012_256:
813         return 64;
814     case NID_id_GostR3410_2012_512:
815         return 128;
816     }
817
818     return -1;
819 }
820
821 /* ---------------------- ASN1 METHOD for GOST MAC  -------------------*/
822 static void mackey_free_gost(EVP_PKEY *pk)
823 {
824     OPENSSL_free(pk->pkey.ptr);
825 }
826
827 static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
828 {
829     switch (op) {
830     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
831         if (arg2) {
832             *(int *)arg2 = NID_id_Gost28147_89_MAC;
833             return 2;
834         }
835     }
836     return -2;
837 }
838
839 static int mac_ctrl_gost_12(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_gost_mac_12;
845             return 2;
846         }
847     }
848     return -2;
849 }
850
851 static int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
852 {
853     int nid =
854         EC_GROUP_get_curve_name(EC_KEY_get0_group
855                                 (EVP_PKEY_get0((EVP_PKEY *)pkey)));
856     return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
857 }
858
859 static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
860                                  int derlen)
861 {
862     ASN1_OBJECT *obj = NULL;
863     int nid;
864     if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
865         return 0;
866     }
867     nid = OBJ_obj2nid(obj);
868     ASN1_OBJECT_free(obj);
869
870     return gost_decode_nid_params(pkey, NID_id_GostR3410_2001, nid);
871 }
872
873 /* ----------------------------------------------------------------------*/
874 int register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
875                         const char *pemstr, const char *info)
876 {
877     *ameth = EVP_PKEY_asn1_new(nid, ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
878     if (!*ameth)
879         return 0;
880     switch (nid) {
881     case NID_id_GostR3410_2001:
882         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
883         EVP_PKEY_asn1_set_private(*ameth,
884                                   priv_decode_gost, priv_encode_gost,
885                                   priv_print_gost_ec);
886
887         EVP_PKEY_asn1_set_param(*ameth,
888                                 gost2001_param_decode, gost2001_param_encode,
889                                 param_missing_gost_ec, param_copy_gost_ec,
890                                 param_cmp_gost_ec, param_print_gost_ec);
891         EVP_PKEY_asn1_set_public(*ameth,
892                                  pub_decode_gost_ec, pub_encode_gost_ec,
893                                  pub_cmp_gost_ec, pub_print_gost_ec,
894                                  pkey_size_gost, pkey_bits_gost);
895
896         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
897         break;
898     case NID_id_GostR3410_2012_256:
899     case NID_id_GostR3410_2012_512:
900         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
901         EVP_PKEY_asn1_set_private(*ameth,
902                                   priv_decode_gost, priv_encode_gost,
903                                   priv_print_gost_ec);
904
905         EVP_PKEY_asn1_set_param(*ameth,
906                                 NULL, NULL,
907                                 param_missing_gost_ec, param_copy_gost_ec,
908                                 param_cmp_gost_ec, NULL);
909
910         EVP_PKEY_asn1_set_public(*ameth,
911                                  pub_decode_gost_ec, pub_encode_gost_ec,
912                                  pub_cmp_gost_ec, pub_print_gost_ec,
913                                  pkey_size_gost, pkey_bits_gost);
914
915         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
916         break;
917     case NID_id_Gost28147_89_MAC:
918         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
919         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost);
920         break;
921     case NID_gost_mac_12:
922         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
923         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost_12);
924         break;
925     }
926     return 1;
927 }