Skip to content

Add DTLS secondary cookie secret for app-driven rotation#10634

Open
julek-wolfssl wants to merge 1 commit into
wolfSSL:masterfrom
julek-wolfssl:dtls-secondary-cookie-secret
Open

Add DTLS secondary cookie secret for app-driven rotation#10634
julek-wolfssl wants to merge 1 commit into
wolfSSL:masterfrom
julek-wolfssl:dtls-secondary-cookie-secret

Conversation

@julek-wolfssl

Copy link
Copy Markdown
Member

Description

Add verify-only secondary cookie secrets for both DTLS 1.2 (HelloVerifyRequest) and DTLS 1.3 (HelloRetryRequest). A secondary secret is used only during cookie verification, and only if the primary secret fails to verify the cookie; it is never used to issue cookies.

This lets an application rotate the cookie secret on a stateless DTLS server without rejecting clients that received a cookie under the previous secret: after rotating the primary, the application installs the old secret as the secondary so in-flight cookies still verify for an overlap window (RFC 9147 Section 5.1).

Why two APIs

The DTLS 1.2 and 1.3 cookie mechanisms keep separate secrets and separate verify routines, set their primary secret through different APIs (wolfSSL_DTLS_SetCookieSecret for 1.2, wolfSSL_send_hrr_cookie for 1.3), and live under different build guards (a DTLS-1.2-only build has none of the TLS 1.3 / HRR machinery). So each version gets its own sibling API:

  • wolfSSL_set_hrr_cookie_secret_secondary() — DTLS 1.3. Per-connection and DTLS-only; returns BAD_FUNC_ARG for a non-DTLS or non-TLS-1.3 object, since TLS 1.3 over a reliable transport does not verify cookies statelessly across the HelloRetryRequest exchange.
  • wolfSSL_DTLS_SetCookieSecretSecondary() — DTLS 1.2, the counterpart of the above. NULL/0 clears it. A server handling both versions sets both secondary secrets.

Implementation

  • New per-SSL buffers tls13CookieSecretSecondary and dtlsCookieSecretSecondary, freed on SSL teardown (the 1.3 buffer is also freed in wolfSSL_disable_hrr_cookie()).
  • TlsCheckCookie() factors its HMAC compute/compare into TlsCheckCookieMac() and tries the primary secret, then the secondary on mismatch.
  • CreateDtls12Cookie() now takes the secret as parameters; CheckDtlsCookie() computes with the primary and retries with the secondary on mismatch.
  • Issuance (CreateCookieExt, SendHelloVerifyRequest) always uses the primary.

Testing

Tests cover, for both versions: a handshake where the cookie is accepted via the secondary after a rotation; a negative case where the signing secret has been rotated out of both slots; secondary clear behavior; primary still wins on the fast path; replacing the secondary activates the new value; secondary equal to primary is harmless; and issuance uses the primary, not the verify-only secondary. The 1.3 API additionally has NULL/side/version argument-validation coverage.

Copilot AI review requested due to automatic review settings June 8, 2026 14:12
@julek-wolfssl julek-wolfssl self-assigned this Jun 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 adds “verify-only” secondary cookie secrets for DTLS 1.2 (HelloVerifyRequest) and DTLS 1.3 (HelloRetryRequest) so applications can rotate the primary cookie secret on stateless servers without breaking in-flight handshakes.

Changes:

  • Introduces two new public APIs to configure a secondary cookie secret used only for verification (never for cookie issuance).
  • Updates DTLS 1.2 and DTLS 1.3 cookie verification paths to try the primary secret first, then the secondary on verification failure.
  • Adds API-level tests covering rotation overlap, drop/clear/replacement behavior, and argument/side validation.

Reviewed changes

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

