diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 9f9dce6c1e1de..f706c27982519 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1944,7 +1944,7 @@ STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s) ssl_set_client_disabled(s); for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i); - if (!ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED)) { + if (!ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) { if (!sk) sk = sk_SSL_CIPHER_new_null(); if (!sk) diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index eb7e8c9d2b735..de4a520c2a6b1 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -2070,7 +2070,7 @@ __owur size_t tls12_get_psigalgs(SSL *s, int sent, const unsigned char **psigs); __owur int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, const unsigned char *sig, EVP_PKEY *pkey); void ssl_set_client_disabled(SSL *s); -__owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op); +__owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int echde); __owur int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen); diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index a2a6684fa975a..c4963f5767586 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -1038,7 +1038,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) * If it is a disabled cipher we either didn't send it in client hello, * or it's not allowed for the selected protocol. So we return an error. */ - if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK)) { + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK, 1)) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED); goto f_err; @@ -2919,7 +2919,7 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, unsigned char *p) for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { c = sk_SSL_CIPHER_value(sk, i); /* Skip disabled ciphers */ - if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED)) + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) continue; j = s->method->put_cipher_by_char(c, p); p += j; diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 3f9702b9c2ddb..377ed328b44d5 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -863,19 +863,31 @@ void ssl_set_client_disabled(SSL *s) * @s: SSL connection that you want to use the cipher on * @c: cipher to check * @op: Security check that you want to do + * @ecdhe: If set to 1 then TLSv1 ECDHE ciphers are also allowed in SSLv3 * * Returns 1 when it's disabled, 0 when enabled. */ -int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op) +int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int ecdhe) { if (c->algorithm_mkey & s->s3->tmp.mask_k || c->algorithm_auth & s->s3->tmp.mask_a) return 1; if (s->s3->tmp.max_ver == 0) return 1; - if (!SSL_IS_DTLS(s) && ((c->min_tls > s->s3->tmp.max_ver) - || (c->max_tls < s->s3->tmp.min_ver))) - return 1; + if (!SSL_IS_DTLS(s)) { + int min_tls = c->min_tls; + + /* + * For historical reasons we will allow ECHDE to be selected by a server + * in SSLv3 if we are a client + */ + if (min_tls == TLS1_VERSION && ecdhe + && (c->algorithm_mkey & (SSL_kECDHE | SSL_kECDHEPSK)) != 0) + min_tls = SSL3_VERSION; + + if ((min_tls > s->s3->tmp.max_ver) || (c->max_tls < s->s3->tmp.min_ver)) + return 1; + } if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3->tmp.max_ver) || DTLS_VERSION_LT(c->max_dtls, s->s3->tmp.min_ver))) return 1;