1 /* $OpenBSD: gostr341001_ameth.c,v 1.8 2015/02/11 04:05:14 beck 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 #ifndef OPENSSL_NO_CMS
65 #include <openssl/cms.h>
66 #endif
67 
68 #include "asn1_locl.h"
69 #include "gost_locl.h"
70 #include "gost_asn1.h"
71 
72 static void
73 pkey_free_gost01(EVP_PKEY *key)
74 {
75 	GOST_KEY_free(key->pkey.gost);
76 }
77 
78 /*
79  * Parses GOST algorithm parameters from X509_ALGOR and
80  * modifies pkey setting NID and parameters
81  */
82 static int
83 decode_gost01_algor_params(EVP_PKEY *pkey, const unsigned char **p, int len)
84 {
85 	int param_nid = NID_undef, digest_nid = NID_undef;
86 	GOST_KEY_PARAMS *gkp = NULL;
87 	EC_GROUP *group;
88 	GOST_KEY *ec;
89 
90 	gkp = d2i_GOST_KEY_PARAMS(NULL, p, len);
91 	if (gkp == NULL) {
92 		GOSTerr(GOST_F_DECODE_GOST01_ALGOR_PARAMS,
93 			GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
94 		return 0;
95 	}
96 	param_nid = OBJ_obj2nid(gkp->key_params);
97 	digest_nid = OBJ_obj2nid(gkp->hash_params);
98 	GOST_KEY_PARAMS_free(gkp);
99 
100 	ec = pkey->pkey.gost;
101 	if (ec == NULL) {
102 		ec = GOST_KEY_new();
103 		if (ec == NULL)
104 			return 0;
105 		if (EVP_PKEY_assign_GOST(pkey, ec) == 0)
106 			return 0;
107 	}
108 
109 	group = EC_GROUP_new_by_curve_name(param_nid);
110 	if (group == NULL)
111 		return 0;
112 	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
113 	if (GOST_KEY_set_group(ec, group) == 0) {
114 		EC_GROUP_free(group);
115 		return 0;
116 	}
117 	EC_GROUP_free(group);
118 	if (GOST_KEY_set_digest(ec, digest_nid) == 0)
119 		return 0;
120 	return 1;
121 }
122 
123 static ASN1_STRING *
124 encode_gost01_algor_params(const EVP_PKEY *key)
125 {
126 	ASN1_STRING *params = ASN1_STRING_new();
127 	GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
128 	int pkey_param_nid = NID_undef;
129 
130 	if (params == NULL || gkp == NULL) {
131 		GOSTerr(GOST_F_ENCODE_GOST01_ALGOR_PARAMS,
132 		    ERR_R_MALLOC_FAILURE);
133 		ASN1_STRING_free(params);
134 		params = NULL;
135 		goto err;
136 	}
137 
138 	pkey_param_nid =
139 	    EC_GROUP_get_curve_name(GOST_KEY_get0_group(key->pkey.gost));
140 	gkp->key_params = OBJ_nid2obj(pkey_param_nid);
141 	gkp->hash_params = OBJ_nid2obj(GOST_KEY_get_digest(key->pkey.gost));
142 	/*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid); */
143 	params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
144 	if (params->length <= 0) {
145 		GOSTerr(GOST_F_ENCODE_GOST01_ALGOR_PARAMS,
146 		    ERR_R_MALLOC_FAILURE);
147 		ASN1_STRING_free(params);
148 		params = NULL;
149 		goto err;
150 	}
151 	params->type = V_ASN1_SEQUENCE;
152 err:
153 	GOST_KEY_PARAMS_free(gkp);
154 	return params;
155 }
156 
157 static int
158 pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
159 {
160 	const GOST_KEY *ea = a->pkey.gost;
161 	const GOST_KEY *eb = b->pkey.gost;
162 	const EC_POINT *ka, *kb;
163 	int ret = 0;
164 
165 	if (ea == NULL || eb == NULL)
166 		return 0;
167 	ka = GOST_KEY_get0_public_key(ea);
168 	kb = GOST_KEY_get0_public_key(eb);
169 	if (ka == NULL || kb == NULL)
170 		return 0;
171 	ret = (0 == EC_POINT_cmp(GOST_KEY_get0_group(ea), ka, kb, NULL));
172 	return ret;
173 }
174 
175 static int
176 pkey_size_gost01(const EVP_PKEY *pk)
177 {
178 	if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
179 		return 128;
180 	return 64;
181 }
182 
183 static int
184 pkey_bits_gost01(const EVP_PKEY *pk)
185 {
186 	if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
187 		return 512;
188 	return 256;
189 }
190 
191 static int
192 pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub)
193 {
194 	X509_ALGOR *palg = NULL;
195 	const unsigned char *pubkey_buf = NULL;
196 	const unsigned char *p;
197 	ASN1_OBJECT *palgobj = NULL;
198 	int pub_len;
199 	BIGNUM *X, *Y;
200 	ASN1_OCTET_STRING *octet = NULL;
201 	int len;
202 	int ret;
203 	int ptype = V_ASN1_UNDEF;
204 	ASN1_STRING *pval = NULL;
205 
206 	if (X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub)
207 	    == 0)
208 		return 0;
209 	(void)EVP_PKEY_assign_GOST(pk, NULL);
210 	X509_ALGOR_get0(NULL, &ptype, (void **)&pval, palg);
211 	if (ptype != V_ASN1_SEQUENCE) {
212 		GOSTerr(GOST_F_PUB_DECODE_GOST01,
213 		    GOST_R_BAD_KEY_PARAMETERS_FORMAT);
214 		return 0;
215 	}
216 	p = pval->data;
217 	if (decode_gost01_algor_params(pk, &p, pval->length) == 0)
218 		return 0;
219 
220 	octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
221 	if (octet == NULL) {
222 		GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_MALLOC_FAILURE);
223 		return 0;
224 	}
225 	len = octet->length / 2;
226 
227 	X = GOST_le2bn(octet->data, len, NULL);
228 	Y = GOST_le2bn(octet->data + len, len, NULL);
229 
230 	ASN1_OCTET_STRING_free(octet);
231 
232 	ret = GOST_KEY_set_public_key_affine_coordinates(pk->pkey.gost, X, Y);
233 	if (ret == 0)
234 		GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB);
235 
236 	BN_free(X);
237 	BN_free(Y);
238 
239 	return ret;
240 }
241 
242 static int
243 pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
244 {
245 	ASN1_OBJECT *algobj = NULL;
246 	ASN1_OCTET_STRING *octet = NULL;
247 	ASN1_STRING *params = NULL;
248 	void *pval = NULL;
249 	unsigned char *buf = NULL, *sptr;
250 	int key_size, ret = 0;
251 	const EC_POINT *pub_key;
252 	BIGNUM *X = NULL, *Y = NULL;
253 	const GOST_KEY *ec = pk->pkey.gost;
254 	int ptype = V_ASN1_UNDEF;
255 
256 	algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(ec)));
257 	if (pk->save_parameters) {
258 		params = encode_gost01_algor_params(pk);
259 		if (params == NULL)
260 			return 0;
261 		pval = params;
262 		ptype = V_ASN1_SEQUENCE;
263 	}
264 
265 	key_size = GOST_KEY_get_size(ec);
266 
267 	pub_key = GOST_KEY_get0_public_key(ec);
268 	if (pub_key == NULL) {
269 		GOSTerr(GOST_F_PUB_ENCODE_GOST01, GOST_R_PUBLIC_KEY_UNDEFINED);
270 		goto err;
271 	}
272 
273 	octet = ASN1_OCTET_STRING_new();
274 	if (octet == NULL) {
275 		GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
276 		goto err;
277 	}
278 
279 	ret = ASN1_STRING_set(octet, NULL, 2 * key_size);
280 	if (ret == 0) {
281 		GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_INTERNAL_ERROR);
282 		goto err;
283 	}
284 
285 	sptr = ASN1_STRING_data(octet);
286 
287 	X = BN_new();
288 	Y = BN_new();
289 	if (X == NULL || Y == NULL) {
290 		GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE);
291 		goto err;
292 	}
293 
294 	if (EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(ec),
295 	    pub_key, X, Y, NULL) == 0) {
296 		GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_EC_LIB);
297 		goto err;
298 	}
299 
300 	GOST_bn2le(X, sptr, key_size);
301 	GOST_bn2le(Y, sptr + key_size, key_size);
302 
303 	BN_free(Y);
304 	BN_free(X);
305 
306 	ret = i2d_ASN1_OCTET_STRING(octet, &buf);
307 	ASN1_BIT_STRING_free(octet);
308 	if (ret < 0)
309 		return 0;
310 
311 	return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
312 
313 err:
314 	BN_free(Y);
315 	BN_free(X);
316 	ASN1_BIT_STRING_free(octet);
317 	ASN1_STRING_free(params);
318 	return 0;
319 }
320 
321 static int
322 param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
323 {
324 	int param_nid =
325 	    EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost));
326 
327 	if (BIO_indent(out, indent, 128) == 0)
328 		return 0;
329 	BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
330 	if (BIO_indent(out, indent, 128) == 0)
331 		return 0;
332 	BIO_printf(out, "Digest Algorithm: %s\n",
333 	    OBJ_nid2ln(GOST_KEY_get_digest(pkey->pkey.gost)));
334 	return 1;
335 }
336 
337 static int
338 pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
339 {
340 	BN_CTX *ctx = BN_CTX_new();
341 	BIGNUM *X, *Y;
342 	const EC_POINT *pubkey;
343 	const EC_GROUP *group;
344 
345 	if (ctx == NULL) {
346 		GOSTerr(GOST_F_PUB_PRINT_GOST01, ERR_R_MALLOC_FAILURE);
347 		return 0;
348 	}
349 	BN_CTX_start(ctx);
350 	if ((X = BN_CTX_get(ctx)) == NULL)
351 		goto err;
352 	if ((Y = BN_CTX_get(ctx)) == NULL)
353 		goto err;
354 	pubkey = GOST_KEY_get0_public_key(pkey->pkey.gost);
355 	group = GOST_KEY_get0_group(pkey->pkey.gost);
356 	if (EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y,
357 	    ctx) == 0) {
358 		GOSTerr(GOST_F_PUB_PRINT_GOST01, ERR_R_EC_LIB);
359 		goto err;
360 	}
361 	if (BIO_indent(out, indent, 128) == 0)
362 		goto err;
363 	BIO_printf(out, "Public key:\n");
364 	if (BIO_indent(out, indent + 3, 128) == 0)
365 		goto err;
366 	BIO_printf(out, "X:");
367 	BN_print(out, X);
368 	BIO_printf(out, "\n");
369 	BIO_indent(out, indent + 3, 128);
370 	BIO_printf(out, "Y:");
371 	BN_print(out, Y);
372 	BIO_printf(out, "\n");
373 
374 	BN_CTX_end(ctx);
375 	BN_CTX_free(ctx);
376 
377 	return param_print_gost01(out, pkey, indent, pctx);
378 
379 err:
380 	BN_CTX_end(ctx);
381 	BN_CTX_free(ctx);
382 	return 0;
383 }
384 
385 static int
386 priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
387 {
388 	const BIGNUM *key;
389 
390 	if (BIO_indent(out, indent, 128) == 0)
391 		return 0;
392 	BIO_printf(out, "Private key: ");
393 	key = GOST_KEY_get0_private_key(pkey->pkey.gost);
394 	if (key == NULL)
395 		BIO_printf(out, "<undefined)");
396 	else
397 		BN_print(out, key);
398 	BIO_printf(out, "\n");
399 
400 	return pub_print_gost01(out, pkey, indent, pctx);
401 }
402 
403 static int
404 priv_decode_gost01(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf)
405 {
406 	const unsigned char *pkey_buf = NULL, *p = NULL;
407 	int priv_len = 0;
408 	BIGNUM *pk_num = NULL;
409 	int ret = 0;
410 	X509_ALGOR *palg = NULL;
411 	ASN1_OBJECT *palg_obj = NULL;
412 	ASN1_INTEGER *priv_key = NULL;
413 	GOST_KEY *ec;
414 	int ptype = V_ASN1_UNDEF;
415 	ASN1_STRING *pval = NULL;
416 
417 	if (PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf) == 0)
418 		return 0;
419 	(void)EVP_PKEY_assign_GOST(pk, NULL);
420 	X509_ALGOR_get0(NULL, &ptype, (void **)&pval, palg);
421 	if (ptype != V_ASN1_SEQUENCE) {
422 		GOSTerr(GOST_F_PUB_DECODE_GOST01,
423 		    GOST_R_BAD_KEY_PARAMETERS_FORMAT);
424 		return 0;
425 	}
426 	p = pval->data;
427 	if (decode_gost01_algor_params(pk, &p, pval->length) == 0)
428 		return 0;
429 	p = pkey_buf;
430 	if (V_ASN1_OCTET_STRING == *p) {
431 		/* New format - Little endian octet string */
432 		unsigned char rev_buf[32];
433 		int i;
434 		ASN1_OCTET_STRING *s =
435 		    d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
436 
437 		if (s == NULL || s->length != 32) {
438 			GOSTerr(GOST_F_PRIV_DECODE_GOST01, EVP_R_DECODE_ERROR);
439 			ASN1_STRING_free(s);
440 			return 0;
441 		}
442 		for (i = 0; i < 32; i++) {
443 			rev_buf[31 - i] = s->data[i];
444 		}
445 		ASN1_STRING_free(s);
446 		pk_num = BN_bin2bn(rev_buf, 32, NULL);
447 	} else {
448 		priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
449 		if (priv_key == NULL)
450 			return 0;
451 		ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
452 		ASN1_INTEGER_free(priv_key);
453 		if (ret == 0) {
454 			GOSTerr(GOST_F_PRIV_DECODE_GOST01, EVP_R_DECODE_ERROR);
455 			return 0;
456 		}
457 	}
458 
459 	ec = pk->pkey.gost;
460 	if (ec == NULL) {
461 		ec = GOST_KEY_new();
462 		if (ec == NULL) {
463 			BN_free(pk_num);
464 			return 0;
465 		}
466 		if (EVP_PKEY_assign_GOST(pk, ec) == 0) {
467 			BN_free(pk_num);
468 			GOST_KEY_free(ec);
469 			return 0;
470 		}
471 	}
472 	if (GOST_KEY_set_private_key(ec, pk_num) == 0) {
473 		BN_free(pk_num);
474 		return 0;
475 	}
476 	ret = 0;
477 	if (EVP_PKEY_missing_parameters(pk) == 0)
478 		ret = gost2001_compute_public(ec) != 0;
479 	BN_free(pk_num);
480 
481 	return ret;
482 }
483 
484 static int
485 priv_encode_gost01(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
486 {
487 	ASN1_OBJECT *algobj =
488 	    OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost)));
489 	ASN1_STRING *params = encode_gost01_algor_params(pk);
490 	unsigned char *priv_buf = NULL;
491 	int priv_len;
492 	ASN1_INTEGER *asn1key = NULL;
493 
494 	if (params == NULL)
495 		return 0;
496 
497 	asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost),
498 	    NULL);
499 	if (asn1key == NULL) {
500 		ASN1_STRING_free(params);
501 		return 0;
502 	}
503 	priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf);
504 	ASN1_INTEGER_free(asn1key);
505 	return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, priv_buf,
506 	    priv_len);
507 }
508 
509 static int
510 param_encode_gost01(const EVP_PKEY *pkey, unsigned char **pder)
511 {
512 	ASN1_STRING *params = encode_gost01_algor_params(pkey);
513 	int len;
514 
515 	if (params == NULL)
516 		return 0;
517 	len = params->length;
518 	if (pder != NULL)
519 		memcpy(*pder, params->data, params->length);
520 	ASN1_STRING_free(params);
521 	return len;
522 }
523 
524 static int
525 param_decode_gost01(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
526 {
527 	ASN1_OBJECT *obj = NULL;
528 	int nid;
529 	GOST_KEY *ec;
530 	EC_GROUP *group;
531 	int ret;
532 
533 	/* New format */
534 	if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == **pder)
535 		return decode_gost01_algor_params(pkey, pder, derlen);
536 
537 	/* Compatibility */
538 	if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
539 		GOSTerr(GOST_F_PARAM_DECODE_GOST01, ERR_R_MALLOC_FAILURE);
540 		return 0;
541 	}
542 	nid = OBJ_obj2nid(obj);
543 	ASN1_OBJECT_free(obj);
544 
545 	ec = GOST_KEY_new();
546 	if (ec == NULL) {
547 		GOSTerr(GOST_F_PARAM_DECODE_GOST01, ERR_R_MALLOC_FAILURE);
548 		return 0;
549 	}
550 	group = EC_GROUP_new_by_curve_name(nid);
551 	if (group == NULL) {
552 		GOSTerr(GOST_F_PARAM_DECODE_GOST01,
553 		    EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
554 		GOST_KEY_free(ec);
555 		return 0;
556 	}
557 
558 	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
559 	if (GOST_KEY_set_group(ec, group) == 0) {
560 		GOSTerr(GOST_F_PARAM_DECODE_GOST01, ERR_R_EC_LIB);
561 		EC_GROUP_free(group);
562 		GOST_KEY_free(ec);
563 		return 0;
564 	}
565 	EC_GROUP_free(group);
566 	if (GOST_KEY_set_digest(ec,
567 	    NID_id_GostR3411_94_CryptoProParamSet) == 0) {
568 		GOSTerr(GOST_F_PARAM_DECODE_GOST01, GOST_R_INVALID_DIGEST_TYPE);
569 		GOST_KEY_free(ec);
570 		return 0;
571 	}
572 	ret = EVP_PKEY_assign_GOST(pkey, ec);
573 	if (ret == 0)
574 		GOST_KEY_free(ec);
575 	return ret;
576 }
577 
578 static int
579 param_missing_gost01(const EVP_PKEY *pk)
580 {
581 	const GOST_KEY *ec = pk->pkey.gost;
582 
583 	if (ec == NULL)
584 		return 1;
585 	if (GOST_KEY_get0_group(ec) == NULL)
586 		return 1;
587 	if (GOST_KEY_get_digest(ec) == NID_undef)
588 		return 1;
589 	return 0;
590 }
591 
592 static int
593 param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
594 {
595 	GOST_KEY *eto = to->pkey.gost;
596 	const GOST_KEY *efrom = from->pkey.gost;
597 	int ret = 1;
598 
599 	if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
600 		GOSTerr(GOST_F_PARAM_COPY_GOST01,
601 		    GOST_R_INCOMPATIBLE_ALGORITHMS);
602 		return 0;
603 	}
604 	if (efrom == NULL) {
605 		GOSTerr(GOST_F_PARAM_COPY_GOST01,
606 		    GOST_R_KEY_PARAMETERS_MISSING);
607 		return 0;
608 	}
609 	if (eto == NULL) {
610 		eto = GOST_KEY_new();
611 		if (eto == NULL) {
612 			GOSTerr(GOST_F_PARAM_COPY_GOST01,
613 			    ERR_R_MALLOC_FAILURE);
614 			return 0;
615 		}
616 		if (EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto) == 0) {
617 			GOST_KEY_free(eto);
618 			return 0;
619 		}
620 	}
621 	GOST_KEY_set_group(eto, GOST_KEY_get0_group(efrom));
622 	GOST_KEY_set_digest(eto, GOST_KEY_get_digest(efrom));
623 	if (GOST_KEY_get0_private_key(eto) != NULL)
624 		ret = gost2001_compute_public(eto);
625 
626 	return ret;
627 }
628 
629 static int
630 param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
631 {
632 	if (EC_GROUP_get_curve_name(GOST_KEY_get0_group(a->pkey.gost)) !=
633 	    EC_GROUP_get_curve_name(GOST_KEY_get0_group(b->pkey.gost)))
634 		return 0;
635 
636 	if (GOST_KEY_get_digest(a->pkey.gost) !=
637 	    GOST_KEY_get_digest(b->pkey.gost))
638 		return 0;
639 
640 	return 1;
641 }
642 
643 static int
644 pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2)
645 {
646 	X509_ALGOR *alg1 = NULL, *alg2 = NULL, *alg3 = NULL;
647 	int digest = GOST_KEY_get_digest(pkey->pkey.gost);
648 
649 	switch (op) {
650 	case ASN1_PKEY_CTRL_PKCS7_SIGN:
651 		if (arg1 == 0)
652 			PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
653 		break;
654 
655 	case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
656 		if (arg1 == 0)
657 			PKCS7_RECIP_INFO_get0_alg(arg2, &alg3);
658 		break;
659 #ifndef OPENSSL_NO_CMS
660 	case ASN1_PKEY_CTRL_CMS_SIGN:
661 		if (arg1 == 0)
662 			CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
663 		break;
664 
665 	case ASN1_PKEY_CTRL_CMS_ENVELOPE:
666 		if (arg1 == 0)
667 			CMS_RecipientInfo_ktri_get0_algs(arg2, NULL, NULL, &alg3);
668 		break;
669 #endif
670 	case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
671 		*(int *)arg2 = GostR3410_get_md_digest(digest);
672 		return 2;
673 
674 	default:
675 		return -2;
676 	}
677 
678 	if (alg1)
679 		X509_ALGOR_set0(alg1, OBJ_nid2obj(GostR3410_get_md_digest(digest)), V_ASN1_NULL, 0);
680 	if (alg2)
681 		X509_ALGOR_set0(alg2, OBJ_nid2obj(GostR3410_get_pk_digest(digest)), V_ASN1_NULL, 0);
682 	if (alg3) {
683 		ASN1_STRING *params = encode_gost01_algor_params(pkey);
684 		if (params == NULL) {
685 			return -1;
686 		}
687 		X509_ALGOR_set0(alg3,
688 		    OBJ_nid2obj(GostR3410_get_pk_digest(digest)),
689 		    V_ASN1_SEQUENCE, params);
690 	}
691 
692 	return 1;
693 }
694 
695 const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[] = {
696 	{
697 		.pkey_id = EVP_PKEY_GOSTR01,
698 		.pkey_base_id = EVP_PKEY_GOSTR01,
699 		.pkey_flags = ASN1_PKEY_SIGPARAM_NULL,
700 
701 		.pem_str = "GOST2001",
702 		.info = "GOST R 34.10-2001",
703 
704 		.pkey_free = pkey_free_gost01,
705 		.pkey_ctrl = pkey_ctrl_gost01,
706 
707 		.priv_decode = priv_decode_gost01,
708 		.priv_encode = priv_encode_gost01,
709 		.priv_print = priv_print_gost01,
710 
711 		.param_decode = param_decode_gost01,
712 		.param_encode = param_encode_gost01,
713 		.param_missing = param_missing_gost01,
714 		.param_copy = param_copy_gost01,
715 		.param_cmp = param_cmp_gost01,
716 		.param_print = param_print_gost01,
717 
718 		.pub_decode = pub_decode_gost01,
719 		.pub_encode = pub_encode_gost01,
720 		.pub_cmp = pub_cmp_gost01,
721 		.pub_print = pub_print_gost01,
722 		.pkey_size = pkey_size_gost01,
723 		.pkey_bits = pkey_bits_gost01,
724 	},
725 	{
726 		.pkey_id = EVP_PKEY_GOSTR12_256,
727 		.pkey_base_id = EVP_PKEY_GOSTR01,
728 		.pkey_flags = ASN1_PKEY_ALIAS
729 	},
730 	{
731 		.pkey_id = EVP_PKEY_GOSTR12_512,
732 		.pkey_base_id = EVP_PKEY_GOSTR01,
733 		.pkey_flags = ASN1_PKEY_ALIAS
734 	},
735 };
736 
737 #endif
738