Commit f0288f05 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Submitted by: Artem Chuprina <ran@cryptocom.ru>

Reviewed by: steve@openssl.org

Various GOST ciphersuite and ENGINE fixes. Including...

Allow EVP_PKEY_set_derive_peerkey() in encryption operations.

New flag when certificate verify should be omitted in client key exchange.
parent 31db43df
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -285,13 +285,13 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
	{
	int ret;
	if (!ctx || !ctx->pmeth || !(ctx->pmeth->derive||ctx->pmeth->encrypt) || !ctx->pmeth->ctrl)
	if (!ctx || !ctx->pmeth || !(ctx->pmeth->derive||ctx->pmeth->encrypt||ctx->pmeth->decrypt) || !ctx->pmeth->ctrl)
		{
		EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
			EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
		return -2;
		}
	if (ctx->operation != EVP_PKEY_OP_DERIVE && ctx->operation != EVP_PKEY_OP_ENCRYPT)
	if (ctx->operation != EVP_PKEY_OP_DERIVE && ctx->operation != EVP_PKEY_OP_ENCRYPT && ctx->operation != EVP_PKEY_OP_DECRYPT)
		{
		EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
					EVP_R_OPERATON_NOT_INITIALIZED);
@@ -319,6 +319,11 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
		return -1;
		}

	/* ran@cryptocom.ru: For clarity.  The error is if parameters in peer are
	 * present (!missing) but don't match.  EVP_PKEY_cmp_parameters may return
	 * 1 (match), 0 (don't match) and -2 (comparison is not defined).  -1
	 * (different key types) is impossible here because it is checked earlier.
	 * -2 is OK for us here, as well as 1, so we can check for 0 only. */
	if (!EVP_PKEY_missing_parameters(peer) &&
		!EVP_PKEY_cmp_parameters(ctx->pkey, peer))
		{
@@ -327,6 +332,8 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
		return -1;
		}

	if (ctx->peerkey)
		EVP_PKEY_free(ctx->peerkey);
	ctx->peerkey = peer;

	ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
+1 −1
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ EVP_PKEY_ctrl, EVP_PKEY_ctrl_str - algorithm specific control operations
=head1 DESCRIPTION

The function EVP_PKEY_CTX_ctrl() sends a control operation to the context
B<ctx>. The key type used must match B<keytype> if it is not zero. The parameter
B<ctx>. The key type used must match B<keytype> if it is not -1. The parameter
B<optype> is a mask indicating which operations the control can be applied to.
The control command is indicated in B<cmd> and any additional arguments in
B<p1> and B<p2>.
+3 −1
Original line number Diff line number Diff line
/* e_gost_err.c */
/* ====================================================================
 * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
 * Copyright (c) 1999-2009 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
@@ -120,10 +120,12 @@ static ERR_STRING_DATA GOST_str_reasons[]=
{ERR_REASON(GOST_R_BAD_KEY_PARAMETERS_FORMAT),"bad key parameters format"},
{ERR_REASON(GOST_R_BAD_PKEY_PARAMETERS_FORMAT),"bad pkey parameters format"},
{ERR_REASON(GOST_R_CANNOT_PACK_EPHEMERAL_KEY),"cannot pack ephemeral key"},
{ERR_REASON(GOST_R_CTRL_CALL_FAILED)     ,"ctrl call failed"},
{ERR_REASON(GOST_R_ERROR_COMPUTING_SHARED_KEY),"error computing shared key"},
{ERR_REASON(GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO),"error packing key transport info"},
{ERR_REASON(GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO),"error parsing key transport info"},
{ERR_REASON(GOST_R_INCOMPATIBLE_ALGORITHMS),"incompatible algorithms"},
{ERR_REASON(GOST_R_INCOMPATIBLE_PEER_KEY),"incompatible peer key"},
{ERR_REASON(GOST_R_INVALID_CIPHER_PARAMS),"invalid cipher params"},
{ERR_REASON(GOST_R_INVALID_CIPHER_PARAM_OID),"invalid cipher param oid"},
{ERR_REASON(GOST_R_INVALID_DIGEST_TYPE)  ,"invalid digest type"},
+2 −0
Original line number Diff line number Diff line
@@ -118,10 +118,12 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
#define GOST_R_BAD_KEY_PARAMETERS_FORMAT		 99
#define GOST_R_BAD_PKEY_PARAMETERS_FORMAT		 100
#define GOST_R_CANNOT_PACK_EPHEMERAL_KEY		 101
#define GOST_R_CTRL_CALL_FAILED				 132
#define GOST_R_ERROR_COMPUTING_SHARED_KEY		 102
#define GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO		 103
#define GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO		 104
#define GOST_R_INCOMPATIBLE_ALGORITHMS			 105
#define GOST_R_INCOMPATIBLE_PEER_KEY			 131
#define GOST_R_INVALID_CIPHER_PARAMS			 106
#define GOST_R_INVALID_CIPHER_PARAM_OID			 107
#define GOST_R_INVALID_DIGEST_TYPE			 108
+39 −12
Original line number Diff line number Diff line
@@ -203,6 +203,16 @@ int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_le
	ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
	gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
	if (key_is_ephemeral && sec_key) EVP_PKEY_free(sec_key);
	if (!key_is_ephemeral)
		{
		/* Set control "public key from client certificate used" */
		if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0)
			{
			GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT,
				GOST_R_CTRL_CALL_FAILED);
			goto err;
			}
		}
	if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL))>0) ret =1;
	GOST_KEY_TRANSPORT_free(gkt);
	return ret;	
