GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/crypto/../../libssl/src/crypto/gost/gostr341001_pmeth.c Lines: 0 349 0.0 %
Date: 2016-12-06 Branches: 0 197 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: gostr341001_pmeth.c,v 1.12 2015/02/14 15:08:37 miod 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
		GOSTerr(GOST_F_UNPACK_SIGNATURE_CP, 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
		GOSTerr(GOST_F_UNPACK_SIGNATURE_LE, 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
		GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN, 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
		GOSTerr(GOST_F_PKEY_GOST01_SIGN, EC_R_BUFFER_TOO_SMALL);
250
		return 0;
251
	}
252
	if (tbs_len != 32 && tbs_len != 64) {
253
		GOSTerr(GOST_F_PKEY_GOST01_SIGN, 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
		GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
390
		    GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
391
		return -1;
392
	}
393
394
	/* If key transport structure contains public key, use it */
395
	eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
396
	if (eph_key != NULL) {
397
		if (EVP_PKEY_derive_set_peer(pctx, eph_key) <= 0) {
398
			GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
399
			    GOST_R_INCOMPATIBLE_PEER_KEY);
400
			goto err;
401
		}
402
	} else {
403
		/* Set control "public key from client certificate used" */
404
		if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3,
405
		    NULL) <= 0) {
406
			GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
407
			    GOST_R_CTRL_CALL_FAILED);
408
			goto err;
409
		}
410
	}
411
	peerkey = EVP_PKEY_CTX_get0_peerkey(pctx);
412
	if (peerkey == NULL) {
413
		GOSTerr(GOST_F_PKEY_GOST01_DECRYPT, GOST_R_NO_PEER_KEY);
414
		goto err;
415
	}
416
417
	nid = OBJ_obj2nid(gkt->key_agreement_info->cipher);
418
419
	if (gkt->key_agreement_info->eph_iv->length != 8) {
420
		GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
421
		    GOST_R_INVALID_IV_LENGTH);
422
		goto err;
423
	}
424
	memcpy(wrappedKey, gkt->key_agreement_info->eph_iv->data, 8);
425
	if (gkt->key_info->encrypted_key->length != 32) {
426
		GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
427
		    EVP_R_BAD_KEY_LENGTH);
428
		goto err;
429
	}
430
	memcpy(wrappedKey + 8, gkt->key_info->encrypted_key->data, 32);
431
	if (gkt->key_info->imit->length != 4) {
432
		GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
433
		    ERR_R_INTERNAL_ERROR);
434
		goto err;
435
	}
436
	memcpy(wrappedKey + 40, gkt->key_info->imit->data, 4);
437
	if (gost01_VKO_key(peerkey, priv, wrappedKey, sharedKey) <= 0)
438
		goto err;
439
	if (gost_key_unwrap_crypto_pro(nid, sharedKey, wrappedKey, key) == 0) {
440
		GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
441
		    GOST_R_ERROR_COMPUTING_SHARED_KEY);
442
		goto err;
443
	}
444
445
	ret = 1;
446
err:
447
	EVP_PKEY_free(eph_key);
448
	GOST_KEY_TRANSPORT_free(gkt);
449
	return ret;
450
}
451
452
int
453
pkey_gost01_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
454
{
455
	/*
456
	 * Public key of peer in the ctx field peerkey
457
	 * Our private key in the ctx pkey
458
	 * ukm is in the algorithm specific context data
459
	 */
460
	EVP_PKEY *my_key = EVP_PKEY_CTX_get0_pkey(ctx);
461
	EVP_PKEY *peer_key = EVP_PKEY_CTX_get0_peerkey(ctx);
462
	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
463
464
	if (data->shared_ukm == NULL) {
465
		GOSTerr(GOST_F_PKEY_GOST01_DERIVE, GOST_R_UKM_NOT_SET);
466
		return 0;
467
	}
468
469
	if (key == NULL) {
470
		*keylen = 32;
471
		return 32;
472
	}
473
474
	if (gost01_VKO_key(peer_key, my_key, data->shared_ukm, key) <= 0)
475
		return 0;
476
477
	*keylen = 32;
478
	return 1;
479
}
480
481
int
482
pkey_gost01_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len,
483
    const unsigned char *key, size_t key_len)
484
{
485
	GOST_KEY_TRANSPORT *gkt = NULL;
486
	EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx);
487
	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx);
488
	unsigned char ukm[8], shared_key[32], crypted_key[44];
