Updates from HEAD.
This commit is contained in:
parent
f1ed5fa827
commit
bfd502f027
@ -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);
|
||||
|
@ -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>.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* 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"},
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
@ -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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
gost_init(&ctx,param->sblock);
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx);
|
||||
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
|
||||
int size=-1;
|
||||
gost_ctx cctx;
|
||||
int key_is_ephemeral=1;
|
||||
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,
|
||||
ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
|
||||
gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
|
||||
*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);
|
||||
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);
|
||||
return 1;
|
||||
@ -207,7 +216,7 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len
|
||||
unsigned char sharedKey[32];
|
||||
gost_ctx cctx;
|
||||
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);
|
||||
|
||||
if (!key)
|
||||
@ -224,19 +233,32 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len
|
||||
return 0;
|
||||
}
|
||||
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) {
|
||||
eph_key = EVP_PKEY_CTX_get0_peerkey(ctx);
|
||||
if (! eph_key) {
|
||||
if (eph_key)
|
||||
{
|
||||
if (EVP_PKEY_derive_set_peer(ctx, eph_key) <= 0)
|
||||
{
|
||||
GOSTerr(GOST_F_PKEY_GOST94CP_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(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);
|
||||
gost_init(&cctx,param->sblock);
|
||||
@ -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);
|
||||
OPENSSL_assert(gkt->key_info->imit->length==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))
|
||||
{
|
||||
GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
|
||||
|
@ -27,7 +27,7 @@ IMPLEMENT_ASN1_FUNCTIONS(GOST_KEY_INFO)
|
||||
|
||||
ASN1_NDEF_SEQUENCE(GOST_KEY_AGREEMENT_INFO) = {
|
||||
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_NDEF_SEQUENCE_END(GOST_KEY_AGREEMENT_INFO)
|
||||
|
||||
|
@ -47,6 +47,7 @@
|
||||
int sign_param_nid; /* Should be set whenever parameters are filled */
|
||||
EVP_MD *md;
|
||||
unsigned char *shared_ukm;
|
||||
int peer_key_used;
|
||||
};
|
||||
|
||||
struct gost_mac_pmeth_data {
|
||||
|
@ -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);
|
||||
memcpy(pctx->shared_ukm,p2,(int) p1);
|
||||
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;
|
||||
}
|
||||
|
@ -404,6 +404,11 @@ int ssl3_connect(SSL *s)
|
||||
s->state=SSL3_ST_CW_CHANGE_A;
|
||||
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;
|
||||
break;
|
||||
@ -2416,7 +2421,7 @@ int ssl3_send_client_key_exchange(SSL *s)
|
||||
size_t msglen;
|
||||
unsigned int md_len;
|
||||
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_PKEY *pub_key;
|
||||
|
||||
@ -2442,16 +2447,13 @@ int ssl3_send_client_key_exchange(SSL *s)
|
||||
/* Generate session key */
|
||||
RAND_bytes(premaster_secret,32);
|
||||
/* If we have client certificate, use its secret as peer key */
|
||||
if (s->cert->key->privatekey) {
|
||||
if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <0) {
|
||||
if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
|
||||
if (EVP_PKEY_derive_set_peer(pkey_ctx,s->cert->key->privatekey) <=0) {
|
||||
/* If there was an error - just ignore it. Ephemeral key
|
||||
* would be used
|
||||
*/
|
||||
ERR_clear_error();
|
||||
} else {
|
||||
/* Set flag "client cert key is used for key
|
||||
* exchange"*/
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Compute shared IV and store it in algorithm-specific
|
||||
* context data */
|
||||
@ -2470,15 +2472,30 @@ int ssl3_send_client_key_exchange(SSL *s)
|
||||
/* Make GOST keytransport blob message */
|
||||
/*Encapsulate it into sequence */
|
||||
*(p++)=V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
|
||||
*(p++)=0x81;
|
||||
msglen=256;
|
||||
if (EVP_PKEY_encrypt(pkey_ctx,(unsigned char *)p+1,&msglen,premaster_secret,32)<0) {
|
||||
msglen=255;
|
||||
if (EVP_PKEY_encrypt(pkey_ctx,tmp,&msglen,premaster_secret,32)<0) {
|
||||
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
|
||||
SSL_R_LIBRARY_BUG);
|
||||
goto err;
|
||||
}
|
||||
*(p++)= msglen & 0xff;
|
||||
n=msglen+3;
|
||||
}
|
||||
if (msglen >= 0x80)
|
||||
{
|
||||
*(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);
|
||||
s->session->master_key_length=
|
||||
s->method->ssl3_enc->generate_master_secret(s,
|
||||
|
@ -514,6 +514,9 @@ int ssl3_accept(SSL *s)
|
||||
* the client sends its ECDH pub key in
|
||||
* a certificate, the CertificateVerify
|
||||
* 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->init_num = 0;
|
||||
@ -2496,33 +2499,70 @@ int ssl3_get_client_key_exchange(SSL *s)
|
||||
else
|
||||
#endif
|
||||
if (alg_k & SSL_kGOST)
|
||||
{
|
||||
{
|
||||
int ret = 0;
|
||||
EVP_PKEY_CTX *pkey_ctx;
|
||||
unsigned char premaster_secret[32];
|
||||
size_t outlen;
|
||||
EVP_PKEY *client_pub_pkey = NULL;
|
||||
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);
|
||||
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 */
|
||||
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);
|
||||
goto err;
|
||||
}
|
||||
if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,p+3,p[2]) <0)
|
||||
goto gerr;
|
||||
}
|
||||
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);
|
||||
goto err;
|
||||
goto gerr;
|
||||
}
|
||||
/* Generate master secret */
|
||||
EVP_PKEY_CTX_free(pkey_ctx);
|
||||
s->session->master_key_length=
|
||||
s->method->ssl3_enc->generate_master_secret(s,
|
||||
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
|
||||
{
|
||||
al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
|
@ -375,6 +375,7 @@ typedef struct ssl3_buffer_st
|
||||
#define SSL3_FLAGS_DELAY_CLIENT_FINISHED 0x0002
|
||||
#define SSL3_FLAGS_POP_BUFFER 0x0004
|
||||
#define TLS1_FLAGS_TLS_PADDING_BUG 0x0008
|
||||
#define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010
|
||||
|
||||
typedef struct ssl3_state_st
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user