diff --git a/src/tls13.c b/src/tls13.c index dce053278..d597d03c7 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -6835,7 +6835,8 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, * * Note that if WOLFSSL_ALLOW_BAD_TLS_LEGACY_VERSION is defined then the * semantics of RFC 5246 Appendix E will be followed. A ServerHello with - * version 1.2 will be sent. */ + * version 1.2 will be sent. The same is true if TLS 1.3 is not enabled. + */ if (args->pv.major == SSLv3_MAJOR && args->pv.minor >= TLSv1_3_MINOR) { WOLFSSL_MSG("Legacy version field is TLS 1.3 or later. Aborting."); ERROR_OUT(VERSION_ERROR, exit_dch); diff --git a/tests/api.c b/tests/api.c index 0b2bbeb14..c5730f1ed 100644 --- a/tests/api.c +++ b/tests/api.c @@ -13237,6 +13237,87 @@ static int test_tls_ext_duplicate(void) return EXPECT_RESULT(); } + +/* Test TLS connection abort when legacy version field indicates TLS 1.3 or + * higher. Based on test_tls_ext_duplicate() but with legacy version modified + * to 0x0304. + */ +static int test_tls_bad_legacy_version(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_ALLOW_BAD_TLS_LEGACY_VERSION) +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) && \ + !defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC)) + /* This is exactly the same as the buffer in test_tls_ext_duplicate() except + * the 11th byte is set to 0x04. That change means the legacy protocol + * version field is invalid. That will be caught before the dulplicate + * signature algorithms extension. */ + const unsigned char clientHelloBadLegacyVersion[] = { + 0x16, 0x03, 0x03, 0x00, 0x6a, 0x01, 0x00, 0x00, + 0x66, 0x03, 0x04, 0xf4, 0x65, 0xbd, 0x22, 0xfe, + 0x6e, 0xab, 0x66, 0xdd, 0xcf, 0xe9, 0x65, 0x55, + 0xe8, 0xdf, 0xc3, 0x8e, 0x4b, 0x00, 0xbc, 0xf8, + 0x23, 0x57, 0x1b, 0xa0, 0xc8, 0xa9, 0xe2, 0x8c, + 0x91, 0x6e, 0xf9, 0x20, 0xf7, 0x5c, 0xc5, 0x5b, + 0x75, 0x8c, 0x47, 0x0a, 0x0e, 0xc4, 0x1a, 0xda, + 0xef, 0x75, 0xe5, 0x21, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x13, 0x01, + 0x00, 0x9e, 0x01, 0x00, + /* Extensions - duplicate signature algorithms. */ + 0x00, 0x19, 0x00, 0x0d, + 0x00, 0x04, 0x00, 0x02, 0x04, 0x01, 0x00, 0x0d, + 0x00, 0x04, 0x00, 0x02, 0x04, 0x01, + /* Supported Versions extension for TLS 1.3. */ + 0x00, 0x2b, + 0x00, 0x05, 0x04, 0x03, 0x04, 0x03, 0x03 + }; + + WOLFSSL_BUFFER_INFO msg; + const char* testCertFile; + const char* testKeyFile; + WOLFSSL_CTX *ctx = NULL; + WOLFSSL *ssl = NULL; + +#ifndef NO_RSA + testCertFile = svrCertFile; + testKeyFile = svrKeyFile; +#elif defined(HAVE_ECC) + testCertFile = eccCertFile; + testKeyFile = eccKeyFile; +#endif + + ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + + ExpectTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, + WOLFSSL_FILETYPE_PEM)); + + /* Read from 'msg'. */ + wolfSSL_SetIORecv(ctx, BufferInfoRecv); + /* No where to send to - dummy sender. */ + wolfSSL_SetIOSend(ctx, DummySend); + + ssl = wolfSSL_new(ctx); + ExpectNotNull(ssl); + + msg.buffer = (unsigned char*)clientHelloBadLegacyVersion; + msg.length = (unsigned int)sizeof(clientHelloBadLegacyVersion); + wolfSSL_SetIOReadCtx(ssl, &msg); + + ExpectIntNE(wolfSSL_accept(ssl), WOLFSSL_SUCCESS); + /* Connection should fail due to bad legacy version field. When that + * happens the return code is VERSION_ERROR but that gets transformed into + * SOCKET_ERROR_E. */ + ExpectIntEQ(wolfSSL_get_error(ssl, 0), WC_NO_ERR_TRACE(SOCKET_ERROR_E)); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif +#endif + return EXPECT_RESULT(); +} /*----------------------------------------------------------------------------* | X509 Tests *----------------------------------------------------------------------------*/ @@ -68400,6 +68481,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation), TEST_DECL(test_wolfSSL_SCR_Reconnect), TEST_DECL(test_tls_ext_duplicate), + TEST_DECL(test_tls_bad_legacy_version), #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) && \ defined(HAVE_IO_TESTS_DEPENDENCIES) TEST_DECL(test_wolfSSL_Tls13_ECH_params),