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