489
	int ret = 0;
490
	int key_is_ephemeral;
491
	EVP_PKEY *sec_key = EVP_PKEY_CTX_get0_peerkey(pctx);
492
	int nid = NID_id_Gost28147_89_CryptoPro_A_ParamSet;
493
494
	if (data->shared_ukm != NULL) {
495
		memcpy(ukm, data->shared_ukm, 8);
496
	} else /* if (out != NULL) */ {
497
		arc4random_buf(ukm, 8);
498
	}
499
	/* Check for private key in the peer_key of context */
500
	if (sec_key) {
501
		key_is_ephemeral = 0;
502
		if (GOST_KEY_get0_private_key(sec_key->pkey.gost) == 0) {
503
			GOSTerr(GOST_F_PKEY_GOST01_ENCRYPT,
504
			    GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR);
505
			goto err;
506
		}
507
	} else {
508
		key_is_ephemeral = 1;
509
		if (out != NULL) {
510
			GOST_KEY *tmp_key;
511
512
			sec_key = EVP_PKEY_new();
513
			if (sec_key == NULL)
514
				goto err;
515
			tmp_key = GOST_KEY_new();
516
			if (tmp_key == NULL)
517
				goto err;
518
			if (EVP_PKEY_assign(sec_key, EVP_PKEY_base_id(pubk),
519
			    tmp_key) == 0) {
520
				GOST_KEY_free(tmp_key);
521
				goto err;
522
			}
523
			if (EVP_PKEY_copy_parameters(sec_key, pubk) == 0)
524
				goto err;
525
			if (gost2001_keygen(sec_key->pkey.gost) == 0) {
526
				goto err;
527
			}
528
		}
529
	}
530
531
	if (out != NULL) {
532
		if (gost01_VKO_key(pubk, sec_key, ukm, shared_key) <= 0)
533
			goto err;
534
		gost_key_wrap_crypto_pro(nid, shared_key, ukm, key,
535
		    crypted_key);
536
	}
537
	gkt = GOST_KEY_TRANSPORT_new();
538
	if (gkt == NULL)
539
		goto err;
540
	if (ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm, 8) == 0)
541
		goto err;
542
	if (ASN1_OCTET_STRING_set(gkt->key_info->imit, crypted_key + 40,
543
	    4) == 0)
544
		goto err;
545
	if (ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key, crypted_key + 8,
546
	    32) == 0)
547
		goto err;
548
	if (key_is_ephemeral) {
549
		if (X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,
550
		    out != NULL ? sec_key : pubk) == 0) {
551
			GOSTerr(GOST_F_PKEY_GOST01_ENCRYPT,
552
			    GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
553
			goto err;
554
		}
555
	}
556
	ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
557
	gkt->key_agreement_info->cipher = OBJ_nid2obj(nid);
558
	if (key_is_ephemeral)
559
		EVP_PKEY_free(sec_key);
560
	else {
561
		/* Set control "public key from client certificate used" */
562
		if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3,
563
		    NULL) <= 0) {
564
			GOSTerr(GOST_F_PKEY_GOST01_ENCRYPT,
565
			    GOST_R_CTRL_CALL_FAILED);
566
			goto err;
567
		}
568
	}
569
	if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt, out ? &out : NULL)) > 0)
570
		ret = 1;
571
	GOST_KEY_TRANSPORT_free(gkt);
572
	return ret;
573
574
err:
575
	if (key_is_ephemeral)
576
		EVP_PKEY_free(sec_key);
577
	GOST_KEY_TRANSPORT_free(gkt);
578
	return -1;
