Skip to content

DTLS 1.3: don't echo legacy_session_id in ServerHello#10007

Open
julek-wolfssl wants to merge 3 commits intowolfSSL:masterfrom
julek-wolfssl:zd/21376
Open

DTLS 1.3: don't echo legacy_session_id in ServerHello#10007
julek-wolfssl wants to merge 3 commits intowolfSSL:masterfrom
julek-wolfssl:zd/21376

Conversation

@julek-wolfssl
Copy link
Member

@julek-wolfssl julek-wolfssl commented Mar 18, 2026

ZD21376

Copilot AI review requested due to automatic review settings March 18, 2026 18:27
@julek-wolfssl julek-wolfssl self-assigned this Mar 18, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds DTLS 1.3 compliance behavior to avoid echoing the ClientHello legacy session ID in ServerHello, along with a regression test to validate the on-wire encoding.

Changes:

  • Add a new DTLS 1.3 test that verifies legacy_session_id_echo is empty in ServerHello.
  • Update TLS 1.3 message construction/parsing paths to ensure DTLS 1.3 does not include/echo a session ID (including HRR transcript reconstruction).
  • Add a guard in DoTls13ServerHello to enforce an empty session ID for DTLS 1.3.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
tests/api/test_dtls.h Registers the new DTLS 1.3 regression test in the test declarations list.
tests/api/test_dtls.c Implements a memio-based DTLS 1.3 test that inspects the ServerHello bytes for empty legacy_session_id_echo.
src/tls13.c Ensures DTLS 1.3 does not store/echo legacy session IDs and adjusts HRR handshake-hash reconstruction accordingly.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

@julek-wolfssl julek-wolfssl requested a review from rizlik March 18, 2026 18:42
src/tls13.c Outdated

case TLS_ASYNC_FINALIZE:
{
#ifdef WOLFSSL_DTLS13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be merged to the QUIC check some lines below?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging

length = HRR_BODY_SZ - ID_LEN + ssl->session->sessionIDSz +
HRR_COOKIE_HDR_SZ + cookie->len;
length = HRR_BODY_SZ - ID_LEN + HRR_COOKIE_HDR_SZ + cookie->len;
#ifdef WOLFSSL_DTLS13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't gather single if without the body as it makes the code very hard to read.
options.dtls is not guarded.
Prefer using an extra sessionIDSz variable set to zero when options.dtls is true

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using var

src/tls13.c Outdated
if (ssl->session->sessionIDSz > 0) {
XMEMCPY(hrr + hrrIdx, ssl->session->sessionID, ssl->session->sessionIDSz);
hrrIdx += ssl->session->sessionIDSz;
#ifdef WOLFSSL_DTLS13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer using extra variable sessId size to avoid this if/else

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using var

src/tls13.c Outdated
/* Extensions' length */
length -= HRR_BODY_SZ - ID_LEN + ssl->session->sessionIDSz;
length -= HRR_BODY_SZ - ID_LEN;
#ifdef WOLFSSL_DTLS13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar to comments above

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using var

ssl->session->sessionIDSz = sessIdSz;
if (sessIdSz > 0)
XMEMCPY(ssl->session->sessionID, input + args->idx, sessIdSz);
#ifdef WOLFSSL_DTLS13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar to comments above

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using var

src/tls13.c Outdated
length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->session->sessionIDSz +
SUITE_LEN + COMP_LEN;
length = VERSION_SZ + RAN_LEN + ENUM_LEN + SUITE_LEN + COMP_LEN;
#ifdef WOLFSSL_DTLS13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here sessionIDSz should be already be zero because of the changes in DoTls13ClientHello.
is ssl->sessionIDSz is used by tls 1.3 resumption code (not checked assumption), just use new var set to zero at the beginning of the function to avoid if/else branches.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverting

Copy link
Contributor

@rizlik rizlik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think we should avoid to send the legacy session id in client hello if doing 1.3 resumption.
This also means we should manually set the legacy id in the test.
Add test for flexible 1.3/1.2 client doing 1.2 resumption against a flexible 1.3/1.2 server for both dtls and tls

@julek-wolfssl
Copy link
Member Author

I'm not sure about that. This section encourages populating it in the CH

legacy_session_id:
Versions of TLS and DTLS before version 1.3 supported a "session resumption" feature, which has been merged with pre-shared keys (PSK) in version 1.3. A client which has a cached session ID set by a pre-DTLS 1.3 server SHOULD set this field to that value. Otherwise, it MUST be set as a zero-length vector (i.e., a zero-valued single byte length field).

@julek-wolfssl julek-wolfssl requested a review from rizlik March 19, 2026 11:58
@rizlik
Copy link
Contributor

rizlik commented Mar 19, 2026

I'm not sure about that. This section encourages populating it in the CH

legacy_session_id:
Versions of TLS and DTLS before version 1.3 supported a "session resumption" feature, which has been merged with pre-shared keys (PSK) in version 1.3. A client which has a cached session ID set by a pre-DTLS 1.3 server SHOULD set this field to that value. Otherwise, it MUST be set as a zero-length vector (i.e., a zero-valued single byte length field).

Check the important MUST part:

Otherwise, it MUST be set as a zero-length vector (i.e., a zero-valued single byte length field).

We probably send a random value due to Middlebox compatibility if resuming with 1.3 PSK method.

Copilot AI review requested due to automatic review settings March 19, 2026 17:04
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates wolfSSL DTLS 1.3 behavior to comply with RFC 9147 by ensuring legacy_session_id_echo is empty in ServerHello, and adds regression tests to prevent session-id resumption/version-downgrade issues.

Changes:

  • Enforce empty legacy_session_id_echo for DTLS 1.3 (and QUIC) in TLS 1.3 ServerHello processing/sending.
  • Adjust DTLS 1.3 handling around session IDs/HRR hashing to avoid echoing the client’s legacy session id.
  • Add new TLS/DTLS API tests covering DTLS 1.3 session id echo behavior and a session-id resumption downgrade scenario.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/api/test_tls.h Registers the new TLS resumption/downgrade regression test.
tests/api/test_tls.c Adds test_tls_session_id_resume_downgrade covering resumption behavior.
tests/api/test_dtls.h Registers the new DTLS 1.3 legacy session id echo regression test.
tests/api/test_dtls.c Adds test_dtls13_no_session_id_echo validating RFC 9147 ServerHello requirements.
src/tls13.c Ensures DTLS 1.3/QUIC don’t echo legacy session id; updates HRR hashing and ClientHello options.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +4667 to +4672
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls) {
/* RFC 9147 Section 5: DTLS implementations do not use the
* TLS 1.3 "compatibility mode" */
ssl->options.tls13MiddleBoxCompat = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants