1 /* $OpenBSD: gostr341001_ameth.c,v 1.15 2018/08/24 20:22:15 tb Exp $ */
2 /*
3  * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
4  * Copyright (c) 2005-2006 Cryptocom LTD
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * 3. All advertising materials mentioning features or use of this
19  *    software must display the following acknowledgment:
20  *    "This product includes software developed by the OpenSSL Project
21  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
22  *
23  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
24  *    endorse or promote products derived from this software without
25  *    prior written permission. For written permission, please contact
26  *    openssl-core@openssl.org.
27  *
28  * 5. Products derived from this software may not be called "OpenSSL"
29  *    nor may "OpenSSL" appear in their names without prior written
30  *    permission of the OpenSSL Project.
31  *
32  * 6. Redistributions of any form whatsoever must retain the following
33  *    acknowledgment:
34  *    "This product includes software developed by the OpenSSL Project
35  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
38  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
48  * OF THE POSSIBILITY OF SUCH DAMAGE.
49  * ====================================================================
50  */
51 
52 #include <string.h>
53 
54 #include <openssl/opensslconf.h>
55 
56 #ifndef OPENSSL_NO_GOST
57 #include <openssl/bn.h>
58 #include <openssl/evp.h>
59 #include <openssl/ec.h>
60 #include <openssl/err.h>
61 #include <openssl/x509.h>
62 #include <openssl/gost.h>
63 
64 
65 #include "asn1_locl.h"
66 #include "gost_locl.h"
67 #include "gost_asn1.h"
68 
69 static void
70 pkey_free_gost01(EVP_PKEY *key)
71 {
72 	GOST_KEY_free(key->pkey.gost);
73 }
74 
75 /*
76  * Parses GOST algorithm parameters from X509_ALGOR and
77  * modifies pkey setting NID and parameters
78  */
79 static int
80 decode_gost01_algor_params(EVP_PKEY *pkey, const unsigned char **p, int len)
81 {
82 	int param_nid = NID_undef, digest_nid = NID_undef;
83 	GOST_KEY_PARAMS *gkp = NULL;
84 	EC_GROUP *group;
85 	GOST_KEY *ec;
86 
87 	gkp = d2i_GOST_KEY_PARAMS(NULL, p, len);
88 	if (gkp == NULL) {
89 		GOSTerror(GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
90 		return 0;
91 	}
92 	param_nid = OBJ_obj2nid(gkp->key_params);
93 	digest_nid = OBJ_obj2nid(gkp->hash_params);
94 	GOST_KEY_PARAMS_free(gkp);
95 
96 	ec = pkey->pkey.gost;
97 	if (ec == NULL) {
98 		ec = GOST_KEY_new();
99 		if (ec == NULL)
100 			return 0;
101 		if (EVP_PKEY_assign_GOST(pkey, ec) == 0)
102 			return 0;
103 	}
104 
105 	group = EC_GROUP_new_by_curve_name(param_nid);
106 	if (group == NULL)
107 		return 0;
108 	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
109 	if (GOST_KEY_set_group(ec, group) == 0) {
110 		EC_GROUP_free(group);
111 		return 0;
112 	}
113 	EC_GROUP_free(group);
114 	if (GOST_KEY_set_digest(ec, digest_nid) == 0)
115 		return 0;
116 	return 1;
117 }
118 
119 static ASN1_STRING *
120 encode_gost01_algor_params(const EVP_PKEY *key)
121 {
122 	ASN1_STRING *params = ASN1_STRING_new();
123 	GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
124 	int pkey_param_nid = NID_undef;
125 
126 	if (params == NULL || gkp == NULL) {
127 		GOSTerror(ERR_R_MALLOC_FAILURE);
128 		ASN1_STRING_free(params);
129 		params = NULL;
130 		goto err;
131 	}
132 
133 	pkey_param_nid =
134 	    EC_GROUP_get_curve_name(GOST_KEY_get0_group(key->pkey.gost));
135 	gkp->key_params = OBJ_nid2obj(pkey_param_nid);
136 	gkp->hash_params = OBJ_nid2obj(GOST_KEY_get_digest(key->pkey.gost));
137 	/*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid); */
138 	params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
139 	if (params->length <= 0) {
140 		GOSTerror(ERR_R_MALLOC_FAILURE);
141 		ASN1_STRING_free(params);
142 		params = NULL;
143 		goto err;
144 	}
145 	params->type = V_ASN1_SEQUENCE;
146 err:
147 	GOST_KEY_PARAMS_free(gkp);
148 	return params;
149 }
150 
151 static int
152 pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
153 {
154 	const GOST_KEY *ea = a->pkey.gost;
155 	const GOST_KEY *eb = b->pkey.gost;
156 	const EC_POINT *ka, *kb;
157 	int ret = 0;
158 
159 	if (ea == NULL || eb == NULL)
160 		return 0;
161 	ka = GOST_KEY_get0_public_key(ea);
162 	kb = GOST_KEY_get0_public_key(eb);
163 	if (ka == NULL || kb == NULL)
164 		return 0;
165 	ret = (0 == EC_POINT_cmp(GOST_KEY_get0_group(ea), ka, kb, NULL));
166 	return ret;
167 }
168 
169 static int
170 pkey_size_gost01(const EVP_PKEY *pk)
171 {
172 	if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
173 		return 128;
174 	return 64;
175 }
176 
177 static int
178 pkey_bits_gost01(const EVP_PKEY *pk)
179 {
180 	if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
181 		return 512;
182 	return 256;
183 }
184 
185 static int
186 pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub)
187 {
188 	X509_ALGOR *palg = NULL;
189 	const unsigned char *pubkey_buf = NULL;
190 	const unsigned char *p;
191 	ASN1_OBJECT *palgobj = NULL;
192 	int pub_len;
193 	BIGNUM *X, *Y;
194 	ASN1_OCTET_STRING *octet = NULL;
195 	int len;
196 	int ret;
197 	int ptype = V_ASN1_UNDEF;
198 	ASN1_STRING *pval = NULL;
199 
200 	if (X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub)
201 	    == 0)
202 		return 0;
203 	(void)EVP_PKEY_assign_GOST(pk, NULL);
204 	X509_ALGOR_get0(NULL, &ptype, (const void **)&pval, palg);
205 	if (ptype != V_ASN1_SEQUENCE) {
206 		GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
207 		return 0;
208 	}
209 	p = pval->data;
210 	if (decode_gost01_algor_params(pk, &p, pval->length) == 0)
211 		return 0;
212 
213 	octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
214 	if (octet == NULL) {
215 		GOSTerror(ERR_R_MALLOC_FAILURE);
216 		return 0;
217 	}
218 	len = octet->length / 2;
219 
220 	X = GOST_le2bn(octet->data, len, NULL);
221 	Y = GOST_le2bn(octet->data + len, len, NULL);
222 
223 	ASN1_OCTET_STRING_free(octet);
224 
225 	ret = GOST_KEY_set_public_key_affine_coordinates(pk->pkey.gost, X, Y);
226 	if (ret == 0)
227 		GOSTerror(ERR_R_EC_LIB);
228 
229 	BN_free(X);
230 	BN_free(Y);
231 
232 	return ret;
233 }
234 
235 static int
236 pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
237 {
238 	ASN1_OBJECT *algobj = NULL;
239 	ASN1_OCTET_STRING *octet = NULL;
240 	ASN1_STRING *params = NULL;
241 	void *pval = NULL;
242 	unsigned char *buf = NULL, *sptr;
243 	int key_size, ret = 0;
244 	const EC_POINT *pub_key;
245 	BIGNUM *X = NULL, *Y = NULL;
246 	const GOST_KEY *ec = pk->pkey.gost;
247 	int ptype = V_ASN1_UNDEF;
248 
249 	algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(ec)));
250 	if (pk->save_parameters) {
251 		params = encode_gost01_algor_params(pk);
252 		if (params == NULL)
253 			return 0;
254 		pval = params;
255 		ptype = V_ASN1_SEQUENCE;
256 	}
257 
258 	key_size = GOST_KEY_get_size(ec);
259 
260 	pub_key = GOST_KEY_get0_public_key(ec);
261 	if (pub_key == NULL) {
262 		GOSTerror(GOST_R_PUBLIC_KEY_UNDEFINED);
263 		goto err;
264 	}
265 
266 	octet = ASN1_OCTET_STRING_new();
267 	if (octet == NULL) {
268 		GOSTerror(ERR_R_MALLOC_FAILURE);
269 		goto err;
270 	}
271 
272 	ret = ASN1_STRING_set(octet, NULL, 2 * key_size);
273 	if (ret == 0) {
274 		GOSTerror(ERR_R_INTERNAL_ERROR);
275 		goto err;
276 	}
277 
278 	sptr = ASN1_STRING_data(octet);
279 
280 	X = BN_new();
281 	Y = BN_new();
282 	if (X == NULL || Y == NULL) {
283 		GOSTerror(ERR_R_MALLOC_FAILURE);
284 		goto err;
285 	}
286 
287 	if (EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(ec),
288 	    pub_key, X, Y, NULL) == 0) {
289 		GOSTerror(ERR_R_EC_LIB);
290 		goto err;
291 	}
292 
293 	GOST_bn2le(X, sptr, key_size);
294 	GOST_bn2le(Y, sptr + key_size, key_size);
295 
296 	BN_free(Y);
297 	BN_free(X);
298 
299 	ret = i2d_ASN1_OCTET_STRING(octet, &buf);
300 	ASN1_BIT_STRING_free(octet);
301 	if (ret < 0)
302 		return 0;
303 
304 	return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
305 
306 err:
307 	BN_free(Y);
308 	BN_free(X);
309 	ASN1_BIT_STRING_free(octet);
310 	ASN1_STRING_free(params);
311 	return 0;
312 }
313 
314 static int
315 param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
316 {
317 	int param_nid =
318 	    EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost));
319 
320 	if (BIO_indent(out, indent, 128) == 0)
321 		return 0;
322 	BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
323 	if (BIO_indent(out, indent, 128) == 0)
324 		return 0;
325 	BIO_printf(out, "Digest Algorithm: %s\n",
326 	    OBJ_nid2ln(GOST_KEY_get_digest(pkey->pkey.gost)));
327 	return 1;
328 }
329 
330 static int
331 pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
332 {
333 	BN_CTX *ctx = BN_CTX_new();
334 	BIGNUM *X, *Y;
335 	const EC_POINT *pubkey;
336 	const EC_GROUP *group;
337 
338 	if (ctx == NULL) {
339 		GOSTerror(ERR_R_MALLOC_FAILURE);
340 		return 0;
341 	}
342 	BN_CTX_start(ctx);
343 	if ((X = BN_CTX_get(ctx)) == NULL)
344 		goto err;
345 	if ((Y = BN_CTX_get(ctx)) == NULL)
346 		goto err;
347 	pubkey = GOST_KEY_get0_public_key(pkey->pkey.gost);
348 	group = GOST_KEY_get0_group(pkey->pkey.gost);
349 	if (EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y,
350 	    ctx) == 0) {
351 		GOSTerror(ERR_R_EC_LIB);
352 		goto err;
353 	}
354 	if (BIO_indent(out, indent, 128) == 0)
355 		goto err;
356 	BIO_printf(out, "Public key:\n");
357 	if (BIO_indent(out, indent + 3, 128) == 0)
358 		goto err;
359 	BIO_printf(out, "X:");
360 	BN_print(out, X);
361 	BIO_printf(out, "\n");
362 	BIO_indent(out, indent + 3, 128);
363 	BIO_printf(out, "Y:");
364 	BN_print(out, Y);
365 	BIO_printf(out, "\n");
366 
367 	BN_CTX_end(ctx);
368 	BN_CTX_free(ctx);
369 
370 	return param_print_gost01(out, pkey, indent, pctx);
371 
372 err:
373 	BN_CTX_end(ctx);
374 	BN_CTX_free(ctx);
375 	return 0;
376 }
377 
378 static int
379 priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
380 {
381 	const BIGNUM *key;
382 
383 	if (BIO_indent(out, indent, 128) == 0)
384 		return 0;
385 	BIO_printf(out, "Private key: ");
386 	key = GOST_KEY_get0_private_key(pkey->pkey.gost);
387 	if (key == NULL)
388 		BIO_printf(out, "<undefined)");
389 	else
390 		BN_print(out, key);
391 	BIO_printf(out, "\n");
392 
393 	return pub_print_gost01(out, pkey, indent, pctx);
394 }
395 
396 static int
397 priv_decode_gost01(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf)
398 {
399 	const unsigned char *pkey_buf = NULL, *p = NULL;
400 	int priv_len = 0;
401 	BIGNUM *pk_num = NULL;
402 	int ret = 0;
403 	const X509_ALGOR *palg = NULL;
404 	const ASN1_OBJECT *palg_obj = NULL;
405 	ASN1_INTEGER *priv_key = NULL;
406 	GOST_KEY *ec;
407 	int ptype = V_ASN1_UNDEF;
408 	ASN1_STRING *pval = NULL;
409 
410 	if (PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf) == 0)
411 		return 0;
412 	(void)EVP_PKEY_assign_GOST(pk, NULL);
413 	X509_ALGOR_get0(NULL, &ptype, (const void **)&pval, palg);
414 	if (ptype != V_ASN1_SEQUENCE) {
415 		GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
416 		return 0;
417 	}
418 	p = pval->data;
419 	if (decode_gost01_algor_params(pk, &p, pval->length) == 0)
420 		return 0;
421 	p = pkey_buf;
422 	if (V_ASN1_OCTET_STRING == *p) {
423 		/* New format - Little endian octet string */
424 		ASN1_OCTET_STRING *s =
425 		    d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
426 
427 		if (s == NULL) {
428 			GOSTerror(EVP_R_DECODE_ERROR);
429 			ASN1_STRING_free(s);
430 			return 0;
431 		}
432 
433 		pk_num = GOST_le2bn(s->data, s->length, NULL);
434 		ASN1_STRING_free(s);
435 	} else {
436 		priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
437 		if (priv_key == NULL)
438 			return 0;
439 		ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
440 		ASN1_INTEGER_free(priv_key);
441 		if (ret == 0) {
442 			GOSTerror(EVP_R_DECODE_ERROR);
443 			return 0;
444 		}
445 	}
446 
447 	ec = pk->pkey.gost;
448 	if (ec == NULL) {
449 		ec = GOST_KEY_new();
450 		if (ec == NULL) {
451 			BN_free(pk_num);
452 			return 0;
453 		}
454 		if (EVP_PKEY_assign_GOST(pk, ec) == 0) {
455 			BN_free(pk_num);
456 			GOST_KEY_free(ec);
457 			return 0;
458 		}
459 	}
460 	if (GOST_KEY_set_private_key(ec, pk_num) == 0) {
461 		BN_free(pk_num);
462 		return 0;
463 	}
464 	ret = 0;
465 	if (EVP_PKEY_missing_parameters(pk) == 0)
466 		ret = gost2001_compute_public(ec) != 0;
467 	BN_free(pk_num);
468 
469 	return ret;
470 }
471 
472 static int
473 priv_encode_gost01(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
474 {
475 	ASN1_OBJECT *algobj =
476 	    OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost)));
477 	ASN1_STRING *params = encode_gost01_algor_params(pk);
478 	unsigned char *priv_buf = NULL;
479 	int priv_len;
480 	ASN1_INTEGER *asn1key = NULL;
481 
482 	if (params == NULL)
483 		return 0;
484 
485 	asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost),
486 	    NULL);
487 	if (asn1key == NULL) {
488 		ASN1_STRING_free(params);
489 		return 0;
490 	}
491 	priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf);
492 	ASN1_INTEGER_free(asn1key);
493 	return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, priv_buf,
494 	    priv_len);
495 }
496 
497 static int
498 param_encode_gost01(const EVP_PKEY *pkey, unsigned char **pder)
499 {
500 	ASN1_STRING *params = encode_gost01_algor_params(pkey);
501 	int len;
502 
503 	if (params == NULL)
504 		return 0;
505 	len = params->length;
506 	if (pder != NULL)
507 		memcpy(*pder, params->data, params->length);
508 	ASN1_STRING_free(params);
509 	return len;
510 }
511 
512 static int
513 param_decode_gost01(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
514 {
515 	ASN1_OBJECT *obj = NULL;
516 	int nid;
517 	GOST_KEY *ec;
518 	EC_GROUP *group;
519 	int ret;
520 
521 	/* New format */
522 	if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == **pder)
523 		return decode_gost01_algor_params(pkey, pder, derlen);
524 
525 	/* Compatibility */
526 	if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
527 		GOSTerror(ERR_R_MALLOC_FAILURE);
528 		return 0;
529 	}
530 	nid = OBJ_obj2nid(obj);
531 	ASN1_OBJECT_free(obj);
532 
533 	ec = GOST_KEY_new();
534 	if (ec == NULL) {
535 		GOSTerror(ERR_R_MALLOC_FAILURE);
536 		return 0;
537 	}
538 	group = EC_GROUP_new_by_curve_name(nid);
539 	if (group == NULL) {
540 		GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
541 		GOST_KEY_free(ec);
542 		return 0;
543 	}
544 
545 	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
546 	if (GOST_KEY_set_group(ec, group) == 0) {
547 		GOSTerror(ERR_R_EC_LIB);
548 		EC_GROUP_free(group);
549 		GOST_KEY_free(ec);
550 		return 0;
551 	}
552 	EC_GROUP_free(group);
553 	if (GOST_KEY_set_digest(ec,
554 	    NID_id_GostR3411_94_CryptoProParamSet) == 0) {
555 		GOSTerror(GOST_R_INVALID_DIGEST_TYPE);
556 		GOST_KEY_free(ec);
557 		return 0;
558 	}
559 	ret = EVP_PKEY_assign_GOST(pkey, ec);
560 	if (ret == 0)
561 		GOST_KEY_free(ec);
562 	return ret;
563 }
564 
565 static int
566 param_missing_gost01(const EVP_PKEY *pk)
567 {
568 	const GOST_KEY *ec = pk->pkey.gost;
569 
570 	if (ec == NULL)
571 		return 1;
572 	if (GOST_KEY_get0_group(ec) == NULL)
573 		return 1;
574 	if (GOST_KEY_get_digest(ec) == NID_undef)
575 		return 1;
576 	return 0;
577 }
578 
579 static int
580 param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
581 {
582 	GOST_KEY *eto = to->pkey.gost;
583 	const GOST_KEY *efrom = from->pkey.gost;
584 	int ret = 1;
585 
586 	if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
587 		GOSTerror(GOST_R_INCOMPATIBLE_ALGORITHMS);
588 		return 0;
589 	}
590 	if (efrom == NULL) {
591 		GOSTerror(GOST_R_KEY_PARAMETERS_MISSING);
592 		return 0;
593 	}
594 	if (eto == NULL) {
595 		eto = GOST_KEY_new();
596 		if (eto == NULL) {
597 			GOSTerror(ERR_R_MALLOC_FAILURE);
598 			return 0;
599 		}
600 		if (EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto) == 0) {
601 			GOST_KEY_free(eto);
602 			return 0;
603 		}
604 	}
605 	GOST_KEY_set_group(eto, GOST_KEY_get0_group(efrom));
606 	GOST_KEY_set_digest(eto, GOST_KEY_get_digest(efrom));
607 	if (GOST_KEY_get0_private_key(eto) != NULL)
608 		ret = gost2001_compute_public(eto);
609 
610 	return ret;
611 }
612 
613 static int
614 param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
615 {
616 	if (EC_GROUP_get_curve_name(GOST_KEY_get0_group(a->pkey.gost)) !=
617 	    EC_GROUP_get_curve_name(GOST_KEY_get0_group(b->pkey.gost)))
618 		return 0;
619 
620 	if (GOST_KEY_get_digest(a->pkey.gost) !=
621 	    GOST_KEY_get_digest(b->pkey.gost))
622 		return 0;
623 
624 	return 1;
625 }
626 
627 static int
628 pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2)
629 {
630 	X509_ALGOR *alg1 = NULL, *alg2 = NULL, *alg3 = NULL;
631 	int digest = GOST_KEY_get_digest(pkey->pkey.gost);
632 
633 	switch (op) {
634 	case ASN1_PKEY_CTRL_PKCS7_SIGN:
635 		if (arg1 == 0)
636 			PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
637 		break;
638 
639 	case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
640 		if (arg1 == 0)
641 			PKCS7_RECIP_INFO_get0_alg(arg2, &alg3);
642 		break;
643 	case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
644 		*(int *)arg2 = GostR3410_get_md_digest(digest);
645 		return 2;
646 
647 	default:
648 		return -2;
649 	}
650 
651 	if (alg1)
652 		X509_ALGOR_set0(alg1, OBJ_nid2obj(GostR3410_get_md_digest(digest)), V_ASN1_NULL, 0);
653 	if (alg2)
654 		X509_ALGOR_set0(alg2, OBJ_nid2obj(GostR3410_get_pk_digest(digest)), V_ASN1_NULL, 0);
655 	if (alg3) {
656 		ASN1_STRING *params = encode_gost01_algor_params(pkey);
657 		if (params == NULL) {
658 			return -1;
659 		}
660 		X509_ALGOR_set0(alg3,
661 		    OBJ_nid2obj(GostR3410_get_pk_digest(digest)),
662 		    V_ASN1_SEQUENCE, params);
663 	}
664 
665 	return 1;
666 }
667 
668 const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[] = {
669 	{
670 		.pkey_id = EVP_PKEY_GOSTR01,
671 		.pkey_base_id = EVP_PKEY_GOSTR01,
672 		.pkey_flags = ASN1_PKEY_SIGPARAM_NULL,
673 
674 		.pem_str = "GOST2001",
675 		.info = "GOST R 34.10-2001",
676 
677 		.pkey_free = pkey_free_gost01,
678 		.pkey_ctrl = pkey_ctrl_gost01,
679 
680 		.priv_decode = priv_decode_gost01,
681 		.priv_encode = priv_encode_gost01,
682 		.priv_print = priv_print_gost01,
683 
684 		.param_decode = param_decode_gost01,
685 		.param_encode = param_encode_gost01,
686 		.param_missing = param_missing_gost01,
687 		.param_copy = param_copy_gost01,
688 		.param_cmp = param_cmp_gost01,
689 		.param_print = param_print_gost01,
690 
691 		.pub_decode = pub_decode_gost01,
692 		.pub_encode = pub_encode_gost01,
693 		.pub_cmp = pub_cmp_gost01,
694 		.pub_print = pub_print_gost01,
695 		.pkey_size = pkey_size_gost01,
696 		.pkey_bits = pkey_bits_gost01,
697 	},
698 	{
699 		.pkey_id = EVP_PKEY_GOSTR12_256,
700 		.pkey_base_id = EVP_PKEY_GOSTR01,
701 		.pkey_flags = ASN1_PKEY_ALIAS
702 	},
703 	{
704 		.pkey_id = EVP_PKEY_GOSTR12_512,
705 		.pkey_base_id = EVP_PKEY_GOSTR01,
706 		.pkey_flags = ASN1_PKEY_ALIAS
707 	},
708 };
709 
710 #endif
711