gost_pmeth.c 18.8 KB
Newer Older
1
/**********************************************************************
2
 *                          gost_pmeth.c                              *
3 4 5 6 7 8 9 10 11 12
 *             Copyright (c) 2005-2006 Cryptocom LTD                  *
 *         This file is distributed under the same license as OpenSSL *
 *                                                                    *
 *   Implementation of RFC 4357 (GOST R 34.10) Publick key method     *
 *       for OpenSSL                                                  *
 *          Requires OpenSSL 0.9.9 for compilation                    *
 **********************************************************************/
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/ec.h>
13
#include <openssl/x509v3.h> /*For string_to_hex */
14 15 16
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
17 18
#include "gost_params.h"
#include "gost_lcl.h"
19 20 21
#include "e_gost_err.h"
/*-------init, cleanup, copy - uniform for all algs  ---------------*/
/* Allocates new gost_pmeth_data structure and assigns it as data */
22 23
static int pkey_gost_init(EVP_PKEY_CTX *ctx)
	{
24 25 26 27 28 29
	struct gost_pmeth_data *data;
	data = OPENSSL_malloc(sizeof(struct gost_pmeth_data));
	if (!data) return 0;
	memset(data,0,sizeof(struct gost_pmeth_data));
	EVP_PKEY_CTX_set_data(ctx,data);
	return 1;
30 31
	}

32 33
/* Copies contents of gost_pmeth_data structure */
static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
34
	{
35
	struct gost_pmeth_data *dst_data,*src_data;
36 37
	if (!pkey_gost_init(dst))
		{
38
		return 0;
39
		}
40 41 42
	src_data = EVP_PKEY_CTX_get_data(src);
	dst_data = EVP_PKEY_CTX_get_data(dst);
	*dst_data = *src_data;
43 44
	if (src_data -> eph_seckey)
		{
45
		dst_data ->eph_seckey = NULL;
46
		}	
47
	return 1;
48 49
	}

50
/* Frees up gost_pmeth_data structure */
51 52
static void pkey_gost_cleanup (EVP_PKEY_CTX *ctx)
	{
53 54 55
	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
	if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey);
	OPENSSL_free(data);
56 57
	}	

58 59
/* --------------------- control functions  ------------------------------*/
static int pkey_gost_ctrl (EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
60
	{
61 62
	struct gost_pmeth_data *pctx = (struct gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx);
	switch (type)
63
		{
64
		case EVP_PKEY_CTRL_MD:
65 66
		{
		if (EVP_MD_type((const EVP_MD *)p2) != NID_id_GostR3411_94)
67
			{
68 69
			GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE);
			return 0;
70
			}
71 72 73 74
		pctx->md = (EVP_MD *)p2;
		return 1;
		}
		break;
75 76 77 78

		case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
		case EVP_PKEY_CTRL_PKCS7_DECRYPT:
		case EVP_PKEY_CTRL_PKCS7_SIGN:
79
			return 1;
80 81 82 83 84

		case EVP_PKEY_CTRL_GOST_PARAMSET:
			pctx->sign_param_nid = (int)p1;
			return 1;
			
85
		}
86
	return -2;
87
	}
88

89 90 91 92 93
static int pkey_gost_ctrl94cc_str(EVP_PKEY_CTX *ctx,
	const char *type, const char *value)
	{
	if(!strcmp(type, param_ctrl_string))
		{
94
		return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
95 96 97
			NID_id_GostR3410_94_CryptoPro_A_ParamSet,
			NULL);
		}
98
	return -2;
99
	}
100

101 102 103 104 105
static int pkey_gost_ctrl01cc_str(EVP_PKEY_CTX *ctx,
	const char *type, const char *value)
	{
	if(!strcmp(type, param_ctrl_string))
		{
106
		return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
107 108
			NID_id_GostR3410_2001_ParamSet_cc,NULL);
		}
109
	return -2;
110 111 112 113 114
	}

