gost_ameth.c 22.3 KB
Newer Older
1
/**********************************************************************
2
 *                          gost_ameth.c                              *
3 4 5 6 7 8 9
 *             Copyright (c) 2005-2006 Cryptocom LTD                  *
 *         This file is distributed under the same license as OpenSSL *
 *                                                                    *
 *       Implementation of RFC 4490/4491 ASN1 method                  *
 *       for OpenSSL                                                  *
 *          Requires OpenSSL 0.9.9 for compilation                    *
 **********************************************************************/
10 11 12
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
13 14
#include <openssl/engine.h>
#include <openssl/evp.h>
15
#include <openssl/asn1.h>
16 17
#include "gost_params.h"
#include "gost_lcl.h"
18 19 20
#include "e_gost_err.h"

int gost94_nid_by_params(DSA *p) 
21
	{
22 23
	R3410_params *gost_params;
	BIGNUM *q=BN_new();
24 25
	for (gost_params = R3410_paramset;gost_params->q!=NULL; gost_params++) 
		{
26 27
		BN_dec2bn(&q,gost_params->q);
		if (!BN_cmp(q,p->q)) 
28
			{
29 30
			BN_free(q);
			return gost_params->nid;
31 32
			}
		}	
33 34
	BN_free(q);
	return NID_undef;
35
	}
36 37

static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
38
	{
39 40 41 42
	ASN1_STRING *params = ASN1_STRING_new();
	GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
	int pkey_param_nid = NID_undef;
	int cipher_param_nid = NID_undef;
43 44
	if (!params || !gkp) 
		{
45 46 47 48 49 50
		GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
			ERR_R_MALLOC_FAILURE);
		ASN1_STRING_free(params);
		params = NULL;
		goto err;
		}	
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
	switch (EVP_PKEY_base_id(key)) 
		{
		case NID_id_GostR3410_2001:
			pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
			cipher_param_nid = get_encryption_params(NULL)->nid;
			break;
		case NID_id_GostR3410_94:
			pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
			if (pkey_param_nid == NID_undef) 
				{
				GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
					GOST_R_INVALID_GOST94_PARMSET);
				ASN1_STRING_free(params);
				params=NULL;
				goto err;
				}	
			cipher_param_nid = get_encryption_params(NULL)->nid;
			break;
		}	
70 71 72 73 74
	gkp->key_params = OBJ_nid2obj(pkey_param_nid);
	gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
	/*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);*/
	params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
	if (params->length <=0 ) 
75
		{
76 77 78 79 80
		GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
			ERR_R_MALLOC_FAILURE);
		ASN1_STRING_free(params);
		params = NULL;
		goto err;
81
		}
82
	params ->type = V_ASN1_SEQUENCE;
83
	err:
84 85
	GOST_KEY_PARAMS_free(gkp);
	return params;
86 87
	}

88 89 90 91
/* Parses GOST algorithm parameters from X509_ALGOR and
 * modifies pkey setting NID and parameters
 */
static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg) 
92
	{
93 94 95
	ASN1_OBJECT *palg_obj =NULL;
	int ptype = V_ASN1_UNDEF;
	int pkey_nid = NID_undef,param_nid = NID_undef;
B
Ben Laurie 已提交
96
        void *_pval;
97 98 99 100
	ASN1_STRING *pval = NULL;
	const unsigned char  *p;
	GOST_KEY_PARAMS *gkp = NULL;

B
Ben Laurie 已提交
101 102
	X509_ALGOR_get0(&palg_obj, &ptype, &_pval, palg);
        pval = _pval;
103 104
	if (ptype != V_ASN1_SEQUENCE) 
		{
105 106 107
		GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
			GOST_R_BAD_KEY_PARAMETERS_FORMAT);
		return 0;
108
		}	
109 110 111 112
	p=pval->data;
	pkey_nid = OBJ_obj2nid(palg_obj);

	gkp = d2i_GOST_KEY_PARAMS(NULL,&p,pval->length);
