1 /* $OpenBSD: gostr341001_pmeth.c,v 1.14 2017/01/29 17:49:23 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/err.h>
60 #include <openssl/gost.h>
61 #include <openssl/ec.h>
62 #include <openssl/ecdsa.h>
63 #include <openssl/x509.h>
64 
65 #include "evp_locl.h"
66 #include "gost_locl.h"
67 #include "gost_asn1.h"
68 
69 static ECDSA_SIG *
70 unpack_signature_cp(const unsigned char *sig, size_t siglen)
71 {
72 	ECDSA_SIG *s;
73 
74 	s = ECDSA_SIG_new();
75 	if (s == NULL) {
76 		GOSTerror(ERR_R_MALLOC_FAILURE);
77 		return NULL;
78 	}
79 	BN_bin2bn(sig, siglen / 2, s->s);
80 	BN_bin2bn(sig + siglen / 2, siglen / 2, s->r);
81 	return s;
82 }
83 
84 static int
85 pack_signature_cp(ECDSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
86 {
87 	int r_len = BN_num_bytes(s->r);
88 	int s_len = BN_num_bytes(s->s);
89 
90 	if (r_len > order || s_len > order)
91 		return 0;
92 
93 	*siglen = 2 * order;
94 
95 	memset(sig, 0, *siglen);
96 	BN_bn2bin(s->s, sig + order - s_len);
97 	BN_bn2bin(s->r, sig + 2 * order - r_len);
98 	ECDSA_SIG_free(s);
99 	return 1;
100 }
101 
102 static ECDSA_SIG *
103 unpack_signature_le(const unsigned char *sig, size_t siglen)
104 {
105 	ECDSA_SIG *s;
106 
107 	s = ECDSA_SIG_new();
108 	if (s == NULL) {
109 		GOSTerror(ERR_R_MALLOC_FAILURE);
110 		return NULL;
111 	}
112 	GOST_le2bn(sig, siglen / 2, s->r);
113 	GOST_le2bn(sig + siglen / 2, siglen / 2, s->s);
114 	return s;
115 }
116 
117 static int
118 pack_signature_le(ECDSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
119 {
120 	*siglen = 2 * order;
121 	memset(sig, 0, *siglen);
122 	GOST_bn2le(s->r, sig, order);
123 	GOST_bn2le(s->s, sig + order, order);
124 	ECDSA_SIG_free(s);
125 	return 1;
126 }
127 
128 struct gost_pmeth_data {
129 	int sign_param_nid; /* Should be set whenever parameters are filled */
130 	int digest_nid;
131 	EVP_MD *md;
132 	unsigned char *shared_ukm;
133 	int peer_key_used;
134 	int sig_format;
135 };
136 
137 static int
138 pkey_gost01_init(EVP_PKEY_CTX *ctx)
139 {
140 	struct gost_pmeth_data *data;
141 	EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
142 
143 	data = calloc(1, sizeof(struct gost_pmeth_data));
144 	if (data == NULL)
145 		return 0;
146 
147 	if (pkey != NULL && pkey->pkey.gost != NULL) {
148 		data->sign_param_nid =
149 		    EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost));
150 		data->digest_nid = GOST_KEY_get_digest(pkey->pkey.gost);
151 	}
152 	EVP_PKEY_CTX_set_data(ctx, data);
153 	return 1;
154 }
155 
156 /* Copies contents of gost_pmeth_data structure */
157 static int
158 pkey_gost01_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
159 {
160 	struct gost_pmeth_data *dst_data, *src_data;
161 
162 	if (pkey_gost01_init(dst) == 0)
163 		return 0;
164 
165 	src_data = EVP_PKEY_CTX_get_data(src);
166 	dst_data = EVP_PKEY_CTX_get_data(dst);
167 	*dst_data = *src_data;
168 	if (src_data->shared_ukm != NULL)
169 		dst_data->shared_ukm = NULL;
170 	return 1;
171 }
172 
173 /* Frees up gost_pmeth_data structure */
174 static void
175 pkey_gost01_cleanup(EVP_PKEY_CTX *ctx)
176 {
177 	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
178 
179 	free(data->shared_ukm);
180 	free(data);
181 }
182 
183 static int
184 pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
185 {
186 	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
187 	EC_GROUP *group = NULL;
188 	GOST_KEY *gost = NULL;
189 	int ret = 0;
190 
191 	if (data->sign_param_nid == NID_undef ||
192 	    data->digest_nid == NID_undef) {
193 		GOSTerror(GOST_R_NO_PARAMETERS_SET);
194 		return 0;
195 	}
196 
197 	group = EC_GROUP_new_by_curve_name(data->sign_param_nid);
198 	if (group == NULL)
199 		goto done;
200 
201 	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
202 
203 	gost = GOST_KEY_new();
204 	if (gost == NULL)
205 		goto done;
206 
207 	if (GOST_KEY_set_digest(gost, data->digest_nid) == 0)
208 		goto done;
209 
210 	if (GOST_KEY_set_group(gost, group) != 0)
211 		ret = EVP_PKEY_assign_GOST(pkey, gost);
212 
213 done:
214 	if (ret == 0)
215 		GOST_KEY_free(gost);
216 	EC_GROUP_free(group);
217 	return ret;
218 }
219 
220 static int
221 pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
222 {
223 	if (pkey_gost01_paramgen(ctx, pkey) == 0)
224 		return 0;
225 	return gost2001_keygen(pkey->pkey.gost) != 0;
226 }
227 
228 static int
229 pkey_gost01_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
230     const unsigned char *tbs, size_t tbs_len)
231 {
232 	ECDSA_SIG *unpacked_sig = NULL;
233 	EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
234 	struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
235 	BIGNUM *md;
236 	size_t size;
237 	int ret;
238 
239 	if (pkey == NULL || pkey->pkey.gost == NULL)
240 		return 0;
241 	size = GOST_KEY_get_size(pkey->pkey.gost);
242 
243 	if (siglen == NULL)
244 		return 0;
245 	if (sig == NULL) {
246 		*siglen = 2 * size;
247 		return 1;
248 	} else if (*siglen < 2 * size) {
249 		GOSTerror(EC_R_BUFFER_TOO_SMALL);
250 		return 0;
251 	}
252 	if (tbs_len != 32 && tbs_len != 64) {
253 		GOSTerror(EVP_R_BAD_BLOCK_LENGTH);
254 		return 0;
255 	}
256 	md = GOST_le2bn(tbs, tbs_len, NULL);
257 	if (md == NULL)
258 		return 0;
259 	unpacked_sig = gost2001_do_sign(md, pkey->pkey.gost);
260 	BN_free(md);
261 	if (unpacked_sig == NULL) {
262 		return 0;
263 	}
264 	switch (pctx->sig_format) {
265 	case GOST_SIG_FORMAT_SR_BE:
266 		ret = pack_signature_cp(unpacked_sig, size, sig, siglen);
267 		break;
268 	case GOST_SIG_FORMAT_RS_LE:
269 		ret = pack_signature_le(unpacked_sig, size, sig, siglen);
270 		break;
271 	default:
272 		ret = -1;
273 		break;
274 	}
275 	if (ret <= 0)
276 		ECDSA_SIG_free(unpacked_sig);
277 	return ret;
278 }
279 
280 static int
281 pkey_gost01_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
282     const unsigned char *tbs, size_t tbs_len)
283 {
284 	int ok = 0;
285 	EVP_PKEY *pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
286 	struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
287 	ECDSA_SIG *s = NULL;
288 	BIGNUM *md;
289 
290 	if (pub_key == NULL)
291 		return 0;
292 	switch (pctx->sig_format) {
293 	case GOST_SIG_FORMAT_SR_BE:
294 		s = unpack_signature_cp(sig, siglen);
295 		break;
296 	case GOST_SIG_FORMAT_RS_LE:
297 		s = unpack_signature_le(sig, siglen);
298 		break;
299 	}
300 	if (s == NULL)
301 		return 0;
302 	md = GOST_le2bn(tbs, tbs_len, NULL);
303 	if (md == NULL)
304 		goto err;
305 	ok = gost2001_do_verify(md, s, pub_key->pkey.gost);
306 
307 err:
308 	BN_free(md);
309 	ECDSA_SIG_free(s);
310 	return ok;
311 }
312 
313 static int
314 gost01_VKO_key(EVP_PKEY *pub_key, EVP_PKEY *priv_key, const unsigned char *ukm,
315     unsigned char *key)
316 {
317 	unsigned char hashbuf[128];
318 	int digest_nid;
319 	int ret = 0;
320 	BN_CTX *ctx = BN_CTX_new();
321 	BIGNUM *UKM, *X, *Y;
322 
323 	if (ctx == NULL)
324 		return 0;
325 
326 	BN_CTX_start(ctx);
327 	if ((UKM = BN_CTX_get(ctx)) == NULL)
328 		goto err;
329 	if ((X = BN_CTX_get(ctx)) == NULL)
330 		goto err;
331 	if ((Y = BN_CTX_get(ctx)) == NULL)
332 		goto err;
333 
334 	GOST_le2bn(ukm, 8, UKM);
335 
336 	digest_nid = GOST_KEY_get_digest(priv_key->pkey.gost);
337 	if (VKO_compute_key(X, Y, pub_key->pkey.gost, priv_key->pkey.gost,
338 	    UKM) == 0)
339 		goto err;
340 
341 	switch (digest_nid) {
342 	case NID_id_GostR3411_94_CryptoProParamSet:
343 		GOST_bn2le(X, hashbuf, 32);
344 		GOST_bn2le(Y, hashbuf + 32, 32);
345 		GOSTR341194(hashbuf, 64, key, digest_nid);
346 		ret = 1;
347 		break;
348 	case NID_id_tc26_gost3411_2012_256:
349 		GOST_bn2le(X, hashbuf, 32);
350 		GOST_bn2le(Y, hashbuf + 32, 32);
351 		STREEBOG256(hashbuf, 64, key);
352 		ret = 1;
353 		break;
354 	case NID_id_tc26_gost3411_2012_512:
355 		GOST_bn2le(X, hashbuf, 64);
356 		GOST_bn2le(Y, hashbuf + 64, 64);
357 		STREEBOG256(hashbuf, 128, key);
358 		ret = 1;
359 		break;
360 	default:
361 		ret = -2;
362 		break;
363 	}
364 err:
365 	BN_CTX_end(ctx);
366 	BN_CTX_free(ctx);
367 	return ret;
368 }
369 
370 int
371 pkey_gost01_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len,
372     const unsigned char *in, size_t in_len)
373 {
374 	const unsigned char *p = in;
375 	EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx);
376 	GOST_KEY_TRANSPORT *gkt = NULL;
377 	int ret = 0;
378 	unsigned char wrappedKey[44];
379 	unsigned char sharedKey[32];
380 	EVP_PKEY *eph_key = NULL, *peerkey = NULL;
381 	int nid;
382 
383 	if (key == NULL) {
384 		*key_len = 32;
385 		return 1;
386 	}
387 	gkt = d2i_GOST_KEY_TRANSPORT(NULL, (const unsigned char **)&p, in_len);
388 	if (gkt == NULL) {
389 		GOSTerror(GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
390 		return -1;
391 	}
392 
393 	/* If key transport structure contains public key, use it */
394 	eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
395 	if (eph_key != NULL) {
396 		if (EVP_PKEY_derive_set_peer(pctx, eph_key) <= 0) {
397 			GOSTerror(GOST_R_INCOMPATIBLE_PEER_KEY);
398 			goto err;
399 		}
400 	} else {
401 		/* Set control "public key from client certificate used" */
402 		if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3,
403 		    NULL) <= 0) {
404 			GOSTerror(GOST_R_CTRL_CALL_FAILED);
405 			goto err;
406 		}
407 	}
408 	peerkey = EVP_PKEY_CTX_get0_peerkey(pctx);
409 	if (peerkey == NULL) {
410 		GOSTerror(GOST_R_NO_PEER_KEY);
411 		goto err;
412 	}
413 
414 	nid = OBJ_obj2nid(gkt->key_agreement_info->cipher);
415 
416 	if (gkt->key_agreement_info->eph_iv->length != 8) {
417 		GOSTerror(GOST_R_INVALID_IV_LENGTH);
418 		goto err;
419 	}
420 	memcpy(wrappedKey, gkt->key_agreement_info->eph_iv->data, 8);
421 	if (gkt->key_info->encrypted_key->length != 32) {
422 		GOSTerror(EVP_R_BAD_KEY_LENGTH);
423 		goto err;
424 	}
425 	memcpy(wrappedKey + 8, gkt->key_info->encrypted_key->data, 32);
426 	if (gkt->key_info->imit->length != 4) {
427 		GOSTerror(ERR_R_INTERNAL_ERROR);
428 		goto err;
429 	}
430 	memcpy(wrappedKey + 40, gkt->key_info->imit->data, 4);
431 	if (gost01_VKO_key(peerkey, priv, wrappedKey, sharedKey) <= 0)
432 		goto err;
433 	if (gost_key_unwrap_crypto_pro(nid, sharedKey, wrappedKey, key) == 0) {
434 		GOSTerror(GOST_R_ERROR_COMPUTING_SHARED_KEY);
435 		goto err;
436 	}
437 
438 	ret = 1;
439 err:
440 	EVP_PKEY_free(eph_key);
441 	GOST_KEY_TRANSPORT_free(gkt);
442 	return ret;
443 }
444 
445 int
446 pkey_gost01_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
447 {
448 	/*
449 	 * Public key of peer in the ctx field peerkey
450 	 * Our private key in the ctx pkey
451 	 * ukm is in the algorithm specific context data
452 	 */
453 	EVP_PKEY *my_key = EVP_PKEY_CTX_get0_pkey(ctx);
454 	EVP_PKEY *peer_key = EVP_PKEY_CTX_get0_peerkey(ctx);
455 	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
456 
457 	if (data->shared_ukm == NULL) {
458 		GOSTerror(GOST_R_UKM_NOT_SET);
459 		return 0;
460 	}
461 
462 	if (key == NULL) {
463 		*keylen = 32;
464 		return 32;
465 	}
466 
467 	if (gost01_VKO_key(peer_key, my_key, data->shared_ukm, key) <= 0)
468 		return 0;
469 
470 	*keylen = 32;
471 	return 1;
472 }
473 
474 int
475 pkey_gost01_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len,
476     const unsigned char *key, size_t key_len)
477 {
478 	GOST_KEY_TRANSPORT *gkt = NULL;
479 	EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx);
480 	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx);
481 	unsigned char ukm[8], shared_key[32], crypted_key[44];
482 	int ret = 0;
483 	int key_is_ephemeral;
484 	EVP_PKEY *sec_key = EVP_PKEY_CTX_get0_peerkey(pctx);
485 	int nid = NID_id_Gost28147_89_CryptoPro_A_ParamSet;
486 
487 	if (data->shared_ukm != NULL) {
488 		memcpy(ukm, data->shared_ukm, 8);
489 	} else /* if (out != NULL) */ {
490 		arc4random_buf(ukm, 8);
491 	}
492 	/* Check for private key in the peer_key of context */
493 	if (sec_key) {
494 		key_is_ephemeral = 0;
495 		if (GOST_KEY_get0_private_key(sec_key->pkey.gost) == 0) {
496 			GOSTerror(GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR);
497 			goto err;
498 		}
499 	} else {
500 		key_is_ephemeral = 1;
501 		if (out != NULL) {
502 			GOST_KEY *tmp_key;
503 
504 			sec_key = EVP_PKEY_new();
505 			if (sec_key == NULL)
506 				goto err;
507 			tmp_key = GOST_KEY_new();
508 			if (tmp_key == NULL)
509 				goto err;
510 			if (EVP_PKEY_assign(sec_key, EVP_PKEY_base_id(pubk),
511 			    tmp_key) == 0) {
512 				GOST_KEY_free(tmp_key);
513 				goto err;
514 			}
515 			if (EVP_PKEY_copy_parameters(sec_key, pubk) == 0)
516 				goto err;
517 			if (gost2001_keygen(sec_key->pkey.gost) == 0) {
518 				goto err;
519 			}
520 		}
521 	}
522 
523 	if (out != NULL) {
524 		if (gost01_VKO_key(pubk, sec_key, ukm, shared_key) <= 0)
525 			goto err;
526 		gost_key_wrap_crypto_pro(nid, shared_key, ukm, key,
527 		    crypted_key);
528 	}
529 	gkt = GOST_KEY_TRANSPORT_new();
530 	if (gkt == NULL)
531 		goto err;
532 	if (ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm, 8) == 0)
533 		goto err;
534 	if (ASN1_OCTET_STRING_set(gkt->key_info->imit, crypted_key + 40,
535 	    4) == 0)
536 		goto err;
537 	if (ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key, crypted_key + 8,
538 	    32) == 0)
539 		goto err;
540 	if (key_is_ephemeral) {
541 		if (X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,
542 		    out != NULL ? sec_key : pubk) == 0) {
543 			GOSTerror(GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
544 			goto err;
545 		}
546 	}
547 	ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
548 	gkt->key_agreement_info->cipher = OBJ_nid2obj(nid);
549 	if (key_is_ephemeral)
550 		EVP_PKEY_free(sec_key);
551 	else {
552 		/* Set control "public key from client certificate used" */
553 		if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3,
554 		    NULL) <= 0) {
555 			GOSTerror(GOST_R_CTRL_CALL_FAILED);
556 			goto err;
557 		}
558 	}
559 	if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt, out ? &out : NULL)) > 0)
560 		ret = 1;
561 	GOST_KEY_TRANSPORT_free(gkt);
562 	return ret;
563 
564 err:
565 	if (key_is_ephemeral)
566 		EVP_PKEY_free(sec_key);
567 	GOST_KEY_TRANSPORT_free(gkt);
568 	return -1;
569 }
570 
571 
572 static int
573 pkey_gost01_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
574 {
575 	struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
576 
577 	switch (type) {
578 	case EVP_PKEY_CTRL_MD:
579 		if (EVP_MD_type(p2) !=
580 		    GostR3410_get_md_digest(pctx->digest_nid)) {
581 			GOSTerror(GOST_R_INVALID_DIGEST_TYPE);
582 			return 0;
583 		}
584 		pctx->md = p2;
585 		return 1;
586 	case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
587 	case EVP_PKEY_CTRL_PKCS7_DECRYPT:
588 	case EVP_PKEY_CTRL_PKCS7_SIGN:
589 	case EVP_PKEY_CTRL_DIGESTINIT:
590 		return 1;
591 
592 	case EVP_PKEY_CTRL_GOST_PARAMSET:
593 		pctx->sign_param_nid = (int)p1;
594 		return 1;
595 
596 	case EVP_PKEY_CTRL_SET_IV:
597 	    {
598 		char *ukm = malloc(p1);
599 
600 		if (ukm == NULL) {
601 			GOSTerror(ERR_R_MALLOC_FAILURE);
602 			return 0;
603 		}
604 		memcpy(ukm, p2, p1);
605 		free(pctx->shared_ukm);
606 		pctx->shared_ukm = ukm;
607 		return 1;
608 	    }
609 
610 	case EVP_PKEY_CTRL_PEER_KEY:
611 		if (p1 == 0 || p1 == 1)	/* call from EVP_PKEY_derive_set_peer */
612 			return 1;
613 		if (p1 == 2)	/* TLS: peer key used? */
614 			return pctx->peer_key_used;
615 		if (p1 == 3)	/* TLS: peer key used! */
616 			return (pctx->peer_key_used = 1);
617 		return -2;
618 	case EVP_PKEY_CTRL_GOST_SIG_FORMAT:
619 		switch (p1) {
620 		case GOST_SIG_FORMAT_SR_BE:
621 		case GOST_SIG_FORMAT_RS_LE:
622 			pctx->sig_format = p1;
623 			return 1;
624 		default:
625 			return 0;
626 		}
627 		break;
628 	case EVP_PKEY_CTRL_GOST_SET_DIGEST:
629 		pctx->digest_nid = (int)p1;
630 		return 1;
631 	case EVP_PKEY_CTRL_GOST_GET_DIGEST:
632 		*(int *)p2 = pctx->digest_nid;
633 		return 1;
634 	default:
635 		return -2;
636 	}
637 }
638 
639 static int
640 pkey_gost01_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
641 {
642 	int param_nid = NID_undef;
643 	int digest_nid = NID_undef;
644 
645 	if (strcmp(type, "paramset") == 0) {
646 		if (value == NULL)
647 			return 0;
648 		if (pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_GET_DIGEST, 0,
649 		    &digest_nid) == 0)
650 			return 0;
651 		if (digest_nid == NID_id_tc26_gost3411_2012_512)
652 			param_nid = GostR3410_512_param_id(value);
653 		else
654 			param_nid = GostR3410_256_param_id(value);
655 		if (param_nid == NID_undef)
656 			param_nid = OBJ_txt2nid(value);
657 		if (param_nid == NID_undef)
658 			return 0;
659 
660 		return pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
661 		    param_nid, NULL);
662 	}
663 	if (strcmp(type, "dgst") == 0) {
664 		if (value == NULL)
665 			return 0;
666 		else if (strcmp(value, "gost94") == 0 ||
667 		    strcmp(value, "md_gost94") == 0)
668 			digest_nid = NID_id_GostR3411_94_CryptoProParamSet;
669 		else if (strcmp(value, "streebog256") == 0)
670 			digest_nid = NID_id_tc26_gost3411_2012_256;
671 		else if (strcmp(value, "streebog512") == 0)
672 			digest_nid = NID_id_tc26_gost3411_2012_512;
673 
674 		if (digest_nid == NID_undef)
675 			return 0;
676 
677 		return pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_SET_DIGEST,
678 		    digest_nid, NULL);
679 	}
680 	return -2;
681 }
682 
683 const EVP_PKEY_METHOD gostr01_pkey_meth = {
684 	.pkey_id = EVP_PKEY_GOSTR01,
685 
686 	.init = pkey_gost01_init,
687 	.copy = pkey_gost01_copy,
688 	.cleanup = pkey_gost01_cleanup,
689 
690 	.paramgen = pkey_gost01_paramgen,
691 	.keygen = pkey_gost01_keygen,
692 	.sign = pkey_gost01_sign,
693 	.verify = pkey_gost01_verify,
694 
695 	.encrypt = pkey_gost01_encrypt,
696 	.decrypt = pkey_gost01_decrypt,
697 	.derive = pkey_gost01_derive,
698 
699 	.ctrl = pkey_gost01_ctrl,
700 	.ctrl_str = pkey_gost01_ctrl_str,
701 };
702 #endif
703