Skip to content

TLS 1.3: gate 0-RTT on a cache-backed resumption ticket#10289

Open
julek-wolfssl wants to merge 1 commit intowolfSSL:masterfrom
julek-wolfssl:zd/21652
Open

TLS 1.3: gate 0-RTT on a cache-backed resumption ticket#10289
julek-wolfssl wants to merge 1 commit intowolfSSL:masterfrom
julek-wolfssl:zd/21652

Conversation

@julek-wolfssl
Copy link
Copy Markdown
Member

RFC 8446 section 8 requires any server instance to accept 0-RTT for a
given ClientHello at most once. Prior to this change wolfSSL's behaviour
diverged from that requirement in several ways:

  • ctx->maxEarlyDataSz defaulted to MAX_EARLY_DATA_SZ whenever the
    library was built with WOLFSSL_EARLY_DATA, so servers auto-
    advertised 0-RTT in NewSessionTicket without the application
    asking. RFC 8446 E.5 says 0-RTT MUST NOT be enabled unless
    specifically requested.
  • The post-accept eviction is compiled out under NO_SESSION_CACHE,
    so builds without the cache accepted 0-RTT with no replay defence.
  • Stateless self-encrypted tickets do not carry a session ID on the
    stateless DoClientTicket decrypt path, so wolfSSL_SSL_CTX_remove_
    session could not locate them to evict.
  • wolfSSL_SSL_CTX_remove_session always returned 0 on success
    regardless of whether the session was actually in the cache,
    diverging from OpenSSL's SSL_CTX_remove_session (1 on success,
    0 on not-found).

Changes:

  • src/internal.c: ctx->maxEarlyDataSz defaults to 0; applications
    must opt in with wolfSSL_CTX_set_max_early_data.
  • src/tls13.c: #error when WOLFSSL_EARLY_DATA is built with
    HAVE_SESSION_TICKET and NO_SESSION_CACHE. Escape hatch
    WOLFSSL_EARLY_DATA_NO_ANTI_REPLAY for deployments that take
    application-layer responsibility.
  • wolfssl/internal.h: imply WOLFSSL_TICKET_HAVE_ID from
    WOLFSSL_EARLY_DATA so stateless-ticket issuance populates the
    cache under an ID that eviction can find.
  • src/ssl_sess.c: wolfSSL_SSL_CTX_remove_session returns 1 when the
    session was found (internal-cache hit, or ctx->rem_sess_cb fired
    for an external cache), 0 otherwise. Matches OpenSSL semantics.
  • src/tls13.c: the 0-RTT acceptance condition in CheckPreSharedKeys
    now calls wolfSSL_SSL_CTX_remove_session and checks its return:
    the eviction is the check. If the session was in the cache, 0-RTT
    is accepted and the single-use requirement is satisfied. If not,
    the early_data extension is rejected through the normal path so
    the record layer correctly skips in-flight 0-RTT records.
    WOLFSSL_MSG at each rejection site.
  • doc/dox_comments/header_files/ssl.h: document runtime opt-in.
  • tests: four new tests —
    test_tls13_0rtt_default_off (fails without default-to-0 fix),
    test_tls13_0rtt_stateless_replay (fails without TICKET_HAVE_ID
    implication and remove_session gate),
    test_tls13_remove_session_return (fails without return-value fix),
    test_tls13_0rtt_ext_cache_eviction (fails without ext-cache
    counts-as-found fix).
    test_tls13_early_data explicitly opts in via
    wolfSSL_CTX_set_max_early_data.
    tests/api.c: two SSL_CTX_remove_session == 0 assertions updated
    to == 1.

Copilot AI review requested due to automatic review settings April 23, 2026 14:13
@julek-wolfssl julek-wolfssl self-assigned this Apr 23, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 23, 2026

MemBrowse Memory Report

No memory changes detected for:

Copy link
Copy Markdown
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

This PR aligns wolfSSL’s TLS 1.3 0-RTT behavior with RFC 8446 by making early data opt-in, requiring a cache-backed eviction for single-use tickets, and matching OpenSSL semantics for session removal.

Changes:

  • Default server ctx->maxEarlyDataSz to 0 and document runtime opt-in for 0-RTT.
  • Gate 0-RTT acceptance on successful cache eviction (wolfSSL_SSL_CTX_remove_session) and enforce build-time constraints when anti-replay can’t work.
  • Adjust wolfSSL_SSL_CTX_remove_session return semantics and add tests covering default-off, replay prevention, and external cache behavior.