113 114
	if (!gkp) 
		{
115
		GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
116
			GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
117
		return 0;
118
		}	
119 120 121
	param_nid = OBJ_obj2nid(gkp->key_params);
	GOST_KEY_PARAMS_free(gkp);
	EVP_PKEY_set_type(pkey,pkey_nid);
122 123 124 125 126 127 128 129 130
	switch (pkey_nid) 
		{
		case NID_id_GostR3410_94:
		{
		DSA *dsa= EVP_PKEY_get0(pkey);
		if (!dsa) 
			{
			dsa = DSA_new();
			if (!EVP_PKEY_assign(pkey,pkey_nid,dsa)) return 0;
131
			}
132 133
		if (!fill_GOST94_params(dsa,param_nid)) return 0;
		break;
134
		}
135 136 137 138 139 140 141
		case NID_id_GostR3410_2001:
		{
		EC_KEY *ec = EVP_PKEY_get0(pkey);
		if (!ec) 
			{
			ec = EC_KEY_new();
			if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
142
			}
143 144 145
		if (!fill_GOST2001_params(ec,param_nid)) return 0;
		}
		}
146 147

	return 1;
148
	}
149 150

static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv) 
151 152 153 154 155 156 157 158 159 160
	{
	switch (EVP_PKEY_base_id(pkey)) 
		{
		case NID_id_GostR3410_94:
		{
		DSA *dsa = EVP_PKEY_get0(pkey);
		if (!dsa) 
			{
			dsa = DSA_new();
			EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),dsa);
161
			}	
162 163 164 165
		dsa->priv_key = BN_dup(priv);
		if (!EVP_PKEY_missing_parameters(pkey)) 
			gost94_compute_public(dsa);
		break;
166
		}	
167 168 169 170 171 172 173
		case NID_id_GostR3410_2001:
		{
		EC_KEY *ec = EVP_PKEY_get0(pkey);
		if (!ec) 
			{
			ec = EC_KEY_new();
			EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),ec);
174
			}	
175 176 177 178 179
		if (!EC_KEY_set_private_key(ec,priv)) return 0;
		if (!EVP_PKEY_missing_parameters(pkey)) 
			gost2001_compute_public(ec);
		break;
		}
180 181
		}
	return 1;		
182
	}
183
BIGNUM* gost_get0_priv_key(const EVP_PKEY *pkey) 
184 185 186 187 188 189 190 191 192
	{
	switch (EVP_PKEY_base_id(pkey)) 
		{
		case NID_id_GostR3410_94:
		{
		DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
		if (!dsa) 
			{
			return NULL;
193
			}	
194
		if (!dsa->priv_key) return NULL;
195
		return dsa->priv_key;
196
		break;
197
		}	
198 199 200 201 202 203 204
		case NID_id_GostR3410_2001:
		{
		EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
		const BIGNUM* priv;
		if (!ec) 
			{
			return NULL;
205
			}	
206
		if (!(priv=EC_KEY_get0_private_key(ec))) return NULL;
207
		return (BIGNUM *)priv;
208 209
		break;
		}
210 211
		}
	return NULL;		
212 213
	}

214
static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
215
	long arg1, void *arg2)
216
	{
217 218
	switch (op)
		{
219
		case ASN1_PKEY_CTRL_PKCS7_SIGN:
220 221
			if (arg1 == 0) 
				{
222 223 224
				X509_ALGOR *alg1 = NULL, *alg2 = NULL;
				int nid = EVP_PKEY_base_id(pkey);
				PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO*)arg2, 
225
					NULL, &alg1, &alg2);
226
				X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
227 228 229
					V_ASN1_NULL, 0);
				if (nid == NID_undef) 
					{
230
					return (-1);
231
					}
232
				X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
233
				}
234 235 236 237 238 239
			return 1;
		case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
			if (arg1 == 0)
				{
				X509_ALGOR *alg;
				ASN1_STRING * params = encode_gost_algor_params(pkey);
240 241
				if (!params) 
					{
242
					return -1;
243
					}
244 245
				PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO*)arg2, &alg);
				X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type),
246
					V_ASN1_SEQUENCE, params);
247 248 249
				}
			return 1;
		case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
250 251 252
			*(int *)arg2 = NID_id_GostR3411_94;
			return 2;
		}
253 254
	
	return -2;
255
	}
256
/*----------------------- free functions * ------------------------------*/
257 258 259 260
static void pkey_free_gost94(EVP_PKEY *key) 
	{
	if (key->pkey.dsa) 
		{
261
		DSA_free(key->pkey.dsa);
262
		}
263
	}
264 265 266 267 268 269 270 271 272

static void pkey_free_gost01(EVP_PKEY *key) 
	{
	if (key->pkey.ec) 
		{
		EC_KEY_free(key->pkey.ec);
		}
	}	

273 274
/* ------------------ private key functions  -----------------------------*/
static int priv_decode_gost( EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf) 
275
	{
276 277 278 279 280 281 282 283 284 285 286
	const unsigned char *pkey_buf = NULL,*p=NULL;
	int priv_len = 0;
	BIGNUM *pk_num=NULL;
	int ret =0;
	X509_ALGOR *palg =NULL;
	ASN1_OBJECT *palg_obj = NULL;
	ASN1_INTEGER *priv_key=NULL;

	if (!PKCS8_pkey_get0(&palg_obj,&pkey_buf,&priv_len,&palg,p8inf)) 
		return 0;
	p = pkey_buf;
287 288
	if (!decode_gost_algor_params(pk,palg)) 
		{
289
		return 0;
290 291 292 293 294 295 296 297 298
		}
	if (V_ASN1_OCTET_STRING == *p) 
		{
		/* New format - Little endian octet string */
		unsigned char rev_buf[32];
		int i;
		ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL,&p,priv_len);
		if (!s||s->length !=32) 
			{
299
			GOSTerr(GOST_F_PRIV_DECODE_GOST,
300 301 302 303 304 305 306 307 308 309 310 311 312
				EVP_R_DECODE_ERROR);
			return 0;	
			}
		for (i=0;i<32;i++)
			{
			rev_buf[31-i]=s->data[i];
			}
		ASN1_STRING_free(s);
		pk_num = getbnfrombuf(rev_buf,32);
		} 
	else
		{
		priv_key=d2i_ASN1_INTEGER(NULL,&p,priv_len);
313 314 315 316
		if (!priv_key) return 0;
		ret= ((pk_num =  ASN1_INTEGER_to_BN(priv_key, NULL))!=NULL) ;
		ASN1_INTEGER_free(priv_key);
		if (!ret)
317
			{
318
			GOSTerr(GOST_F_PRIV_DECODE_GOST,
319 320 321 322
				EVP_R_DECODE_ERROR);
			return 0;	
			}
		}
323 324 325 326

	ret= gost_set_priv_key(pk,pk_num);
	BN_free(pk_num);
	return ret;
327 328
	}

329 330
/* ----------------------------------------------------------------------*/
static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
331
	{
332 333 334 335 336 337
	ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
	ASN1_STRING *params = encode_gost_algor_params(pk);
	unsigned char *priv_buf = NULL;
	int priv_len;

	ASN1_INTEGER *asn1key=NULL;
338 339
	if (!params) 
		{
340
		return 0;
341
		}
342
	asn1key = BN_to_ASN1_INTEGER(gost_get0_priv_key(pk),NULL);
343 344 345 346
	priv_len = i2d_ASN1_INTEGER(asn1key,&priv_buf);
	ASN1_INTEGER_free(asn1key);
	return PKCS8_pkey_set0(p8,algobj,0,V_ASN1_SEQUENCE,params,
		priv_buf,priv_len);
347
	}
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
/* --------- printing keys --------------------------------*/
static int print_gost_94(BIO *out, const EVP_PKEY *pkey, int indent,
	ASN1_PCTX *pctx, int type) 
	{
	int param_nid = NID_undef;

	if (type == 2) 
		{
		BIGNUM *key;

		if (!BIO_indent(out,indent,128)) return 0;
		BIO_printf(out,"Private key: ");
		key = gost_get0_priv_key(pkey);
		if (!key) 
			BIO_printf(out,"<undefined>");
		else 
			BN_print(out,key);
		BIO_printf(out,"\n");
		}
	if (type >= 1)
		{
		BIGNUM *pubkey;
		
		pubkey = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key;
		BIO_indent(out,indent,128);
		BIO_printf(out,"Public key: ");
		BN_print(out,pubkey);
		BIO_printf(out,"\n");
	}	

	param_nid = gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
	BIO_indent(out,indent,128);
	BIO_printf(out, "Parameter set: %s\n",OBJ_nid2ln(param_nid));
	return 1;
}

static int param_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
	ASN1_PCTX *pctx) 
	{
	return print_gost_94(out, pkey, indent, pctx,0);
	}
389

390 391 392 393 394 395
static int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
	ASN1_PCTX *pctx)
	{
	return print_gost_94(out,pkey, indent, pctx,1);
	}
static int priv_print_gost94(BIO *out,const EVP_PKEY *pkey, int indent,
396 397
	ASN1_PCTX *pctx) 
	{
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
	return print_gost_94(out,pkey,indent,pctx,2);
	}

static int print_gost_01(BIO *out, const EVP_PKEY *pkey, int indent,
	ASN1_PCTX *pctx, int type)
	{
	int param_nid = NID_undef;
	if (type == 2) 
		{
		BIGNUM *key;

		if (!BIO_indent(out,indent,128)) return 0;
		BIO_printf(out,"Private key: ");
		key = gost_get0_priv_key(pkey);
		if (!key) 
			BIO_printf(out,"<undefined)");
		else 
			BN_print(out,key);
		BIO_printf(out,"\n");
		}
418
	if (type >= 1) 
419 420 421 422 423
		{
		BN_CTX *ctx = BN_CTX_new();
		BIGNUM *X,*Y;
		const EC_POINT *pubkey;
		const EC_GROUP *group;
424

425 426 427 428 429
		if (!ctx) 
			{
			GOSTerr(GOST_F_PRINT_GOST_01,ERR_R_MALLOC_FAILURE);
			return 0;
			}
430 431 432
		BN_CTX_start(ctx);
		X = BN_CTX_get(ctx);
		Y = BN_CTX_get(ctx);
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
		pubkey = EC_KEY_get0_public_key((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
		group = EC_KEY_get0_group((EC_KEY *)EVP_PKEY_get0((EVP_PKEY *)pkey));
		if (!EC_POINT_get_affine_coordinates_GFp(group,pubkey,X,Y,ctx)) 
			{
			GOSTerr(GOST_F_PRINT_GOST_01,ERR_R_EC_LIB);
			BN_CTX_free(ctx);
			return 0;
			}
		if (!BIO_indent(out,indent,128)) return 0;
		BIO_printf(out,"Public key:\n");
		if (!BIO_indent(out,indent+3,128)) return 0;
		BIO_printf(out,"X:");
		BN_print(out,X);
		BIO_printf(out,"\n");
		BIO_indent(out,indent+3,128);
		BIO_printf(out,"Y:");
		BN_print(out,Y);
		BIO_printf(out,"\n");
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
		}

	param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)));
456
	if (!BIO_indent(out,indent,128)) return 0;
457
	BIO_printf(out,"Parameter set: %s\n",OBJ_nid2ln(param_nid));
458
	return 1;
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
}
static int param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
	ASN1_PCTX *pctx) 
	{	
	return print_gost_01(out,pkey,indent,pctx,0);
	}
static int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
	ASN1_PCTX *pctx)
	{
	return print_gost_01(out,pkey, indent, pctx,1);
	}
