Skip to content

Commit 136e5f9

Browse files
committed
Error out in case of unknown extensions in response message in TLS 1.3
1 parent 8093875 commit 136e5f9

5 files changed

Lines changed: 86 additions & 6 deletions

File tree

src/tls.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16640,13 +16640,13 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
1664016640

1664116641
break;
1664216642

16643-
#ifdef WOLFSSL_SEND_HRR_COOKIE
16643+
1664416644
case TLSX_COOKIE:
1664516645
WOLFSSL_MSG("Cookie extension received");
1664616646
#ifdef WOLFSSL_DEBUG_TLS
1664716647
WOLFSSL_BUFFER(input + offset, size);
1664816648
#endif
16649-
16649+
#ifdef WOLFSSL_SEND_HRR_COOKIE
1665016650
if (!IsAtLeastTLSv1_3(ssl->version))
1665116651
break;
1665216652

@@ -16656,8 +16656,8 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
1665616656
}
1665716657

1665816658
ret = CKE_PARSE(ssl, input + offset, size, msgType);
16659-
break;
1666016659
#endif
16660+
break;
1666116661

1666216662
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
1666316663
case TLSX_PRE_SHARED_KEY:
@@ -16898,6 +16898,16 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
1689816898
#endif
1689916899
default:
1690016900
WOLFSSL_MSG("Unknown TLS extension type");
16901+
#if defined(WOLFSSL_TLS13)
16902+
/* RFC 8446 §4.2: for TLS 1.3 server-to-client messages, the
16903+
* client MUST abort with unsupported_extension upon receiving
16904+
* an extension that was not advertised in the ClientHello. */
16905+
if (IsAtLeastTLSv1_3(ssl->version) && !isRequest) {
16906+
SendAlert((WOLFSSL*)ssl, alert_fatal, unsupported_extension);
16907+
WOLFSSL_ERROR_VERBOSE(UNSUPPORTED_EXTENSION);
16908+
return UNSUPPORTED_EXTENSION;
16909+
}
16910+
#endif
1690116911
}
1690216912

1690316913
/* offset should be updated here! */

tests/api.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30329,7 +30329,8 @@ static int test_TLSX_CA_NAMES_bad_extension(void)
3032930329

3033030330
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
3033130331
#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS
30332-
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WC_NO_ERR_TRACE(EXT_MISSING));
30332+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1),
30333+
WC_NO_ERR_TRACE(UNSUPPORTED_EXTENSION));
3033330334
#else
3033430335
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WC_NO_ERR_TRACE(BUFFER_ERROR));
3033530336
#endif

tests/api/test_tls13.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3148,6 +3148,75 @@ int test_tls13_warning_alert_is_fatal(void)
31483148
return EXPECT_RESULT();
31493149
}
31503150