579
}
580
581
582
static int
583
pkey_gost01_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
584
{
585
	struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
586
587
	switch (type) {
588
	case EVP_PKEY_CTRL_MD:
589
		if (EVP_MD_type(p2) !=
590
		    GostR3410_get_md_digest(pctx->digest_nid)) {
591
			GOSTerr(GOST_F_PKEY_GOST01_CTRL,
592
			    GOST_R_INVALID_DIGEST_TYPE);
593
			return 0;
594
		}
595
		pctx->md = p2;
596
		return 1;
597
	case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
598
	case EVP_PKEY_CTRL_PKCS7_DECRYPT:
599
	case EVP_PKEY_CTRL_PKCS7_SIGN:
600
	case EVP_PKEY_CTRL_DIGESTINIT:
601
#ifndef OPENSSL_NO_CMS
602
	case EVP_PKEY_CTRL_CMS_ENCRYPT:
603
	case EVP_PKEY_CTRL_CMS_DECRYPT:
604
	case EVP_PKEY_CTRL_CMS_SIGN:
605
#endif
606
		return 1;
607
608
	case EVP_PKEY_CTRL_GOST_PARAMSET:
609
		pctx->sign_param_nid = (int)p1;
610
		return 1;
611
612
	case EVP_PKEY_CTRL_SET_IV:
613
	    {
614
		char *ukm = malloc(p1);
615
616
		if (ukm == NULL) {
617
			GOSTerr(GOST_F_PKEY_GOST01_CTRL,
618
			    ERR_R_MALLOC_FAILURE);
619
			return 0;
620
		}
621
		memcpy(ukm, p2, p1);
622
		free(pctx->shared_ukm);
623
		pctx->shared_ukm = ukm;
624
		return 1;
625
	    }
626
627
	case EVP_PKEY_CTRL_PEER_KEY:
628
		if (p1 == 0 || p1 == 1)	/* call from EVP_PKEY_derive_set_peer */
629
			return 1;
630
		if (p1 == 2)	/* TLS: peer key used? */
631
			return pctx->peer_key_used;
632
		if (p1 == 3)	/* TLS: peer key used! */
633
			return (pctx->peer_key_used = 1);
634
		return -2;
635
	case EVP_PKEY_CTRL_GOST_SIG_FORMAT:
636
		switch (p1) {
637
		case GOST_SIG_FORMAT_SR_BE:
638
		case GOST_SIG_FORMAT_RS_LE:
639
			pctx->sig_format = p1;
640
			return 1;
641
		default:
642
			return 0;
643
		}
644
		break;
645
	case EVP_PKEY_CTRL_GOST_SET_DIGEST:
646
		pctx->digest_nid = (int)p1;
647
		return 1;
648
	case EVP_PKEY_CTRL_GOST_GET_DIGEST:
649
		*(int *)p2 = pctx->digest_nid;
650
		return 1;
651
	default:
652
		return -2;
653
	}
654
}
655
656
static int
657
pkey_gost01_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
658
{
659
	int param_nid = NID_undef;
660
	int digest_nid = NID_undef;
661
662
	if (strcmp(type, "paramset") == 0) {
663
		if (value == NULL)
664
			return 0;
665
		if (pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_GET_DIGEST, 0,
666
		    &digest_nid) == 0)
667
			return 0;
668
		if (digest_nid == NID_id_tc26_gost3411_2012_512)
669
			param_nid = GostR3410_512_param_id(value);
670
		else
671
			param_nid = GostR3410_256_param_id(value);
672
		if (param_nid == NID_undef)
673
			param_nid = OBJ_txt2nid(value);
674
		if (param_nid == NID_undef)
675
			return 0;
676
677
		return pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
678
		    param_nid, NULL);
679
	}
680
	if (strcmp(type, "dgst") == 0) {
681
		if (value == NULL)
682
			return 0;
683
		else if (strcmp(value, "gost94") == 0 ||
684
		    strcmp(value, "md_gost94") == 0)
685
			digest_nid = NID_id_GostR3411_94_CryptoProParamSet;
686
		else if (strcmp(value, "streebog256") == 0)
687
			digest_nid = NID_id_tc26_gost3411_2012_256;
688
		else if (strcmp(value, "streebog512") == 0)
689
			digest_nid = NID_id_tc26_gost3411_2012_512;
690
691
		if (digest_nid == NID_undef)
692
			return 0;
693
694
		return pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_SET_DIGEST,
695
		    digest_nid, NULL);
696
	}
697
	return -2;
698
}
699
700
const EVP_PKEY_METHOD gostr01_pkey_meth = {
701
	.pkey_id = EVP_PKEY_GOSTR01,
702
703
	.init = pkey_gost01_init,
704
	.copy = pkey_gost01_copy,
705
	.cleanup = pkey_gost01_cleanup,
706
707
	.paramgen = pkey_gost01_paramgen,
708
	.keygen = pkey_gost01_keygen,
709
	.sign = pkey_gost01_sign,
710
	.verify = pkey_gost01_verify,
711
712
	.encrypt = pkey_gost01_encrypt,
713
	.decrypt = pkey_gost01_decrypt,
714
	.derive = pkey_gost01_derive,
715
716
	.ctrl = pkey_gost01_ctrl,
717
	.ctrl_str = pkey_gost01_ctrl_str,
718
};
719
#endif