static int priv_print_gost01(BIO *out,const EVP_PKEY *pkey, int indent,
	ASN1_PCTX *pctx) 
	{
	return print_gost_01(out,pkey,indent,pctx,2);
474
	}
475 476
/* ---------------------------------------------------------------------*/
static int param_missing_gost94(const EVP_PKEY *pk) 
477
	{
478 479 480 481
	const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
	if (!dsa) return 1;
	if (!dsa->q) return 1;
	return 0;
482 483
	}

484
static int param_missing_gost01(const EVP_PKEY *pk) 
485
	{
486 487 488 489
	const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
	if (!ec) return 1;
	if (!EC_KEY_get0_group(ec)) return 1;
	return 0;
490
	}
491 492

static int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from) 
493
	{
494 495 496
	const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from);
	DSA *dto = EVP_PKEY_get0(to);
	if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) 
497
		{
498
		GOSTerr(GOST_F_PARAM_COPY_GOST94,
499
			GOST_R_INCOMPATIBLE_ALGORITHMS);
500
		return 0;
501
		}	
502
	if (!dfrom) 
503
		{
504
		GOSTerr(GOST_F_PARAM_COPY_GOST94,
505
			GOST_R_KEY_PARAMETERS_MISSING);
506
		return 0;
507
		}	
508
	if (!dto) 
509
		{
510 511
		dto = DSA_new();
		EVP_PKEY_assign(to,EVP_PKEY_base_id(from),dto);
512
		}	
513 514
#define COPYBIGNUM(a,b,x) if (a->x) BN_free(a->x); a->x=BN_dup(b->x);	
	COPYBIGNUM(dto,dfrom,p)
515 516
		COPYBIGNUM(dto,dfrom,q)
		COPYBIGNUM(dto,dfrom,g)
517

518 519
		if (dto->priv_key) 
			gost94_compute_public(dto);
520
	return 1;	
521 522 523
	}
static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) 
	{
524 525
	EC_KEY *eto = EVP_PKEY_get0(to);
	const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
526 527
	if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) 
		{
528
		GOSTerr(GOST_F_PARAM_COPY_GOST01,
529
			GOST_R_INCOMPATIBLE_ALGORITHMS);
530
		return 0;
531 532 533
		}	
	if (!efrom) 
		{
534
		GOSTerr(GOST_F_PARAM_COPY_GOST01,
535
			GOST_R_KEY_PARAMETERS_MISSING);
536
		return 0;
537 538 539
		}	
	if (!eto) 
		{
540 541
		eto = EC_KEY_new();
		EVP_PKEY_assign(to,EVP_PKEY_base_id(from),eto);
542
		}	
543
	EC_KEY_set_group(eto,EC_KEY_get0_group(efrom));
544 545
	if (EC_KEY_get0_private_key(eto)) 
		{
546
		gost2001_compute_public(eto);
547
		}
548
	return 1;
549
	}
550

551 552
static int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b) 
	{
553 554 555 556 557
	const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
	const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
	if (!BN_cmp(da->q,db->q)) return 1;
	return 0;
	}
558 559 560 561 562 563 564 565

static int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) 
	{
	if (EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)a)))==
		EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)b)))) 
		{
		return 1;
		}
566 567
	return 0;

568 569
	}

570 571
/* ---------- Public key functions * --------------------------------------*/
static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
572
	{
573 574 575 576 577 578 579 580 581
	X509_ALGOR *palg = NULL;
	const unsigned char *pubkey_buf = NULL;
	unsigned char *databuf;
	ASN1_OBJECT *palgobj = NULL;
	int pub_len,i,j;
	DSA *dsa;
	ASN1_OCTET_STRING *octet= NULL;

	if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len,
582
			&palg, pub)) return 0;
583 584 585 586
	EVP_PKEY_assign(pk,OBJ_obj2nid(palgobj),NULL);	
	if (!decode_gost_algor_params(pk,palg)) return 0;
	octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len);
	if (!octet) 
