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