Remove support on both sides for *_fixed_(ec)dh client auth.
In the fixed_ecdh case, it wasn't even implemented, but there was stub code for it. It complicates the ClientKeyExchange (the client parameters become implicit in the certificate) and isn't used. Change-Id: I3627a37042539c90e05e59cd0cb3cd6c56225561 Reviewed-on: https://boringssl-review.googlesource.com/1563 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
committed by
Adam Langley
parent
d0639af978
commit
bd30f8e34a
@@ -341,7 +341,6 @@ typedef struct ssl3_buffer_st
|
||||
#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001
|
||||
#define SSL3_FLAGS_POP_BUFFER 0x0004
|
||||
#define TLS1_FLAGS_TLS_PADDING_BUG 0x0008
|
||||
#define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010
|
||||
#define TLS1_FLAGS_KEEP_HANDSHAKE 0x0020
|
||||
/* TODO(davidben): This flag can probably be merged into s3->change_cipher_spec
|
||||
* to something tri-state. (Normal / Expect CCS / Between CCS and Finished). */
|
||||
|
||||
@@ -375,9 +375,6 @@ int dtls1_connect(SSL *s)
|
||||
dtls1_start_timer(s);
|
||||
ret=ssl3_send_client_key_exchange(s);
|
||||
if (ret <= 0) goto end;
|
||||
|
||||
/* EAY EAY EAY need to check for DH fix cert
|
||||
* sent back */
|
||||
/* For TLS, cert_req is set to 2, so a cert chain
|
||||
* of nothing is sent, but no verify packet is sent */
|
||||
if (s->s3->tmp.cert_req == 1)
|
||||
|
||||
+3
-16
@@ -492,22 +492,9 @@ int dtls1_accept(SSL *s)
|
||||
case SSL3_ST_SR_KEY_EXCH_A:
|
||||
case SSL3_ST_SR_KEY_EXCH_B:
|
||||
ret=ssl3_get_client_key_exchange(s);
|
||||
if (ret <= 0) goto end;
|
||||
|
||||
s->state=SSL3_ST_SR_CERT_VRFY_A;
|
||||
s->init_num=0;
|
||||
|
||||
if (ret == 2)
|
||||
{
|
||||
/* For the ECDH ciphersuites when
|
||||
* the client sends its ECDH pub key in
|
||||
* a certificate, the CertificateVerify
|
||||
* message is not sent.
|
||||
*/
|
||||
s->state=SSL3_ST_SR_FINISHED_A;
|
||||
s->init_num = 0;
|
||||
}
|
||||
else if (SSL_USE_SIGALGS(s))
|
||||
if (ret <= 0)
|
||||
goto end;
|
||||
if (SSL_USE_SIGALGS(s))
|
||||
{
|
||||
s->state=SSL3_ST_SR_CERT_VRFY_A;
|
||||
s->init_num=0;
|
||||
|
||||
+56
-176
@@ -362,17 +362,8 @@ int ssl3_connect(SSL *s)
|
||||
case SSL3_ST_CW_KEY_EXCH_B:
|
||||
ret=ssl3_send_client_key_exchange(s);
|
||||
if (ret <= 0) goto end;
|
||||
/* EAY EAY EAY need to check for DH fix cert
|
||||
* sent back */
|
||||
/* For TLS, cert_req is set to 2, so a cert chain
|
||||
* of nothing is sent, but no verify packet is sent */
|
||||
/* XXX: For now, we do not support client
|
||||
* authentication in ECDH cipher suites with
|
||||
* ECDH (rather than ECDSA) certificates.
|
||||
* We need to skip the certificate verify
|
||||
* message when client's ECDH public key is sent
|
||||
* inside the client certificate.
|
||||
*/
|
||||
if (s->s3->tmp.cert_req == 1)
|
||||
{
|
||||
s->state=SSL3_ST_CW_CERT_VRFY_A;
|
||||
@@ -382,11 +373,6 @@ 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;
|
||||
@@ -2122,33 +2108,17 @@ int ssl3_send_client_key_exchange(SSL *s)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
|
||||
/* generate a new random key */
|
||||
if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)
|
||||
{
|
||||
/* Use client certificate key */
|
||||
EVP_PKEY *clkey = s->cert->key->privatekey;
|
||||
dh_clnt = NULL;
|
||||
if (clkey)
|
||||
dh_clnt = EVP_PKEY_get1_DH(clkey);
|
||||
if (dh_clnt == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
if (!DH_generate_key(dh_clnt))
|
||||
{
|
||||
/* generate a new random key */
|
||||
if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (!DH_generate_key(dh_clnt))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
|
||||
DH_free(dh_clnt);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
|
||||
DH_free(dh_clnt);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* use the 'p' output buffer for the DH key, but
|
||||
@@ -2172,16 +2142,11 @@ int ssl3_send_client_key_exchange(SSL *s)
|
||||
/* clean up */
|
||||
memset(p,0,n);
|
||||
|
||||
if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY)
|
||||
n = 0;
|
||||
else
|
||||
{
|
||||
/* send off the data */
|
||||
n=BN_num_bytes(dh_clnt->pub_key);
|
||||
s2n(n,p);
|
||||
BN_bn2bin(dh_clnt->pub_key,p);
|
||||
n+=2;
|
||||
}
|
||||
/* send off the data */
|
||||
n=BN_num_bytes(dh_clnt->pub_key);
|
||||
s2n(n,p);
|
||||
BN_bn2bin(dh_clnt->pub_key,p);
|
||||
n+=2;
|
||||
|
||||
DH_free(dh_clnt);
|
||||
|
||||
@@ -2194,7 +2159,6 @@ int ssl3_send_client_key_exchange(SSL *s)
|
||||
{
|
||||
const EC_GROUP *srvr_group = NULL;
|
||||
EC_KEY *tkey;
|
||||
int ecdh_clnt_cert = 0;
|
||||
int field_size = 0;
|
||||
unsigned char *pre_ms;
|
||||
unsigned char *t;
|
||||
@@ -2208,34 +2172,6 @@ int ssl3_send_client_key_exchange(SSL *s)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Did we send out the client's
|
||||
* ECDH share for use in premaster
|
||||
* computation as part of client certificate?
|
||||
* If so, set ecdh_clnt_cert to 1.
|
||||
*/
|
||||
if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->cert != NULL))
|
||||
{
|
||||
/* XXX: For now, we do not support client
|
||||
* authentication using ECDH certificates.
|
||||
* To add such support, one needs to add
|
||||
* code that checks for appropriate
|
||||
* conditions and sets ecdh_clnt_cert to 1.
|
||||
* For example, the cert have an ECC
|
||||
* key on the same curve as the server's
|
||||
* and the key should be authorized for
|
||||
* key agreement.
|
||||
*
|
||||
* One also needs to add code in ssl3_connect
|
||||
* to skip sending the certificate verify
|
||||
* message.
|
||||
*
|
||||
* if ((s->cert->key->privatekey != NULL) &&
|
||||
* (s->cert->key->privatekey->type ==
|
||||
* EVP_PKEY_EC) && ...)
|
||||
* ecdh_clnt_cert = 1;
|
||||
*/
|
||||
}
|
||||
|
||||
if (s->session->sess_cert->peer_ecdh_tmp != NULL)
|
||||
{
|
||||
tkey = s->session->sess_cert->peer_ecdh_tmp;
|
||||
@@ -2276,34 +2212,11 @@ int ssl3_send_client_key_exchange(SSL *s)
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (ecdh_clnt_cert)
|
||||
{
|
||||
/* Reuse key info from our certificate
|
||||
* We only need our private key to perform
|
||||
* the ECDH computation.
|
||||
*/
|
||||
const BIGNUM *priv_key;
|
||||
tkey = s->cert->key->privatekey->pkey.ec;
|
||||
priv_key = EC_KEY_get0_private_key(tkey);
|
||||
if (priv_key == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (!EC_KEY_set_private_key(clnt_ecdh, priv_key))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Generate a new ECDH key pair */
|
||||
if (!(EC_KEY_generate_key(clnt_ecdh)))
|
||||
{
|
||||
/* Generate a new ECDH key pair */
|
||||
if (!(EC_KEY_generate_key(clnt_ecdh)))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* use the 'p' output buffer for the ECDH key, but
|
||||
@@ -2355,59 +2268,51 @@ int ssl3_send_client_key_exchange(SSL *s)
|
||||
}
|
||||
memset(p, 0, n); /* clean up */
|
||||
|
||||
if (ecdh_clnt_cert)
|
||||
{
|
||||
/* Send empty client key exch message */
|
||||
n = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* First check the size of encoding and
|
||||
* allocate memory accordingly.
|
||||
*/
|
||||
encoded_pt_len =
|
||||
EC_POINT_point2oct(srvr_group,
|
||||
/* First check the size of encoding and
|
||||
* allocate memory accordingly.
|
||||
*/
|
||||
encoded_pt_len =
|
||||
EC_POINT_point2oct(srvr_group,
|
||||
EC_KEY_get0_public_key(clnt_ecdh),
|
||||
POINT_CONVERSION_UNCOMPRESSED,
|
||||
NULL, 0, NULL);
|
||||
|
||||
encodedPoint = (unsigned char *)
|
||||
OPENSSL_malloc(encoded_pt_len *
|
||||
encodedPoint = (unsigned char *)
|
||||
OPENSSL_malloc(encoded_pt_len *
|
||||
sizeof(unsigned char));
|
||||
bn_ctx = BN_CTX_new();
|
||||
if ((encodedPoint == NULL) ||
|
||||
(bn_ctx == NULL))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Encode the public key */
|
||||
encoded_pt_len = EC_POINT_point2oct(srvr_group,
|
||||
EC_KEY_get0_public_key(clnt_ecdh),
|
||||
POINT_CONVERSION_UNCOMPRESSED,
|
||||
encodedPoint, encoded_pt_len, bn_ctx);
|
||||
|
||||
n = 0;
|
||||
if ((alg_a & SSL_aPSK) && psk_len != 0)
|
||||
{
|
||||
i = strlen(s->session->psk_identity);
|
||||
s2n(i, p);
|
||||
memcpy(p, s->session->psk_identity, i);
|
||||
p += i;
|
||||
n = i + 2;
|
||||
}
|
||||
|
||||
*p = encoded_pt_len; /* length of encoded point */
|
||||
/* Encoded point will be copied here */
|
||||
p += 1;
|
||||
n += 1;
|
||||
/* copy the point */
|
||||
memcpy((unsigned char *)p, encodedPoint, encoded_pt_len);
|
||||
/* increment n to account for length field */
|
||||
n += encoded_pt_len;
|
||||
bn_ctx = BN_CTX_new();
|
||||
if ((encodedPoint == NULL) ||
|
||||
(bn_ctx == NULL))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Encode the public key */
|
||||
encoded_pt_len = EC_POINT_point2oct(srvr_group,
|
||||
EC_KEY_get0_public_key(clnt_ecdh),
|
||||
POINT_CONVERSION_UNCOMPRESSED,
|
||||
encodedPoint, encoded_pt_len, bn_ctx);
|
||||
|
||||
n = 0;
|
||||
if ((alg_a & SSL_aPSK) && psk_len != 0)
|
||||
{
|
||||
i = strlen(s->session->psk_identity);
|
||||
s2n(i, p);
|
||||
memcpy(p, s->session->psk_identity, i);
|
||||
p += i;
|
||||
n = i + 2;
|
||||
}
|
||||
|
||||
*p = encoded_pt_len; /* length of encoded point */
|
||||
/* Encoded point will be copied here */
|
||||
p += 1;
|
||||
n += 1;
|
||||
/* copy the point */
|
||||
memcpy((unsigned char *)p, encodedPoint, encoded_pt_len);
|
||||
/* increment n to account for length field */
|
||||
n += encoded_pt_len;
|
||||
|
||||
/* Free allocated memory */
|
||||
BN_CTX_free(bn_ctx);
|
||||
if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
|
||||
@@ -2560,12 +2465,10 @@ err:
|
||||
}
|
||||
|
||||
/* Check a certificate can be used for client authentication. Currently
|
||||
* check cert exists, if we have a suitable digest for TLS 1.2 if
|
||||
* static DH client certificates can be used.
|
||||
* check the cert exists and if we have a suitable digest for TLS 1.2.
|
||||
*/
|
||||
static int ssl3_check_client_certificate(SSL *s)
|
||||
{
|
||||
unsigned long alg_k;
|
||||
if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey)
|
||||
return 0;
|
||||
/* If no suitable signature algorithm can't use certificate */
|
||||
@@ -2576,29 +2479,6 @@ static int ssl3_check_client_certificate(SSL *s)
|
||||
if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT &&
|
||||
!tls1_check_chain(s, NULL, NULL, NULL, -2))
|
||||
return 0;
|
||||
alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
|
||||
/* See if we can use client certificate for fixed DH */
|
||||
if (alg_k & (SSL_kDHr|SSL_kDHd))
|
||||
{
|
||||
SESS_CERT *scert = s->session->sess_cert;
|
||||
int i = scert->peer_cert_type;
|
||||
EVP_PKEY *clkey = NULL, *spkey = NULL;
|
||||
clkey = s->cert->key->privatekey;
|
||||
/* If client key not DH assume it can be used */
|
||||
if (EVP_PKEY_id(clkey) != EVP_PKEY_DH)
|
||||
return 1;
|
||||
if (i >= 0)
|
||||
spkey = X509_get_pubkey(scert->peer_pkeys[i].x509);
|
||||
if (spkey)
|
||||
{
|
||||
/* Compare server and client parameters */
|
||||
i = EVP_PKEY_cmp_parameters(clkey, spkey);
|
||||
EVP_PKEY_free(spkey);
|
||||
if (i != 1)
|
||||
return 0;
|
||||
}
|
||||
s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -2538,8 +2538,6 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
|
||||
#ifndef OPENSSL_NO_ECDSA
|
||||
int have_ecdsa_sign = 0;
|
||||
#endif
|
||||
int nostrict = 1;
|
||||
unsigned long alg_k;
|
||||
|
||||
/* If we have custom certificate types set, use them */
|
||||
if (s->cert->client_certificate_types)
|
||||
@@ -2550,8 +2548,6 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
|
||||
}
|
||||
/* get configured sigalgs */
|
||||
siglen = tls12_get_psigalgs(s, &sig);
|
||||
if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
|
||||
nostrict = 0;
|
||||
for (i = 0; i < siglen; i+=2, sig+=2)
|
||||
{
|
||||
switch(sig[1])
|
||||
@@ -2571,45 +2567,12 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
|
||||
}
|
||||
}
|
||||
|
||||
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
|
||||
|
||||
#ifndef OPENSSL_NO_DH
|
||||
if (alg_k & (SSL_kDHr|SSL_kEDH))
|
||||
{
|
||||
/* Since this refers to a certificate signed with an RSA
|
||||
* algorithm, only check for rsa signing in strict mode.
|
||||
*/
|
||||
if (nostrict || have_rsa_sign)
|
||||
p[ret++]=SSL3_CT_RSA_FIXED_DH;
|
||||
# ifndef OPENSSL_NO_DSA
|
||||
if (nostrict || have_dsa_sign)
|
||||
p[ret++]=SSL3_CT_DSS_FIXED_DH;
|
||||
# endif
|
||||
}
|
||||
if ((s->version == SSL3_VERSION) &&
|
||||
(alg_k & (SSL_kEDH|SSL_kDHd|SSL_kDHr)))
|
||||
{
|
||||
p[ret++]=SSL3_CT_RSA_EPHEMERAL_DH;
|
||||
# ifndef OPENSSL_NO_DSA
|
||||
p[ret++]=SSL3_CT_DSS_EPHEMERAL_DH;
|
||||
# endif
|
||||
}
|
||||
#endif /* !OPENSSL_NO_DH */
|
||||
if (have_rsa_sign)
|
||||
p[ret++]=SSL3_CT_RSA_SIGN;
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
if (have_dsa_sign)
|
||||
p[ret++]=SSL3_CT_DSS_SIGN;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->version >= TLS1_VERSION))
|
||||
{
|
||||
if (nostrict || have_rsa_sign)
|
||||
p[ret++]=TLS_CT_RSA_FIXED_ECDH;
|
||||
if (nostrict || have_ecdsa_sign)
|
||||
p[ret++]=TLS_CT_ECDSA_FIXED_ECDH;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_ECDSA
|
||||
/* ECDSA certs can be used with RSA cipher suites as well
|
||||
|
||||
+26
-112
@@ -259,7 +259,6 @@ int ssl3_accept(SSL *s)
|
||||
|
||||
s->init_num=0;
|
||||
s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE;
|
||||
s->s3->flags &= ~TLS1_FLAGS_SKIP_CERT_VERIFY;
|
||||
|
||||
if (s->state != SSL_ST_RENEGOTIATE)
|
||||
{
|
||||
@@ -493,17 +492,7 @@ int ssl3_accept(SSL *s)
|
||||
ret=ssl3_get_client_key_exchange(s);
|
||||
if (ret <= 0)
|
||||
goto end;
|
||||
if (ret == 2)
|
||||
{
|
||||
/* For the ECDH ciphersuites when
|
||||
* the client sends its ECDH pub key in
|
||||
* a certificate, the CertificateVerify
|
||||
* message is not sent.
|
||||
*/
|
||||
s->init_num = 0;
|
||||
s->state = SSL3_ST_SR_CHANGE;
|
||||
}
|
||||
else if (SSL_USE_SIGALGS(s))
|
||||
if (SSL_USE_SIGALGS(s))
|
||||
{
|
||||
s->state=SSL3_ST_SR_CERT_VRFY_A;
|
||||
s->init_num=0;
|
||||
@@ -1885,13 +1874,12 @@ int ssl3_get_client_key_exchange(SSL *s)
|
||||
unsigned long alg_a;
|
||||
uint8_t *premaster_secret = NULL;
|
||||
size_t premaster_secret_len = 0;
|
||||
int skip_certificate_verify = 0;
|
||||
RSA *rsa=NULL;
|
||||
uint8_t *decrypt_buf = NULL;
|
||||
EVP_PKEY *pkey=NULL;
|
||||
#ifndef OPENSSL_NO_DH
|
||||
BIGNUM *pub=NULL;
|
||||
DH *dh_srvr, *dh_clnt = NULL;
|
||||
DH *dh_srvr;
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
@@ -1972,8 +1960,7 @@ int ssl3_get_client_key_exchange(SSL *s)
|
||||
}
|
||||
|
||||
/* Depending on the key exchange method, compute |premaster_secret| and
|
||||
* |premaster_secret_len|. Also, for DH and ECDH, set
|
||||
* |skip_certificate_verify| as appropriate. */
|
||||
* |premaster_secret_len|. */
|
||||
if (alg_k & SSL_kRSA)
|
||||
{
|
||||
CBS encrypted_premaster_secret;
|
||||
@@ -2139,6 +2126,7 @@ int ssl3_get_client_key_exchange(SSL *s)
|
||||
EVP_PKEY *skey = NULL;
|
||||
|
||||
if (!CBS_get_u16_length_prefixed(&client_key_exchange, &dh_Yc) ||
|
||||
CBS_len(&dh_Yc) == 0 ||
|
||||
CBS_len(&client_key_exchange) != 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
|
||||
@@ -2172,33 +2160,7 @@ int ssl3_get_client_key_exchange(SSL *s)
|
||||
else
|
||||
dh_srvr=s->s3->tmp.dh;
|
||||
|
||||
if (CBS_len(&dh_Yc) == 0)
|
||||
{
|
||||
/* Get pubkey from the client certificate. This is the
|
||||
* 'implicit' case of ClientDiffieHellman.
|
||||
*
|
||||
* TODO(davidben): Either lose this code or fix a bug
|
||||
* (or get the spec changed): if there is a fixed_dh
|
||||
* client certificate, per spec, the 'implicit' mode
|
||||
* MUST be used. This logic will still accept 'explicit'
|
||||
* mode. */
|
||||
EVP_PKEY *clkey=X509_get_pubkey(s->session->peer);
|
||||
if (clkey)
|
||||
{
|
||||
if (EVP_PKEY_cmp_parameters(clkey, skey) == 1)
|
||||
dh_clnt = EVP_PKEY_get1_DH(clkey);
|
||||
}
|
||||
if (dh_clnt == NULL)
|
||||
{
|
||||
al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_MISSING_TMP_DH_KEY);
|
||||
goto f_err;
|
||||
}
|
||||
EVP_PKEY_free(clkey);
|
||||
pub = dh_clnt->pub_key;
|
||||
}
|
||||
else
|
||||
pub = BN_bin2bn(CBS_data(&dh_Yc), CBS_len(&dh_Yc), NULL);
|
||||
pub = BN_bin2bn(CBS_data(&dh_Yc), CBS_len(&dh_Yc), NULL);
|
||||
if (pub == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_BN_LIB);
|
||||
@@ -2223,15 +2185,10 @@ int ssl3_get_client_key_exchange(SSL *s)
|
||||
|
||||
DH_free(s->s3->tmp.dh);
|
||||
s->s3->tmp.dh=NULL;
|
||||
if (dh_clnt)
|
||||
DH_free(dh_clnt);
|
||||
else
|
||||
BN_clear_free(pub);
|
||||
BN_clear_free(pub);
|
||||
pub=NULL;
|
||||
|
||||
premaster_secret_len = dh_len;
|
||||
if (dh_clnt)
|
||||
skip_certificate_verify = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2242,6 +2199,7 @@ int ssl3_get_client_key_exchange(SSL *s)
|
||||
const EC_KEY *tkey;
|
||||
const EC_GROUP *group;
|
||||
const BIGNUM *priv_key;
|
||||
CBS ecdh_Yc;
|
||||
|
||||
/* initialize structures for server's ECDH key pair */
|
||||
if ((srvr_ecdh = EC_KEY_new()) == NULL)
|
||||
@@ -2281,72 +2239,28 @@ int ssl3_get_client_key_exchange(SSL *s)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (CBS_len(&client_key_exchange) == 0)
|
||||
/* Get client's public key from encoded point
|
||||
* in the ClientKeyExchange message.
|
||||
*/
|
||||
if (!CBS_get_u8_length_prefixed(&client_key_exchange, &ecdh_Yc) ||
|
||||
CBS_len(&client_key_exchange) != 0)
|
||||
{
|
||||
/* Client Publickey was in Client Certificate */
|
||||
|
||||
if (alg_k & SSL_kEECDH)
|
||||
{
|
||||
al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_MISSING_TMP_ECDH_KEY);
|
||||
goto f_err;
|
||||
}
|
||||
if (((clnt_pub_pkey=X509_get_pubkey(s->session->peer))
|
||||
== NULL) ||
|
||||
(clnt_pub_pkey->type != EVP_PKEY_EC))
|
||||
{
|
||||
/* XXX: For now, we do not support client
|
||||
* authentication using ECDH certificates
|
||||
* so this branch (n == 0L) of the code is
|
||||
* never executed. When that support is
|
||||
* added, we ought to ensure the key
|
||||
* received in the certificate is
|
||||
* authorized for key agreement.
|
||||
* ECDH_compute_key implicitly checks that
|
||||
* the two ECDH shares are for the same
|
||||
* group.
|
||||
*/
|
||||
al=SSL_AD_HANDSHAKE_FAILURE;
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_UNABLE_TO_DECODE_ECDH_CERTS);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
if (EC_POINT_copy(clnt_ecpoint,
|
||||
EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)) == 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
/* Skip certificate verify processing */
|
||||
skip_certificate_verify = 1;
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR);
|
||||
goto f_err;
|
||||
}
|
||||
else
|
||||
|
||||
if ((bn_ctx = BN_CTX_new()) == NULL)
|
||||
{
|
||||
CBS ecdh_Yc;
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get client's public key from encoded point
|
||||
* in the ClientKeyExchange message.
|
||||
*/
|
||||
if (!CBS_get_u8_length_prefixed(&client_key_exchange, &ecdh_Yc) ||
|
||||
CBS_len(&client_key_exchange) != 0)
|
||||
{
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
if ((bn_ctx = BN_CTX_new()) == NULL)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EC_POINT_oct2point(group, clnt_ecpoint,
|
||||
CBS_data(&ecdh_Yc), CBS_len(&ecdh_Yc), bn_ctx))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (!EC_POINT_oct2point(group, clnt_ecpoint,
|
||||
CBS_data(&ecdh_Yc), CBS_len(&ecdh_Yc), bn_ctx))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Allocate a buffer for both the secret and the PSK. */
|
||||
@@ -2441,7 +2355,7 @@ int ssl3_get_client_key_exchange(SSL *s)
|
||||
|
||||
OPENSSL_cleanse(premaster_secret, premaster_secret_len);
|
||||
OPENSSL_free(premaster_secret);
|
||||
return skip_certificate_verify ? 2 : 1;
|
||||
return 1;
|
||||
f_err:
|
||||
ssl3_send_alert(s,SSL3_AL_FATAL,al);
|
||||
err:
|
||||
|
||||
Reference in New Issue
Block a user