From 0ec0db93570d909212ea393cbed7523908d80299 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 3 Jun 2026 00:27:25 +0200 Subject: [PATCH] F-5813: fail TLS 1.2 record send before the sequence number wraps GetSEQIncrement silently rolled the 64-bit write sequence counter from 2^64-1 back to 0, reusing sequence number 0 with the same keys. Per RFC 5246 Section 6.1 sequence numbers MUST NOT wrap. BuildMessage now refuses to emit a TLS 1.2 record once the write sequence number has reached its maximum, returning the new SEQUENCE_NUMBER_E error so the caller renegotiates or closes instead. --- src/internal.c | 16 ++++++++++++++++ wolfssl/error-ssl.h | 4 +++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 317c4fed28..9dd5c00dcf 100644 --- a/src/internal.c +++ b/src/internal.c @@ -24662,6 +24662,19 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #endif #ifndef WOLFSSL_NO_TLS12 + /* RFC 5246 6.1: record sequence numbers MUST NOT wrap. Refuse to emit a + * record once the write sequence number has reached its maximum value + * (2^64-1); reusing sequence number 0 with the same keys would break the + * record protection. The caller must renegotiate or close the connection + * instead. DTLS sequence numbers are epoch-scoped and handled elsewhere. */ + if (!sizeOnly && !ssl->options.dtls && + ssl->keys.sequence_number_hi == 0xFFFFFFFFU && + ssl->keys.sequence_number_lo == 0xFFFFFFFFU) { + WOLFSSL_MSG("TLS write sequence number would wrap"); + WOLFSSL_ERROR_VERBOSE(SEQUENCE_NUMBER_E); + return SEQUENCE_NUMBER_E; + } + #ifdef WOLFSSL_ASYNC_CRYPT ret = WC_NO_PENDING_E; if (asyncOkay) { @@ -28108,6 +28121,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case ECH_REQUIRED_E: return "ECH offered but rejected by server"; + + case SEQUENCE_NUMBER_E: + return "Record sequence number would wrap"; } return "unknown error number"; diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index b98a52d40c..379008afb0 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -244,7 +244,9 @@ enum wolfSSL_ErrorCodes { ECH_REQUIRED_E = -519, /* ECH offered but rejected by server */ - WOLFSSL_LAST_E = -519 + SEQUENCE_NUMBER_E = -520, /* Record sequence number would wrap */ + + WOLFSSL_LAST_E = -520 /* codes -1000 to -1999 are reserved for wolfCrypt. */ };