提交 f0288f05 编写于 作者: D Dr. Stephen Henson

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.
上级 31db43df
...@@ -285,13 +285,13 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) ...@@ -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 EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
{ {
int ret; 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, EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2; 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, EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
EVP_R_OPERATON_NOT_INITIALIZED); EVP_R_OPERATON_NOT_INITIALIZED);
...@@ -319,6 +319,11 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) ...@@ -319,6 +319,11 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
return -1; 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) && if (!EVP_PKEY_missing_parameters(peer) &&
!EVP_PKEY_cmp_parameters(ctx->pkey, 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) ...@@ -327,6 +332,8 @@ int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
return -1; return -1;
} }
if (ctx->peerkey)
EVP_PKEY_free(ctx->peerkey);
ctx->peerkey = peer; ctx->peerkey = peer;
ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer); ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
......
...@@ -37,7 +37,7 @@ EVP_PKEY_ctrl, EVP_PKEY_ctrl_str - algorithm specific control operations ...@@ -37,7 +37,7 @@ EVP_PKEY_ctrl, EVP_PKEY_ctrl_str - algorithm specific control operations
=head1 DESCRIPTION =head1 DESCRIPTION
The function EVP_PKEY_CTX_ctrl() sends a control operation to the context 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. 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 The control command is indicated in B<cmd> and any additional arguments in
B<p1> and B<p2>. B<p1> and B<p2>.
......
/* e_gost_err.c */ /* 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -120,10 +120,12 @@ static ERR_STRING_DATA GOST_str_reasons[]= ...@@ -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_KEY_PARAMETERS_FORMAT),"bad key parameters format"},
{ERR_REASON(GOST_R_BAD_PKEY_PARAMETERS_FORMAT),"bad pkey 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_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_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_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_ERROR_PARSING_KEY_TRANSPORT_INFO),"error parsing key transport info"},
{ERR_REASON(GOST_R_INCOMPATIBLE_ALGORITHMS),"incompatible algorithms"}, {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_PARAMS),"invalid cipher params"},
{ERR_REASON(GOST_R_INVALID_CIPHER_PARAM_OID),"invalid cipher param oid"}, {ERR_REASON(GOST_R_INVALID_CIPHER_PARAM_OID),"invalid cipher param oid"},
{ERR_REASON(GOST_R_INVALID_DIGEST_TYPE) ,"invalid digest type"}, {ERR_REASON(GOST_R_INVALID_DIGEST_TYPE) ,"invalid digest type"},
......
...@@ -118,10 +118,12 @@ void ERR_GOST_error(int function, int reason, char *file, int 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_KEY_PARAMETERS_FORMAT 99
#define GOST_R_BAD_PKEY_PARAMETERS_FORMAT 100 #define GOST_R_BAD_PKEY_PARAMETERS_FORMAT 100
#define GOST_R_CANNOT_PACK_EPHEMERAL_KEY 101 #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_COMPUTING_SHARED_KEY 102
#define GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO 103 #define GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO 103
#define GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO 104 #define GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO 104
#define GOST_R_INCOMPATIBLE_ALGORITHMS 105 #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_PARAMS 106
#define GOST_R_INVALID_CIPHER_PARAM_OID 107 #define GOST_R_INVALID_CIPHER_PARAM_OID 107
#define GOST_R_INVALID_DIGEST_TYPE 108 #define GOST_R_INVALID_DIGEST_TYPE 108
......
...@@ -203,6 +203,16 @@ int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_le ...@@ -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); ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
if (key_is_ephemeral && sec_key) EVP_PKEY_free(sec_key); 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; if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL))>0) ret =1;
GOST_KEY_TRANSPORT_free(gkt); GOST_KEY_TRANSPORT_free(gkt);
return ret; return ret;
...@@ -225,7 +235,7 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l ...@@ -225,7 +235,7 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l
unsigned char sharedKey[32]; unsigned char sharedKey[32];
gost_ctx ctx; gost_ctx ctx;
const struct gost_cipher_info *param=NULL; const struct gost_cipher_info *param=NULL;
EVP_PKEY *eph_key=NULL; EVP_PKEY *eph_key=NULL, *peerkey=NULL;
if (!key) if (!key)
{ {
...@@ -239,18 +249,35 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l ...@@ -239,18 +249,35 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l
GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
return -1; return -1;
} }
/* If key transport structure contains public key, use it */
eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key); eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
if (!eph_key) { if (eph_key)
eph_key = EVP_PKEY_CTX_get0_peerkey(pctx); {
if (! eph_key) { if (EVP_PKEY_derive_set_peer(pctx, eph_key) <= 0)
{
GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT, GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,
GOST_R_NO_PEER_KEY); GOST_R_INCOMPATIBLE_PEER_KEY);
goto err; 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;
}
}
peerkey = EVP_PKEY_CTX_get0_peerkey(pctx);
if (!peerkey)
{
GOSTerr(GOST_F_PKEY_GOST01CP_DECRYPT,
GOST_R_NO_PEER_KEY);
goto err;
} }
/* Increment reference count of peer key */
CRYPTO_add(&(eph_key->references),1 ,CRYPTO_LOCK_EVP_PKEY);
}
param = get_encryption_params(gkt->key_agreement_info->cipher); param = get_encryption_params(gkt->key_agreement_info->cipher);
gost_init(&ctx,param->sblock); gost_init(&ctx,param->sblock);
...@@ -260,7 +287,7 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l ...@@ -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); memcpy(wrappedKey+8,gkt->key_info->encrypted_key->data,32);
OPENSSL_assert(gkt->key_info->imit->length==4); OPENSSL_assert(gkt->key_info->imit->length==4);
memcpy(wrappedKey+40,gkt->key_info->imit->data,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); EVP_PKEY_get0(priv),wrappedKey);
if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key)) 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 ...@@ -269,9 +296,9 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l
goto err; goto err;
} }
EVP_PKEY_free(eph_key);
GOST_KEY_TRANSPORT_free(gkt);
ret=1; ret=1;
err: err:
if (eph_key) EVP_PKEY_free(eph_key);
if (gkt) GOST_KEY_TRANSPORT_free(gkt);
return ret; return ret;
} }
...@@ -92,7 +92,6 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, ...@@ -92,7 +92,6 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
const struct gost_cipher_info *param=get_encryption_params(NULL); const struct gost_cipher_info *param=get_encryption_params(NULL);
EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx);
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
int size=-1;
gost_ctx cctx; gost_ctx cctx;
int key_is_ephemeral=1; int key_is_ephemeral=1;
EVP_PKEY *mykey = EVP_PKEY_CTX_get0_peerkey(ctx); EVP_PKEY *mykey = EVP_PKEY_CTX_get0_peerkey(ctx);
...@@ -178,10 +177,20 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, ...@@ -178,10 +177,20 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
ASN1_OBJECT_free(gkt->key_agreement_info->cipher); ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
*outlen = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL); *outlen = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL);
if (!size) if (*outlen <= 0)
{ {
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO); GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO);
size=-1; goto err;
}
if (!key_is_ephemeral)
{
/* Set control "public key from client certificate used" */
if (EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0)
{
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
GOST_R_CTRL_CALL_FAILED);
goto err;
}
} }
GOST_KEY_TRANSPORT_free(gkt); GOST_KEY_TRANSPORT_free(gkt);
return 1; return 1;
...@@ -207,7 +216,7 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len ...@@ -207,7 +216,7 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len
unsigned char sharedKey[32]; unsigned char sharedKey[32];
gost_ctx cctx; gost_ctx cctx;
const struct gost_cipher_info *param=NULL; const struct gost_cipher_info *param=NULL;
EVP_PKEY *eph_key=NULL; EVP_PKEY *eph_key=NULL, *peerkey=NULL;
EVP_PKEY *priv= EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *priv= EVP_PKEY_CTX_get0_pkey(ctx);
if (!key) if (!key)
...@@ -224,19 +233,32 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len ...@@ -224,19 +233,32 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len
return 0; return 0;
} }
eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key); eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
/* No ephemeral key in the structure. Check peer key in the context if (eph_key)
*/ {
if (!eph_key) { if (EVP_PKEY_derive_set_peer(ctx, eph_key) <= 0)
eph_key = EVP_PKEY_CTX_get0_peerkey(ctx); {
if (! eph_key) {
GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
GOST_R_NO_PEER_KEY); GOST_R_INCOMPATIBLE_PEER_KEY);
goto err; goto err;
}
}
else
{
/* Set control "public key from client certificate used" */
if (EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0)
{
GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
GOST_R_CTRL_CALL_FAILED);
goto err;
}
}
peerkey = EVP_PKEY_CTX_get0_peerkey(ctx);
if (!peerkey)
{
GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
GOST_R_NO_PEER_KEY);
goto err;
} }
/* Increment reference count of peer key */
CRYPTO_add(&(eph_key->references),1 ,CRYPTO_LOCK_EVP_PKEY);
}
param = get_encryption_params(gkt->key_agreement_info->cipher); param = get_encryption_params(gkt->key_agreement_info->cipher);
gost_init(&cctx,param->sblock); gost_init(&cctx,param->sblock);
...@@ -246,7 +268,7 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len ...@@ -246,7 +268,7 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len
memcpy(wrappedKey+8,gkt->key_info->encrypted_key->data,32); memcpy(wrappedKey+8,gkt->key_info->encrypted_key->data,32);
OPENSSL_assert(gkt->key_info->imit->length==4); OPENSSL_assert(gkt->key_info->imit->length==4);
memcpy(wrappedKey+40,gkt->key_info->imit->data,4); memcpy(wrappedKey+40,gkt->key_info->imit->data,4);
make_cp_exchange_key(gost_get0_priv_key(priv),eph_key,sharedKey); make_cp_exchange_key(gost_get0_priv_key(priv),peerkey,sharedKey);
if (!keyUnwrapCryptoPro(&cctx,sharedKey,wrappedKey,key)) if (!keyUnwrapCryptoPro(&cctx,sharedKey,wrappedKey,key))
{ {
GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
......
...@@ -27,7 +27,7 @@ IMPLEMENT_ASN1_FUNCTIONS(GOST_KEY_INFO) ...@@ -27,7 +27,7 @@ IMPLEMENT_ASN1_FUNCTIONS(GOST_KEY_INFO)
ASN1_NDEF_SEQUENCE(GOST_KEY_AGREEMENT_INFO) = { ASN1_NDEF_SEQUENCE(GOST_KEY_AGREEMENT_INFO) = {
ASN1_SIMPLE(GOST_KEY_AGREEMENT_INFO, cipher, ASN1_OBJECT), ASN1_SIMPLE(GOST_KEY_AGREEMENT_INFO, cipher, ASN1_OBJECT),
ASN1_IMP(GOST_KEY_AGREEMENT_INFO, ephem_key, X509_PUBKEY, 0), ASN1_IMP_OPT(GOST_KEY_AGREEMENT_INFO, ephem_key, X509_PUBKEY, 0),
ASN1_SIMPLE(GOST_KEY_AGREEMENT_INFO, eph_iv, ASN1_OCTET_STRING) ASN1_SIMPLE(GOST_KEY_AGREEMENT_INFO, eph_iv, ASN1_OCTET_STRING)
} ASN1_NDEF_SEQUENCE_END(GOST_KEY_AGREEMENT_INFO) } ASN1_NDEF_SEQUENCE_END(GOST_KEY_AGREEMENT_INFO)
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
int sign_param_nid; /* Should be set whenever parameters are filled */ int sign_param_nid; /* Should be set whenever parameters are filled */
EVP_MD *md; EVP_MD *md;
unsigned char *shared_ukm; unsigned char *shared_ukm;
int peer_key_used;
}; };
struct gost_mac_pmeth_data { struct gost_mac_pmeth_data {
......
...@@ -98,7 +98,14 @@ static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) ...@@ -98,7 +98,14 @@ static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
pctx->shared_ukm=OPENSSL_malloc((int)p1); pctx->shared_ukm=OPENSSL_malloc((int)p1);
memcpy(pctx->shared_ukm,p2,(int) p1); memcpy(pctx->shared_ukm,p2,(int) p1);
return 1; return 1;
case EVP_PKEY_CTRL_PEER_KEY:
if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */
return 1;
if (p1 == 2) /* TLS: peer key used? */
return pctx->peer_key_used;
if (p1 == 3) /* TLS: peer key used! */
return (pctx->peer_key_used = 1);
return -2;
} }
return -2; return -2;
} }
......
...@@ -404,6 +404,11 @@ int ssl3_connect(SSL *s) ...@@ -404,6 +404,11 @@ int ssl3_connect(SSL *s)
s->state=SSL3_ST_CW_CHANGE_A; s->state=SSL3_ST_CW_CHANGE_A;
s->s3->change_cipher_spec=0; s->s3->change_cipher_spec=0;
} }
if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
{
s->state=SSL3_ST_CW_CHANGE_A;
s->s3->change_cipher_spec=0;
}
s->init_num=0; s->init_num=0;
break; break;
...@@ -2416,7 +2421,7 @@ int ssl3_send_client_key_exchange(SSL *s) ...@@ -2416,7 +2421,7 @@ int ssl3_send_client_key_exchange(SSL *s)
size_t msglen; size_t msglen;
unsigned int md_len; unsigned int md_len;
int keytype; int keytype;
unsigned char premaster_secret[32],shared_ukm[32]; unsigned char premaster_secret[32],shared_ukm[32], tmp[256];
EVP_MD_CTX *ukm_hash; EVP_MD_CTX *ukm_hash;
EVP_PKEY *pub_key; EVP_PKEY *pub_key;
...@@ -2442,16 +2447,13 @@ int ssl3_send_client_key_exchange(SSL *s) ...@@ -2442,16 +2447,13 @@ int ssl3_send_client_key_exchange(SSL *s)
/* Generate session key */ /* Generate session key */
RAND_bytes(premaster_secret,32); RAND_bytes(premaster_secret,32);
/* If we have client certificate, use its secret as peer key */ /* If we have client certificate, use its secret as peer key */
if (s->cert->key->privatekey) { if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <0) { if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <=0) {
/* If there was an error - just ignore it. Ephemeral key /* If there was an error - just ignore it. Ephemeral key
* would be used * would be used
*/ */
ERR_clear_error(); ERR_clear_error();
} else { }
/* Set flag "client cert key is used for key
* exchange"*/
}
} }
/* Compute shared IV and store it in algorithm-specific /* Compute shared IV and store it in algorithm-specific
* context data */ * context data */
...@@ -2470,15 +2472,30 @@ int ssl3_send_client_key_exchange(SSL *s) ...@@ -2470,15 +2472,30 @@ int ssl3_send_client_key_exchange(SSL *s)
/* Make GOST keytransport blob message */ /* Make GOST keytransport blob message */
/*Encapsulate it into sequence */ /*Encapsulate it into sequence */
*(p++)=V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED; *(p++)=V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
*(p++)=0x81; msglen=255;
msglen=256; if (EVP_PKEY_encrypt(pkey_ctx,tmp,&msglen,premaster_secret,32)<0) {
if (EVP_PKEY_encrypt(pkey_ctx,(unsigned char *)p+1,&msglen,premaster_secret,32)<0) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
SSL_R_LIBRARY_BUG); SSL_R_LIBRARY_BUG);
goto err; goto err;
} }
*(p++)= msglen & 0xff; if (msglen >= 0x80)
n=msglen+3; {
*(p++)=0x81;
*(p++)= msglen & 0xff;
n=msglen+3;
}
else
{
*(p++)= msglen & 0xff;
n=msglen+2;
}
memcpy(p, tmp, msglen);
/* Check if pubkey from client certificate was used */
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
{
/* Set flag "skip certificate verify" */
s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
}
EVP_PKEY_CTX_free(pkey_ctx); EVP_PKEY_CTX_free(pkey_ctx);
s->session->master_key_length= s->session->master_key_length=
s->method->ssl3_enc->generate_master_secret(s, s->method->ssl3_enc->generate_master_secret(s,
......
...@@ -514,6 +514,9 @@ int ssl3_accept(SSL *s) ...@@ -514,6 +514,9 @@ int ssl3_accept(SSL *s)
* the client sends its ECDH pub key in * the client sends its ECDH pub key in
* a certificate, the CertificateVerify * a certificate, the CertificateVerify
* message is not sent. * message is not sent.
* Also for GOST ciphersuites when
* the client uses its key from the certificate
* for key exchange.
*/ */
s->state=SSL3_ST_SR_FINISHED_A; s->state=SSL3_ST_SR_FINISHED_A;
s->init_num = 0; s->init_num = 0;
...@@ -2496,33 +2499,70 @@ int ssl3_get_client_key_exchange(SSL *s) ...@@ -2496,33 +2499,70 @@ int ssl3_get_client_key_exchange(SSL *s)
else else
#endif #endif
if (alg_k & SSL_kGOST) if (alg_k & SSL_kGOST)
{ {
int ret = 0;
EVP_PKEY_CTX *pkey_ctx; EVP_PKEY_CTX *pkey_ctx;
unsigned char premaster_secret[32]; EVP_PKEY *client_pub_pkey = NULL;
size_t outlen; unsigned char premaster_secret[32], *start;
size_t outlen, inlen;
/* Get our certificate privatec key*/ /* Get our certificate private key*/
pkey_ctx = EVP_PKEY_CTX_new(s->cert->key->privatekey,NULL); pkey_ctx = EVP_PKEY_CTX_new(s->cert->key->privatekey,NULL);
EVP_PKEY_decrypt_init(pkey_ctx); EVP_PKEY_decrypt_init(pkey_ctx);
/* If client certificate is present and is of the same type, maybe
* use it for key exchange. Don't mind errors from
* EVP_PKEY_derive_set_peer, because it is completely valid to use
* a client certificate for authorization only. */
client_pub_pkey = X509_get_pubkey(s->session->peer);
if (client_pub_pkey)
{
if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
ERR_clear_error();
}
/* Decrypt session key */ /* Decrypt session key */
if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED)) || p[1]!=0x81 ) if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED)))
{ {
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
goto err; goto gerr;
} }
if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,p+3,p[2]) <0) if (p[1] == 0x81)
{
start = p+3;
inlen = p[2];
}
else if (p[1] < 0x80)
{
start = p+2;
inlen = p[1];
}
else
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
goto gerr;
}
if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0)
{ {
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED); SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
goto err; goto gerr;
} }
/* Generate master secret */ /* Generate master secret */
EVP_PKEY_CTX_free(pkey_ctx);
s->session->master_key_length= s->session->master_key_length=
s->method->ssl3_enc->generate_master_secret(s, s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key,premaster_secret,32); s->session->master_key,premaster_secret,32);
/* Check if pubkey from client certificate was used */
} if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
ret = 2;
else
ret = 1;
gerr:
EVP_PKEY_free(client_pub_pkey);
EVP_PKEY_CTX_free(pkey_ctx);
if (ret)
return ret;
else
goto err;
}
else else
{ {
al=SSL_AD_HANDSHAKE_FAILURE; al=SSL_AD_HANDSHAKE_FAILURE;
......
...@@ -375,6 +375,7 @@ typedef struct ssl3_buffer_st ...@@ -375,6 +375,7 @@ typedef struct ssl3_buffer_st
#define SSL3_FLAGS_DELAY_CLIENT_FINISHED 0x0002 #define SSL3_FLAGS_DELAY_CLIENT_FINISHED 0x0002
#define SSL3_FLAGS_POP_BUFFER 0x0004 #define SSL3_FLAGS_POP_BUFFER 0x0004
#define TLS1_FLAGS_TLS_PADDING_BUG 0x0008 #define TLS1_FLAGS_TLS_PADDING_BUG 0x0008
#define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010
typedef struct ssl3_state_st typedef struct ssl3_state_st
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册