Loading ssl/ssl_locl.h +3 −0 Original line number Diff line number Diff line Loading @@ -2077,6 +2077,9 @@ __owur int dtls1_process_heartbeat(SSL *s, unsigned char *p, size_t length); # endif __owur RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts, size_t numexts, unsigned int type); __owur int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, SSL_SESSION **ret); __owur int tls_check_client_ems_support(SSL *s, const CLIENTHELLO_MSG *hello); Loading ssl/statem/statem_clnt.c +6 −1 Original line number Diff line number Diff line Loading @@ -779,8 +779,13 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt) * TLS 1.0 and renegotiating with TLS 1.2. We do this by using * client_version in client hello and not resetting it to * the negotiated version. * * For TLS 1.3 we always set the ClientHello version to 1.2 and rely on the * supported_versions extension for the reall supported versions. */ if (!WPACKET_put_bytes_u16(pkt, s->client_version) if (!WPACKET_put_bytes_u16(pkt, (!SSL_IS_DTLS(s) && s->client_version >= TLS1_3_VERSION) ? TLS1_2_VERSION : s->client_version) || !WPACKET_memcpy(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) { SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); return 0; Loading ssl/statem/statem_lib.c +68 −0 Original line number Diff line number Diff line Loading @@ -996,6 +996,7 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello) const version_info *vent; const version_info *table; int disabled = 0; RAW_EXTENSION *suppversions; s->client_version = client_version; Loading @@ -1019,6 +1020,73 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello) break; } suppversions = tls_get_extension_by_type(hello->pre_proc_exts, hello->num_extensions, TLSEXT_TYPE_supported_versions); /* * TODO(TLS1.3): We only look at this if our max protocol version is TLS1.3 * or above. Should we allow it for lower versions too? */ if (suppversions != NULL && !SSL_IS_DTLS(s) && (s->max_proto_version == 0 || TLS1_3_VERSION <= s->max_proto_version)) { unsigned int candidate_vers = 0; unsigned int best_vers = 0; const SSL_METHOD *best_method = NULL; PACKET versionslist; if (!PACKET_get_length_prefixed_1(&suppversions->data, &versionslist) || PACKET_remaining(&suppversions->data) != 0) { /* Trailing or invalid data? */ return SSL_R_LENGTH_MISMATCH; } while (PACKET_get_net_2(&versionslist, &candidate_vers)) { /* TODO(TLS1.3): Remove this before release */ if (candidate_vers == TLS1_3_VERSION_DRAFT) candidate_vers = TLS1_3_VERSION; if ((int)candidate_vers > s->client_version) s->client_version = candidate_vers; if (version_cmp(s, candidate_vers, best_vers) <= 0) continue; for (vent = table; vent->version != 0 && vent->version != (int)candidate_vers; ++vent); if (vent->version != 0) { const SSL_METHOD *method; method = vent->smeth(); if (ssl_method_error(s, method) == 0) { best_vers = candidate_vers; best_method = method; } } } if (PACKET_remaining(&versionslist) != 0) { /* Trailing data? */ return SSL_R_LENGTH_MISMATCH; } if (best_vers > 0) { s->version = best_vers; s->method = best_method; return 0; } return SSL_R_UNSUPPORTED_PROTOCOL; } /* * If the supported versions extension isn't present, then the highest * version we can negotiate is TLSv1.2 */ if (version_cmp(s, client_version, TLS1_3_VERSION) >= 0) client_version = TLS1_2_VERSION; /* * No supported versions extension, so we just use the version supplied in * the ClientHello. */ for (vent = table; vent->version != 0; ++vent) { const SSL_METHOD *method; Loading ssl/t1_lib.c +8 −7 Original line number Diff line number Diff line Loading @@ -2826,7 +2826,7 @@ int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt) * * Returns a pointer to the found RAW_EXTENSION data, or NULL if not found. */ static RAW_EXTENSION *get_extension_by_type(RAW_EXTENSION *exts, size_t numexts, RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts, size_t numexts, unsigned int type) { size_t loop; Loading Loading @@ -2885,7 +2885,7 @@ int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, if (s->version <= SSL3_VERSION || !tls_use_ticket(s)) return 0; ticketext = get_extension_by_type(hello->pre_proc_exts, ticketext = tls_get_extension_by_type(hello->pre_proc_exts, hello->num_extensions, TLSEXT_TYPE_session_ticket); if (ticketext == NULL) Loading Loading @@ -2948,7 +2948,8 @@ int tls_check_client_ems_support(SSL *s, const CLIENTHELLO_MSG *hello) if (s->version <= SSL3_VERSION) return 1; emsext = get_extension_by_type(hello->pre_proc_exts, hello->num_extensions, emsext = tls_get_extension_by_type(hello->pre_proc_exts, hello->num_extensions, TLSEXT_TYPE_extended_master_secret); /* Loading test/recipes/70-test_sslvertol.t +6 −3 Original line number Diff line number Diff line Loading @@ -34,15 +34,18 @@ my $proxy = TLSProxy::Proxy->new( (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) ); #Test 1: Asking for TLS1.3 should pass my $client_version = TLSProxy::Record::VERS_TLS_1_3; #Test 1: Asking for TLS1.4 should pass my $client_version = TLSProxy::Record::VERS_TLS_1_4; #We don't want the supported versions extension for this test $proxy->clientflags("-no_tls1_3"); $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; plan tests => 2; ok(TLSProxy::Message->success(), "Version tolerance test, TLS 1.3"); ok(TLSProxy::Message->success(), "Version tolerance test, TLS 1.4"); #Test 2: Testing something below SSLv3 should fail $client_version = TLSProxy::Record::VERS_SSL_3_0 - 1; $proxy->clear(); $proxy->clientflags("-no_tls1_3"); $proxy->start(); ok(TLSProxy::Message->fail(), "Version tolerance test, SSL < 3.0"); Loading Loading
ssl/ssl_locl.h +3 −0 Original line number Diff line number Diff line Loading @@ -2077,6 +2077,9 @@ __owur int dtls1_process_heartbeat(SSL *s, unsigned char *p, size_t length); # endif __owur RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts, size_t numexts, unsigned int type); __owur int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, SSL_SESSION **ret); __owur int tls_check_client_ems_support(SSL *s, const CLIENTHELLO_MSG *hello); Loading
ssl/statem/statem_clnt.c +6 −1 Original line number Diff line number Diff line Loading @@ -779,8 +779,13 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt) * TLS 1.0 and renegotiating with TLS 1.2. We do this by using * client_version in client hello and not resetting it to * the negotiated version. * * For TLS 1.3 we always set the ClientHello version to 1.2 and rely on the * supported_versions extension for the reall supported versions. */ if (!WPACKET_put_bytes_u16(pkt, s->client_version) if (!WPACKET_put_bytes_u16(pkt, (!SSL_IS_DTLS(s) && s->client_version >= TLS1_3_VERSION) ? TLS1_2_VERSION : s->client_version) || !WPACKET_memcpy(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) { SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); return 0; Loading
ssl/statem/statem_lib.c +68 −0 Original line number Diff line number Diff line Loading @@ -996,6 +996,7 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello) const version_info *vent; const version_info *table; int disabled = 0; RAW_EXTENSION *suppversions; s->client_version = client_version; Loading @@ -1019,6 +1020,73 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello) break; } suppversions = tls_get_extension_by_type(hello->pre_proc_exts, hello->num_extensions, TLSEXT_TYPE_supported_versions); /* * TODO(TLS1.3): We only look at this if our max protocol version is TLS1.3 * or above. Should we allow it for lower versions too? */ if (suppversions != NULL && !SSL_IS_DTLS(s) && (s->max_proto_version == 0 || TLS1_3_VERSION <= s->max_proto_version)) { unsigned int candidate_vers = 0; unsigned int best_vers = 0; const SSL_METHOD *best_method = NULL; PACKET versionslist; if (!PACKET_get_length_prefixed_1(&suppversions->data, &versionslist) || PACKET_remaining(&suppversions->data) != 0) { /* Trailing or invalid data? */ return SSL_R_LENGTH_MISMATCH; } while (PACKET_get_net_2(&versionslist, &candidate_vers)) { /* TODO(TLS1.3): Remove this before release */ if (candidate_vers == TLS1_3_VERSION_DRAFT) candidate_vers = TLS1_3_VERSION; if ((int)candidate_vers > s->client_version) s->client_version = candidate_vers; if (version_cmp(s, candidate_vers, best_vers) <= 0) continue; for (vent = table; vent->version != 0 && vent->version != (int)candidate_vers; ++vent); if (vent->version != 0) { const SSL_METHOD *method; method = vent->smeth(); if (ssl_method_error(s, method) == 0) { best_vers = candidate_vers; best_method = method; } } } if (PACKET_remaining(&versionslist) != 0) { /* Trailing data? */ return SSL_R_LENGTH_MISMATCH; } if (best_vers > 0) { s->version = best_vers; s->method = best_method; return 0; } return SSL_R_UNSUPPORTED_PROTOCOL; } /* * If the supported versions extension isn't present, then the highest * version we can negotiate is TLSv1.2 */ if (version_cmp(s, client_version, TLS1_3_VERSION) >= 0) client_version = TLS1_2_VERSION; /* * No supported versions extension, so we just use the version supplied in * the ClientHello. */ for (vent = table; vent->version != 0; ++vent) { const SSL_METHOD *method; Loading
ssl/t1_lib.c +8 −7 Original line number Diff line number Diff line Loading @@ -2826,7 +2826,7 @@ int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt) * * Returns a pointer to the found RAW_EXTENSION data, or NULL if not found. */ static RAW_EXTENSION *get_extension_by_type(RAW_EXTENSION *exts, size_t numexts, RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts, size_t numexts, unsigned int type) { size_t loop; Loading Loading @@ -2885,7 +2885,7 @@ int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello, if (s->version <= SSL3_VERSION || !tls_use_ticket(s)) return 0; ticketext = get_extension_by_type(hello->pre_proc_exts, ticketext = tls_get_extension_by_type(hello->pre_proc_exts, hello->num_extensions, TLSEXT_TYPE_session_ticket); if (ticketext == NULL) Loading Loading @@ -2948,7 +2948,8 @@ int tls_check_client_ems_support(SSL *s, const CLIENTHELLO_MSG *hello) if (s->version <= SSL3_VERSION) return 1; emsext = get_extension_by_type(hello->pre_proc_exts, hello->num_extensions, emsext = tls_get_extension_by_type(hello->pre_proc_exts, hello->num_extensions, TLSEXT_TYPE_extended_master_secret); /* Loading
test/recipes/70-test_sslvertol.t +6 −3 Original line number Diff line number Diff line Loading @@ -34,15 +34,18 @@ my $proxy = TLSProxy::Proxy->new( (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) ); #Test 1: Asking for TLS1.3 should pass my $client_version = TLSProxy::Record::VERS_TLS_1_3; #Test 1: Asking for TLS1.4 should pass my $client_version = TLSProxy::Record::VERS_TLS_1_4; #We don't want the supported versions extension for this test $proxy->clientflags("-no_tls1_3"); $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; plan tests => 2; ok(TLSProxy::Message->success(), "Version tolerance test, TLS 1.3"); ok(TLSProxy::Message->success(), "Version tolerance test, TLS 1.4"); #Test 2: Testing something below SSLv3 should fail $client_version = TLSProxy::Record::VERS_SSL_3_0 - 1; $proxy->clear(); $proxy->clientflags("-no_tls1_3"); $proxy->start(); ok(TLSProxy::Message->fail(), "Version tolerance test, SSL < 3.0"); Loading