static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
	const char *type, const char *value)
	{
115
	int param_nid=0;
116 117 118 119
	if(!strcmp(type, param_ctrl_string))
		{
		if (!value)
			{
120
			return 0;
121 122 123 124 125
			}
		if (strlen(value) == 1)
			{
			switch(toupper(value[0]))
				{
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
				case 'A':
					param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
					break;
				case 'B':
					param_nid = NID_id_GostR3410_94_CryptoPro_B_ParamSet;
					break;
				case 'C':
					param_nid = NID_id_GostR3410_94_CryptoPro_C_ParamSet;
					break;
				case 'D':
					param_nid = NID_id_GostR3410_94_CryptoPro_D_ParamSet;
					break;
				default:
					return 0;
					break;
141
				}
142
			}
143 144 145 146
		else if ((strlen(value) == 2) && (toupper(value[0]) == 'X'))
			{
			switch (toupper(value[1]))
				{
147 148 149 150 151 152 153 154 155 156 157 158
				case 'A':
					param_nid = NID_id_GostR3410_94_CryptoPro_XchA_ParamSet;
					break;
				case 'B':
					param_nid = NID_id_GostR3410_94_CryptoPro_XchB_ParamSet;
					break;
				case 'C':
					param_nid = NID_id_GostR3410_94_CryptoPro_XchC_ParamSet;
					break;
				default:
					return 0;
					break;
159
				}
160
			}
161 162
		else
			{
163 164
			R3410_params *p = R3410_paramset;
			param_nid = OBJ_txt2nid(value);
165 166
			if (param_nid == NID_undef)
				{
167
				return 0;
168 169 170
				}
			for (;p->nid != NID_undef;p++)
				{
171
				if (p->nid == param_nid) break;
172 173 174
				}
			if (p->nid == NID_undef)
				{
175
				GOSTerr(GOST_F_PKEY_GOST_CTRL94_STR,
176
					GOST_R_INVALID_PARAMSET);
177
				return 0;
178
				}
179 180
			}

181 182 183
		return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
			param_nid, NULL);
		}
184
	return -2;
185
	}
186

187 188 189
static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
	const char *type, const char *value)
	{
190
	int param_nid=0;
191 192 193 194
	if(!strcmp(type, param_ctrl_string))
		{
		if (!value)
			{
195
			return 0;
196 197 198 199 200
			}
		if (strlen(value) == 1)
			{
			switch(toupper(value[0]))
				{
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
				case 'A':
					param_nid = NID_id_GostR3410_2001_CryptoPro_A_ParamSet;
					break;	
				case 'B':
					param_nid = NID_id_GostR3410_2001_CryptoPro_B_ParamSet;
					break;
				case 'C':
					param_nid = NID_id_GostR3410_2001_CryptoPro_C_ParamSet;
					break;
				case '0':
					param_nid = NID_id_GostR3410_2001_TestParamSet;
					break;
				default:
					return 0;
					break;
216
				}
217
			}
218 219 220 221
		else if ((strlen(value) == 2) && (toupper(value[0]) == 'X'))
			{
			switch (toupper(value[1]))
				{
222 223 224 225 226 227 228 229 230
				case 'A':
					param_nid = NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet;
					break;
				case 'B':
					param_nid = NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet;
					break;
				default:
					return 0;
					break;
231
				}
232
			}
233 234
		else
			{
235 236
			R3410_2001_params *p = R3410_2001_paramset;
			param_nid = OBJ_txt2nid(value);
237 238
			if (param_nid == NID_undef)
				{
239
				return 0;
240 241 242
				}
			for (;p->nid != NID_undef;p++)
				{
243
				if (p->nid == param_nid) break;
244 245 246
				}
			if (p->nid == NID_undef)
				{
247
				GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR,
248
					GOST_R_INVALID_PARAMSET);
249
				return 0;
250
				}
251 252
			}

253 254 255
		return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
			param_nid, NULL);
		}
256
	return -2;
257 258
	}

259 260 261
/* --------------------- key generation  --------------------------------*/
/* Generates GOST 94 key and assigns it setting specified type */
static int pkey_gost94_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type)
262
	{
263 264
	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
	DSA *dsa=NULL;
265 266 267 268
	if (data->sign_param_nid == NID_undef)
		{
		if (type== NID_id_GostR3410_94_cc)
			{
269
			data->sign_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
270 271 272
			}
		else
			{
273
			GOSTerr(GOST_F_PKEY_GOST94_KEYGEN,
274
				GOST_R_NO_PARAMETERS_SET);
275
			return 0;
276 277
			}	
		}
278
	dsa = DSA_new();
279 280
	if (!fill_GOST94_params(dsa,data->sign_param_nid))
		{
281 282
		DSA_free(dsa);
		return 0;
283
		}
284 285 286
	gost_sign_keygen(dsa);
	EVP_PKEY_assign(pkey,type,dsa);
	return 1;
287 288
	}

289
/* Generates Gost_R3410_94_cc key */
290 291
static int pkey_gost94cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
	{
292
	return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94_cc);
293
	}
294 295

/* Generates Gost_R3410_94_cp key */
296 297
static int pkey_gost94cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
	{
298
	return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94);
299 300
	}

