Error out in case of unknown extensions in response message in TLS 1.3

This commit is contained in:
Tobias Frauenschläger
2026-03-05 16:21:57 +01:00
parent 80938758ac
commit a2622746cd
5 changed files with 85 additions and 13 deletions
+12 -10
View File
@@ -7383,7 +7383,7 @@ int TLSX_Cookie_Use(const WOLFSSL* ssl, const byte* data, word16 len, byte* mac,
#else
#define CKE_FREE_ALL(a, b) 0
#define CKE_FREE_ALL(a, b) WC_DO_NOTHING
#define CKE_GET_SIZE(a, b, c) 0
#define CKE_WRITE(a, b, c, d) 0
#define CKE_PARSE(a, b, c, d) 0
@@ -13901,12 +13901,10 @@ void TLSX_FreeAll(TLSX* list, void* heap)
WOLFSSL_MSG("Supported Versions extension free");
break;
#ifdef WOLFSSL_SEND_HRR_COOKIE
case TLSX_COOKIE:
WOLFSSL_MSG("Cookie extension free");
CKE_FREE_ALL((Cookie*)extension->data, heap);
break;
#endif
#ifdef WOLFSSL_EARLY_DATA
case TLSX_EARLY_DATA:
@@ -14098,11 +14096,9 @@ static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
ret = SV_GET_SIZE(extension->data, msgType, &length);
break;
#ifdef WOLFSSL_SEND_HRR_COOKIE
case TLSX_COOKIE:
ret = CKE_GET_SIZE((Cookie*)extension->data, msgType, &length);
break;
#endif
#ifdef WOLFSSL_EARLY_DATA
case TLSX_EARLY_DATA:
@@ -14333,13 +14329,11 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
&offset);
break;
#ifdef WOLFSSL_SEND_HRR_COOKIE
case TLSX_COOKIE:
WOLFSSL_MSG("Cookie extension to write");
ret = CKE_WRITE((Cookie*)extension->data, output + offset,
msgType, &offset);
break;
#endif
#ifdef WOLFSSL_EARLY_DATA
case TLSX_EARLY_DATA:
@@ -16640,13 +16634,12 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
break;
#ifdef WOLFSSL_SEND_HRR_COOKIE
case TLSX_COOKIE:
WOLFSSL_MSG("Cookie extension received");
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_BUFFER(input + offset, size);
#endif
if (!IsAtLeastTLSv1_3(ssl->version))
break;
@@ -16657,7 +16650,6 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
ret = CKE_PARSE(ssl, input + offset, size, msgType);
break;
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
case TLSX_PRE_SHARED_KEY:
@@ -16898,6 +16890,16 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
#endif
default:
WOLFSSL_MSG("Unknown TLS extension type");
#if defined(WOLFSSL_TLS13)
/* RFC 8446 §4.2: for TLS 1.3 server-to-client messages, the
* client MUST abort with unsupported_extension upon receiving
* an extension that was not advertised in the ClientHello. */
if (IsAtLeastTLSv1_3(ssl->version) && !isRequest) {
SendAlert((WOLFSSL*)ssl, alert_fatal, unsupported_extension);
WOLFSSL_ERROR_VERBOSE(UNSUPPORTED_EXTENSION);
return UNSUPPORTED_EXTENSION;
}
#endif
}
/* offset should be updated here! */
+2 -1
View File
@@ -30329,7 +30329,8 @@ static int test_TLSX_CA_NAMES_bad_extension(void)
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WC_NO_ERR_TRACE(EXT_MISSING));
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1),
WC_NO_ERR_TRACE(UNSUPPORTED_EXTENSION));
#else
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WC_NO_ERR_TRACE(BUFFER_ERROR));
#endif
+69
View File
@@ -3148,6 +3148,75 @@ int test_tls13_warning_alert_is_fatal(void)
return EXPECT_RESULT();
}
/* Test that an unknown extension in a TLS 1.3 server-to-client message is
* rejected with unsupported_extension (RFC 8446 §4.2). The client MUST abort
* the handshake when it receives an extension it did not advertise.
*/
int test_tls13_unknown_ext_rejected(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
!defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_AES_128) && \
defined(HAVE_AESGCM) && !defined(NO_SHA256) && \
!defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL *ssl_c = NULL;
struct test_memio_ctx test_ctx;
/* HelloRetryRequest carrying TLS_AES_128_GCM_SHA256, supported_versions
* (TLS 1.3), and an extra unknown extension type 0xFABC.
*
* The base HRR (from test_tls13_same_ch) extended with 4 bytes:
* extensions length: 6 → 10 (0x00,0x0a)
* handshake body length: 46 → 50 (0x00,0x00,0x32)
* record body length: 50 → 54 (0x00,0x36)
* appended: 0xfa,0xbc,0x00,0x00 (unknown type, zero-length value)
*/
static const unsigned char hrr_unknown_ext[] = {
/* TLS record header: handshake, TLS 1.2 compat, len=54 */
0x16, 0x03, 0x03, 0x00, 0x36,
/* Handshake header: ServerHello, len=50 */
0x02, 0x00, 0x00, 0x32,
/* legacy_version: TLS 1.2 */
0x03, 0x03,
/* HelloRetryRequest magic random */
0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11,
0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91,
0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c,
/* session ID length: 0 */
0x00,
/* cipher suite: TLS_AES_128_GCM_SHA256 */
0x13, 0x01,
/* compression: null */
0x00,
/* extensions length: 10 */
0x00, 0x0a,
/* supported_versions: TLS 1.3 (0x0304) */
0x00, 0x2b, 0x00, 0x02, 0x03, 0x04,
/* unknown extension type 0xFABC, zero-length value */
0xfa, 0xbc, 0x00, 0x00
};
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL,
wolfTLSv1_3_client_method, NULL), 0);
/* Inject the crafted HRR before the client starts the handshake.
* wolfSSL_connect will send the ClientHello and then read this message. */
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
(const char *)hrr_unknown_ext, sizeof(hrr_unknown_ext)), 0);
/* RFC 8446 §4.2: the client MUST abort with unsupported_extension. */
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1),
WC_NO_ERR_TRACE(UNSUPPORTED_EXTENSION));
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
#endif
return EXPECT_RESULT();
}
/* Test that wolfSSL_set1_sigalgs_list() is honored in TLS 1.3
*/
int test_tls13_cert_req_sigalgs(void)
+2
View File
@@ -39,6 +39,7 @@ int test_key_share_mismatch(void);
int test_tls13_middlebox_compat_empty_session_id(void);
int test_tls13_plaintext_alert(void);
int test_tls13_warning_alert_is_fatal(void);
int test_tls13_unknown_ext_rejected(void);
int test_tls13_cert_req_sigalgs(void);
#define TEST_TLS13_DECLS \
@@ -57,6 +58,7 @@ int test_tls13_cert_req_sigalgs(void);
TEST_DECL_GROUP("tls13", test_tls13_middlebox_compat_empty_session_id), \
TEST_DECL_GROUP("tls13", test_tls13_plaintext_alert), \
TEST_DECL_GROUP("tls13", test_tls13_warning_alert_is_fatal), \
TEST_DECL_GROUP("tls13", test_tls13_unknown_ext_rejected), \
TEST_DECL_GROUP("tls13", test_tls13_cert_req_sigalgs)
#endif /* WOLFCRYPT_TEST_TLS13_H */
-2
View File
@@ -3012,9 +3012,7 @@ typedef enum {
TLSX_EARLY_DATA = TLSXT_EARLY_DATA,
#endif
TLSX_SUPPORTED_VERSIONS = TLSXT_SUPPORTED_VERSIONS,
#ifdef WOLFSSL_SEND_HRR_COOKIE
TLSX_COOKIE = TLSXT_COOKIE,
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
TLSX_PSK_KEY_EXCHANGE_MODES = TLSXT_PSK_KEY_EXCHANGE_MODES,
#endif