]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_ameth.c
Initial commit providing GOST 2012 algorithms.
[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_params.h"
20 #include "gost_lcl.h"
21 #include "e_gost_err.h"
22
23 static int pkey_bits_gost(const EVP_PKEY *pk);
24
25 int gost94_nid_by_params(DSA *p)
26 {
27     R3410_params *gost_params;
28     BIGNUM *q = BN_new();
29     for (gost_params = R3410_paramset; gost_params->nid != NID_undef;
30          gost_params++) {
31         BN_dec2bn(&q, gost_params->q);
32         if (!BN_cmp(q, p->q))
33             break;
34     }
35     BN_free(q);
36     return gost_params->nid;
37 }
38
39 static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
40 {
41     ASN1_STRING *params = ASN1_STRING_new();
42     GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
43     int pkey_param_nid = NID_undef;
44     void *key_ptr = EVP_PKEY_get0((EVP_PKEY *)key);
45     int result = 0;
46
47     if (!params || !gkp) {
48         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
49         goto err;
50     }
51     switch (EVP_PKEY_base_id(key)) {
52     case NID_id_GostR3410_2012_256:
53         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
54         gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_2012_256);
55         break;
56     case NID_id_GostR3410_2012_512:
57         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
58         gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_2012_512);
59         break;
60     case NID_id_GostR3410_2001:
61         pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(key_ptr));
62         gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
63         break;
64     case NID_id_GostR3410_94:
65         pkey_param_nid = (int)gost94_nid_by_params(key_ptr);
66         gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
67         break;
68     }
69
70     if (pkey_param_nid == NID_undef) {
71         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, GOST_R_INVALID_PARAMSET);
72         goto err;
73     }
74
75     gkp->key_params = OBJ_nid2obj(pkey_param_nid);
76     /*
77      * gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);
78      */
79     params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
80     if (params->length <= 0) {
81         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
82         goto err;
83     }
84     params->type = V_ASN1_SEQUENCE;
85     result = 1;
86  err:
87     if (gkp)
88         GOST_KEY_PARAMS_free(gkp);
89     if (result == 0) {          /* if error */
90         if (params)
91             ASN1_STRING_free(params);
92         return NULL;
93     }
94     return params;
95 }
96
97 static int gost_decode_nid_params(EVP_PKEY *pkey, int pkey_nid, int param_nid)
98 {
99     void *key_ptr = EVP_PKEY_get0(pkey);
100
101     switch (pkey_nid) {
102     case NID_id_GostR3410_2012_256:
103     case NID_id_GostR3410_2012_512:
104     case NID_id_GostR3410_2001:
105         if (!key_ptr) {
106             key_ptr = EC_KEY_new();
107             if (!EVP_PKEY_assign(pkey, pkey_nid, key_ptr)) {
108                 EC_KEY_free(key_ptr);
109                 break;
110             }
111         }
112         return fill_GOST_EC_params(key_ptr, param_nid);
113
114     case NID_id_GostR3410_94:
115         if (!key_ptr) {
116             key_ptr = DSA_new();
117             if (!EVP_PKEY_assign(pkey, pkey_nid, key_ptr)) {
118                 DSA_free(key_ptr);
119                 break;
120             }
121         }
122         return fill_GOST94_params(key_ptr, param_nid);
123     }
124
125     return 0;
126 }
127
128 /*
129  * Parses GOST algorithm parameters from X509_ALGOR and modifies pkey setting
130  * NID and parameters
131  */
132 static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
133 {
134     ASN1_OBJECT *palg_obj = NULL;
135     int ptype = V_ASN1_UNDEF;
136     int pkey_nid = NID_undef, param_nid = NID_undef;
137     ASN1_STRING *pval = NULL;
138     const unsigned char *p;
139     GOST_KEY_PARAMS *gkp = NULL;
140
141     if (!pkey || !palg)
142         return 0;
143     X509_ALGOR_get0(&palg_obj, &ptype, (void **)&pval, palg);
144     if (ptype != V_ASN1_SEQUENCE) {
145         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
146                 GOST_R_BAD_KEY_PARAMETERS_FORMAT);
147         return 0;
148     }
149     p = pval->data;
150     pkey_nid = OBJ_obj2nid(palg_obj);
151
152     gkp = d2i_GOST_KEY_PARAMS(NULL, &p, pval->length);
153     if (!gkp) {
154         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
155                 GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
156         return 0;
157     }
158     param_nid = OBJ_obj2nid(gkp->key_params);
159     GOST_KEY_PARAMS_free(gkp);
160     if (!EVP_PKEY_set_type(pkey, pkey_nid)) {
161         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR);
162         return 0;
163     }
164
165     return gost_decode_nid_params(pkey, pkey_nid, param_nid);
166 }
167
168 static int gost_set_priv_key(EVP_PKEY *pkey, BIGNUM *priv)
169 {
170     switch (EVP_PKEY_base_id(pkey)) {
171     case NID_id_GostR3410_94:
172         {
173             DSA *dsa = EVP_PKEY_get0(pkey);
174             if (!dsa) {
175                 dsa = DSA_new();
176                 EVP_PKEY_assign(pkey, EVP_PKEY_base_id(pkey), dsa);
177             }
178             dsa->priv_key = BN_dup(priv);
179             if (!EVP_PKEY_missing_parameters(pkey))
180                 gost94_compute_public(dsa);
181             break;
182         }
183     case NID_id_GostR3410_2012_512:
184     case NID_id_GostR3410_2012_256:
185     case NID_id_GostR3410_2001:
186         {
187             EC_KEY *ec = EVP_PKEY_get0(pkey);
188             if (!ec) {
189                 ec = EC_KEY_new();
190                 EVP_PKEY_assign(pkey, EVP_PKEY_base_id(pkey), ec);
191             }
192             if (!EC_KEY_set_private_key(ec, priv))
193                 return 0;
194             if (!EVP_PKEY_missing_parameters(pkey))
195                 gost_ec_compute_public(ec);
196             break;
197         }
198     default:
199         return 0;
200     }
201     return 1;
202 }
203
204 BIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey)
205 {
206     switch (EVP_PKEY_base_id(pkey)) {
207     case NID_id_GostR3410_94:
208         {
209             DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
210             if (dsa)
211                 return dsa->priv_key;
212             break;
213         }
214     case NID_id_GostR3410_2012_512:
215     case NID_id_GostR3410_2012_256:
216     case NID_id_GostR3410_2001:
217         {
218             EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
219             if (ec)
220                 return (BIGNUM *)EC_KEY_get0_private_key(ec);
221             break;
222         }
223     }
224     return NULL;
225 }
226
227 /*
228  * Control function
229  */
230 static int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
231 {
232     int nid = EVP_PKEY_base_id(pkey), md_nid = NID_undef;
233     X509_ALGOR *alg1 = NULL, *alg2 = NULL;
234
235     switch (nid) {
236     case NID_id_GostR3410_2012_512:
237         md_nid = NID_id_GostR3411_2012_512;
238         break;
239     case NID_id_GostR3410_2012_256:
240         md_nid = NID_id_GostR3411_2012_256;
241         break;
242     case NID_id_GostR3410_2001:
243     case NID_id_GostR3410_94:
244         md_nid = NID_id_GostR3411_94;
245         break;
246     default:
247         return -1;
248     }
249
250     switch (op) {
251     case ASN1_PKEY_CTRL_PKCS7_SIGN:
252         if (arg1 == 0) {
253             PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO *)arg2, NULL,
254                                         &alg1, &alg2);
255             X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid), V_ASN1_NULL, 0);
256             X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
257         }
258         return 1;
259 #ifndef OPENSSL_NO_CMS
260     case ASN1_PKEY_CTRL_CMS_SIGN:
261         if (arg1 == 0) {
262             CMS_SignerInfo_get0_algs((CMS_SignerInfo *)arg2, NULL, NULL,
263                                      &alg1, &alg2);
264             X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid), V_ASN1_NULL, 0);
265             X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
266         }
267         return 1;
268 #endif
269     case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
270         if (arg1 == 0) {
271             ASN1_STRING *params = encode_gost_algor_params(pkey);
272             if (!params) {
273                 return -1;
274             }
275             PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO *)arg2, &alg1);
276             X509_ALGOR_set0(alg1, OBJ_nid2obj(pkey->type),
277                             V_ASN1_SEQUENCE, params);
278         }
279         return 1;
280 #ifndef OPENSSL_NO_CMS
281     case ASN1_PKEY_CTRL_CMS_ENVELOPE:
282         if (arg1 == 0) {
283             ASN1_STRING *params = encode_gost_algor_params(pkey);
284             if (!params) {
285                 return -1;
286             }
287             CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL,
288                                              NULL, &alg1);
289             X509_ALGOR_set0(alg1, OBJ_nid2obj(pkey->type), V_ASN1_SEQUENCE,
290                             params);
291         }
292         return 1;
293 #endif
294     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
295         *(int *)arg2 = md_nid;
296         return 2;
297     }
298
299     return -2;
300 }
301
302 /* --------------------- free functions * ------------------------------*/
303 static void pkey_free_gost94(EVP_PKEY *key)
304 {
305     if (key->pkey.dsa) {
306         DSA_free(key->pkey.dsa);
307     }
308 }
309
310 static void pkey_free_gost_ec(EVP_PKEY *key)
311 {
312     if (key->pkey.ec) {
313         EC_KEY_free(key->pkey.ec);
314     }
315 }
316
317 /* ------------------ private key functions  -----------------------------*/
318
319 static BIGNUM *unmask_priv_key(EVP_PKEY *pk,
320                                const unsigned char *buf, int len,
321                                int num_masks)
322 {
323     BIGNUM *pknum_masked = NULL, *q = NULL;
324     const EC_KEY *key_ptr = (pk) ? EVP_PKEY_get0(pk) : NULL;
325     const EC_GROUP *group = (key_ptr) ? EC_KEY_get0_group(key_ptr) : NULL;
326
327     pknum_masked = hashsum2bn(buf, len);
328     if (!pknum_masked)
329         return NULL;
330
331     if (num_masks > 0) {
332         /*
333          * XXX Remove sign by gost94
334          */
335         const unsigned char *p = buf + num_masks * len;
336
337         q = BN_new();
338         if (!q || !group || EC_GROUP_get_order(group, q, NULL) <= 0) {
339             BN_free(pknum_masked);
340             pknum_masked = NULL;
341             goto end;
342         }
343
344         for (; p != buf; p -= len) {
345             BIGNUM *mask = hashsum2bn(p, len);
346             BN_CTX *ctx = BN_CTX_new();
347
348             BN_mod_mul(pknum_masked, pknum_masked, mask, q, ctx);
349
350             BN_CTX_free(ctx);
351             BN_free(mask);
352         }
353     }
354
355  end:
356     if (q)
357         BN_free(q);
358     return pknum_masked;
359 }
360
361 static int priv_decode_gost(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf)
362 {
363     const unsigned char *pkey_buf = NULL, *p = NULL;
364     int priv_len = 0;
365     BIGNUM *pk_num = NULL;
366     int ret = 0;
367     X509_ALGOR *palg = NULL;
368     ASN1_OBJECT *palg_obj = NULL;
369     ASN1_INTEGER *priv_key = NULL;
370     int expected_key_len = 32;
371
372     if (!PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf))
373         return 0;
374     p = pkey_buf;
375     if (!decode_gost_algor_params(pk, palg)) {
376         return 0;
377     }
378
379     expected_key_len = pkey_bits_gost(pk) > 0 ? pkey_bits_gost(pk) / 8 : 0;
380     if (expected_key_len == 0) {
381         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
382         return 0;
383     }
384
385     if (priv_len % expected_key_len == 0) {
386         /* Key is not wrapped but masked */
387         pk_num = unmask_priv_key(pk, pkey_buf, expected_key_len,
388                                  priv_len / expected_key_len - 1);
389     } else if (V_ASN1_OCTET_STRING == *p) {
390         /* New format - Little endian octet string */
391         ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
392         if (!s || ((s->length != 32) && (s->length != 64))) {
393             ASN1_STRING_free(s);
394             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
395             return 0;
396         }
397         pk_num = hashsum2bn(s->data, s->length);
398         ASN1_STRING_free(s);
399     } else if (V_ASN1_INTEGER == *p) {
400         priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
401         if (!priv_key) {
402             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
403             return 0;
404         }
405         pk_num = ASN1_INTEGER_to_BN(priv_key, NULL);
406         ASN1_INTEGER_free(priv_key);
407     } else if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == *p) {
408         MASKED_GOST_KEY *mgk = NULL;
409         mgk = d2i_MASKED_GOST_KEY(NULL, &p, priv_len);
410
411         if (!mgk) {
412             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
413             return 0;
414         }
415
416         priv_len = mgk->masked_priv_key->length;
417         if (priv_len % expected_key_len) {
418             MASKED_GOST_KEY_free(mgk);
419             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
420             return 0;
421         }
422
423         pk_num = unmask_priv_key(pk, mgk->masked_priv_key->data,
424                                  expected_key_len,
425                                  priv_len / expected_key_len - 1);
426         MASKED_GOST_KEY_free(mgk);
427     } else {
428         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
429         return 0;
430     }
431
432     if (pk_num == NULL) {
433         GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
434         return 0;
435     }
436
437     ret = gost_set_priv_key(pk, pk_num);
438     BN_free(pk_num);
439     return ret;
440 }
441
442 /* ----------------------------------------------------------------------*/
443 static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
444 {
445     ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
446     ASN1_STRING *params = encode_gost_algor_params(pk);
447     unsigned char *priv_buf = NULL, *buf = NULL;
448     int key_len = pkey_bits_gost(pk), priv_len = 0, i = 0;
449
450     ASN1_STRING *octet = NULL;
451     if (!params) {
452         return 0;
453     }
454
455     key_len = (key_len < 0) ? 0 : key_len / 8;
456     if (key_len == 0 || !(buf = OPENSSL_malloc(key_len))) {
457         return 0;
458     }
459
460     if (!store_bignum(gost_get0_priv_key(pk), buf, key_len)) {
461         OPENSSL_free(buf);
462         return 0;
463     }
464
465     /* Convert buf to Little-endian */
466     for (i = 0; i < key_len / 2; i++) {
467         unsigned char tmp = buf[i];
468         buf[i] = buf[key_len - 1 - i];
469         buf[key_len - 1 - i] = tmp;
470     }
471
472     octet = ASN1_STRING_new();
473     M_ASN1_OCTET_STRING_set(octet, buf, key_len);
474
475     priv_len = i2d_ASN1_OCTET_STRING(octet, &priv_buf);
476     ASN1_STRING_free(octet);
477     OPENSSL_free(buf);
478
479     return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
480                            priv_buf, priv_len);
481 }
482
483 /* --------- printing keys --------------------------------*/
484 static int print_gost_priv(BIO *out, const EVP_PKEY *pkey, int indent)
485 {
486     BIGNUM *key;
487
488     if (!BIO_indent(out, indent, 128))
489         return 0;
490     BIO_printf(out, "Private key: ");
491     key = gost_get0_priv_key(pkey);
492     if (!key)
493         BIO_printf(out, "<undefined>");
494     else
495         BN_print(out, key);
496     BIO_printf(out, "\n");
497
498     return 1;
499 }
500
501 static int print_gost_ec_pub(BIO *out, const EVP_PKEY *pkey, int indent)
502 {
503     BN_CTX *ctx;
504     BIGNUM *X, *Y;
505     const EC_POINT *pubkey;
506     const EC_GROUP *group;
507     EC_KEY *key = (EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey);
508     int ok = 0;
509
510     ctx = BN_CTX_new();
511     if (!ctx) {
512         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_MALLOC_FAILURE);
513         return 0;
514     }
515
516     BN_CTX_start(ctx);
517     X = BN_CTX_get(ctx);
518     Y = BN_CTX_get(ctx);
519     pubkey = (key) ? EC_KEY_get0_public_key(key) : NULL;
520     group = (key) ? EC_KEY_get0_group(key) : NULL;
521     if (!pubkey || !group)
522         goto err;
523
524     if (!EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx)) {
525         GOSTerr(GOST_F_PRINT_GOST_EC_PUB, ERR_R_EC_LIB);
526         goto err;
527     }
528     if (!BIO_indent(out, indent, 128))
529         goto err;
530     BIO_printf(out, "Public key:\n");
531     if (!BIO_indent(out, indent + 3, 128))
532         goto err;
533     BIO_printf(out, "X:");
534     BN_print(out, X);
535     BIO_printf(out, "\n");
536     if (!BIO_indent(out, indent + 3, 128))
537         goto err;
538     BIO_printf(out, "Y:");
539     BN_print(out, Y);
540     BIO_printf(out, "\n");
541     ok = 1;
542  err:
543     BN_CTX_end(ctx);
544     BN_CTX_free(ctx);
545
546     return ok;
547 }
548
549 static int print_gost_ec_param(BIO *out, const EVP_PKEY *pkey, int indent)
550 {
551     EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
552     const EC_GROUP *group = (ec) ? EC_KEY_get0_group(ec) : NULL;
553     int param_nid;
554
555     if (!group)
556         return 0;
557
558     param_nid = EC_GROUP_get_curve_name(group);
559     if (!BIO_indent(out, indent, 128))
560         return 0;
561     BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
562
563     return 1;
564 }
565
566 static int print_gost_94(BIO *out, const EVP_PKEY *pkey, int indent,
567                          ASN1_PCTX *pctx, int type)
568 {
569     int param_nid = NID_undef;
570
571     if (type == 2) {
572         if (print_gost_priv(out, pkey, indent) == 0)
573             return 0;
574     }
575     if (type >= 1) {
576         BIGNUM *pubkey;
577
578         pubkey = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key;
579         BIO_indent(out, indent, 128);
580         BIO_printf(out, "Public key: ");
581         BN_print(out, pubkey);
582         BIO_printf(out, "\n");
583     }
584
585     param_nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
586     BIO_indent(out, indent, 128);
587     BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
588     return 1;
589 }
590
591 static int param_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
592                               ASN1_PCTX *pctx)
593 {
594     return print_gost_94(out, pkey, indent, pctx, 0);
595 }
596
597 static int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
598                             ASN1_PCTX *pctx)
599 {
600     return print_gost_94(out, pkey, indent, pctx, 1);
601 }
602
603 static int priv_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
604                              ASN1_PCTX *pctx)
605 {
606     return print_gost_94(out, pkey, indent, pctx, 2);
607 }
608
609 static int print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
610                          ASN1_PCTX *pctx, int type)
611 {
612     if (type == 2) {
613         if (print_gost_priv(out, pkey, indent) == 0)
614             return 0;
615     }
616     if (type >= 1) {
617         if (print_gost_ec_pub(out, pkey, indent) == 0)
618             return 0;
619     }
620
621     return print_gost_ec_param(out, pkey, indent);
622 }
623
624 static int param_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
625                                ASN1_PCTX *pctx)
626 {
627     return print_gost_ec(out, pkey, indent, pctx, 0);
628 }
629
630 static int pub_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
631                              ASN1_PCTX *pctx)
632 {
633     return print_gost_ec(out, pkey, indent, pctx, 1);
634 }
635
636 static int priv_print_gost_ec(BIO *out, const EVP_PKEY *pkey, int indent,
637                               ASN1_PCTX *pctx)
638 {
639     return print_gost_ec(out, pkey, indent, pctx, 2);
640 }
641
642 /* ---------------------------------------------------------------------*/
643 static int param_missing_gost94(const EVP_PKEY *pk)
644 {
645     const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
646     if (!dsa)
647         return 1;
648     if (!dsa->q)
649         return 1;
650     return 0;
651 }
652
653 static int param_missing_gost_ec(const EVP_PKEY *pk)
654 {
655     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
656     if (!ec)
657         return 1;
658     if (!EC_KEY_get0_group(ec))
659         return 1;
660     return 0;
661 }
662
663 static int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from)
664 {
665     const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from);
666     DSA *dto = EVP_PKEY_get0(to);
667     if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
668         GOSTerr(GOST_F_PARAM_COPY_GOST94, GOST_R_INCOMPATIBLE_ALGORITHMS);
669         return 0;
670     }
671     if (!dfrom) {
672         GOSTerr(GOST_F_PARAM_COPY_GOST94, GOST_R_KEY_PARAMETERS_MISSING);
673         return 0;
674     }
675     if (!dto) {
676         dto = DSA_new();
677         EVP_PKEY_assign(to, EVP_PKEY_base_id(from), dto);
678     }
679 #define COPYBIGNUM(a,b,x) if (a->x) BN_free(a->x); a->x=BN_dup(b->x);
680     COPYBIGNUM(dto, dfrom, p)
681         COPYBIGNUM(dto, dfrom, q)
682         COPYBIGNUM(dto, dfrom, g)
683
684         if (dto->priv_key)
685         gost94_compute_public(dto);
686     return 1;
687 }
688
689 static int param_copy_gost_ec(EVP_PKEY *to, const EVP_PKEY *from)
690 {
691     EC_KEY *eto = EVP_PKEY_get0(to);
692     const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
693     if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
694         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_INCOMPATIBLE_ALGORITHMS);
695         return 0;
696     }
697     if (!efrom) {
698         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, GOST_R_KEY_PARAMETERS_MISSING);
699         return 0;
700     }
701     if (!eto) {
702         eto = EC_KEY_new();
703         if (!eto) {
704             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_MALLOC_FAILURE);
705             return 0;
706         }
707         if (!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
708             GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
709             EC_KEY_free(eto);
710             return 0;
711         }
712     }
713     if (!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
714         GOSTerr(GOST_F_PARAM_COPY_GOST_EC, ERR_R_INTERNAL_ERROR);
715         return 0;
716     }
717     if (EC_KEY_get0_private_key(eto)) {
718         return gost_ec_compute_public(eto);
719     }
720     return 1;
721 }
722
723 static int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
724 {
725     const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
726     const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
727     if (!da || !db)
728         return 0;
729     return (BN_cmp(da->q, db->q) == 0) ? 1 : 0;
730 }
731
732 static int param_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
733 {
734     const EC_GROUP *group_a, *group_b;
735     EC_KEY *ec_a = EVP_PKEY_get0((EVP_PKEY *)a);
736     EC_KEY *ec_b = EVP_PKEY_get0((EVP_PKEY *)b);
737     if (!ec_a || !ec_b)
738         return 0;
739
740     group_a = EC_KEY_get0_group(ec_a);
741     group_b = EC_KEY_get0_group(ec_b);
742     if (!group_a || !group_b)
743         return 0;
744
745     if (EC_GROUP_get_curve_name(group_a) == EC_GROUP_get_curve_name(group_b)) {
746         return 1;
747     }
748     return 0;
749 }
750
751 /* ---------- Public key functions * --------------------------------------*/
752 static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
753 {
754     X509_ALGOR *palg = NULL;
755     const unsigned char *pubkey_buf = NULL;
756     unsigned char *databuf;
757     ASN1_OBJECT *palgobj = NULL;
758     int pub_len, i, j;
759     DSA *dsa;
760     ASN1_OCTET_STRING *octet = NULL;
761
762     if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
763         return 0;
764     EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
765     if (!decode_gost_algor_params(pk, palg))
766         return 0;
767     octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
768     if (!octet) {
769         GOSTerr(GOST_F_PUB_DECODE_GOST94, ERR_R_MALLOC_FAILURE);
770         return 0;
771     }
772     databuf = OPENSSL_malloc(octet->length);
773     if (databuf == NULL) {
774         GOSTerr(GOST_F_PUB_DECODE_GOST94, ERR_R_MALLOC_FAILURE);
775         ASN1_OCTET_STRING_free(octet);
776         return 0;
777     }
778     for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
779         databuf[j] = octet->data[i];
780     }
781     dsa = EVP_PKEY_get0(pk);
782     dsa->pub_key = BN_bin2bn(databuf, octet->length, NULL);
783     ASN1_OCTET_STRING_free(octet);
784     OPENSSL_free(databuf);
785     return 1;
786
787 }
788
789 static int pub_encode_gost94(X509_PUBKEY *pub, const EVP_PKEY *pk)
790 {
791     ASN1_OBJECT *algobj = NULL;
792     ASN1_OCTET_STRING *octet = NULL;
793     void *pval = NULL;
794     unsigned char *buf = NULL, *databuf, *sptr;
795     int i, j, data_len, ret = 0;
796
797     int ptype = V_ASN1_UNDEF;
798     DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
799     algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
800     if (pk->save_parameters) {
801         ASN1_STRING *params = encode_gost_algor_params(pk);
802         pval = params;
803         ptype = V_ASN1_SEQUENCE;
804     }
805     data_len = BN_num_bytes(dsa->pub_key);
806     databuf = OPENSSL_malloc(data_len);
807     if (databuf == NULL) {
808         GOSTerr(GOST_F_PUB_ENCODE_GOST94, ERR_R_MALLOC_FAILURE);
809         return 0;
810     }
811     BN_bn2bin(dsa->pub_key, databuf);
812     octet = ASN1_OCTET_STRING_new();
813     if (octet == NULL) {
814         GOSTerr(GOST_F_PUB_ENCODE_GOST94, ERR_R_MALLOC_FAILURE);
815         OPENSSL_free(databuf);
816         return 0;
817     }
818     ASN1_STRING_set(octet, NULL, data_len);
819     sptr = ASN1_STRING_data(octet);
820     for (i = 0, j = data_len - 1; i < data_len; i++, j--) {
821         sptr[i] = databuf[j];
822     }
823     OPENSSL_free(databuf);
824     ret = i2d_ASN1_OCTET_STRING(octet, &buf);
825     ASN1_BIT_STRING_free(octet);
826     if (ret < 0)
827         return 0;
828     return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
829 }
830
831 static int pub_decode_gost_ec(EVP_PKEY *pk, X509_PUBKEY *pub)
832 {
833     X509_ALGOR *palg = NULL;
834     const unsigned char *pubkey_buf = NULL;
835     unsigned char *databuf;
836     ASN1_OBJECT *palgobj = NULL;
837     int pub_len, i, j;
838     EC_POINT *pub_key;
839     BIGNUM *X, *Y;
840     ASN1_OCTET_STRING *octet = NULL;
841     int len;
842     const EC_GROUP *group;
843
844     if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
845         return 0;
846     EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
847     if (!decode_gost_algor_params(pk, palg))
848         return 0;
849     group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
850     octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
851     if (!octet) {
852         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
853         return 0;
854     }
855     databuf = OPENSSL_malloc(octet->length);
856     if (databuf == NULL) {
857         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_MALLOC_FAILURE);
858         ASN1_OCTET_STRING_free(octet);
859         return 0;
860     }
861     for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
862         databuf[j] = octet->data[i];
863     }
864     len = octet->length / 2;
865     ASN1_OCTET_STRING_free(octet);
866
867     Y = getbnfrombuf(databuf, len);
868     X = getbnfrombuf(databuf + len, len);
869     OPENSSL_free(databuf);
870     pub_key = EC_POINT_new(group);
871     if (!EC_POINT_set_affine_coordinates_GFp(group, pub_key, X, Y, NULL)) {
872         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
873         EC_POINT_free(pub_key);
874         BN_free(X);
875         BN_free(Y);
876         return 0;
877     }
878     BN_free(X);
879     BN_free(Y);
880     if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
881         GOSTerr(GOST_F_PUB_DECODE_GOST_EC, ERR_R_EC_LIB);
882         EC_POINT_free(pub_key);
883         return 0;
884     }
885     EC_POINT_free(pub_key);
886     return 1;
887
888 }
889
890 static int pub_encode_gost_ec(X509_PUBKEY *pub, const EVP_PKEY *pk)
891 {
892     ASN1_OBJECT *algobj = NULL;
893     ASN1_OCTET_STRING *octet = NULL;
894     void *pval = NULL;
895     unsigned char *buf = NULL, *databuf = NULL, *sptr;
896     int i, j, data_len, ret = -1;
897     const EC_POINT *pub_key;
898     BIGNUM *X = NULL, *Y = NULL, *order = NULL;
899     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
900     int ptype = V_ASN1_UNDEF;
901
902     algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
903     if (pk->save_parameters) {
904         ASN1_STRING *params = encode_gost_algor_params(pk);
905         pval = params;
906         ptype = V_ASN1_SEQUENCE;
907     }
908     order = BN_new();
909     if (!order) {
910         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
911         goto err;
912     }
913     EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
914     pub_key = EC_KEY_get0_public_key(ec);
915     if (!pub_key) {
916         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, GOST_R_PUBLIC_KEY_UNDEFINED);
917         goto err;
918     }
919     X = BN_new();
920     Y = BN_new();
921     if (!X || !Y) {
922         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
923         goto err;
924     }
925     if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
926                                              pub_key, X, Y, NULL)) {
927         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_INTERNAL_ERROR);
928         goto err;
929     }
930     data_len = 2 * BN_num_bytes(order);
931     databuf = OPENSSL_malloc(data_len);
932     if (databuf == NULL) {
933         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
934         goto err;
935     }
936     memset(databuf, 0, data_len);
937
938     store_bignum(X, databuf + data_len / 2, data_len / 2);
939     store_bignum(Y, databuf, data_len / 2);
940
941     octet = ASN1_OCTET_STRING_new();
942     if (octet == NULL) {
943         GOSTerr(GOST_F_PUB_ENCODE_GOST_EC, ERR_R_MALLOC_FAILURE);
944         goto err;
945     }
946     ASN1_STRING_set(octet, NULL, data_len);
947     sptr = ASN1_STRING_data(octet);
948     for (i = 0, j = data_len - 1; i < data_len; i++, j--) {
949         sptr[i] = databuf[j];
950     }
951
952     ret = i2d_ASN1_OCTET_STRING(octet, &buf);
953     ASN1_BIT_STRING_free(octet);
954 err:
955     if (X)
956         BN_free(X);
957     if (Y)
958         BN_free(Y);
959     if (order)
960         BN_free(order);
961     if (databuf)
962         OPENSSL_free(databuf);
963
964     if (ret < 0)
965         return 0;
966     return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
967 }
968
969 static int pub_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
970 {
971     const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
972     const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
973     if (!da || !db)
974         return 0;
975
976     if (!da->pub_key || !db->pub_key)
977         return 0;
978
979     return (BN_cmp(da->pub_key, db->pub_key) == 0) ? 1 : 0;
980 }
981
982 static int pub_cmp_gost_ec(const EVP_PKEY *a, const EVP_PKEY *b)
983 {
984     const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
985     const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
986     const EC_POINT *ka, *kb;
987     if (!ea || !eb)
988         return 0;
989     ka = EC_KEY_get0_public_key(ea);
990     kb = EC_KEY_get0_public_key(eb);
991     if (!ka || !kb)
992         return 0;
993     return (0 == EC_POINT_cmp(EC_KEY_get0_group(ea), ka, kb, NULL));
994 }
995
996 static int pkey_size_gost(const EVP_PKEY *pk)
997 {
998     if (!pk)
999         return -1;
1000
1001     switch (EVP_PKEY_base_id(pk)) {
1002     case NID_id_GostR3410_94:
1003     case NID_id_GostR3410_2001:
1004     case NID_id_GostR3410_2012_256:
1005         return 64;
1006     case NID_id_GostR3410_2012_512:
1007         return 128;
1008     }
1009
1010     return -1;
1011 }
1012
1013 static int pkey_bits_gost(const EVP_PKEY *pk)
1014 {
1015     if (!pk)
1016         return -1;
1017
1018     switch (EVP_PKEY_base_id(pk)) {
1019     case NID_id_GostR3410_94:
1020     case NID_id_GostR3410_2001:
1021     case NID_id_GostR3410_2012_256:
1022         return 256;
1023     case NID_id_GostR3410_2012_512:
1024         return 512;
1025     }
1026
1027     return -1;
1028 }
1029
1030 /* ---------------------- ASN1 METHOD for GOST MAC  -------------------*/
1031 static void mackey_free_gost(EVP_PKEY *pk)
1032 {
1033     if (pk->pkey.ptr) {
1034         OPENSSL_free(pk->pkey.ptr);
1035     }
1036 }
1037
1038 static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
1039 {
1040     switch (op) {
1041     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
1042         if (arg2) {
1043             *(int *)arg2 = NID_id_Gost28147_89_MAC;
1044             return 2;
1045         }
1046     }
1047     return -2;
1048 }
1049
1050 static int mac_ctrl_gost_12(EVP_PKEY *pkey, int op, long arg1, void *arg2)
1051 {
1052     switch (op) {
1053     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
1054         if (arg2) {
1055             *(int *)arg2 = NID_gost_mac_12;
1056             return 2;
1057         }
1058     }
1059     return -2;
1060 }
1061
1062 static int gost94_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
1063 {
1064     int nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
1065     return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
1066 }
1067
1068 static int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
1069 {
1070     int nid =
1071         EC_GROUP_get_curve_name(EC_KEY_get0_group
1072                                 (EVP_PKEY_get0((EVP_PKEY *)pkey)));
1073     return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
1074 }
1075
1076 static int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
1077                                int derlen)
1078 {
1079     ASN1_OBJECT *obj = NULL;
1080     int nid;
1081     if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
1082         return 0;
1083     }
1084     nid = OBJ_obj2nid(obj);
1085     ASN1_OBJECT_free(obj);
1086
1087     return gost_decode_nid_params(pkey, NID_id_GostR3410_94, nid);
1088 }
1089
1090 static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
1091                                  int derlen)
1092 {
1093     ASN1_OBJECT *obj = NULL;
1094     int nid;
1095     if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
1096         return 0;
1097     }
1098     nid = OBJ_obj2nid(obj);
1099     ASN1_OBJECT_free(obj);
1100
1101     return gost_decode_nid_params(pkey, NID_id_GostR3410_2001, nid);
1102 }
1103
1104 /* ----------------------------------------------------------------------*/
1105 int register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
1106                         const char *pemstr, const char *info)
1107 {
1108     *ameth = EVP_PKEY_asn1_new(nid, ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
1109     if (!*ameth)
1110         return 0;
1111     switch (nid) {
1112     case NID_id_GostR3410_94:
1113         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost94);
1114         EVP_PKEY_asn1_set_private(*ameth,
1115                                   priv_decode_gost, priv_encode_gost,
1116                                   priv_print_gost94);
1117
1118         EVP_PKEY_asn1_set_param(*ameth,
1119                                 gost94_param_decode, gost94_param_encode,
1120                                 param_missing_gost94, param_copy_gost94,
1121                                 param_cmp_gost94, param_print_gost94);
1122         EVP_PKEY_asn1_set_public(*ameth,
1123                                  pub_decode_gost94, pub_encode_gost94,
1124                                  pub_cmp_gost94, pub_print_gost94,
1125                                  pkey_size_gost, pkey_bits_gost);
1126
1127         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
1128         break;
1129     case NID_id_GostR3410_2001:
1130         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
1131         EVP_PKEY_asn1_set_private(*ameth,
1132                                   priv_decode_gost, priv_encode_gost,
1133                                   priv_print_gost_ec);
1134
1135         EVP_PKEY_asn1_set_param(*ameth,
1136                                 gost2001_param_decode, gost2001_param_encode,
1137                                 param_missing_gost_ec, param_copy_gost_ec,
1138                                 param_cmp_gost_ec, param_print_gost_ec);
1139         EVP_PKEY_asn1_set_public(*ameth,
1140                                  pub_decode_gost_ec, pub_encode_gost_ec,
1141                                  pub_cmp_gost_ec, pub_print_gost_ec,
1142                                  pkey_size_gost, pkey_bits_gost);
1143
1144         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
1145         break;
1146     case NID_id_GostR3410_2012_256:
1147     case NID_id_GostR3410_2012_512:
1148         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost_ec);
1149         EVP_PKEY_asn1_set_private(*ameth,
1150                                   priv_decode_gost, priv_encode_gost,
1151                                   priv_print_gost_ec);
1152
1153         EVP_PKEY_asn1_set_param(*ameth,
1154                                 NULL, NULL,
1155                                 param_missing_gost_ec, param_copy_gost_ec,
1156                                 param_cmp_gost_ec, NULL);
1157
1158         EVP_PKEY_asn1_set_public(*ameth,
1159                                  pub_decode_gost_ec, pub_encode_gost_ec,
1160                                  pub_cmp_gost_ec, pub_print_gost_ec,
1161                                  pkey_size_gost, pkey_bits_gost);
1162
1163         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
1164         break;
1165     case NID_id_Gost28147_89_MAC:
1166         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
1167         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost);
1168         break;
1169     case NID_gost_mac_12:
1170         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
1171         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost_12);
1172         break;
1173     }
1174     return 1;
1175 }