Adapt all engines that need it to opaque EVP_CIPHER
[openssl.git] / engines / ccgost / 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 /* Convert little-endian byte array into bignum */
24 BIGNUM *hashsum2bn(const unsigned char *dgst)
25 {
26     unsigned char buf[32];
27
28     BUF_reverse(buf, (unsigned char*)dgst, 32);
29     return BN_bin2bn(buf, 32, NULL);
30 }
31
32 /*
33  * Pack bignum into byte buffer of given size, filling all leading bytes by
34  * zeros
35  */
36 int store_bignum(BIGNUM *bn, unsigned char *buf, int len)
37 {
38     int bytes = BN_num_bytes(bn);
39
40     if (bytes > len)
41         return 0;
42     memset(buf, 0, len);
43     BN_bn2bin(bn, buf + len - bytes);
44     return 1;
45 }
46
47 static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
48 {
49     ASN1_STRING *params = ASN1_STRING_new();
50     GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
51     int pkey_param_nid = NID_undef;
52
53     if (!params || !gkp) {
54         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
55         ASN1_STRING_free(params);
56         params = NULL;
57         goto err;
58     }
59     switch (EVP_PKEY_base_id(key)) {
60     case NID_id_GostR3410_2001:
61         pkey_param_nid =
62             EC_GROUP_get_curve_name(EC_KEY_get0_group
63                                     (EVP_PKEY_get0((EVP_PKEY *)key)));
64         break;
65     }
66     gkp->key_params = OBJ_nid2obj(pkey_param_nid);
67     gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
68     /*
69      * gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);
70      */
71     params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
72     if (params->length <= 0) {
73         GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, ERR_R_MALLOC_FAILURE);
74         ASN1_STRING_free(params);
75         params = NULL;
76         goto err;
77     }
78     params->type = V_ASN1_SEQUENCE;
79  err:
80     GOST_KEY_PARAMS_free(gkp);
81     return params;
82 }
83
84 /*
85  * Parses GOST algorithm parameters from X509_ALGOR and modifies pkey setting
86  * NID and parameters
87  */
88 static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
89 {
90     ASN1_OBJECT *palg_obj = NULL;
91     int ptype = V_ASN1_UNDEF;
92     int pkey_nid = NID_undef, param_nid = NID_undef;
93     void *_pval;
94     ASN1_STRING *pval = NULL;
95     const unsigned char *p;
96     GOST_KEY_PARAMS *gkp = NULL;
97
98     X509_ALGOR_get0(&palg_obj, &ptype, &_pval, palg);
99     pval = _pval;
100     if (ptype != V_ASN1_SEQUENCE) {
101         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
102                 GOST_R_BAD_KEY_PARAMETERS_FORMAT);
103         return 0;
104     }
105     p = pval->data;
106     pkey_nid = OBJ_obj2nid(palg_obj);
107
108     gkp = d2i_GOST_KEY_PARAMS(NULL, &p, pval->length);
109     if (!gkp) {
110         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
111                 GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
112         return 0;
113     }
114     param_nid = OBJ_obj2nid(gkp->key_params);
115     GOST_KEY_PARAMS_free(gkp);
116     if (!EVP_PKEY_set_type(pkey, pkey_nid)) {
117         GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR);
118         return 0;
119     }
120     switch (pkey_nid) {
121     case NID_id_GostR3410_2001:
122         {
123             EC_KEY *ec = EVP_PKEY_get0(pkey);
124             if (!ec) {
125                 ec = EC_KEY_new();
126                 if (!EVP_PKEY_assign(pkey, pkey_nid, ec))
127                     return 0;
128             }
129             if (!fill_GOST2001_params(ec, param_nid))
130                 return 0;
131         }
132     }
133
134     return 1;
135 }
136
137 static int gost_set_priv_key(EVP_PKEY *pkey, BIGNUM *priv)
138 {
139     switch (EVP_PKEY_base_id(pkey)) {
140     case NID_id_GostR3410_2001:
141         {
142             EC_KEY *ec = EVP_PKEY_get0(pkey);
143             if (!ec) {
144                 ec = EC_KEY_new();
145                 EVP_PKEY_assign(pkey, EVP_PKEY_base_id(pkey), ec);
146             }
147             if (!EC_KEY_set_private_key(ec, priv))
148                 return 0;
149             if (!EVP_PKEY_missing_parameters(pkey))
150                 gost2001_compute_public(ec);
151             break;
152         }
153     }
154     return 1;
155 }
156
157 BIGNUM *gost_get0_priv_key(const EVP_PKEY *pkey)
158 {
159     switch (EVP_PKEY_base_id(pkey)) {
160     case NID_id_GostR3410_2001:
161         {
162             EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
163             const BIGNUM *priv;
164             if (!ec) {
165                 return NULL;
166             }
167             if ((priv = EC_KEY_get0_private_key(ec)) == NULL)
168                 return NULL;
169             return (BIGNUM *)priv;
170         }
171     }
172     return NULL;
173 }
174
175 static int pkey_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
176 {
177     switch (op) {
178     case ASN1_PKEY_CTRL_PKCS7_SIGN:
179         if (arg1 == 0) {
180             X509_ALGOR *alg1 = NULL, *alg2 = NULL;
181             int nid = EVP_PKEY_base_id(pkey);
182             PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO *)arg2,
183                                         NULL, &alg1, &alg2);
184             X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
185                             V_ASN1_NULL, 0);
186             if (nid == NID_undef) {
187                 return (-1);
188             }
189             X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
190         }
191         return 1;
192 #ifndef OPENSSL_NO_CMS
193     case ASN1_PKEY_CTRL_CMS_SIGN:
194         if (arg1 == 0) {
195             X509_ALGOR *alg1 = NULL, *alg2 = NULL;
196             int nid = EVP_PKEY_base_id(pkey);
197             CMS_SignerInfo_get0_algs((CMS_SignerInfo *)arg2,
198                                      NULL, NULL, &alg1, &alg2);
199             X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
200                             V_ASN1_NULL, 0);
201             if (nid == NID_undef) {
202                 return (-1);
203             }
204             X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
205         }
206         return 1;
207 #endif
208     case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
209         if (arg1 == 0) {
210             X509_ALGOR *alg;
211             ASN1_STRING *params = encode_gost_algor_params(pkey);
212             if (!params) {
213                 return -1;
214             }
215             PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO *)arg2, &alg);
216             X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type),
217                             V_ASN1_SEQUENCE, params);
218         }
219         return 1;
220 #ifndef OPENSSL_NO_CMS
221     case ASN1_PKEY_CTRL_CMS_ENVELOPE:
222         if (arg1 == 0) {
223             X509_ALGOR *alg = NULL;
224             ASN1_STRING *params = encode_gost_algor_params(pkey);
225             if (!params) {
226                 return -1;
227             }
228             CMS_RecipientInfo_ktri_get0_algs((CMS_RecipientInfo *)arg2, NULL,
229                                              NULL, &alg);
230             X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type), V_ASN1_SEQUENCE,
231                             params);
232         }
233         return 1;
234 #endif
235     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
236         *(int *)arg2 = NID_id_GostR3411_94;
237         return 2;
238     }
239
240     return -2;
241 }
242
243 /* --------------------- free functions * ------------------------------*/
244 static void pkey_free_gost01(EVP_PKEY *key)
245 {
246     EC_KEY_free(key->pkey.ec);
247 }
248
249 /* ------------------ private key functions  -----------------------------*/
250 static int priv_decode_gost(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf)
251 {
252     const unsigned char *pkey_buf = NULL, *p = NULL;
253     int priv_len = 0;
254     BIGNUM *pk_num = NULL;
255     int ret = 0;
256     X509_ALGOR *palg = NULL;
257     ASN1_OBJECT *palg_obj = NULL;
258     ASN1_INTEGER *priv_key = NULL;
259
260     if (!PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf))
261         return 0;
262     p = pkey_buf;
263     if (!decode_gost_algor_params(pk, palg)) {
264         return 0;
265     }
266     if (V_ASN1_OCTET_STRING == *p) {
267         /* New format - Little endian octet string */
268         unsigned char rev_buf[32];
269         int i;
270         ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
271         if (!s || s->length != 32) {
272             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
273             return 0;
274         }
275         for (i = 0; i < 32; i++) {
276             rev_buf[31 - i] = s->data[i];
277         }
278         ASN1_STRING_free(s);
279         pk_num = BN_bin2bn(rev_buf, 32, NULL);
280     } else {
281         priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
282         if (!priv_key)
283             return 0;
284         ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
285         ASN1_INTEGER_free(priv_key);
286         if (!ret) {
287             GOSTerr(GOST_F_PRIV_DECODE_GOST, EVP_R_DECODE_ERROR);
288             return 0;
289         }
290     }
291
292     ret = gost_set_priv_key(pk, pk_num);
293     BN_free(pk_num);
294     return ret;
295 }
296
297 /* ----------------------------------------------------------------------*/
298 static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
299 {
300     ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
301     ASN1_STRING *params = encode_gost_algor_params(pk);
302     unsigned char *priv_buf = NULL;
303     int priv_len;
304
305     ASN1_INTEGER *asn1key = NULL;
306     if (!params) {
307         return 0;
308     }
309     asn1key = BN_to_ASN1_INTEGER(gost_get0_priv_key(pk), NULL);
310     priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf);
311     ASN1_INTEGER_free(asn1key);
312     return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params,
313                            priv_buf, priv_len);
314 }
315
316 /* --------- printing keys --------------------------------*/
317 static int print_gost_01(BIO *out, const EVP_PKEY *pkey, int indent,
318                          ASN1_PCTX *pctx, int type)
319 {
320     int param_nid = NID_undef;
321     if (type == 2) {
322         BIGNUM *key;
323
324         if (!BIO_indent(out, indent, 128))
325             return 0;
326         BIO_printf(out, "Private key: ");
327         key = gost_get0_priv_key(pkey);
328         if (!key)
329             BIO_printf(out, "<undefined)");
330         else
331             BN_print(out, key);
332         BIO_printf(out, "\n");
333     }
334     if (type >= 1) {
335         BN_CTX *ctx = BN_CTX_new();
336         BIGNUM *X, *Y;
337         const EC_POINT *pubkey;
338         const EC_GROUP *group;
339
340         if (!ctx) {
341             GOSTerr(GOST_F_PRINT_GOST_01, ERR_R_MALLOC_FAILURE);
342             return 0;
343         }
344         BN_CTX_start(ctx);
345         X = BN_CTX_get(ctx);
346         Y = BN_CTX_get(ctx);
347         pubkey =
348             EC_KEY_get0_public_key((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
349         group = EC_KEY_get0_group((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
350         if (!EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx)) {
351             GOSTerr(GOST_F_PRINT_GOST_01, ERR_R_EC_LIB);
352             BN_CTX_free(ctx);
353             return 0;
354         }
355         if (!BIO_indent(out, indent, 128))
356             return 0;
357         BIO_printf(out, "Public key:\n");
358         if (!BIO_indent(out, indent + 3, 128))
359             return 0;
360         BIO_printf(out, "X:");
361         BN_print(out, X);
362         BIO_printf(out, "\n");
363         BIO_indent(out, indent + 3, 128);
364         BIO_printf(out, "Y:");
365         BN_print(out, Y);
366         BIO_printf(out, "\n");
367         BN_CTX_end(ctx);
368         BN_CTX_free(ctx);
369     }
370
371     param_nid =
372         EC_GROUP_get_curve_name(EC_KEY_get0_group
373                                 (EVP_PKEY_get0((EVP_PKEY *)pkey)));
374     if (!BIO_indent(out, indent, 128))
375         return 0;
376     BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
377     return 1;
378 }
379
380 static int param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
381                               ASN1_PCTX *pctx)
382 {
383     return print_gost_01(out, pkey, indent, pctx, 0);
384 }
385
386 static int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
387                             ASN1_PCTX *pctx)
388 {
389     return print_gost_01(out, pkey, indent, pctx, 1);
390 }
391
392 static int priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
393                              ASN1_PCTX *pctx)
394 {
395     return print_gost_01(out, pkey, indent, pctx, 2);
396 }
397
398 /* ---------------------------------------------------------------------*/
399 static int param_missing_gost01(const EVP_PKEY *pk)
400 {
401     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
402     if (!ec)
403         return 1;
404     if (!EC_KEY_get0_group(ec))
405         return 1;
406     return 0;
407 }
408
409
410 static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
411 {
412     EC_KEY *eto = EVP_PKEY_get0(to);
413     const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
414     if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
415         GOSTerr(GOST_F_PARAM_COPY_GOST01, GOST_R_INCOMPATIBLE_ALGORITHMS);
416         return 0;
417     }
418     if (!efrom) {
419         GOSTerr(GOST_F_PARAM_COPY_GOST01, GOST_R_KEY_PARAMETERS_MISSING);
420         return 0;
421     }
422     if (!eto) {
423         eto = EC_KEY_new();
424         if (!eto) {
425             GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_MALLOC_FAILURE);
426             return 0;
427         }
428         if (!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) {
429             GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR);
430             return 0;
431         }
432     }
433     if (!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) {
434         GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR);
435         return 0;
436     }
437     if (EC_KEY_get0_private_key(eto)) {
438         gost2001_compute_public(eto);
439     }
440     return 1;
441 }
442
443 static int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
444 {
445     if (EC_GROUP_get_curve_name
446         (EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)a))) ==
447         EC_GROUP_get_curve_name(EC_KEY_get0_group
448                                 (EVP_PKEY_get0((EVP_PKEY *)b)))) {
449         return 1;
450     }
451     return 0;
452
453 }
454
455 /* ---------- Public key functions * --------------------------------------*/
456
457 static int pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub)
458 {
459     X509_ALGOR *palg = NULL;
460     const unsigned char *pubkey_buf = NULL;
461     unsigned char *databuf;
462     ASN1_OBJECT *palgobj = NULL;
463     int pub_len, i, j;
464     EC_POINT *pub_key;
465     BIGNUM *X, *Y;
466     ASN1_OCTET_STRING *octet = NULL;
467     int len;
468     const EC_GROUP *group;
469
470     if (!X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub))
471         return 0;
472     EVP_PKEY_assign(pk, OBJ_obj2nid(palgobj), NULL);
473     if (!decode_gost_algor_params(pk, palg))
474         return 0;
475     group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
476     octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
477     if (!octet) {
478         GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_MALLOC_FAILURE);
479         return 0;
480     }
481     databuf = OPENSSL_malloc(octet->length);
482     if (databuf == NULL) {
483         GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_MALLOC_FAILURE);
484         ASN1_OCTET_STRING_free(octet);
485         return 0;
486     }
487     for (i = 0, j = octet->length - 1; i < octet->length; i++, j--) {
488         databuf[j] = octet->data[i];
489     }
490     len = octet->length / 2;
491     ASN1_OCTET_STRING_free(octet);
492
493     Y = BN_bin2bn(databuf, len, NULL);
494     X = BN_bin2bn(databuf + len, len, NULL);
495     OPENSSL_free(databuf);
496     pub_key = EC_POINT_new(group);
497     if (!EC_POINT_set_affine_coordinates_GFp(group, pub_key, X, Y, NULL)) {
498         GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB);
499         EC_POINT_free(pub_key);
500         BN_free(X);
501         BN_free(Y);
502         return 0;
503     }
504     BN_free(X);
505     BN_free(Y);
506     if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk), pub_key)) {
507         GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB);
508         EC_POINT_free(pub_key);
509         return 0;
510     }
511     EC_POINT_free(pub_key);
512     return 1;
513
514 }
515
516 static int pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
517 {
518     ASN1_OBJECT *algobj = NULL;
519     ASN1_OCTET_STRING *octet = NULL;
520     void *pval = NULL;
521     unsigned char *buf = NULL, *databuf, *sptr;
522     int i, j, data_len, ret = 0;
523     const EC_POINT *pub_key;
524     BIGNUM *X, *Y, *order;
525     const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
526     int ptype = V_ASN1_UNDEF;
527
528     algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
529     if (pk->save_parameters) {
530         ASN1_STRING *params = encode_gost_algor_params(pk);
531         pval = params;
532         ptype = V_ASN1_SEQUENCE;
533     }
534     order = BN_new();
535     EC_GROUP_get_order(EC_KEY_get0_group(ec), order, NULL);
536     pub_key = EC_KEY_get0_public_key(ec);
537     if (!pub_key) {
538         GOSTerr(GOST_F_PUB_ENCODE_GOST01, GOST_R_PUBLIC_KEY_UNDEFINED);
539         BN_free(order);
540         return 0;
541     }
542     X = BN_new();
543     Y = BN_new();
544     if (!X || !Y) {
545         GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
546         BN_free(X);
547         BN_free(Y);
548         BN_free(order);
549         return 0;
550     }
551     if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
552                                         pub_key, X, Y, NULL)) {
553         GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_INTERNAL_ERROR);
554         BN_free(X);
555         BN_free(Y);
556         BN_free(order);
557         return 0;
558     }
559     data_len = 2 * BN_num_bytes(order);
560     BN_free(order);
561     databuf = OPENSSL_malloc(data_len);
562     if (databuf == NULL) {
563         GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
564         BN_free(X);
565         BN_free(Y);
566         return 0;
567     }
568     memset(databuf, 0, data_len);
569
570     store_bignum(X, databuf + data_len / 2, data_len / 2);
571     store_bignum(Y, databuf, data_len / 2);
572
573     BN_free(X);
574     BN_free(Y);
575     octet = ASN1_OCTET_STRING_new();
576     if (octet == NULL) {
577         GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
578         OPENSSL_free(databuf);
579         return 0;
580     }
581     ASN1_STRING_set(octet, NULL, data_len);
582     sptr = ASN1_STRING_data(octet);
583     for (i = 0, j = data_len - 1; i < data_len; i++, j--) {
584         sptr[i] = databuf[j];
585     }
586     OPENSSL_free(databuf);
587     ret = i2d_ASN1_OCTET_STRING(octet, &buf);
588     ASN1_BIT_STRING_free(octet);
589     if (ret < 0)
590         return 0;
591     return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
592 }
593
594 static int pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
595 {
596     const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
597     const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
598     const EC_POINT *ka, *kb;
599     int ret = 0;
600     if (!ea || !eb)
601         return 0;
602     ka = EC_KEY_get0_public_key(ea);
603     kb = EC_KEY_get0_public_key(eb);
604     if (!ka || !kb)
605         return 0;
606     ret = (0 == EC_POINT_cmp(EC_KEY_get0_group(ea), ka, kb, NULL));
607     return ret;
608 }
609
610 static int pkey_size_gost(const EVP_PKEY *pk)
611 {
612     return 64;
613 }
614
615 static int pkey_bits_gost(const EVP_PKEY *pk)
616 {
617     return 256;
618 }
619
620 /* ---------------------- ASN1 METHOD for GOST MAC  -------------------*/
621 static void mackey_free_gost(EVP_PKEY *pk)
622 {
623     OPENSSL_free(pk->pkey.ptr);
624 }
625
626 static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
627 {
628     switch (op) {
629     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
630         *(int *)arg2 = NID_id_Gost28147_89_MAC;
631         return 2;
632     }
633     return -2;
634 }
635
636 static int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
637 {
638     int nid =
639         EC_GROUP_get_curve_name(EC_KEY_get0_group
640                                 (EVP_PKEY_get0((EVP_PKEY *)pkey)));
641     return i2d_ASN1_OBJECT(OBJ_nid2obj(nid), pder);
642 }
643
644 static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder,
645                                  int derlen)
646 {
647     ASN1_OBJECT *obj = NULL;
648     int nid;
649     EC_KEY *ec = EVP_PKEY_get0(pkey);
650     if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
651         return 0;
652     }
653     nid = OBJ_obj2nid(obj);
654     ASN1_OBJECT_free(obj);
655     if (!ec) {
656         ec = EC_KEY_new();
657         if (!EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec))
658             return 0;
659     }
660     if (!fill_GOST2001_params(ec, nid))
661         return 0;
662     return 1;
663 }
664
665 /* ----------------------------------------------------------------------*/
666 int register_ameth_gost(int nid, EVP_PKEY_ASN1_METHOD **ameth,
667                         const char *pemstr, const char *info)
668 {
669     *ameth = EVP_PKEY_asn1_new(nid, ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
670     if (!*ameth)
671         return 0;
672     switch (nid) {
673     case NID_id_GostR3410_2001:
674         EVP_PKEY_asn1_set_free(*ameth, pkey_free_gost01);
675         EVP_PKEY_asn1_set_private(*ameth,
676                                   priv_decode_gost, priv_encode_gost,
677                                   priv_print_gost01);
678
679         EVP_PKEY_asn1_set_param(*ameth,
680                                 gost2001_param_decode, gost2001_param_encode,
681                                 param_missing_gost01, param_copy_gost01,
682                                 param_cmp_gost01, param_print_gost01);
683         EVP_PKEY_asn1_set_public(*ameth,
684                                  pub_decode_gost01, pub_encode_gost01,
685                                  pub_cmp_gost01, pub_print_gost01,
686                                  pkey_size_gost, pkey_bits_gost);
687
688         EVP_PKEY_asn1_set_ctrl(*ameth, pkey_ctrl_gost);
689         break;
690     case NID_id_Gost28147_89_MAC:
691         EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
692         EVP_PKEY_asn1_set_ctrl(*ameth, mac_ctrl_gost);
693         break;
694     }
695     return 1;
696 }