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