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;