From 9e4e58fe8c3536c649edf663efdbd4382751a85e Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Mon, 16 Oct 2017 13:59:24 +1000 Subject: [PATCH] Disallow upgrading to TLS v1.3 Change SupportedVersions extension to only include TLS v1.3 if downgrade is disabled. Fix parsing of SupportedVersions extension Don't upgrade Only downgrade in SupportedVersions extension if option enabled --- scripts/tls13.test | 2 +- src/internal.c | 10 +++----- src/tls.c | 57 +++++++++++++++++++++++++++------------------- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/scripts/tls13.test b/scripts/tls13.test index e0ad2b875..4ba1bb86e 100755 --- a/scripts/tls13.test +++ b/scripts/tls13.test @@ -379,7 +379,7 @@ create_port ./examples/client/client -v 4 -p $port RESULT=$? remove_ready_file -if [ $RESULT -ne 0 ]; then +if [ $RESULT -eq 0 ]; then echo -e "\n\nIssue with TLS v1.3 client upgrading server to TLS v1.3" do_cleanup exit 1 diff --git a/src/internal.c b/src/internal.c index 7a6fbfda0..a47feae29 100755 --- a/src/internal.c +++ b/src/internal.c @@ -22776,13 +22776,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_TLS13 if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) != NULL) { - TLSX_FreeAll(ssl->extensions, ssl->heap); - ssl->extensions = NULL; - ssl->version.minor = TLSv1_3_MINOR; - *inOutIdx = begin; - if ((ret = InitHandshakeHashes(ssl)) != 0) - return ret; - return DoTls13ClientHello(ssl, input, inOutIdx, helloSz); + WOLFSSL_MSG( + "Client attempting to connect with higher version"); + return VERSION_ERROR; } #endif #if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) diff --git a/src/tls.c b/src/tls.c index 4115233ce..8da5bb13c 100755 --- a/src/tls.c +++ b/src/tls.c @@ -4308,7 +4308,7 @@ int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz, */ static word16 TLSX_SupportedVersions_GetSize(void* data) { - (void)data; + WOLFSSL* ssl = (WOLFSSL*)data; /* TLS v1.2 and TLS v1.3 */ int cnt = 2; @@ -4318,6 +4318,9 @@ static word16 TLSX_SupportedVersions_GetSize(void* data) cnt += 2; #endif + if (!ssl->options.downgrade) + cnt = 1; + return OPAQUE8_LEN + cnt * OPAQUE16_LEN; } @@ -4340,6 +4343,9 @@ static word16 TLSX_SupportedVersions_Write(void* data, byte* output) cnt += 2; #endif + if (!ssl->options.downgrade) + cnt = 1; + *(output++) = cnt * OPAQUE16_LEN; for (i = 0; i < cnt; i++) { /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ @@ -4370,8 +4376,9 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, { ProtocolVersion pv = ssl->ctx->method->version; int i; - int ret = 0; + int ret = VERSION_ERROR; int len; + byte major, minor; /* Must contain a length and at least one version. */ if (length < OPAQUE8_LEN + OPAQUE16_LEN || (length & 1) != 1) @@ -4387,39 +4394,41 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, /* Find first match. */ for (i = 0; i < len; i += OPAQUE16_LEN) { + major = input[i]; + minor = input[i + OPAQUE8_LEN]; + /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ - if (input[i] == TLS_DRAFT_MAJOR && - input[i + OPAQUE8_LEN] == TLS_DRAFT_MINOR) { - ssl->version.minor = TLSv1_3_MINOR; - ssl->options.tls1_3 = 1; - TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, input, - ssl->heap); - break; + if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) { + major = SSLv3_MAJOR; + minor = TLSv1_3_MINOR; } - if (input[i] != pv.major) + if (major != pv.major) continue; -#ifndef NO_OLD_TLS - if (input[i + OPAQUE8_LEN] == TLSv1_MINOR || - input[i + OPAQUE8_LEN] == TLSv1_1_MINOR) { - ssl->version.minor = input[i + OPAQUE8_LEN]; - break; - } + /* No upgrade allowed. */ + if (ssl->version.minor > minor) + continue; + /* Check downgrade. */ + if (ssl->version.minor < minor) { + if (!ssl->options.downgrade) + continue; + +#ifdef NO_OLD_TLS + if (minor < TLSv1_2_MINOR) + continue; #endif - if (input[i + OPAQUE8_LEN] == TLSv1_2_MINOR) { - ssl->version.minor = input[i + OPAQUE8_LEN]; - TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, input, - ssl->heap); - break; + /* Downgrade the version. */ + ssl->version.minor = minor; } - if (input[i + OPAQUE8_LEN] == TLSv1_3_MINOR) { - ssl->version.minor = input[i + OPAQUE8_LEN]; + + if (minor >= TLSv1_3_MINOR) { ssl->options.tls1_3 = 1; TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, input, ssl->heap); - break; } + ret = 0; + break; } return ret;