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>
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index cba98a7..253cf81 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -362,17 +362,8 @@
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 @@
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 @@
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 @@
/* 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 @@
{
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 @@
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 @@
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 @@
}
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 @@
}
/* 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 @@
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;
}