Repository navigation
Conversation
A TLS 1.2 client sends its ticket with an empty session ID and learns from the server's next handshake message whether the ticket was accepted, as RFC 5077 Section 3.4 allows. When a Certificate or ServerKeyExchange follows, the client falls back to a full handshake, but only if the ServerHello carried no session ID: a session ID was taken as a promise to resume, and the handshake failed with OUT_OF_ORDER_E. A server that declines the ticket may still send a session ID, to offer stateful resumption (RFC 5077 Section 3.4), and a client that sent an empty session ID ignores it. Any server that declined or ignored the ticket and sent a session ID made the client fail. That includes a server without ticket support, and a wolfSSL server with its session cache on, for example after a restart with a new ticket key. A server that declines with an empty session ID, as OpenSSL does, was not affected. Keep the fatal error for a session ID the client sent and the server echoed, and ignore the ServerHello session ID when the client offered a ticket. After the fallback the client also kept the declined ticket next to the new session. Its next connection offered that ticket, so a server that could still decrypt it resumed with the ticket's master secret while the client used the new one, and the handshake failed. The fallback now drops the ticket, as a failed Finished check already does, and the client resumes by the new session ID instead. The fallback also drops the session ID the client made up for the ticket. With that ID left in place, SetupSession() stored the new session under it, and the next connection offered it in place of the server's session ID. test_tls12_resume_ticket_decline_fallback turned the server's session cache off to avoid the first failure. It now keeps the cache on, checks that the declining server sent a session ID, and resumes a third connection by that session ID. It fails without this change. A second run gets its first ticket with an empty session ID, so the client makes up an ID, and frees every other reference to the session before the fallback, so the made-up ID survives to SetupSession(). It fails without the new reset.
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues are recorded for the TLS 1.2 session-ticket rejection changes.
No open issues 🎉
What changed in this PR
Fixes TLS 1.2 session-ticket rejection handling so clients can complete a full handshake and servers do not fall back to session-ID resumption when a ticket is declined, consistent with RFC 5077.
Changes:
- Allows client fallback when the server supplies a new session ID, clearing the declined ticket and generated ID.
- Prevents session-ID resumption alongside an unused ticket, including during DTLS cookie checks.
- Expands regression tests for ticket rejection and subsequent session-ID resumption.
| File | Description |
|---|---|
tests/api/test_tls.h |
Declares and registers the new server-side regression test. |
tests/api/test_tls.c |
Adds rejection scenarios and extends client fallback tests through a third connection. |
src/tls.c |
Disables stateful resumption when a nonempty TLS 1.2 ticket is received. |
src/internal.c |
Permits full-handshake fallback and clears declined ticket state. |
src/dtls.c |
Prevents session-ID fallback from bypassing the DTLS cookie exchange when a ticket is present. |
Review effort: Balanced
|
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #12064
Scan targets checked: wolfssl-src, wolfssl-bugs
Not reviewed (no scan target covers them): tests/api/test_tls.h
Coverage: 4 of 4 in-scope changed file(s) opened by the reviewer
Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Reported findings require changes before merge.
Review tier: Max
e02f962 to
6195b8b
Compare
|
@claude review |
RFC 5077 Section 3.4 says a server that gets a ticket must not use the ClientHello session ID for stateful resumption. A wolfSSL server that did not use the ticket kept the resumption attempt the session ID had started, and looked the ID up in its session cache. That happened when the ticket failed to decrypt, when TLS 1.2 tickets were turned off with wolfSSL_NoTicketTLSv12(), and when no ticket callback was set. A client that sends a session ID next to its ticket, as OpenSSL does, could then be resumed from the cache. End the resumption attempt whenever a TLS 1.2 ClientHello carries a ticket; an accepted ticket starts it again. With WOLFSSL_DTLS_NO_HVR_ON_RESUME the stateless ClientHello check made the same choice. A ticket that failed to decrypt fell back to the session ID, so the server skipped the cookie exchange and then ran a full handshake. It also resumed on a ticket that decrypted while wolfSSL_NoTicketTLSv12() was set, which the server then ignores. The check now looks at the session ID only when the ClientHello has no ticket, and treats a TLS 1.2 ticket as declined under wolfSSL_NoTicketTLSv12(). An empty ticket counts as a ticket when the server would answer it with a new one, because the server then does not resume by the session ID either. test_tls12_ticket_declined_no_id_resumption puts a session ID the server has cached into a ClientHello carrying a ticket the server cannot use, for each of the three cases. It checks that the server does not resume. The wolfSSL_NoTicketTLSv12() case uses a ticket the server can decrypt. With WOLFSSL_DTLS_NO_HVR_ON_RESUME, the only build where the stateless check can resume, DTLS 1.2 runs of the three cases and of a cached session ID with an empty ticket also check that the server asks for a cookie. Each case fails without this change.
6195b8b to
7ea4866
Compare
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #12064
Scan targets checked: wolfssl-src, wolfssl-bugs
Not reviewed (no scan target covers them): tests/api/test_tls.h
Coverage: 1 of 2 in-scope changed file(s) opened by the reviewer; not opened: tests/api/test_tls.c
Fenrir result: Approved ✅
No new issues found in the changed files.
Advisory only — this automated result does not count as a GitHub approval.
Review tier: Lite
Fenrir's latest completed scan found no issues; clearing the prior automated change request.
Fix TLS 1.2 session ticket handling when a server declines the ticket, on both the client and the server side (RFC 5077 Section 3.4).
Client:
Server:
wolfSSL_NoTicketTLSv12(), or no ticket callback.WOLFSSL_DTLS_NO_HVR_ON_RESUME, the stateless ClientHello check uses the session ID only when there is no ticket, so a declined ticket no longer skips the cookie exchange.Tests:
test_tls12_resume_ticket_decline_fallbacknow keeps the server cache on and resumes a third connection by session ID.test_tls12_ticket_declined_no_id_resumptioncovers the three server cases, plus DTLS 1.2 withWOLFSSL_DTLS_NO_HVR_ON_RESUME.