587
		{
588 589
		GOSTerr(GOST_F_PUB_DECODE_GOST94,ERR_R_MALLOC_FAILURE);
		return 0;
590
		}	
591 592
	databuf = OPENSSL_malloc(octet->length);
	for (i=0,j=octet->length-1;i<octet->length;i++,j--)
593
		{
594
		databuf[j]=octet->data[i];
595
		}	
596 597 598 599 600 601
	dsa = EVP_PKEY_get0(pk);
	dsa->pub_key=BN_bin2bn(databuf,octet->length,NULL);
	ASN1_OCTET_STRING_free(octet);
	OPENSSL_free(databuf);
	return 1;

602 603
	}

604
static int pub_encode_gost94(X509_PUBKEY *pub,const EVP_PKEY *pk)
605
	{
606 607 608 609 610 611
	ASN1_OBJECT *algobj = NULL;
	ASN1_OCTET_STRING *octet = NULL;
	void *pval = NULL;
	unsigned char *buf=NULL,*databuf,*sptr;
	int i,j,data_len,ret=0;

612
	int ptype = V_ASN1_UNDEF;
613 614
	DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
	algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
615 616
	if (pk->save_parameters) 
		{
617 618 619
		ASN1_STRING *params = encode_gost_algor_params(pk);
		pval = params;
		ptype = V_ASN1_SEQUENCE;
620
		}	
621 622 623 624 625 626 627
	data_len = BN_num_bytes(dsa->pub_key);
	databuf = OPENSSL_malloc(data_len);
	BN_bn2bin(dsa->pub_key,databuf);
	octet = ASN1_OCTET_STRING_new();
	ASN1_STRING_set(octet,NULL,data_len);
	sptr = ASN1_STRING_data(octet);
	for (i=0,j=data_len-1; i< data_len;i++,j--)
628
		{
629
		sptr[i]=databuf[j];
630
		}
631 632 633 634 635
	OPENSSL_free(databuf);
	ret = i2d_ASN1_OCTET_STRING(octet,&buf);
	ASN1_BIT_STRING_free(octet);
	if (ret <0)  return 0;
	return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
636 637
	}

638
static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
639
	{
640 641 642 643 644 645 646 647
	X509_ALGOR *palg = NULL;
	const unsigned char *pubkey_buf = NULL;
	unsigned char *databuf;
	ASN1_OBJECT *palgobj = NULL;
	int pub_len,i,j;
	EC_POINT *pub_key;
	BIGNUM *X,*Y;
	ASN1_OCTET_STRING *octet= NULL;
648
	int len;
649 650 651
	const EC_GROUP *group;

	if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len,
652
			&palg, pub)) return 0;
653 654 655 656 657
	EVP_PKEY_assign(pk,OBJ_obj2nid(palgobj),NULL);	
	if (!decode_gost_algor_params(pk,palg)) return 0;
	group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
	octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len);
	if (!octet) 
658
		{
659
		GOSTerr(GOST_F_PUB_DECODE_GOST01,ERR_R_MALLOC_FAILURE);
660
		return 0;
661
		}	
662 663
	databuf = OPENSSL_malloc(octet->length);
	for (i=0,j=octet->length-1;i<octet->length;i++,j--)
664
		{
665
		databuf[j]=octet->data[i];
666
		}
667 668 669 670 671
	len=octet->length/2;
	ASN1_OCTET_STRING_free(octet);	
	
	Y= getbnfrombuf(databuf,len);
	X= getbnfrombuf(databuf+len,len);
672 673 674
	OPENSSL_free(databuf);
	pub_key = EC_POINT_new(group);
	if (!EC_POINT_set_affine_coordinates_GFp(group
675 676
			,pub_key,X,Y,NULL))
		{
677
		GOSTerr(GOST_F_PUB_DECODE_GOST01,
678
			ERR_R_EC_LIB);
679 680 681
		EC_POINT_free(pub_key);
		BN_free(X);
		BN_free(Y);
682
		return 0;
683
		}	