Show a summary per file
File Description
wolfssl/ssl.h Adds public API declarations for DTLS 1.2 and DTLS 1.3 secondary cookie-secret setters.
wolfssl/internal.h Adds per-SSL secondary secret buffers for DTLS 1.2 cookies and DTLS 1.3 HRR cookies.
src/tls13.c Factors cookie MAC verification and adds secondary-secret fallback for DTLS 1.3 HRR cookie verification; adds wolfSSL_set_hrr_cookie_secret_secondary().
src/dtls.c Refactors DTLS 1.2 cookie generation to accept an explicit secret; adds secondary-secret fallback during cookie verification.
src/ssl.c Adds wolfSSL_DTLS_SetCookieSecretSecondary() API implementation and manages secondary secret lifetime.
src/internal.c Frees/zeroes the new secondary secret buffers during SSL teardown.
tests/api/test_dtls.h Registers new DTLS cookie secondary-secret tests.
tests/api/test_dtls.c Adds DTLS 1.2 + DTLS 1.3 memio tests for secondary-secret behavior and API validation.

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

Comment thread tests/api/test_dtls.c Outdated
Comment thread wolfssl/ssl.h
Comment thread wolfssl/ssl.h
Add verify-only secondary cookie secrets for both DTLS 1.2
(HelloVerifyRequest) and DTLS 1.3 (HelloRetryRequest). A secondary secret
is used only during cookie verification, and only if the primary secret
fails to verify the cookie; it is never used to issue cookies.

This lets an application rotate the cookie secret on a stateless DTLS
server without rejecting clients that received a cookie under the previous
secret: after rotating the primary, the application installs the old
secret as the secondary so in-flight cookies still verify for an overlap
window (RFC 9147 Section 5.1).

Two APIs rather than one. The 1.2 and 1.3 cookie mechanisms keep separate
secrets and separate verify routines, set their primary secret through
different APIs (wolfSSL_DTLS_SetCookieSecret for 1.2, wolfSSL_send_hrr_cookie
for 1.3), and live under different build guards (a DTLS-1.2-only build has
none of the TLS 1.3 / HRR machinery). So each version gets its own sibling
API:

- wolfSSL_set_hrr_cookie_secret_secondary() - DTLS 1.3. Per-connection and
  DTLS-only; returns BAD_FUNC_ARG for a non-DTLS or non-TLS-1.3 object,
  since TLS 1.3 over a reliable transport does not verify cookies
  statelessly across the HelloRetryRequest exchange.
- wolfSSL_DTLS_SetCookieSecretSecondary() - DTLS 1.2, the counterpart of
  the above. NULL/0 clears it. A server handling both versions sets both
  secondary secrets.

Details:
- New per-SSL buffers tls13CookieSecretSecondary and dtlsCookieSecretSecondary,
  freed on SSL teardown (the 1.3 buffer is also freed in
  wolfSSL_disable_hrr_cookie()).
- TlsCheckCookie() factors its HMAC compute/compare into TlsCheckCookieMac()
  and tries the primary secret, then the secondary on mismatch.
  CreateDtls12Cookie() now takes the secret as parameters; CheckDtlsCookie()
  computes with the primary and retries with the secondary on mismatch.
  Issuance (CreateCookieExt, SendHelloVerifyRequest) always uses the primary.

Tests cover, for both versions: a handshake where the cookie is accepted via
the secondary after a rotation; a negative case where the signing secret has
been rotated out of both slots; secondary clear behavior; primary still wins
on the fast path; replacing the secondary activates the new value;
secondary equal to primary is harmless; and issuance uses the primary, not
the verify-only secondary. The 1.3 API additionally has NULL/side/version
argument-validation coverage.
@julek-wolfssl julek-wolfssl force-pushed the dtls-secondary-cookie-secret branch from d19a0d3 to c218d94 Compare June 8, 2026 17:08
@julek-wolfssl julek-wolfssl marked this pull request as ready for review June 8, 2026 19:51
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

retest this please

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

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.

[Bug]: DTLS 1.3 Cookie Secret Rotation Window and Cookie Lifetime Policy Are Application-Managed

2 participants