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