684 685 686
	BN_free(X);
	BN_free(Y);
	if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk),pub_key))
687
		{
688
		GOSTerr(GOST_F_PUB_DECODE_GOST01,
689
			ERR_R_EC_LIB);
690
		EC_POINT_free(pub_key);
691
		return 0;
692
		}	
693
	EC_POINT_free(pub_key);
694 695
	return 1;

696 697
	}

698
static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
699
	{
700 701 702 703 704 705 706 707
	ASN1_OBJECT *algobj = NULL;
	ASN1_OCTET_STRING *octet = NULL;
	void *pval = NULL;
	unsigned char *buf=NULL,*databuf,*sptr;
	int i,j,data_len,ret=0;
	const EC_POINT *pub_key;
	BIGNUM *X,*Y,*order;
	const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
708
	int ptype = V_ASN1_UNDEF;
709 710

	algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
711 712
	if (pk->save_parameters) 
		{
713 714 715
		ASN1_STRING *params = encode_gost_algor_params(pk);
		pval = params;
		ptype = V_ASN1_SEQUENCE;
716
		}
717 718 719
	order = BN_new();
	EC_GROUP_get_order(EC_KEY_get0_group(ec),order,NULL);
	pub_key=EC_KEY_get0_public_key(ec);
720 721
	if (!pub_key) 
		{
722
		GOSTerr(GOST_F_PUB_ENCODE_GOST01,
723
			GOST_R_PUBLIC_KEY_UNDEFINED);
724
		return 0;
725
		}	
726 727 728 729 730 731 732 733
	X=BN_new();
	Y=BN_new();
	EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
		pub_key,X,Y,NULL);
	data_len = 2*BN_num_bytes(order);
	BN_free(order);
	databuf = OPENSSL_malloc(data_len);
	memset(databuf,0,data_len);
734 735 736 737
	
	store_bignum(X,databuf+data_len/2,data_len/2);
	store_bignum(Y,databuf,data_len/2);

738 739 740 741 742
	BN_free(X);
	BN_free(Y);
	octet = ASN1_OCTET_STRING_new();
	ASN1_STRING_set(octet,NULL,data_len);
	sptr=ASN1_STRING_data(octet);
743 744
    for (i=0,j=data_len-1;i<data_len;i++,j--) 
		{
745
        sptr[i]=databuf[j];
746
		}
747 748 749 750 751
    OPENSSL_free(databuf);
	ret = i2d_ASN1_OCTET_STRING(octet,&buf);
	ASN1_BIT_STRING_free(octet);
	if (ret <0)  return 0;
	return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
752 753
	}

754
static int pub_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
755
	{
756 757 758
	const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
	const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
	if (da && db && da->pub_key && db->pub_key
759 760 761 762
		&& !BN_cmp(da->pub_key,db->pub_key)) 
		{
		return 1;
		}		
763
	return 0;
764 765
	}

766
static int pub_cmp_gost01(const EVP_PKEY *a,const EVP_PKEY *b)
767
	{
768 769 770 771 772 773 774 775 776 777
	const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
	const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
	const EC_POINT *ka,*kb;
	int ret=0;
	if (!ea || !eb) return 0;
	ka = EC_KEY_get0_public_key(ea);
	kb = EC_KEY_get0_public_key(eb);
	if (!ka || !kb) return 0;
	ret = (0==EC_POINT_cmp(EC_KEY_get0_group(ea),ka,kb,NULL)) ;
	return ret;
778 779 780
	}


781

782

783
static int pkey_size_gost(const EVP_PKEY *pk)
784
	{
785
	return 64;
786 787
	}

788
static int pkey_bits_gost(const EVP_PKEY *pk)
789
	{
790
	return 256;
791
	}
792 793 794 795 796 797 798 799 800 801 802 803
/*------------------------ ASN1 METHOD for GOST MAC  -------------------*/
static void  mackey_free_gost(EVP_PKEY *pk)
	{
		if (pk->pkey.ptr) {
			OPENSSL_free(pk->pkey.ptr);
		}	
	}
