From 8f477356ce843bd3228e810fd63423f3ea28ef2d Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Mon, 18 May 2026 09:30:28 +0200 Subject: [PATCH] dtls: add compat flag for buggy pre 5.9.0 DTLSv1.3 clients --- .wolfssl_known_macro_extras | 1 + src/dtls.c | 10 ++++++++-- src/tls13.c | 15 +++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 28a171f4fb..da5d51069e 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -744,6 +744,7 @@ WOLFSSL_DRBG_SHA256 WOLFSSL_DTLS_DISALLOW_FUTURE WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS WOLFSSL_DTLS_RESEND_ONLY_TIMEOUT +WOLFSSL_DTLS13_5_9_0_COMPAT WOLFSSL_DUMP_MEMIO_STREAM WOLFSSL_DUP_CERTPOL WOLFSSL_EARLY_DATA_NO_ANTI_REPLAY diff --git a/src/dtls.c b/src/dtls.c index b79db10330..a22b5768bb 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -635,9 +635,8 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) XMEMSET(&cs, 0, sizeof(cs)); - /* We need to echo the session ID sent by the client */ if (ch->sessionId.size > ID_LEN) { - /* Too large. We can't echo this. */ + /* Too large */ ERROR_OUT(INVALID_PARAMETER, dtls13_cleanup); } @@ -861,9 +860,16 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) nonConstSSL->options.tls1_1 = 1; nonConstSSL->options.tls1_3 = 1; +#ifdef WOLFSSL_DTLS13_5_9_0_COMPAT + nonConstSSL->session->sessionIDSz = (byte)ch->sessionId.size; + if (ch->sessionId.size > 0) + XMEMCPY(nonConstSSL->session->sessionID, ch->sessionId.elements, + ch->sessionId.size); +#else /* RFC 9147 Section 5.3: DTLS 1.3 ServerHello must have empty * legacy_session_id_echo. Don't copy the client's session ID. */ nonConstSSL->session->sessionIDSz = 0; +#endif nonConstSSL->options.cipherSuite0 = cs.cipherSuite0; nonConstSSL->options.cipherSuite = cs.cipherSuite; nonConstSSL->extensions = parsedExts; diff --git a/src/tls13.c b/src/tls13.c index 533a03462e..174b0d4684 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -5775,7 +5775,14 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ) { /* RFC 9147 Section 5.3 / RFC 9001 Section 8.4: DTLS 1.3 and QUIC * ServerHello must have empty legacy_session_id_echo. */ - if (args->sessIdSz != 0) { + int requireEmptyEcho = 1; +#ifdef WOLFSSL_DTLS13_5_9_0_COMPAT + /* Compat: a wolfSSL <= 5.9.0 DTLS 1.3 server echoes the client's + * legacy_session_id; accept any echo. */ + if (ssl->options.dtls) + requireEmptyEcho = 0; +#endif + if (requireEmptyEcho && args->sessIdSz != 0) { WOLFSSL_MSG("args->sessIdSz != 0"); WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER); return INVALID_PARAMETER; @@ -6973,7 +6980,7 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) /* Reconstruct the HelloRetryMessage for handshake hash. */ sessIdSz = ssl->session->sessionIDSz; -#ifdef WOLFSSL_DTLS13 +#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_DTLS13_5_9_0_COMPAT) /* RFC 9147 Section 5.3: DTLS 1.3 must use empty legacy_session_id. */ if (ssl->options.dtls) sessIdSz = 0; @@ -7453,7 +7460,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (sessIdSz + args->idx > helloSz) ERROR_OUT(BUFFER_ERROR, exit_dch); -#ifdef WOLFSSL_DTLS13 +#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_DTLS13_5_9_0_COMPAT) /* RFC 9147 Section 5.3: DTLS 1.3 ServerHello must have empty * legacy_session_id_echo. Don't store the client's value so it * won't be echoed in SendTls13ServerHello. */ @@ -8058,7 +8065,7 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) WOLFSSL_BUFFER(ssl->arrays->serverRandom, RAN_LEN); #endif -#ifdef WOLFSSL_DTLS13 +#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_DTLS13_5_9_0_COMPAT) if (ssl->options.dtls) { /* RFC 9147 Section 5.3: DTLS 1.3 ServerHello must have empty * legacy_session_id_echo. */