diff options
Diffstat (limited to 'ssl/statem/statem_lib.c')
-rw-r--r-- | ssl/statem/statem_lib.c | 80 |
1 files changed, 46 insertions, 34 deletions
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index b8e094b..7b18115 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -1739,21 +1739,31 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) * * @s: client SSL handle. * @version: The proposed version from the server's HELLO. - * @checkdgrd: Whether to check the downgrade sentinels in the server_random + * @extensions: The extensions received * * Returns 1 on success or 0 on error. */ -int ssl_choose_client_version(SSL *s, int version, int checkdgrd) +int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions) { const version_info *vent; const version_info *table; int highver = 0; + int origv; - /* TODO(TLS1.3): Remove this before release */ - if (version == TLS1_3_VERSION_DRAFT) - version = TLS1_3_VERSION; + origv = s->version; + s->version = version; - if (s->hello_retry_request && version != TLS1_3_VERSION) { + /* This will overwrite s->version if the extension is present */ + if (!tls_parse_extension(s, TLSEXT_IDX_supported_versions, + SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_SERVER_HELLO, extensions, + NULL, 0)) { + s->version = origv; + return 0; + } + + if (s->hello_retry_request && s->version != TLS1_3_VERSION) { + s->version = origv; SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_WRONG_SSL_VERSION); return 0; @@ -1761,7 +1771,8 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd) switch (s->method->version) { default: - if (version != s->version) { + if (s->version != s->method->version) { + s->version = origv; SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_WRONG_SSL_VERSION); @@ -1790,13 +1801,14 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd) if (vent->cmeth == NULL) continue; - if (highver != 0 && version != vent->version) + if (highver != 0 && s->version != vent->version) continue; method = vent->cmeth(); err = ssl_method_error(s, method); if (err != 0) { - if (version == vent->version) { + if (s->version == vent->version) { + s->version = origv; SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION, err); return 0; @@ -1807,43 +1819,43 @@ int ssl_choose_client_version(SSL *s, int version, int checkdgrd) if (highver == 0) highver = vent->version; - if (version != vent->version) + if (s->version != vent->version) continue; #ifndef OPENSSL_NO_TLS13DOWNGRADE /* Check for downgrades */ - if (checkdgrd) { - if (version == TLS1_2_VERSION && highver > version) { - if (memcmp(tls12downgrade, - s->s3->server_random + SSL3_RANDOM_SIZE - - sizeof(tls12downgrade), - sizeof(tls12downgrade)) == 0) { - SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, - SSL_F_SSL_CHOOSE_CLIENT_VERSION, - SSL_R_INAPPROPRIATE_FALLBACK); - return 0; - } - } else if (!SSL_IS_DTLS(s) - && version < TLS1_2_VERSION - && highver > version) { - if (memcmp(tls11downgrade, - s->s3->server_random + SSL3_RANDOM_SIZE - - sizeof(tls11downgrade), - sizeof(tls11downgrade)) == 0) { - SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, - SSL_F_SSL_CHOOSE_CLIENT_VERSION, - SSL_R_INAPPROPRIATE_FALLBACK); - return 0; - } + if (s->version == TLS1_2_VERSION && highver > s->version) { + if (memcmp(tls12downgrade, + s->s3->server_random + SSL3_RANDOM_SIZE + - sizeof(tls12downgrade), + sizeof(tls12downgrade)) == 0) { + s->version = origv; + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_SSL_CHOOSE_CLIENT_VERSION, + SSL_R_INAPPROPRIATE_FALLBACK); + return 0; + } + } else if (!SSL_IS_DTLS(s) + && s->version < TLS1_2_VERSION + && highver > s->version) { + if (memcmp(tls11downgrade, + s->s3->server_random + SSL3_RANDOM_SIZE + - sizeof(tls11downgrade), + sizeof(tls11downgrade)) == 0) { + s->version = origv; + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, + SSL_F_SSL_CHOOSE_CLIENT_VERSION, + SSL_R_INAPPROPRIATE_FALLBACK); + return 0; } } #endif s->method = method; - s->version = version; return 1; } + s->version = origv; SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION, SSL_R_UNSUPPORTED_PROTOCOL); return 0; |