static int mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
	switch (op)
		{
		case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
D
Dr. Stephen Henson 已提交
804
			*(int *)arg2 = NID_undef;
805 806 807 808
			return 2;
		}
	return -2;
}	
809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861

int gost94_param_encode(const EVP_PKEY *pkey, unsigned char **pder) 
{
   int nid=gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)pkey));
   return i2d_ASN1_OBJECT(OBJ_nid2obj(nid),pder);
}
int gost2001_param_encode(const EVP_PKEY *pkey, unsigned char **pder) 
{
   int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)));
   return i2d_ASN1_OBJECT(OBJ_nid2obj(nid),pder);
}

int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
{
	ASN1_OBJECT *obj=NULL;
	DSA *dsa = EVP_PKEY_get0(pkey);
	int nid;
	if (d2i_ASN1_OBJECT(&obj,pder,derlen)==NULL) {
		return 0;
	}
	nid = OBJ_obj2nid(obj);
	ASN1_OBJECT_free(obj);
	if (!dsa) 
		{
		dsa=DSA_new();
		if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_94,dsa)) return 0;
		}
	if (!fill_GOST94_params(dsa,nid)) return 0;
	return 1;
}	

int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
	ASN1_OBJECT *obj=NULL;
	int nid;
	EC_KEY *ec = EVP_PKEY_get0(pkey);
	if (d2i_ASN1_OBJECT(&obj,pder,derlen)==NULL) {
		return 0;
	}
	nid = OBJ_obj2nid(obj);
	ASN1_OBJECT_free(obj);
	if (!ec) 
		{
		ec = EC_KEY_new();
		if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_2001,ec)) return 0;
		}	
	if (!fill_GOST2001_params(ec, nid)) return 0;
	return 1;
}	





862
/* ----------------------------------------------------------------------*/
863 864
int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info) 
	{
865
	*ameth =	EVP_PKEY_asn1_new(nid, 
866
		ASN1_PKEY_SIGPARAM_NULL, pemstr, info); 
867
	if (!*ameth) return 0;
868 869
	switch (nid) 
		{
870 871 872 873
		case NID_id_GostR3410_94:
			EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost94);
			EVP_PKEY_asn1_set_private (*ameth, 
				priv_decode_gost, priv_encode_gost, 
874
				priv_print_gost94);
875

876 877
			EVP_PKEY_asn1_set_param (*ameth, 
				gost94_param_decode, gost94_param_encode,
878
				param_missing_gost94, param_copy_gost94, 
879
				param_cmp_gost94,param_print_gost94 );
880 881 882 883 884 885 886 887 888 889 890
			EVP_PKEY_asn1_set_public (*ameth,
				pub_decode_gost94, pub_encode_gost94,
				pub_cmp_gost94, pub_print_gost94,
				pkey_size_gost, pkey_bits_gost);
	
			EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
			break;
		case NID_id_GostR3410_2001:
			EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01);
			EVP_PKEY_asn1_set_private (*ameth, 
				priv_decode_gost, priv_encode_gost, 
891
				priv_print_gost01);
892

893 894
			EVP_PKEY_asn1_set_param (*ameth, 
				gost2001_param_decode, gost2001_param_encode,
895
				param_missing_gost01, param_copy_gost01, 
896
				param_cmp_gost01, param_print_gost01);
897 898 899 900 901 902 903
			EVP_PKEY_asn1_set_public (*ameth,
				pub_decode_gost01, pub_encode_gost01,
				pub_cmp_gost01, pub_print_gost01,
				pkey_size_gost, pkey_bits_gost);
	
			EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
			break;
904 905 906 907
		case NID_id_Gost28147_89_MAC:
			EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
			EVP_PKEY_asn1_set_ctrl(*ameth,mac_ctrl_gost);	
			break;
908
		}		
909
	return 1;
910
	}