]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_ameth.c
Adoption to TK26 recommendations
[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 /*
460     octet = ASN1_STRING_new();
461     ASN1_OCTET_STRING_set(octet, buf, key_len);
462
463     priv_len = i2d_ASN1_OCTET_STRING(octet, &priv_buf);
464     ASN1_STRING_free(octet);
465     OPENSSL_free(buf);
466
467     return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
468                            priv_buf, priv_len); */
469     return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
470                            buf, key_len); 
471 }
472
473 /* --------- printing keys --------------------------------*/
474 static int print_gost_priv(BIO *out, const EVP_PKEY *pkey, int indent)
475 {
476     BIGNUM *key;
477
478     if (!BIO_indent(out, indent, 128))
479         return 0;
480     BIO_printf(out, "Private key: ");
481     key = gost_get0_priv_key(pkey);
482     if (!key)
483         BIO_printf(out, "<undefined>");
484     else
485         BN_print(out, key);
486     BIO_printf(out, "\n");
487
488     return 1;
489 }
490
491 static int print_gost_ec_pub(BIO *out, const EVP_PKEY *pkey, int indent)
492 {
493     BN_CTX *ctx;
494     BIGNUM *X, *Y;
495     const EC_POINT *pubkey;
496     const EC_GROUP *group;
497     EC_KEY *key = (EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey);
498     int ok = 0;
499
500     ctx = BN_CTX_new();
501     if (!ctx) {
502         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_MALLOC_FAILURE);
503         return 0;
504     }
505
506     BN_CTX_start(ctx);
507     X = BN_CTX_get(ctx);
508     Y = BN_CTX_get(ctx);
509     pubkey = (key) ? EC_KEY_get0_public_key(key) : NULL;
510     group = (key) ? EC_KEY_get0_group(key) : NULL;
511     if (!pubkey || !group)
512         goto err;
513
514     if (!EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx)) {
515         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_EC_LIB);
516         goto err;
517     }
518     if (!BIO_indent(out, indent, 128))
519         goto err;
520     BIO_printf(out, "Public key:\n");
521     if (!BIO_indent(out, indent + 3, 128))
522         goto err;
523     BIO_printf(out, "X:");
524     BN_print(out, X);
525     BIO_printf(out, "\n");
526     if (!BIO_indent(out, indent + 3, 128))
527         goto err;
528     BIO_printf(out, "Y:");
529     BN_print(out, Y);
530     BIO_printf(out, "\n");
531     ok = 1;
532  err:
533     BN_CTX_end(ctx);
534     BN_CTX_free(ctx);
535
536     return ok;
537 }
538
539 static int print_gost_ec_param(BIO *out, const EVP_PKEY *pkey, int indent)
540 {
541     EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
542     const EC_GROUP *group = (ec) ? EC_KEY_get0_group(ec) : NULL;
543     int param_nid;
544
545     if (!group)
546         return 0;
547
548     param_nid = EC_GROUP_get_curve_name(group);
549     if (!BIO_indent(out, indent, 128))
550         return 0;
551     BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
552
553     return 1;
554 }
555
556 static int print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
557                          ASN1_PCTX *pctx, int type)
558 {
559     if (type == 2) {
560         if (print_gost_priv(out, pkey, indent) == 0)
561             return 0;
562     }
563     if (type >= 1) {
564         if (print_gost_ec_pub(out, pkey, indent) == 0)
565             return 0;
566     }
567
568     return print_gost_ec_param(out, pkey, indent);
569 }
570
571 static int param_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
572                                ASN1_PCTX *pctx)
573 {
574     return print_gost_ec(out, pkey, indent, pctx, 0);
575 }
576
577 static int pub_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
578                              ASN1_PCTX *pctx)
579 {
580     return print_gost_ec(out, pkey, indent, pctx, 1);
581 }
582
583 static int priv_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, 2);
587 }
588
589 /* ---------------------------------------------------------------------*/
590 static int param_missing_gost_ec(const EVP_PKEY *pk)
591 {
592     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
593     if (!ec)
594         return 1;
595     if (!EC_KEY_get0_group(ec))
596         return 1;
597     return 0;
598 }
599
600 static int param_copy_gost_ec(EVP_PKEY *to, const EVP_PKEY *from)
601 {
602     EC_KEY *eto = EVP_PKEY_get0(to);
603     const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
604     if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
605         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_INCOMPATIBLE_ALGORITHMS);
606         return 0;
607     }
608     if (!efrom) {
609         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_KEY_PARAMETERS_MISSING);
610         return 0;
611     }
612     if (!eto) {
613         eto = EC_KEY_new();
614         if (!eto) {
615             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_MALLOC_FAILURE);
616             return 0;
617         }
618         if (!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
619             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
620             EC_KEY_free(eto);
621             return 0;
622         }
623     }
624     if (!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
625         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
626         return 0;
627     }
628     if (EC_KEY_get0_private_key(eto)) {
629         return gost_ec_compute_public(eto);
630     }
631     return 1;
632 }
633
634 static int param_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
635 {
636     const EC_GROUP *group_a, *group_b;
637     EC_KEY *ec_a = EVP_PKEY_get0((EVP_PKEY *)a);
638     EC_KEY *ec_b = EVP_PKEY_get0((EVP_PKEY *)b);
639     if (!ec_a || !ec_b)
640         return 0;
641
642     group_a = EC_KEY_get0_group(ec_a);
643     group_b = EC_KEY_get0_group(ec_b);
644     if (!group_a || !group_b)
645         return 0;
646
647     if (EC_GROUP_get_curve_name(group_a) == EC_GROUP_get_curve_name(group_b)) {
648         return 1;
649     }
650     return 0;
651 }
652
653 /* ---------- Public key functions * --------------------------------------*/
654 static int pub_decode_gost_ec(EVP_PKEY *pk, X509_PUBKEY *pub)
655 {
656     X509_ALGOR *palg = NULL;
657     const unsigned char *pubkey_buf = NULL;
658     unsigned char *databuf;
659     ASN1_OBJECT *palgobj = NULL;
660     int pub_len, i, j;
661     EC_POINT *pub_key;
662     BIGNUM *X, *Y;
663     ASN1_OCTET_STRING *octet = NULL;
664     int len;
665     const EC_GROUP *group;
666
667     if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
668         return 0;
669     EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
670     if (!decode_gost_algor_params(pk, palg))
671         return 0;
672     group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
673     octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
674     if (!octet) {
675         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
676         return 0;
677     }
678     databuf = OPENSSL_malloc(octet->length);
679     if (databuf == NULL) {
680         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
681         ASN1_OCTET_STRING_free(octet);
682         return 0;
683     }
684     for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
685         databuf[j] = octet->data[i];
686     }
687     len = octet->length / 2;
688     ASN1_OCTET_STRING_free(octet);
689
690     Y = getbnfrombuf(databuf, len);
691     X = getbnfrombuf(databuf + len, len);
692     OPENSSL_free(databuf);
693     pub_key = EC_POINT_new(group);
694     if (!EC_POINT_set_affine_coordinates_GFp(group, pub_key, X, Y, NULL)) {
695         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
696         EC_POINT_free(pub_key);
697         BN_free(X);
698         BN_free(Y);
699         return 0;
700     }
701     BN_free(X);
702     BN_free(Y);
703     if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
704         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
705         EC_POINT_free(pub_key);
706         return 0;
707     }
708     EC_POINT_free(pub_key);
709     return 1;
710
711 }
712
713 static int pub_encode_gost_ec(X509_PUBKEY *pub, const EVP_PKEY *pk)
714 {
715     ASN1_OBJECT *algobj = NULL;
716     ASN1_OCTET_STRING *octet = NULL;
717     void *pval = NULL;
718     unsigned char *buf = NULL, *databuf = NULL, *sptr;
719     int i, j, data_len, ret = -1;
720     const EC_POINT *pub_key;
721     BIGNUM *X = NULL, *Y = NULL, *order = NULL;
722     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
723     int ptype = V_ASN1_UNDEF;
724
725     algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
726     if (pk->save_parameters) {
727         ASN1_STRING *params = encode_gost_algor_params(pk);
728         pval = params;
729         ptype = V_ASN1_SEQUENCE;
730     }
731     order = BN_new();
732     if (!order) {
733         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
734         goto err;
735     }
736     EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
737     pub_key = EC_KEY_get0_public_key(ec);
738     if (!pub_key) {
739         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, GOST_R_PUBLIC_KEY_UNDEFINED);
740         goto err;
741     }
742     X = BN_new();
743     Y = BN_new();
744     if (!X || !Y) {
745         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
746         goto err;
747     }
748     if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
749                                              pub_key, X, Y, NULL)) {
750         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_INTERNAL_ERROR);
751         goto err;
752     }
753     data_len = 2 * BN_num_bytes(order);
754     databuf = OPENSSL_malloc(data_len);
755     if (databuf == NULL) {
756         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
757         goto err;
758     }
759     memset(databuf, 0, data_len);
760
761     store_bignum(X, databuf + data_len / 2, data_len / 2);
762     store_bignum(Y, databuf, data_len / 2);
763
764     octet = ASN1_OCTET_STRING_new();
765     if (octet == NULL) {
766         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
767         goto err;
768     }
769     ASN1_STRING_set(octet, NULL, data_len);
770     sptr = ASN1_STRING_data(octet);
771     for (i = 0, j = data_len - 1; i < data_len; i++, j--) {
772         sptr[i] = databuf[j];
773     }
774
775     ret = i2d_ASN1_OCTET_STRING(octet, &buf);
776     ASN1_BIT_STRING_free(octet);
777  err:
778     if (X)
779         BN_free(X);
780     if (Y)
781         BN_free(Y);
782     if (order)
783         BN_free(order);
784     if (databuf)
785         OPENSSL_free(databuf);
786
787     if (ret < 0)
788         return 0;
789     return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
790 }
791
792 static int pub_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
793 {
794     const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
795     const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
796     const EC_POINT *ka, *kb;
797     if (!ea || !eb)
798         return 0;
799     ka = EC_KEY_get0_public_key(ea);
800     kb = EC_KEY_get0_public_key(eb);
801     if (!ka || !kb)
802         return 0;
803     return (0 == EC_POINT_cmp(EC_KEY_get0_group(ea), ka, kb, NULL));
804 }
805
806 static int pkey_size_gost(const EVP_PKEY *pk)
807 {
808     if (!pk)
809         return -1;
810
811     switch (EVP_PKEY_base_id(pk)) {
812     case NID_id_GostR3410_94:
813     case NID_id_GostR3410_2001:
814     case NID_id_GostR3410_2012_256:
815         return 64;
816     case NID_id_GostR3410_2012_512:
817         return 128;
818     }
819
820     return -1;
821 }
822
823 /* ---------------------- ASN1 METHOD for GOST MAC  -------------------*/
824 static void mackey_free_gost(EVP_PKEY *pk)
825 {
826     OPENSSL_free(pk->pkey.ptr);
827 }
828
829 static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
830 {
831     switch (op) {
832     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
833         if (arg2) {
834             *(int *)arg2 = NID_id_Gost28147_89_MAC;
835             return 2;
836         }
837     }
838     return -2;
839 }
840
841 static int mac_ctrl_gost_12(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_gost_mac_12;
847             return 2;
848         }
849     }
850     return -2;
851 }
852
853 static int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
854 {
855     int nid =
856         EC_GROUP_get_curve_name(EC_KEY_get0_group
857                                 (EVP_PKEY_get0((EVP_PKEY *)pkey)));
858     return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
859 }
860
861 static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
862                                  int derlen)
863 {
864     ASN1_OBJECT *obj = NULL;
865     int nid;
866     if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
867         return 0;
868     }
869     nid = OBJ_obj2nid(obj);
870     ASN1_OBJECT_free(obj);
871
872     return gost_decode_nid_params(pkey, NID_id_GostR3410_2001, nid);
873 }
874
875 /* ----------------------------------------------------------------------*/
876 int register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
877                         const char *pemstr, const char *info)
878 {
879     *ameth = EVP_PKEY_asn1_new(nid, ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
880     if (!*ameth)
881         return 0;
882     switch (nid) {
883     case NID_id_GostR3410_2001:
884         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
885         EVP_PKEY_asn1_set_private(*ameth,
886                                   priv_decode_gost, priv_encode_gost,
887                                   priv_print_gost_ec);
888
889         EVP_PKEY_asn1_set_param(*ameth,
890                                 gost2001_param_decode, gost2001_param_encode,
891                                 param_missing_gost_ec, param_copy_gost_ec,
892                                 param_cmp_gost_ec, param_print_gost_ec);
893         EVP_PKEY_asn1_set_public(*ameth,
894                                  pub_decode_gost_ec, pub_encode_gost_ec,
895                                  pub_cmp_gost_ec, pub_print_gost_ec,
896                                  pkey_size_gost, pkey_bits_gost);
897
898         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
899         break;
900     case NID_id_GostR3410_2012_256:
901     case NID_id_GostR3410_2012_512:
902         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
903         EVP_PKEY_asn1_set_private(*ameth,
904                                   priv_decode_gost, priv_encode_gost,
905                                   priv_print_gost_ec);
906
907         EVP_PKEY_asn1_set_param(*ameth,
908                                 NULL, NULL,
909                                 param_missing_gost_ec, param_copy_gost_ec,
910                                 param_cmp_gost_ec, NULL);
911
912         EVP_PKEY_asn1_set_public(*ameth,
913                                  pub_decode_gost_ec, pub_encode_gost_ec,
914                                  pub_cmp_gost_ec, pub_print_gost_ec,
915                                  pkey_size_gost, pkey_bits_gost);
916
917         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
918 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
919         EVP_PKEY_asn1_set_security_bits(*ameth, pkey_bits_gost);
920 #endif
921         break;
922     case NID_id_Gost28147_89_MAC:
923         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
924         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost);
925         break;
926     case NID_gost_mac_12:
927         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
928         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost_12);
929         break;
930     }
931     return 1;
932 }