GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/gost/gostr341001_ameth.c Lines: 0 347 0.0 %
Date: 2017-11-13 Branches: 0 164 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: gostr341001_ameth.c,v 1.11 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/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, (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, 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
	X509_ALGOR *palg = NULL;
404
	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, (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
		unsigned char rev_buf[32];
425
		int i;
426
		ASN1_OCTET_STRING *s =
427
		    d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
428
429
		if (s == NULL || s->length != 32) {
430
			GOSTerror(EVP_R_DECODE_ERROR);
431
			ASN1_STRING_free(s);
432
			return 0;
433
		}
434
		for (i = 0; i < 32; i++) {
435
			rev_buf[31 - i] = s->data[i];
436
		}
437
		ASN1_STRING_free(s);
438
		pk_num = BN_bin2bn(rev_buf, 32, NULL);
439
	} else {
440
		priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
441
		if (priv_key == NULL)
442
			return 0;
443
		ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
444
		ASN1_INTEGER_free(priv_key);
445
		if (ret == 0) {
446
			GOSTerror(EVP_R_DECODE_ERROR);
447
			return 0;
448
		}
449
	}
450
451
	ec = pk->pkey.gost;
452
	if (ec == NULL) {
453
		ec = GOST_KEY_new();
454
		if (ec == NULL) {
455
			BN_free(pk_num);
456
			return 0;
457
		}
458
		if (EVP_PKEY_assign_GOST(pk, ec) == 0) {
459
			BN_free(pk_num);
460
			GOST_KEY_free(ec);
461
			return 0;
462
		}
463
	}
464
	if (GOST_KEY_set_private_key(ec, pk_num) == 0) {
465
		BN_free(pk_num);
466
		return 0;
467
	}
468
	ret = 0;
469
	if (EVP_PKEY_missing_parameters(pk) == 0)
470
		ret = gost2001_compute_public(ec) != 0;
471
	BN_free(pk_num);
472
473
	return ret;
474
}
475
476
static int
477
priv_encode_gost01(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
478
{
479
	ASN1_OBJECT *algobj =
480
	    OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost)));
481
	ASN1_STRING *params = encode_gost01_algor_params(pk);
482
	unsigned char *priv_buf = NULL;
483
	int priv_len;
484
	ASN1_INTEGER *asn1key = NULL;
485
486
	if (params == NULL)
487
		return 0;
488
489
	asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost),
490
	    NULL);
491
	if (asn1key == NULL) {
492
		ASN1_STRING_free(params);
493
		return 0;
494
	}
495
	priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf);
496
	ASN1_INTEGER_free(asn1key);
497
	return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, priv_buf,
498
	    priv_len);
499
}
500
501
static int
502
param_encode_gost01(const EVP_PKEY *pkey, unsigned char **pder)
503
{
504
	ASN1_STRING *params = encode_gost01_algor_params(pkey);
505
	int len;
506
507
	if (params == NULL)
508
		return 0;
509
	len = params->length;
510
	if (pder != NULL)
511
		memcpy(*pder, params->data, params->length);
512
	ASN1_STRING_free(params);
513
	return len;
514
}
515
516
static int
517
param_decode_gost01(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
518
{
519
	ASN1_OBJECT *obj = NULL;
520
	int nid;
521
	GOST_KEY *ec;
522
	EC_GROUP *group;
523
	int ret;
524
525
	/* New format */
526
	if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == **pder)
527
		return decode_gost01_algor_params(pkey, pder, derlen);
528
529
	/* Compatibility */
530
	if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
531
		GOSTerror(ERR_R_MALLOC_FAILURE);
532
		return 0;
533
	}
534
	nid = OBJ_obj2nid(obj);
535
	ASN1_OBJECT_free(obj);
536
537
	ec = GOST_KEY_new();
538
	if (ec == NULL) {
539
		GOSTerror(ERR_R_MALLOC_FAILURE);
540
		return 0;
541
	}
542
	group = EC_GROUP_new_by_curve_name(nid);
543
	if (group == NULL) {
544
		GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
545
		GOST_KEY_free(ec);
546
		return 0;
547
	}
548
549
	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
550
	if (GOST_KEY_set_group(ec, group) == 0) {
551
		GOSTerror(ERR_R_EC_LIB);
552
		EC_GROUP_free(group);
553
		GOST_KEY_free(ec);
554
		return 0;
555
	}
556
	EC_GROUP_free(group);
557
	if (GOST_KEY_set_digest(ec,
558
	    NID_id_GostR3411_94_CryptoProParamSet) == 0) {
559
		GOSTerror(GOST_R_INVALID_DIGEST_TYPE);
560
		GOST_KEY_free(ec);
561
		return 0;
562
	}
563
	ret = EVP_PKEY_assign_GOST(pkey, ec);
564
	if (ret == 0)
565
		GOST_KEY_free(ec);
566
	return ret;
