Clean up ssl_set_cert_masks.
It doesn't depend on the cipher now that export ciphers are gone. It need only be called once. Also remove the valid bit; nothing ever reads it. Its output is also only used within a function, so make mask_k and mask_a local variables. So all the configuration-based checks are in one place, change the input parameter from CERT to SSL and move the PSK and ECDHE checks to the mask computation. This avoids having to evaluate the temporary EC key for each cipher. The remaining uses are on the client which uses them differently (disabled features rather than enabled ones). Those too may as well be local variables, so leave a TODO. Change-Id: Ibcb574341795d4016ea749f0290a793eed798874 Reviewed-on: https://boringssl-review.googlesource.com/2287 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
parent
81257cb2e0
commit
f31e681acf
47
ssl/s3_lib.c
47
ssl/s3_lib.c
@ -1783,7 +1783,6 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||
size_t i;
|
||||
int ok;
|
||||
size_t cipher_index;
|
||||
CERT *cert;
|
||||
unsigned long alg_k,alg_a,mask_k,mask_a;
|
||||
/* in_group_flags will either be NULL, or will point to an array of
|
||||
* bytes which indicate equal-preference groups in the |prio| stack.
|
||||
@ -1794,34 +1793,6 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||
* if no such value exists yet. */
|
||||
int group_min = -1;
|
||||
|
||||
/* Let's see which ciphers we can support */
|
||||
cert=s->cert;
|
||||
|
||||
#if 0
|
||||
/* Do not set the compare functions, because this may lead to a
|
||||
* reordering by "id". We want to keep the original ordering.
|
||||
* We may pay a price in performance during sk_SSL_CIPHER_find(),
|
||||
* but would have to pay with the price of sk_SSL_CIPHER_dup().
|
||||
*/
|
||||
sk_SSL_CIPHER_set_cmp_func(srvr, ssl_cipher_ptr_id_cmp);
|
||||
sk_SSL_CIPHER_set_cmp_func(clnt, ssl_cipher_ptr_id_cmp);
|
||||
#endif
|
||||
|
||||
#ifdef CIPHER_DEBUG
|
||||
printf("Server has %d from %p:\n", sk_SSL_CIPHER_num(srvr), (void *)srvr);
|
||||
for(i=0 ; i < sk_SSL_CIPHER_num(srvr) ; ++i)
|
||||
{
|
||||
c=sk_SSL_CIPHER_value(srvr,i);
|
||||
printf("%p:%s\n",(void *)c,c->name);
|
||||
}
|
||||
printf("Client sent %d from %p:\n", sk_SSL_CIPHER_num(clnt), (void *)clnt);
|
||||
for(i=0 ; i < sk_SSL_CIPHER_num(clnt) ; ++i)
|
||||
{
|
||||
c=sk_SSL_CIPHER_value(clnt,i);
|
||||
printf("%p:%s\n",(void *)c,c->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
|
||||
{
|
||||
prio = srvr;
|
||||
@ -1836,6 +1807,7 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||
}
|
||||
|
||||
tls1_set_cert_validity(s);
|
||||
ssl_get_compatible_server_ciphers(s, &mask_k, &mask_a);
|
||||
|
||||
for (i=0; i<sk_SSL_CIPHER_num(prio); i++)
|
||||
{
|
||||
@ -1848,27 +1820,10 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||
!SSL_USE_TLS1_2_CIPHERS(s))
|
||||
ok = 0;
|
||||
|
||||
ssl_set_cert_masks(cert,c);
|
||||
mask_k = cert->mask_k;
|
||||
mask_a = cert->mask_a;
|
||||
|
||||
alg_k=c->algorithm_mkey;
|
||||
alg_a=c->algorithm_auth;
|
||||
|
||||
/* with PSK there must be server callback set */
|
||||
if ((alg_a & SSL_aPSK) && s->psk_server_callback == NULL)
|
||||
ok = 0;
|
||||
|
||||
ok = ok && (alg_k & mask_k) && (alg_a & mask_a);
|
||||
#ifdef CIPHER_DEBUG
|
||||
printf("%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n",ok,alg_k,alg_a,mask_k,mask_a,(void *)c,
|
||||
c->name);
|
||||
#endif
|
||||
|
||||
/* if we are considering an ECC cipher suite that uses
|
||||
* an ephemeral EC key check it */
|
||||
if (alg_k & SSL_kEECDH)
|
||||
ok = ok && tls1_check_ec_tmp_key(s);
|
||||
|
||||
if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c))
|
||||
{
|
||||
|
@ -199,7 +199,6 @@ CERT *ssl_cert_dup(CERT *cert)
|
||||
/* or ret->key = ret->pkeys + (cert->key - cert->pkeys),
|
||||
* if you find that more readable */
|
||||
|
||||
ret->valid = cert->valid;
|
||||
ret->mask_k = cert->mask_k;
|
||||
ret->mask_a = cert->mask_a;
|
||||
|
||||
|
@ -2104,46 +2104,49 @@ void SSL_set_cert_cb(SSL *s, int (*cb)(SSL *ssl, void *arg), void *arg)
|
||||
ssl_cert_set_cert_cb(s->cert, cb, arg);
|
||||
}
|
||||
|
||||
void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
|
||||
void ssl_get_compatible_server_ciphers(SSL *s, unsigned long *out_mask_k,
|
||||
unsigned long *out_mask_a)
|
||||
{
|
||||
CERT *c = s->cert;
|
||||
CERT_PKEY *cpk;
|
||||
int rsa_enc,rsa_sign,dh_tmp;
|
||||
unsigned long mask_k,mask_a;
|
||||
int rsa_enc, rsa_sign, dh_tmp;
|
||||
unsigned long mask_k, mask_a;
|
||||
int have_ecc_cert, ecdsa_ok;
|
||||
int have_ecdh_tmp;
|
||||
X509 *x = NULL;
|
||||
if (c == NULL) return;
|
||||
X509 *x;
|
||||
|
||||
dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL);
|
||||
if (c == NULL)
|
||||
{
|
||||
/* TODO(davidben): Is this codepath possible? */
|
||||
*out_mask_k = 0;
|
||||
*out_mask_a = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
have_ecdh_tmp=(c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto);
|
||||
cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]);
|
||||
rsa_enc= cpk->valid_flags & CERT_PKEY_VALID;
|
||||
cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]);
|
||||
rsa_sign= cpk->valid_flags & CERT_PKEY_SIGN;
|
||||
cpk= &(c->pkeys[SSL_PKEY_ECC]);
|
||||
have_ecc_cert= cpk->valid_flags & CERT_PKEY_VALID;
|
||||
mask_k=0;
|
||||
mask_a=0;
|
||||
dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL);
|
||||
|
||||
have_ecdh_tmp = (c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto);
|
||||
cpk = &(c->pkeys[SSL_PKEY_RSA_ENC]);
|
||||
rsa_enc = cpk->valid_flags & CERT_PKEY_VALID;
|
||||
cpk = &(c->pkeys[SSL_PKEY_RSA_SIGN]);
|
||||
rsa_sign = cpk->valid_flags & CERT_PKEY_SIGN;
|
||||
cpk = &(c->pkeys[SSL_PKEY_ECC]);
|
||||
have_ecc_cert = cpk->valid_flags & CERT_PKEY_VALID;
|
||||
mask_k = 0;
|
||||
mask_a = 0;
|
||||
|
||||
#ifdef CIPHER_DEBUG
|
||||
printf("rt=%d rte=%d dht=%d ecdht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n",
|
||||
rsa_tmp,rsa_tmp_export,dh_tmp,have_ecdh_tmp,
|
||||
rsa_enc,rsa_enc_export,rsa_sign,dsa_sign,dh_rsa,dh_dsa);
|
||||
#endif
|
||||
|
||||
if (rsa_enc)
|
||||
mask_k|=SSL_kRSA;
|
||||
mask_k |= SSL_kRSA;
|
||||
|
||||
if (dh_tmp)
|
||||
mask_k|=SSL_kEDH;
|
||||
mask_k |= SSL_kEDH;
|
||||
|
||||
if (rsa_enc || rsa_sign)
|
||||
{
|
||||
mask_a|=SSL_aRSA;
|
||||
mask_a |= SSL_aRSA;
|
||||
}
|
||||
|
||||
mask_a|=SSL_aNULL;
|
||||
mask_a |= SSL_aNULL;
|
||||
|
||||
/* An ECC certificate may be usable for ECDSA cipher suites depending on
|
||||
* the key usage extension. */
|
||||
@ -2159,21 +2162,26 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
|
||||
ecdsa_ok = 0;
|
||||
if (ecdsa_ok)
|
||||
{
|
||||
mask_a|=SSL_aECDSA;
|
||||
mask_a |= SSL_aECDSA;
|
||||
}
|
||||
}
|
||||
|
||||
if (have_ecdh_tmp)
|
||||
/* If we are considering an ECC cipher suite that uses an ephemeral EC
|
||||
* key, check it. */
|
||||
if (have_ecdh_tmp && tls1_check_ec_tmp_key(s))
|
||||
{
|
||||
mask_k|=SSL_kEECDH;
|
||||
mask_k |= SSL_kEECDH;
|
||||
}
|
||||
|
||||
mask_k |= SSL_kPSK;
|
||||
mask_a |= SSL_aPSK;
|
||||
/* PSK requires a server callback. */
|
||||
if (s->psk_server_callback != NULL)
|
||||
{
|
||||
mask_k |= SSL_kPSK;
|
||||
mask_a |= SSL_aPSK;
|
||||
}
|
||||
|
||||
c->mask_k=mask_k;
|
||||
c->mask_a=mask_a;
|
||||
c->valid=1;
|
||||
*out_mask_k = mask_k;
|
||||
*out_mask_a = mask_a;
|
||||
}
|
||||
|
||||
/* This handy macro borrowed from crypto/x509v3/v3_purp.c */
|
||||
@ -2223,20 +2231,14 @@ static int ssl_get_server_cert_index(const SSL *s)
|
||||
|
||||
CERT_PKEY *ssl_get_server_send_pkey(const SSL *s)
|
||||
{
|
||||
CERT *c;
|
||||
int i;
|
||||
|
||||
c = s->cert;
|
||||
ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
|
||||
|
||||
i = ssl_get_server_cert_index(s);
|
||||
int i = ssl_get_server_cert_index(s);
|
||||
|
||||
/* This may or may not be an error. */
|
||||
if (i < 0)
|
||||
return NULL;
|
||||
|
||||
/* May be NULL. */
|
||||
return &c->pkeys[i];
|
||||
return &s->cert->pkeys[i];
|
||||
}
|
||||
|
||||
EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
|
||||
|
@ -450,16 +450,19 @@ typedef struct cert_st
|
||||
* Probably it would make more sense to store
|
||||
* an index, not a pointer. */
|
||||
|
||||
/* For servers the following masks are for the key and auth
|
||||
* algorithms that are supported by the certs below.
|
||||
* For clients they are masks of *disabled* algorithms based
|
||||
* on the current session.
|
||||
*/
|
||||
int valid;
|
||||
/* For clients the following masks are of *disabled* key and auth
|
||||
* algorithms based on the current session.
|
||||
*
|
||||
* TODO(davidben): Remove these. They get checked twice: when sending
|
||||
* the ClientHello and when processing the ServerHello. However,
|
||||
* mask_ssl is a different value both times. mask_k and mask_a are not,
|
||||
* but is a round-about way of checking the server's cipher was one of
|
||||
* the advertised ones. (Currently it checks the masks and then the list
|
||||
* of ciphers prior to applying the masks in ClientHello.) */
|
||||
unsigned long mask_k;
|
||||
unsigned long mask_a;
|
||||
/* Client only */
|
||||
unsigned long mask_ssl;
|
||||
|
||||
DH *dh_tmp;
|
||||
DH *(*dh_tmp_cb)(SSL *ssl,int is_export,int keysize);
|
||||
EC_KEY *ecdh_tmp;
|
||||
@ -817,7 +820,14 @@ int ssl_undefined_const_function(const SSL *s);
|
||||
CERT_PKEY *ssl_get_server_send_pkey(const SSL *s);
|
||||
EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *c, const EVP_MD **pmd);
|
||||
int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
|
||||
void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
|
||||
|
||||
/* ssl_get_compatible_server_ciphers determines the key exchange and
|
||||
* authentication cipher suite masks compatible with the server configuration
|
||||
* and current ClientHello parameters of |s|. It sets |*out_mask_k| to the key
|
||||
* exchange mask and |*out_mask_a| to the authentication mask. */
|
||||
void ssl_get_compatible_server_ciphers(SSL *s, unsigned long *out_mask_k,
|
||||
unsigned long *out_mask_a);
|
||||
|
||||
STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
|
||||
int ssl_verify_alarm_type(long type);
|
||||
int ssl_fill_hello_random(SSL *s, int server, unsigned char *field, int len);
|
||||
|
@ -214,7 +214,6 @@ static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey)
|
||||
c->pkeys[i].privatekey = EVP_PKEY_dup(pkey);
|
||||
c->key = &(c->pkeys[i]);
|
||||
|
||||
c->valid=0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -431,7 +430,6 @@ static int ssl_set_cert(CERT *c, X509 *x)
|
||||
c->pkeys[i].x509 = X509_up_ref(x);
|
||||
c->key= &(c->pkeys[i]);
|
||||
|
||||
c->valid=0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
@ -877,7 +877,6 @@ void ssl_set_client_disabled(SSL *s)
|
||||
c->mask_a |= SSL_aPSK;
|
||||
c->mask_k |= SSL_kPSK;
|
||||
}
|
||||
c->valid = 1;
|
||||
}
|
||||
|
||||
/* header_len is the length of the ClientHello header written so far, used to
|
||||
|
Loading…
Reference in New Issue
Block a user