@@ -225,7 +235,7 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l
	unsigned char sharedKey[32];
	gost_ctx ctx;
	const struct gost_cipher_info *param=NULL;
	EVP_PKEY *eph_key=NULL;
	EVP_PKEY *eph_key=NULL, *peerkey=NULL;

	if (!key)
		{
@@ -240,16 +250,33 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l
		return -1;
		}	

	/* If key transport structure contains public key, use it */
	eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
	if (!eph_key) {
		eph_key = EVP_PKEY_CTX_get0_peerkey(pctx);
		if (! eph_key) {
	if (eph_key)
		{
		if (EVP_PKEY_derive_set_peer(pctx, eph_key) <= 0)
			{
			GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,
				GOST_R_NO_PEER_KEY);
				GOST_R_INCOMPATIBLE_PEER_KEY);
			goto err;
			}
		}
	else
		{
		/* Set control "public key from client certificate used" */
		if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0)
			{
			GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,
				GOST_R_CTRL_CALL_FAILED);
			goto err;
			}
		/* Increment reference count of peer key */
		CRYPTO_add(&(eph_key->references),1 ,CRYPTO_LOCK_EVP_PKEY);
		}
	peerkey = EVP_PKEY_CTX_get0_peerkey(pctx);
	if (!peerkey)
		{
		GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,
			GOST_R_NO_PEER_KEY);
		goto err;
		}
		
	param = get_encryption_params(gkt->key_agreement_info->cipher);
@@ -260,7 +287,7 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l
	memcpy(wrappedKey+8,gkt->key_info->encrypted_key->data,32);
	OPENSSL_assert(gkt->key_info->imit->length==4);
	memcpy(wrappedKey+40,gkt->key_info->imit->data,4);	
	VKO_compute_key(sharedKey,32,EC_KEY_get0_public_key(EVP_PKEY_get0(eph_key)),
	VKO_compute_key(sharedKey,32,EC_KEY_get0_public_key(EVP_PKEY_get0(peerkey)),
		EVP_PKEY_get0(priv),wrappedKey);
	if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key))
		{
@@ -269,9 +296,9 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l
		goto err;
		}	
				
	EVP_PKEY_free(eph_key);
	GOST_KEY_TRANSPORT_free(gkt);
	ret=1;
err:	
	if (eph_key) EVP_PKEY_free(eph_key);
	if (gkt) GOST_KEY_TRANSPORT_free(gkt);
	return ret;
	}
Loading