301 302
/* Generates GOST_R3410 2001 key and assigns it using specified type */
static int pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type)
303
	{
304 305
	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
	EC_KEY *ec=NULL;
306 307 308 309
	if (data->sign_param_nid == NID_undef)
		{
		if (type == NID_id_GostR3410_2001_cc)
			{
310
			data->sign_param_nid = NID_id_GostR3410_2001_ParamSet_cc;
311 312
			}
		else {	
313
			GOSTerr(GOST_F_PKEY_GOST01_KEYGEN,
314
				GOST_R_NO_PARAMETERS_SET);
315
			return 0;
316
			}
317 318
		}
	ec = EC_KEY_new();
319 320
	if (!fill_GOST2001_params(ec,data->sign_param_nid))
		{
321 322
		EC_KEY_free(ec);
		return 0;
323
		}
324 325 326 327
	gost2001_keygen(ec);

	EVP_PKEY_assign(pkey,type,ec);
	return 1;
328 329
	}

330
/* Generates GOST R3410 2001_cc key */
331 332
static int pkey_gost01cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
	{
333
	return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001_cc);
334
	}
335 336

/* Generates GOST R3410 2001_cp key */
337 338
static int pkey_gost01cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
	{
339
	return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001);
340 341
	}

342 343 344
/* ----------- sign callbacks --------------------------------------*/
static int pkey_gost94_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
	const unsigned char *tbs, size_t tbs_len)
345
	{
346 347 348
	DSA_SIG *unpacked_sig=NULL;
	EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
	if (!siglen) return 0;
349 350
	if (!sig)
		{
351 352
		*siglen= 64; /* better to check size of pkey->pkey.dsa-q */
		return 1;
353
		}	
354
	unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
355 356
	if (!unpacked_sig)
		{
357
		return 0;
358 359
		}
	return pack_sign_cc(unpacked_sig,32,sig,siglen);
360 361 362 363
	}

static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
	const unsigned char *tbs, size_t tbs_len)
364
	{
365 366 367
	DSA_SIG *unpacked_sig=NULL;
	EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
	if (!siglen) return 0;
368 369
	if (!sig)
		{
370 371
		*siglen= 64; /* better to check size of pkey->pkey.dsa-q */
		return 1;
372
		}	
373
	unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
374 375
	if (!unpacked_sig)
		{
376
		return 0;
377
		}
378
	return pack_sign_cp(unpacked_sig,32,sig,siglen);
379 380
	}

381 382
static int pkey_gost01_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
	const unsigned char *tbs, size_t tbs_len)
383
	{
384 385 386
	DSA_SIG *unpacked_sig=NULL;
	EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
	if (!siglen) return 0;
387 388
	if (!sig)
		{
389 390
		*siglen= 64; /* better to check size of curve order*/
		return 1;
391
		}	
392
	unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
393 394
	if (!unpacked_sig)
		{
395
		return 0;
396
		}
397
	return pack_sign_cc(unpacked_sig,32,sig,siglen);
398 399
	}

400 401
static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
	const unsigned char *tbs, size_t tbs_len)
402
	{
403 404 405
	DSA_SIG *unpacked_sig=NULL;
	EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
	if (!siglen) return 0;
406 407
	if (!sig)
		{
408 409
		*siglen= 64; /* better to check size of curve order*/
		return 1;
410
		}	
411
	unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
412 413
	if (!unpacked_sig)
		{
414
		return 0;
415
		}
416
	return pack_sign_cp(unpacked_sig,32,sig,siglen);
417 418
	}

419 420 421
/* ------------------- verify callbacks ---------------------------*/
static int pkey_gost94_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
	size_t siglen, const unsigned char *tbs, size_t tbs_len)
422
	{
423 424 425 426 427 428 429
	int ok = 0;
	EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
	DSA_SIG *s=unpack_cc_signature(sig,siglen);
	if (!s) return 0;
	if (pub_key) ok = gost_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
	DSA_SIG_free(s);
	return ok;
430
	}
431 432 433

static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
	size_t siglen, const unsigned char *tbs, size_t tbs_len)
434
	{
435 436 437 438 439 440 441
	int ok = 0;
	EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
	DSA_SIG *s=unpack_cp_signature(sig,siglen);
	if (!s) return 0;
	if (pub_key) ok = gost_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
	DSA_SIG_free(s);
	return ok;
442 443
	}

444 445
static int pkey_gost01_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
	size_t siglen, const unsigned char *tbs, size_t tbs_len)