Reviewed changes

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

Show a summary per file
File Description
src/internal.c Defaults early data opt-in setting to off (maxEarlyDataSz = 0).
src/tls13.c Adds build-time guardrails, logs rejection reasons, and gates 0-RTT acceptance on eviction success.
src/ssl_sess.c Changes wolfSSL_SSL_CTX_remove_session to return OpenSSL-compatible found/not-found status.
wolfssl/internal.h Forces WOLFSSL_TICKET_HAVE_ID when early data + tickets are enabled to support eviction keys.
doc/dox_comments/header_files/ssl.h Documents default-off behavior and explicit opt-in requirement for early data.
tests/api/test_tls13.h Registers new TLS 1.3 0-RTT and remove-session tests.
tests/api/test_tls13.c Adds new tests and updates existing early-data test to explicitly opt in.
tests/api.c Updates assertions for new SSL_CTX_remove_session return semantics.

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

Comment thread src/tls13.c
Comment thread src/ssl_sess.c Outdated
@julek-wolfssl julek-wolfssl force-pushed the zd/21652 branch 2 times, most recently from 52d62bb to 29cfc1e Compare April 24, 2026 12:49
@julek-wolfssl
Copy link
Copy Markdown
Member Author

retest this please no history

RFC 8446 section 8 requires any server instance to accept 0-RTT for a
given ClientHello at most once. Prior to this change wolfSSL's behaviour
diverged from that requirement in several ways:

  * ctx->maxEarlyDataSz defaulted to MAX_EARLY_DATA_SZ whenever the
    library was built with WOLFSSL_EARLY_DATA, so servers auto-
    advertised 0-RTT in NewSessionTicket without the application
    asking. RFC 8446 E.5 says 0-RTT MUST NOT be enabled unless
    specifically requested.
  * The post-accept eviction is compiled out under NO_SESSION_CACHE,
    so builds without the cache accepted 0-RTT with no replay defence.
  * Stateless self-encrypted tickets do not carry a session ID on the
    stateless DoClientTicket decrypt path, so wolfSSL_SSL_CTX_remove_
    session could not locate them to evict.
  * wolfSSL_SSL_CTX_remove_session always returned 0 on success
    regardless of whether the session was actually in the cache,
    diverging from OpenSSL's SSL_CTX_remove_session (1 on success,
    0 on not-found).

Changes:
  * src/internal.c: ctx->maxEarlyDataSz defaults to 0; applications
    must opt in with wolfSSL_CTX_set_max_early_data.
  * src/tls13.c: #error when WOLFSSL_EARLY_DATA is built with
    HAVE_SESSION_TICKET and NO_SESSION_CACHE. Escape hatch
    WOLFSSL_EARLY_DATA_NO_ANTI_REPLAY for deployments that take
    application-layer responsibility.
  * wolfssl/internal.h: imply WOLFSSL_TICKET_HAVE_ID from
    WOLFSSL_EARLY_DATA so stateless-ticket issuance populates the
    cache under an ID that eviction can find.
  * src/ssl_sess.c: wolfSSL_SSL_CTX_remove_session returns 1 when the
    session was found (internal-cache hit, or ctx->rem_sess_cb fired
    for an external cache), 0 otherwise. Matches OpenSSL semantics.
  * src/tls13.c: the 0-RTT acceptance condition in CheckPreSharedKeys
    now calls wolfSSL_SSL_CTX_remove_session and checks its return:
    the eviction is the check. If the session was in the cache, 0-RTT
    is accepted and the single-use requirement is satisfied. If not,
    the early_data extension is rejected through the normal path so
    the record layer correctly skips in-flight 0-RTT records.
    WOLFSSL_MSG at each rejection site.
  * doc/dox_comments/header_files/ssl.h: document runtime opt-in.
  * tests: four new tests —
    test_tls13_0rtt_default_off (fails without default-to-0 fix),
    test_tls13_0rtt_stateless_replay (fails without TICKET_HAVE_ID
    implication and remove_session gate),
    test_tls13_remove_session_return (fails without return-value fix),
    test_tls13_0rtt_ext_cache_eviction (fails without ext-cache
    counts-as-found fix).
    test_tls13_early_data explicitly opts in via
    wolfSSL_CTX_set_max_early_data.
    tests/api.c: two SSL_CTX_remove_session == 0 assertions updated
    to == 1.
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