567
}
568
569
static int
570
param_missing_gost01(const EVP_PKEY *pk)
571
{
572
	const GOST_KEY *ec = pk->pkey.gost;
573
574
	if (ec == NULL)
575
		return 1;
576
	if (GOST_KEY_get0_group(ec) == NULL)
577
		return 1;
578
	if (GOST_KEY_get_digest(ec) == NID_undef)
579
		return 1;
580
	return 0;
581
}
582
583
static int
584
param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
585
{
586
	GOST_KEY *eto = to->pkey.gost;
587
	const GOST_KEY *efrom = from->pkey.gost;
588
	int ret = 1;
589
590
	if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
591
		GOSTerror(GOST_R_INCOMPATIBLE_ALGORITHMS);
592
		return 0;
593
	}
594
	if (efrom == NULL) {
595
		GOSTerror(GOST_R_KEY_PARAMETERS_MISSING);
596
		return 0;
597
	}
598
	if (eto == NULL) {
599
		eto = GOST_KEY_new();
600
		if (eto == NULL) {
601
			GOSTerror(ERR_R_MALLOC_FAILURE);
602
			return 0;
603
		}
604
		if (EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto) == 0) {
605
			GOST_KEY_free(eto);
606
			return 0;
607
		}
608
	}
609
	GOST_KEY_set_group(eto, GOST_KEY_get0_group(efrom));
610
	GOST_KEY_set_digest(eto, GOST_KEY_get_digest(efrom));
611
	if (GOST_KEY_get0_private_key(eto) != NULL)
612
		ret = gost2001_compute_public(eto);
613
614
	return ret;
615
}
616
617
static int
618
param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
619
{
620
	if (EC_GROUP_get_curve_name(GOST_KEY_get0_group(a->pkey.gost)) !=
621
	    EC_GROUP_get_curve_name(GOST_KEY_get0_group(b->pkey.gost)))
622
		return 0;
623
624
	if (GOST_KEY_get_digest(a->pkey.gost) !=
625
	    GOST_KEY_get_digest(b->pkey.gost))
626
		return 0;
627
628
	return 1;
629
}
630
631
static int
632
pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2)
633
{
634
	X509_ALGOR *alg1 = NULL, *alg2 = NULL, *alg3 = NULL;
635
	int digest = GOST_KEY_get_digest(pkey->pkey.gost);
636
637
	switch (op) {
638
	case ASN1_PKEY_CTRL_PKCS7_SIGN:
639
		if (arg1 == 0)
640
			PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
641
		break;
642
643
	case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
644
		if (arg1 == 0)
645
			PKCS7_RECIP_INFO_get0_alg(arg2, &alg3);
646
		break;
647
	case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
648
		*(int *)arg2 = GostR3410_get_md_digest(digest);
649
		return 2;
650
651
	default:
652
		return -2;
653
	}
654
655
	if (alg1)
656
		X509_ALGOR_set0(alg1, OBJ_nid2obj(GostR3410_get_md_digest(digest)), V_ASN1_NULL, 0);
657
	if (alg2)
658
		X509_ALGOR_set0(alg2, OBJ_nid2obj(GostR3410_get_pk_digest(digest)), V_ASN1_NULL, 0);
659
	if (alg3) {
660
		ASN1_STRING *params = encode_gost01_algor_params(pkey);
661
		if (params == NULL) {
662
			return -1;
663
		}
664
		X509_ALGOR_set0(alg3,
665
		    OBJ_nid2obj(GostR3410_get_pk_digest(digest)),
666
		    V_ASN1_SEQUENCE, params);
667
	}
668
669
	return 1;
670
}
671
672
const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[] = {
673
	{
674
		.pkey_id = EVP_PKEY_GOSTR01,
675
		.pkey_base_id = EVP_PKEY_GOSTR01,
676
		.pkey_flags = ASN1_PKEY_SIGPARAM_NULL,
677
678
		.pem_str = "GOST2001",
679
		.info = "GOST R 34.10-2001",
680
681
		.pkey_free = pkey_free_gost01,
682
		.pkey_ctrl = pkey_ctrl_gost01,
683
684
		.priv_decode = priv_decode_gost01,
685
		.priv_encode = priv_encode_gost01,
686
		.priv_print = priv_print_gost01,
687
688
		.param_decode = param_decode_gost01,
689
		.param_encode = param_encode_gost01,
690
		.param_missing = param_missing_gost01,
691
		.param_copy = param_copy_gost01,
692
		.param_cmp = param_cmp_gost01,
693
		.param_print = param_print_gost01,
694
695
		.pub_decode = pub_decode_gost01,
696
		.pub_encode = pub_encode_gost01,
697
		.pub_cmp = pub_cmp_gost01,
698
		.pub_print = pub_print_gost01,
699
		.pkey_size = pkey_size_gost01,
700
		.pkey_bits = pkey_bits_gost01,
701
	},
702
	{
703
		.pkey_id = EVP_PKEY_GOSTR12_256,
704
		.pkey_base_id = EVP_PKEY_GOSTR01,
705
		.pkey_flags = ASN1_PKEY_ALIAS
706
	},
707
	{
708
		.pkey_id = EVP_PKEY_GOSTR12_512,
709
		.pkey_base_id = EVP_PKEY_GOSTR01,
710
		.pkey_flags = ASN1_PKEY_ALIAS
711
	},
712
};
713
714
#endif