446
	{
447 448 449
	int ok = 0;
	EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
	DSA_SIG *s=unpack_cc_signature(sig,siglen);
450
#ifdef DEBUG_SIGN	
451 452 453 454 455
	fprintf(stderr,"R=");
	BN_print_fp(stderr,s->r);
	fprintf(stderr,"\nS=");
	BN_print_fp(stderr,s->s);
	fprintf(stderr,"\n");
456
#endif	
457 458 459 460
	if (!s) return 0;
	if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
	DSA_SIG_free(s);
	return ok;
461
	}
462 463 464

static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
	size_t siglen, const unsigned char *tbs, size_t tbs_len)
465
	{
466 467 468 469
	int ok = 0;
	EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
	DSA_SIG *s=unpack_cp_signature(sig,siglen);
	if (!s) return 0;
470
#ifdef DEBUG_SIGN	
471 472 473 474 475
	fprintf(stderr,"R=");
	BN_print_fp(stderr,s->r);
	fprintf(stderr,"\nS=");
	BN_print_fp(stderr,s->s);
	fprintf(stderr,"\n");
476
#endif	
477 478 479
	if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
	DSA_SIG_free(s);
	return ok;
480 481
	}

482 483
/* ------------- encrypt init -------------------------------------*/
/* Generates ephermeral key */
484 485
static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx)
	{
486 487 488 489 490 491 492
	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
	EVP_PKEY *eph_key = EVP_PKEY_new();
	EVP_PKEY *old_key =EVP_PKEY_CTX_get0_pkey(ctx);

	if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey);
	EVP_PKEY_assign(eph_key,EVP_PKEY_base_id(old_key),NULL);
	if (!EVP_PKEY_copy_parameters(eph_key,old_key)) return 0;
493 494 495 496 497 498 499 500 501 502
	switch (EVP_PKEY_base_id(old_key))
		{
		case NID_id_GostR3410_2001:
		case NID_id_GostR3410_2001_cc:
			gost2001_keygen(EVP_PKEY_get0(eph_key));
			break;
		case NID_id_GostR3410_94:
		case NID_id_GostR3410_94_cc:
			gost_sign_keygen(EVP_PKEY_get0(eph_key));
			break;
503 504
	
			
505
		}
506 507 508 509

	
	data->eph_seckey=eph_key;
	return 1;
510
	}
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
/* -------- PKEY_METHOD for GOST MAC algorithm --------------------*/
static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx)
	{
	struct gost_mac_pmeth_data *data;
	data = OPENSSL_malloc(sizeof(struct gost_mac_pmeth_data));
	if (!data) return 0;
	memset(data,0,sizeof(struct gost_mac_pmeth_data));
	EVP_PKEY_CTX_set_data(ctx,data);
	return 1;
	}	
static void pkey_gost_mac_cleanup (EVP_PKEY_CTX *ctx)
	{
	struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
	OPENSSL_free(data);
	}	
static int pkey_gost_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
	{
	struct gost_mac_pmeth_data *dst_data,*src_data;
	if (!pkey_gost_mac_init(dst))
		{
		return 0;
		}
	src_data = EVP_PKEY_CTX_get_data(src);
	dst_data = EVP_PKEY_CTX_get_data(dst);
	*dst_data = *src_data;
	return 1;
	}
	
static int pkey_gost_mac_ctrl (EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
	{
	struct gost_mac_pmeth_data *data =
(struct gost_mac_pmeth_data*)EVP_PKEY_CTX_get_data(ctx);
543

544 545 546 547
	switch (type)
		{
		case EVP_PKEY_CTRL_MD:
		{
D
Dr. Stephen Henson 已提交
548
		if (p2 != NULL)
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
			{
			GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_DIGEST_TYPE);
			return 0;
			}
		data->md = (EVP_MD *)p2;
		return 1;
		}
		break;

		case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
		case EVP_PKEY_CTRL_PKCS7_DECRYPT:
		case EVP_PKEY_CTRL_PKCS7_SIGN:
			return 1;
		case EVP_PKEY_CTRL_SET_MAC_KEY:
			if (p1 != 32) 
				{
				GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,
					GOST_R_INVALID_MAC_KEY_LENGTH);
				return 0;
				}

			memcpy(data->key,p2,32);
			data->key_set = 1;
			return 1;
		case EVP_PKEY_CTRL_DIGESTINIT:
			{ 
			EVP_MD_CTX *mctx = p2;
			void *key;
			if (!data->key_set)
				{ 
				EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
				if (!pkey) 
					{
					GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,GOST_R_MAC_KEY_NOT_SET);
					return 0;
					}
				key = EVP_PKEY_get0(pkey);
				if (!key) 
					{
					GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,GOST_R_MAC_KEY_NOT_SET);
					return 0;
					}
				} else {
				key = &(data->key);
				}