3151+
/* Test that an unknown extension in a TLS 1.3 server-to-client message is
3152+
* rejected with unsupported_extension (RFC 8446 §4.2). The client MUST abort
3153+
* the handshake when it receives an extension it did not advertise.
3154+
*/
3155+
int test_tls13_unknown_ext_rejected(void)
3156+
{
3157+
EXPECT_DECLS;
3158+
#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
3159+
!defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_AES_128) && \
3160+
defined(HAVE_AESGCM) && !defined(NO_SHA256) && \
3161+
!defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
3162+
WOLFSSL_CTX *ctx_c = NULL;
3163+
WOLFSSL *ssl_c = NULL;
3164+
struct test_memio_ctx test_ctx;
3165+
/* HelloRetryRequest carrying TLS_AES_128_GCM_SHA256, supported_versions
3166+
* (TLS 1.3), and an extra unknown extension type 0xFABC.
3167+
*
3168+
* The base HRR (from test_tls13_same_ch) extended with 4 bytes:
3169+
* extensions length: 6 → 10 (0x00,0x0a)
3170+
* handshake body length: 46 → 50 (0x00,0x00,0x32)
3171+
* record body length: 50 → 54 (0x00,0x36)
3172+
* appended: 0xfa,0xbc,0x00,0x00 (unknown type, zero-length value)
3173+
*/
3174+
static const unsigned char hrr_unknown_ext[] = {
3175+
/* TLS record header: handshake, TLS 1.2 compat, len=54 */
3176+
0x16, 0x03, 0x03, 0x00, 0x36,
3177+
/* Handshake header: ServerHello, len=50 */
3178+
0x02, 0x00, 0x00, 0x32,
3179+
/* legacy_version: TLS 1.2 */
3180+
0x03, 0x03,
3181+
/* HelloRetryRequest magic random */
3182+
0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11,
3183+
0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91,
3184+
0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
3185+
0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c,
3186+
/* session ID length: 0 */
3187+
0x00,
3188+
/* cipher suite: TLS_AES_128_GCM_SHA256 */
3189+
0x13, 0x01,
3190+
/* compression: null */
3191+
0x00,
3192+
/* extensions length: 10 */
3193+
0x00, 0x0a,
3194+
/* supported_versions: TLS 1.3 (0x0304) */
3195+
0x00, 0x2b, 0x00, 0x02, 0x03, 0x04,
3196+
/* unknown extension type 0xFABC, zero-length value */
3197+
0xfa, 0xbc, 0x00, 0x00
3198+
};
3199+
3200+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
3201+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL,
3202+
wolfTLSv1_3_client_method, NULL), 0);
3203+
3204+
/* Inject the crafted HRR before the client starts the handshake.
3205+
* wolfSSL_connect will send the ClientHello and then read this message. */
3206+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
3207+
(const char *)hrr_unknown_ext, sizeof(hrr_unknown_ext)), 0);
3208+
3209+
/* RFC 8446 §4.2: the client MUST abort with unsupported_extension. */
3210+
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
3211+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1),
3212+
WC_NO_ERR_TRACE(UNSUPPORTED_EXTENSION));
3213+
3214+
wolfSSL_free(ssl_c);
3215+
wolfSSL_CTX_free(ctx_c);
3216+
#endif
3217+
return EXPECT_RESULT();
3218+
}
3219+
31513220
/* Test that wolfSSL_set1_sigalgs_list() is honored in TLS 1.3
31523221
*/
31533222
int test_tls13_cert_req_sigalgs(void)

tests/api/test_tls13.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ int test_key_share_mismatch(void);
3939
int test_tls13_middlebox_compat_empty_session_id(void);
4040
int test_tls13_plaintext_alert(void);
4141
int test_tls13_warning_alert_is_fatal(void);
42+
int test_tls13_unknown_ext_rejected(void);
4243
int test_tls13_cert_req_sigalgs(void);
4344

4445
#define TEST_TLS13_DECLS \
@@ -57,6 +58,7 @@ int test_tls13_cert_req_sigalgs(void);
5758
TEST_DECL_GROUP("tls13", test_tls13_middlebox_compat_empty_session_id), \
5859
TEST_DECL_GROUP("tls13", test_tls13_plaintext_alert), \
5960
TEST_DECL_GROUP("tls13", test_tls13_warning_alert_is_fatal), \
61+
TEST_DECL_GROUP("tls13", test_tls13_unknown_ext_rejected), \
6062
TEST_DECL_GROUP("tls13", test_tls13_cert_req_sigalgs)
6163

6264
#endif /* WOLFCRYPT_TEST_TLS13_H */

wolfssl/internal.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3012,9 +3012,7 @@ typedef enum {
30123012
TLSX_EARLY_DATA = TLSXT_EARLY_DATA,
30133013
#endif
30143014
TLSX_SUPPORTED_VERSIONS = TLSXT_SUPPORTED_VERSIONS,
3015-
#ifdef WOLFSSL_SEND_HRR_COOKIE
30163015
TLSX_COOKIE = TLSXT_COOKIE,
3017-
#endif
30183016
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
30193017
TLSX_PSK_KEY_EXCHANGE_MODES = TLSXT_PSK_KEY_EXCHANGE_MODES,
30203018
#endif

0 commit comments

Comments
 (0)