Factor out remaining version-related functions.
Now SSLv23 and DTLS_ANY_VERSION share version-related helper functions. ssl3_get_method is temporary until the method switch is no longer necessary. Put them all together so there's one place to refactor them when we add a new version or implement min_version/max_version controls. Change-Id: Ic28a145cad22db08a87fdb854480b22886c451c6 Reviewed-on: https://boringssl-review.googlesource.com/2580 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
committed by
Adam Langley
parent
69b9e597ae
commit
ceb6f2880f
+5
-27
@@ -447,37 +447,15 @@ static int ssl23_get_server_hello(SSL *s)
|
||||
((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) ||
|
||||
(p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2)))
|
||||
{
|
||||
/* we have sslv3 or tls1 (server hello or alert) */
|
||||
|
||||
if ((p[2] == SSL3_VERSION_MINOR) &&
|
||||
!(s->options & SSL_OP_NO_SSLv3))
|
||||
{
|
||||
s->version=SSL3_VERSION;
|
||||
s->method=SSLv3_client_method();
|
||||
}
|
||||
else if ((p[2] == TLS1_VERSION_MINOR) &&
|
||||
!(s->options & SSL_OP_NO_TLSv1))
|
||||
{
|
||||
s->version=TLS1_VERSION;
|
||||
s->method=TLSv1_client_method();
|
||||
}
|
||||
else if ((p[2] == TLS1_1_VERSION_MINOR) &&
|
||||
!(s->options & SSL_OP_NO_TLSv1_1))
|
||||
{
|
||||
s->version=TLS1_1_VERSION;
|
||||
s->method=TLSv1_1_client_method();
|
||||
}
|
||||
else if ((p[2] == TLS1_2_VERSION_MINOR) &&
|
||||
!(s->options & SSL_OP_NO_TLSv1_2))
|
||||
{
|
||||
s->version=TLS1_2_VERSION;
|
||||
s->method=TLSv1_2_client_method();
|
||||
}
|
||||
else
|
||||
uint16_t version = (p[1] << 8) | p[2];
|
||||
if (!ssl3_is_version_enabled(s, version))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl23_get_server_hello, SSL_R_UNSUPPORTED_PROTOCOL);
|
||||
goto err;
|
||||
}
|
||||
s->version = version;
|
||||
s->method = ssl3_get_method(version);
|
||||
assert(s->method != NULL);
|
||||
|
||||
if (p[0] == SSL3_RT_ALERT && p[5] != SSL3_AL_WARNING)
|
||||
{
|
||||
|
||||
+8
-47
@@ -121,20 +121,6 @@
|
||||
static int ssl23_get_client_hello(SSL *s);
|
||||
static int ssl23_get_v2_client_hello(SSL *s);
|
||||
|
||||
static const SSL_METHOD *ssl23_get_server_method(int ver)
|
||||
{
|
||||
if (ver == SSL3_VERSION)
|
||||
return(SSLv3_server_method());
|
||||
else if (ver == TLS1_VERSION)
|
||||
return(TLSv1_server_method());
|
||||
else if (ver == TLS1_1_VERSION)
|
||||
return(TLSv1_1_server_method());
|
||||
else if (ver == TLS1_2_VERSION)
|
||||
return(TLSv1_2_server_method());
|
||||
else
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
int ssl23_accept(SSL *s)
|
||||
{
|
||||
BUF_MEM *buf;
|
||||
@@ -213,7 +199,7 @@ int ssl23_accept(SSL *s)
|
||||
}
|
||||
|
||||
s->state = SSL3_ST_SR_CLNT_HELLO_A;
|
||||
s->method = ssl23_get_server_method(s->version);
|
||||
s->method = ssl3_get_method(s->version);
|
||||
assert(s->method != NULL);
|
||||
s->handshake_func = s->method->ssl_accept;
|
||||
s->init_num = 0;
|
||||
@@ -246,35 +232,6 @@ end:
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/* ssl23_get_mutual_version determines the highest supported version for a
|
||||
* client which reports a highest version of |client_version|. On success, it
|
||||
* returns 1 and sets |*out_version| to the negotiated version. Otherwise, it
|
||||
* returns 0. */
|
||||
static int ssl23_get_mutual_version(SSL *s, int *out_version, uint16_t client_version)
|
||||
{
|
||||
if (client_version >= TLS1_2_VERSION && !(s->options & SSL_OP_NO_TLSv1_2))
|
||||
{
|
||||
*out_version = TLS1_2_VERSION;
|
||||
return 1;
|
||||
}
|
||||
if (client_version >= TLS1_1_VERSION && !(s->options & SSL_OP_NO_TLSv1_1))
|
||||
{
|
||||
*out_version = TLS1_1_VERSION;
|
||||
return 1;
|
||||
}
|
||||
if (client_version >= TLS1_VERSION && !(s->options & SSL_OP_NO_TLSv1))
|
||||
{
|
||||
*out_version = TLS1_VERSION;
|
||||
return 1;
|
||||
}
|
||||
if (client_version >= SSL3_VERSION && !(s->options & SSL_OP_NO_SSLv3))
|
||||
{
|
||||
*out_version = SSL3_VERSION;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssl23_get_client_hello(SSL *s)
|
||||
{
|
||||
uint8_t *p;
|
||||
@@ -336,11 +293,13 @@ static int ssl23_get_client_hello(SSL *s)
|
||||
/* This is a V2ClientHello. Determine the version to
|
||||
* use. */
|
||||
uint16_t client_version = (p[3] << 8) | p[4];
|
||||
if (!ssl23_get_mutual_version(s, &s->version, client_version))
|
||||
uint16_t version = ssl3_get_mutual_version(s, client_version);
|
||||
if (version == 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl23_get_client_hello, SSL_R_UNSUPPORTED_PROTOCOL);
|
||||
goto err;
|
||||
}
|
||||
s->version = version;
|
||||
/* Parse the entire V2ClientHello. */
|
||||
s->state = SSL23_ST_SR_V2_CLNT_HELLO;
|
||||
}
|
||||
@@ -355,7 +314,7 @@ static int ssl23_get_client_hello(SSL *s)
|
||||
* this, so we simply reject such connections to avoid
|
||||
* protocol version downgrade attacks. */
|
||||
uint16_t record_length = (p[3] << 8) | p[4];
|
||||
uint16_t client_version;
|
||||
uint16_t client_version, version;
|
||||
if (record_length < 6)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl23_get_client_hello, SSL_R_RECORD_TOO_SMALL);
|
||||
@@ -363,11 +322,13 @@ static int ssl23_get_client_hello(SSL *s)
|
||||
}
|
||||
|
||||
client_version = (p[9] << 8) | p[10];
|
||||
if (!ssl23_get_mutual_version(s, &s->version, client_version))
|
||||
version = ssl3_get_mutual_version(s, client_version);
|
||||
if (version == 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl23_get_client_hello, SSL_R_UNSUPPORTED_PROTOCOL);
|
||||
goto err;
|
||||
}
|
||||
s->version = version;
|
||||
|
||||
/* Reset the record-layer state for SSL3. */
|
||||
assert(s->rstate == SSL_ST_READ_HEADER);
|
||||
|
||||
+4
-53
@@ -580,49 +580,6 @@ end:
|
||||
return(ret);
|
||||
}
|
||||
|
||||
uint16_t ssl3_get_max_client_version(SSL *s)
|
||||
{
|
||||
unsigned long options = s->options;
|
||||
uint16_t version = 0;
|
||||
|
||||
/* OpenSSL's API for controlling versions entails blacklisting
|
||||
* individual protocols. This has two problems. First, on the client,
|
||||
* the protocol can only express a contiguous range of versions. Second,
|
||||
* a library consumer trying to set a maximum version cannot disable
|
||||
* protocol versions that get added in a future version of the library.
|
||||
*
|
||||
* To account for both of these, OpenSSL interprets the client-side
|
||||
* bitmask as a min/max range by picking the lowest contiguous non-empty
|
||||
* range of enabled protocols. Note that this means it is impossible to
|
||||
* set a maximum version of TLS 1.2 in a future-proof way.
|
||||
*
|
||||
* By this scheme, the maximum version is the lowest version V such that
|
||||
* V is enabled and V+1 is disabled or unimplemented.
|
||||
*
|
||||
* TODO(davidben): Deprecate this API in favor of more sensible
|
||||
* min_version/max_version settings. */
|
||||
if (SSL_IS_DTLS(s))
|
||||
{
|
||||
if (!(options & SSL_OP_NO_DTLSv1_2))
|
||||
version = DTLS1_2_VERSION;
|
||||
if (!(options & SSL_OP_NO_DTLSv1) && (options & SSL_OP_NO_DTLSv1_2))
|
||||
version = DTLS1_VERSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(options & SSL_OP_NO_TLSv1_2))
|
||||
version = TLS1_2_VERSION;
|
||||
if (!(options & SSL_OP_NO_TLSv1_1) && (options & SSL_OP_NO_TLSv1_2))
|
||||
version = TLS1_1_VERSION;
|
||||
if (!(options & SSL_OP_NO_TLSv1) && (options & SSL_OP_NO_TLSv1_1))
|
||||
version = TLS1_VERSION;
|
||||
if (!(options & SSL_OP_NO_SSLv3) && (options & SSL_OP_NO_TLSv1))
|
||||
version = SSL3_VERSION;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
int ssl3_send_client_hello(SSL *s)
|
||||
{
|
||||
unsigned char *buf;
|
||||
@@ -816,22 +773,16 @@ int ssl3_get_server_hello(SSL *s)
|
||||
|
||||
if (s->method->version == DTLS_ANY_VERSION)
|
||||
{
|
||||
/* Work out correct protocol version to use */
|
||||
int options = s->options;
|
||||
if (server_version == DTLS1_2_VERSION
|
||||
&& !(options & SSL_OP_NO_DTLSv1_2))
|
||||
s->method = DTLSv1_2_client_method();
|
||||
else if (server_version == DTLS1_VERSION
|
||||
&& !(options & SSL_OP_NO_DTLSv1))
|
||||
s->method = DTLSv1_client_method();
|
||||
else
|
||||
if (!ssl3_is_version_enabled(s, server_version))
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_SSL_VERSION);
|
||||
s->version = server_version;
|
||||
al = SSL_AD_PROTOCOL_VERSION;
|
||||
goto f_err;
|
||||
}
|
||||
s->version = s->method->version;
|
||||
s->version = server_version;
|
||||
s->method = ssl3_get_method(server_version);
|
||||
assert(s->method != NULL);
|
||||
}
|
||||
|
||||
if (server_version != s->version)
|
||||
|
||||
+5
-13
@@ -854,25 +854,17 @@ int ssl3_get_client_hello(SSL *s)
|
||||
if (s->method->version == DTLS_ANY_VERSION)
|
||||
{
|
||||
/* Select version to use */
|
||||
if (s->client_version <= DTLS1_2_VERSION &&
|
||||
!(s->options & SSL_OP_NO_DTLSv1_2))
|
||||
{
|
||||
s->version = DTLS1_2_VERSION;
|
||||
s->method = DTLSv1_2_server_method();
|
||||
}
|
||||
else if (s->client_version <= DTLS1_VERSION &&
|
||||
!(s->options & SSL_OP_NO_DTLSv1))
|
||||
{
|
||||
s->version = DTLS1_VERSION;
|
||||
s->method = DTLSv1_server_method();
|
||||
}
|
||||
else
|
||||
uint16_t version = ssl3_get_mutual_version(s, client_version);
|
||||
if (version == 0)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_WRONG_VERSION_NUMBER);
|
||||
s->version = s->client_version;
|
||||
al = SSL_AD_PROTOCOL_VERSION;
|
||||
goto f_err;
|
||||
}
|
||||
s->version = version;
|
||||
s->method = ssl3_get_method(version);
|
||||
assert(s->method != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+132
-7
@@ -1498,7 +1498,9 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs)
|
||||
/* Check for FALLBACK_SCSV. */
|
||||
if (s->s3 && cipher_suite == (SSL3_CK_FALLBACK_SCSV & 0xffff))
|
||||
{
|
||||
if (s->version < ssl_get_max_version(s))
|
||||
uint16_t max_version = ssl3_get_max_server_version(s);
|
||||
if (SSL_IS_DTLS(s) ? (uint16_t)s->version > max_version
|
||||
: (uint16_t)s->version < max_version)
|
||||
{
|
||||
OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, SSL_R_INAPPROPRIATE_FALLBACK);
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_INAPPROPRIATE_FALLBACK);
|
||||
@@ -3046,13 +3048,37 @@ int ssl3_can_cutthrough(const SSL *s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ssl_get_max_version returns the maximum SSL/TLS version number supported by
|
||||
* |s|, or zero if all versions are disabled. */
|
||||
int ssl_get_max_version(const SSL *s)
|
||||
const SSL_METHOD *ssl3_get_method(uint16_t version)
|
||||
{
|
||||
/* Only one version supported for DTLS. */
|
||||
if (s->version == DTLS1_VERSION)
|
||||
return DTLS1_VERSION;
|
||||
switch (version)
|
||||
{
|
||||
case SSL3_VERSION:
|
||||
return SSLv3_method();
|
||||
case TLS1_VERSION:
|
||||
return TLSv1_method();
|
||||
case TLS1_1_VERSION:
|
||||
return TLSv1_1_method();
|
||||
case TLS1_2_VERSION:
|
||||
return TLSv1_2_method();
|
||||
case DTLS1_VERSION:
|
||||
return DTLSv1_method();
|
||||
case DTLS1_2_VERSION:
|
||||
return DTLSv1_2_method();
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ssl3_get_max_server_version(const SSL *s)
|
||||
{
|
||||
if (SSL_IS_DTLS(s))
|
||||
{
|
||||
if (!(s->options & SSL_OP_NO_DTLSv1_2))
|
||||
return DTLS1_2_VERSION;
|
||||
if (!(s->options & SSL_OP_NO_DTLSv1))
|
||||
return DTLS1_VERSION;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(s->options & SSL_OP_NO_TLSv1_2))
|
||||
return TLS1_2_VERSION;
|
||||
@@ -3065,6 +3091,105 @@ int ssl_get_max_version(const SSL *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t ssl3_get_mutual_version(SSL *s, uint16_t client_version)
|
||||
{
|
||||
if (SSL_IS_DTLS(s))
|
||||
{
|
||||
if (client_version <= DTLS1_2_VERSION && !(s->options & SSL_OP_NO_DTLSv1_2))
|
||||
return DTLS1_2_VERSION;
|
||||
if (client_version <= DTLS1_VERSION && !(s->options & SSL_OP_NO_DTLSv1))
|
||||
return DTLS1_VERSION;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (client_version >= TLS1_2_VERSION && !(s->options & SSL_OP_NO_TLSv1_2))
|
||||
return TLS1_2_VERSION;
|
||||
if (client_version >= TLS1_1_VERSION && !(s->options & SSL_OP_NO_TLSv1_1))
|
||||
return TLS1_1_VERSION;
|
||||
if (client_version >= TLS1_VERSION && !(s->options & SSL_OP_NO_TLSv1))
|
||||
return TLS1_VERSION;
|
||||
if (client_version >= SSL3_VERSION && !(s->options & SSL_OP_NO_SSLv3))
|
||||
return SSL3_VERSION;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ssl3_get_max_client_version(SSL *s)
|
||||
{
|
||||
unsigned long options = s->options;
|
||||
uint16_t version = 0;
|
||||
|
||||
/* OpenSSL's API for controlling versions entails blacklisting
|
||||
* individual protocols. This has two problems. First, on the client,
|
||||
* the protocol can only express a contiguous range of versions. Second,
|
||||
* a library consumer trying to set a maximum version cannot disable
|
||||
* protocol versions that get added in a future version of the library.
|
||||
*
|
||||
* To account for both of these, OpenSSL interprets the client-side
|
||||
* bitmask as a min/max range by picking the lowest contiguous non-empty
|
||||
* range of enabled protocols. Note that this means it is impossible to
|
||||
* set a maximum version of TLS 1.2 in a future-proof way.
|
||||
*
|
||||
* By this scheme, the maximum version is the lowest version V such that
|
||||
* V is enabled and V+1 is disabled or unimplemented.
|
||||
*
|
||||
* TODO(davidben): Deprecate this API in favor of more sensible
|
||||
* min_version/max_version settings. */
|
||||
if (SSL_IS_DTLS(s))
|
||||
{
|
||||
if (!(options & SSL_OP_NO_DTLSv1_2))
|
||||
version = DTLS1_2_VERSION;
|
||||
if (!(options & SSL_OP_NO_DTLSv1) && (options & SSL_OP_NO_DTLSv1_2))
|
||||
version = DTLS1_VERSION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(options & SSL_OP_NO_TLSv1_2))
|
||||
version = TLS1_2_VERSION;
|
||||
if (!(options & SSL_OP_NO_TLSv1_1) && (options & SSL_OP_NO_TLSv1_2))
|
||||
version = TLS1_1_VERSION;
|
||||
if (!(options & SSL_OP_NO_TLSv1) && (options & SSL_OP_NO_TLSv1_1))
|
||||
version = TLS1_VERSION;
|
||||
if (!(options & SSL_OP_NO_SSLv3) && (options & SSL_OP_NO_TLSv1))
|
||||
version = SSL3_VERSION;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
int ssl3_is_version_enabled(SSL *s, uint16_t version)
|
||||
{
|
||||
if (SSL_IS_DTLS(s))
|
||||
{
|
||||
switch (version)
|
||||
{
|
||||
case DTLS1_VERSION:
|
||||
return !(s->options & SSL_OP_NO_DTLSv1);
|
||||
case DTLS1_2_VERSION:
|
||||
return !(s->options & SSL_OP_NO_DTLSv1_2);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (version)
|
||||
{
|
||||
case SSL3_VERSION:
|
||||
return !(s->options & SSL_OP_NO_SSLv3);
|
||||
case TLS1_VERSION:
|
||||
return !(s->options & SSL_OP_NO_TLSv1);
|
||||
case TLS1_1_VERSION:
|
||||
return !(s->options & SSL_OP_NO_TLSv1_1);
|
||||
case TLS1_2_VERSION:
|
||||
return !(s->options & SSL_OP_NO_TLSv1_2);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocates new EVP_MD_CTX and sets pointer to it into given pointer
|
||||
* vairable, freeing EVP_MD_CTX previously stored in that variable, if
|
||||
* any. If EVP_MD pointer is passed, initializes ctx with this md
|
||||
|
||||
+24
-8
@@ -929,13 +929,6 @@ unsigned int dtls1_min_mtu(void);
|
||||
void dtls1_hm_fragment_free(hm_fragment *frag);
|
||||
|
||||
/* some client-only functions */
|
||||
|
||||
/* ssl3_get_max_client_version returns the maximum protocol version configured
|
||||
* for the client. It is guaranteed that the set of allowed versions at or below
|
||||
* this maximum version is contiguous. If all versions are disabled, it returns
|
||||
* zero. */
|
||||
uint16_t ssl3_get_max_client_version(SSL *s);
|
||||
|
||||
int ssl3_send_client_hello(SSL *s);
|
||||
int ssl3_get_server_hello(SSL *s);
|
||||
int ssl3_get_certificate_request(SSL *s);
|
||||
@@ -1078,7 +1071,30 @@ int ssl_ctx_log_master_secret(SSL_CTX *ctx,
|
||||
const uint8_t *master, size_t master_len);
|
||||
|
||||
int ssl3_can_cutthrough(const SSL *s);
|
||||
int ssl_get_max_version(const SSL *s);
|
||||
|
||||
/* ssl3_get_method returns the version-locked SSL_METHOD corresponding
|
||||
* to |version|. */
|
||||
const SSL_METHOD *ssl3_get_method(uint16_t version);
|
||||
|
||||
/* ssl3_get_max_server_version returns the maximum SSL/TLS version number
|
||||
* supported by |s| as a server, or zero if all versions are disabled. */
|
||||
uint16_t ssl3_get_max_server_version(const SSL *s);
|
||||
|
||||
/* ssl3_get_mutual_version selects the protocol version on |s| for a client
|
||||
* which advertises |client_version|. If no suitable version exists, it returns
|
||||
* zero. */
|
||||
uint16_t ssl3_get_mutual_version(SSL *s, uint16_t client_version);
|
||||
|
||||
/* ssl3_get_max_client_version returns the maximum protocol version configured
|
||||
* for the client. It is guaranteed that the set of allowed versions at or below
|
||||
* this maximum version is contiguous. If all versions are disabled, it returns
|
||||
* zero. */
|
||||
uint16_t ssl3_get_max_client_version(SSL *s);
|
||||
|
||||
/* ssl3_is_version_enabled returns one if |version| is an enabled protocol
|
||||
* version for |s| and zero otherwise. */
|
||||
int ssl3_is_version_enabled(SSL *s, uint16_t version);
|
||||
|
||||
EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;
|
||||
void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
|
||||
int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
|
||||
|
||||
Reference in New Issue
Block a user