Skip to content

Commit 63bee12

Browse files
authored
Merge pull request #9875 from Frauschi/f-158
Treat alerts as fatal errors regardless of level in TLS1.3
2 parents 888081b + 11fc781 commit 63bee12

3 files changed

Lines changed: 65 additions & 0 deletions

File tree

src/internal.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22038,6 +22038,12 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type)
2203822038
if (level == alert_fatal) {
2203922039
ssl->options.isClosed = 1; /* Don't send close_notify */
2204022040
}
22041+
/* RFC 8446 Section 6.2: In TLS 1.3, all error alerts are implicitly
22042+
* fatal regardless of the AlertLevel byte. */
22043+
if (IsAtLeastTLSv1_3(ssl->version) &&
22044+
code != close_notify && code != user_canceled) {
22045+
ssl->options.isClosed = 1;
22046+
}
2204122047
}
2204222048

2204322049
if (++ssl->options.alertCount >= WOLFSSL_ALERT_COUNT_MAX) {
@@ -23517,6 +23523,15 @@ static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
2351723523
if (type == decrypt_error)
2351823524
return FATAL_ERROR;
2351923525

23526+
/* RFC 8446 Section 6.2: In TLS 1.3, all error alerts MUST
23527+
* be treated as fatal regardless of the AlertLevel byte.
23528+
* Only close_notify (handled above) and user_canceled
23529+
* are exempt. */
23530+
if (IsAtLeastTLSv1_3(ssl->version) &&
23531+
type != user_canceled && type != invalid_alert) {
23532+
return FATAL_ERROR;
23533+
}
23534+
2352023535
/* Reset error if we got an alert level in ret */
2352123536
if (ret > 0)
2352223537
ret = 0;

tests/api/test_tls13.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3100,6 +3100,54 @@ int test_tls13_plaintext_alert(void)
31003100
return EXPECT_RESULT();
31013101
}
31023102

3103+
/* Test that TLS 1.3 warning-level alerts are treated as fatal (RFC 8446
3104+
* Section 6.2).
3105+
* A peer sending e.g. {alert_warning, handshake_failure} must still cause the
3106+
* connection to be terminated, not silently continued.
3107+
*/
3108+
int test_tls13_warning_alert_is_fatal(void)
3109+
{
3110+
EXPECT_DECLS;
3111+
#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
3112+
!defined(NO_WOLFSSL_CLIENT)
3113+
WOLFSSL_CTX *ctx_c = NULL;
3114+
WOLFSSL *ssl_c = NULL;
3115+
struct test_memio_ctx test_ctx;
3116+
WOLFSSL_ALERT_HISTORY h;
3117+
/* TLS record: content_type=alert(0x15), version=TLS1.2(0x0303), len=2,
3118+
* level=warning(0x01), code=handshake_failure(0x28=40) */
3119+
static const unsigned char warn_alert[] =
3120+
{ 0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x28 };
3121+
3122+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
3123+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL,
3124+
wolfTLSv1_3_client_method, NULL), 0);
3125+
3126+
/* Client sends ClientHello, then waits for the server response. */
3127+
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
3128+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
3129+
3130+
/* Inject a warning-level handshake_failure alert as if from the server.
3131+
* RFC 8446 Section 6.2: In TLS 1.3, all error alerts MUST be treated as
3132+
* fatalregardless of the AlertLevel byte. */
3133+
ExpectIntEQ(test_memio_inject_message(&test_ctx, 1,
3134+
(const char *)warn_alert, sizeof(warn_alert)), 0);
3135+
3136+
/* Expect the connection to be terminated, not silently continued. */
3137+
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
3138+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WC_NO_ERR_TRACE(FATAL_ERROR));
3139+
3140+
/* The alert details should be recorded correctly. */
3141+
ExpectIntEQ(wolfSSL_get_alert_history(ssl_c, &h), WOLFSSL_SUCCESS);
3142+
ExpectIntEQ(h.last_rx.code, handshake_failure);
3143+
ExpectIntEQ(h.last_rx.level, alert_warning);
3144+
3145+
wolfSSL_free(ssl_c);
3146+
wolfSSL_CTX_free(ctx_c);
3147+
#endif
3148+
return EXPECT_RESULT();
3149+
}
3150+
31033151
/* Test that wolfSSL_set1_sigalgs_list() is honored in TLS 1.3
31043152
*/
31053153
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
@@ -38,6 +38,7 @@ int test_tls13_duplicate_extension(void);
3838
int test_key_share_mismatch(void);
3939
int test_tls13_middlebox_compat_empty_session_id(void);
4040
int test_tls13_plaintext_alert(void);
41+
int test_tls13_warning_alert_is_fatal(void);
4142
int test_tls13_cert_req_sigalgs(void);
4243

4344
#define TEST_TLS13_DECLS \
@@ -55,6 +56,7 @@ int test_tls13_cert_req_sigalgs(void);
5556
TEST_DECL_GROUP("tls13", test_key_share_mismatch), \
5657
TEST_DECL_GROUP("tls13", test_tls13_middlebox_compat_empty_session_id), \
5758
TEST_DECL_GROUP("tls13", test_tls13_plaintext_alert), \
59+
TEST_DECL_GROUP("tls13", test_tls13_warning_alert_is_fatal), \
5860
TEST_DECL_GROUP("tls13", test_tls13_cert_req_sigalgs)
5961

6062
#endif /* WOLFCRYPT_TEST_TLS13_H */

0 commit comments

Comments
 (0)