D
Dr. Stephen Henson 已提交
594
			return imit_gost_vizir.md_ctrl(mctx,EVP_MD_CTRL_SET_KEY,32,key);
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
			}  
		}	
	return -2;
	}
static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx,
	const char *type, const char *value)
	{
	if (!strcmp(type, key_ctrl_string)) 
		{
		if (strlen(value)!=32) 
			{
			GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR,
				GOST_R_INVALID_MAC_KEY_LENGTH);
			return 0;	
			}
		return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
			32,(char *)value);
		}
	if (!strcmp(type, hexkey_ctrl_string)) 
		{
			long keylen; int ret;
			unsigned char *keybuf=string_to_hex(value,&keylen);
			if (keylen != 32) 
				{
				GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR,
					GOST_R_INVALID_MAC_KEY_LENGTH);
				return 0;	
				}
			ret= pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
				32,keybuf);
			OPENSSL_free(keybuf);
			return ret;
	
		}
	return -2;
	}	

static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
	{
		struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
		unsigned char *keydata;
		if (!data->key_set) 
		{
			GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN,GOST_R_MAC_KEY_NOT_SET);
			return 0;
		}
		keydata = OPENSSL_malloc(32);
		memcpy(keydata,data->key,32);
		EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata);
		return 1;
	}

static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
	{
D
Dr. Stephen Henson 已提交
649
	return 1;
650 651 652 653 654 655 656 657 658 659 660
}

static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, EVP_MD_CTX *mctx)
	{
		if (!sig) 
			{
			*siglen = 4;
			return 1;
			}
		return EVP_DigestFinal_ex(mctx,sig,siglen);
	}
661
/* ----------------------------------------------------------------*/
662 663
int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
	{
664 665 666
	*pmeth = EVP_PKEY_meth_new(id, flags);
	if (!*pmeth) return 0;

667 668
	switch (id)
		{
669
		case NID_id_GostR3410_94_cc:
670
			EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94cc_str);
671 672 673
			EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cc_keygen);
			EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost94_cc_sign);
			EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost94_cc_verify);
674
			EVP_PKEY_meth_set_encrypt(*pmeth,
675
				pkey_gost_encrypt_init, pkey_GOST94cc_encrypt);
676
			EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cc_decrypt);
677 678 679 680 681 682
			break;
		case NID_id_GostR3410_94:
			EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94_str);
			EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cp_keygen);
			EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost94_cp_sign);
			EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost94_cp_verify);
683
			EVP_PKEY_meth_set_encrypt(*pmeth,
684
				pkey_gost_encrypt_init, pkey_GOST94cp_encrypt);
685
			EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cp_decrypt);
686 687 688 689 690 691 692 693 694 695

	
			break;
		case NID_id_GostR3410_2001_cc:
			EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01cc_str);
			EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cc_sign);
			EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cc_verify);

			EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cc_keygen);

696
			EVP_PKEY_meth_set_encrypt(*pmeth,
697
				pkey_gost_encrypt_init, pkey_GOST01cc_encrypt);
698
			EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cc_decrypt);
699 700 701 702 703 704 705 706 707
			break;
			/* There is intentionally no break here */
		case NID_id_GostR3410_2001:
			EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01_str);
			EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
			EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);

			EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cp_keygen);

708
			EVP_PKEY_meth_set_encrypt(*pmeth,
709
				pkey_gost_encrypt_init, pkey_GOST01cp_encrypt);
710
			EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
711
			break;
712 713 714 715 716 717 718 719
		case NID_id_Gost28147_89_MAC:
			EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_mac_ctrl, pkey_gost_mac_ctrl_str);
			EVP_PKEY_meth_set_signctx(*pmeth,pkey_gost_mac_signctx_init, pkey_gost_mac_signctx);
			EVP_PKEY_meth_set_keygen(*pmeth,NULL, pkey_gost_mac_keygen);
			EVP_PKEY_meth_set_init(*pmeth,pkey_gost_mac_init);
			EVP_PKEY_meth_set_cleanup(*pmeth,pkey_gost_mac_cleanup);
			EVP_PKEY_meth_set_copy(*pmeth,pkey_gost_mac_copy);
			return 1;
720
		default: /*Unsupported method*/
721
			return 0;
722
		}
723 724 725 726
	EVP_PKEY_meth_set_init(*pmeth, pkey_gost_init);
	EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_cleanup);

	EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_copy);
727
	/*FIXME derive etc...*/
728 729
	
	return 1;
730
	}
731