Default build without WOLFSSL_SEND_HRR_COOKIE does not echo HRR cookies
Verdict
- Verdict:
issue_found
- Confidence:
high
- Record ID:
cand-11762dbda8b8-missing
Problem Description
In the tested wolfSSL TLS 1.3 client build, WOLFSSL_SEND_HRR_COOKIE is not defined. When a server sends a HelloRetryRequest that contains a cookie extension and requests a changed key share, the client sends a follow-up ClientHello but omits the required cookie extension. RFC 8446 requires the client to copy the server-provided HRR cookie into that new ClientHello. A separate control build with WOLFSSL_HRR_COOKIE=yes does echo the cookie, so the confirmed issue is scoped to builds where the HRR cookie path is compiled out.
Standard Requirement
When sending the new ClientHello, the client MUST copy
the contents of the extension received in the HelloRetryRequest into
a "cookie" extension in the new ClientHello.
Interpretation:
When sending the new ClientHello the client MUST copy the contents of the extension received in the HelloRetryRequest into a "cookie" extension in the new ClientHello..
Relevant Source Code
wolfSSL implements HRR cookie parse/save/write support only when WOLFSSL_SEND_HRR_COOKIE is defined. The tested client build leaves that macro undefined, which turns the cookie parse/write helpers into no-ops and also gates TLSX_COOKIE emission from ClientHello extension serialization.
src/tls13.c:34-39
*
* Handshake:
* WOLFSSL_TLS13_MIDDLEBOX_COMPAT: Enable middlebox compatibility default: on
* Sends ChangeCipherSpec and includes session id
* WOLFSSL_SEND_HRR_COOKIE: Send cookie in HelloRetryRequest default: off
* for stateless ClientHello tracking
The TLS 1.3 build-options comment documents WOLFSSL_SEND_HRR_COOKIE as default off.
src/tls.c:7506-7510
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_SEND_HRR_COOKIE)
/******************************************************************************/
/* Cookie */
/******************************************************************************/
The Cookie extension implementation is compiled only when both WOLFSSL_TLS13 and WOLFSSL_SEND_HRR_COOKIE are defined.
src/tls.c:7552-7560
static int TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType,
word16* pSz)
{
if (msgType == client_hello || msgType == hello_retry_request) {
c16toa(cookie->len, output);
output += OPAQUE16_LEN;
XMEMCPY(output, cookie->data, cookie->len);
*pSz += OPAQUE16_LEN + cookie->len;
}
When the macro is enabled, TLSX_Cookie_Write serializes the Cookie extension body into ClientHello or HelloRetryRequest.
src/tls.c:7600-7603
if (msgType == hello_retry_request) {
ssl->options.hrrSentCookie = 1;
return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 1,
&ssl->extensions);
When parsing a HelloRetryRequest cookie with the macro enabled, wolfSSL marks hrrSentCookie and stores the cookie through TLSX_Cookie_Use().
src/tls.c:7689-7696
#else
#define CKE_FREE_ALL(a, b) WC_DO_NOTHING
#define CKE_GET_SIZE(a, b, c) 0
#define CKE_WRITE(a, b, c, d) 0
#define CKE_PARSE(a, b, c, d) 0
#endif
When WOLFSSL_SEND_HRR_COOKIE is not defined, the cookie get-size, write, and parse hooks become no-ops.
src/tls.c:17720-17722
#ifdef WOLFSSL_SEND_HRR_COOKIE
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
#endif
ClientHello extension serialization only permits TLSX_COOKIE when WOLFSSL_SEND_HRR_COOKIE is defined.
src/tls13.c:6070-6075
/* Check if the HRR contained a cookie or a keyshare */
if (!ssl->options.hrrSentKeyShare
#ifdef WOLFSSL_SEND_HRR_COOKIE
&& !ssl->options.hrrSentCookie
#endif
) {
The client-side HRR acceptance check only considers hrrSentCookie when WOLFSSL_SEND_HRR_COOKIE is defined; otherwise a key_share change can allow the HRR path to continue without retaining the cookie.
Runtime Evidence
Round 1
- Test target: default wolfSSL client build from
harness-build/cmake-mingw-examples-psk/examples/client/client.exe.
- Build configuration:
WOLFSSL_SEND_HRR_COOKIE is not defined and WOLFSSL_HRR_COOKIE=undefined.
- Harness: TLS-Attacker server workflow
tasks/cand-11762dbda8b8-missing-default-no-macro-user-rerun/runtime-artifacts/tlsattacker-workflow.xml.
- Server action: send a TLS 1.3 HelloRetryRequest containing Cookie extension value
AA BB CC DD 01 02 03 04 and request a changed key_share group.
- Positive control: passed. TLS-Attacker captured two ClientHello messages, showing that wolfSSL accepted the HRR path far enough to generate a follow-up ClientHello instead of aborting before retry.
- Reproducer: passed. The first ClientHello had key_share group
00 1D; the second ClientHello changed key_share to 00 17, confirming this was a real HRR retry. However, the second ClientHello had cookie_present=false.
- Wire observation: the second ClientHello extension bytes did not contain extension type
00 2C and did not contain the expected cookie bytes AA BB CC DD 01 02 03 04.
- Runtime result: TLS-Attacker completed the server script with exit code
0; wolfSSL exited with wolfSSL_connect error -308, after sending the non-compliant second ClientHello.
- Artifact:
tasks/cand-11762dbda8b8-missing-default-no-macro-user-rerun/runtime-artifacts/summary.json.
Round 2
- Test target: separate control build from
harness-build/cmake-mingw-examples-psk-hrrcookie.
- Build configuration: CMake was run with
-DWOLFSSL_HRR_COOKIE=yes, which defines WOLFSSL_SEND_HRR_COOKIE.
- Harness: same HRR-cookie scenario, adjusted to a legal
SECP384R1 HelloRetryRequest so the selected group differs from the original ClientHello key_share.
- Positive control: passed. TLS-Attacker again captured two ClientHello messages.
- Control result: passed. In this enabled build, the second ClientHello had
cookie_present=true.
- Wire observation: the second ClientHello extension bytes contained
00 2C 00 0A 00 08 AA BB CC DD 01 02 03 04, i.e. a Cookie extension with the exact HRR cookie value.
- Artifact:
tasks/cand-11762dbda8b8-missing-hrrcookie-enabled-secp384r1/runtime-artifacts/summary.json.
Inconsistency Reason
RFC 8446 requires the client to copy a HelloRetryRequest cookie into the new ClientHello. In the no-macro build, wolfSSL accepts the HRR because the key_share changes, but the HRR cookie is not saved or written into the follow-up ClientHello. The enabled-macro control demonstrates that the missing echo is caused by the compiled-out HRR cookie path.
Decision Reason
The current tested build does not define WOLFSSL_SEND_HRR_COOKIE. Static review shows that this compiles HRR cookie parse/save/write hooks into no-ops and prevents TLSX_COOKIE from being emitted in ClientHello. Runtime reproduction with that build observed a second ClientHello after a cookie-bearing HRR with no cookie extension. A control build with WOLFSSL_HRR_COOKIE=yes echoed the same cookie, confirming the behavior is configuration-dependent but real for the default/no-macro build under test.
Default build without WOLFSSL_SEND_HRR_COOKIE does not echo HRR cookies
Verdict
issue_foundhighcand-11762dbda8b8-missingProblem Description
In the tested wolfSSL TLS 1.3 client build, WOLFSSL_SEND_HRR_COOKIE is not defined. When a server sends a HelloRetryRequest that contains a cookie extension and requests a changed key share, the client sends a follow-up ClientHello but omits the required cookie extension. RFC 8446 requires the client to copy the server-provided HRR cookie into that new ClientHello. A separate control build with WOLFSSL_HRR_COOKIE=yes does echo the cookie, so the confirmed issue is scoped to builds where the HRR cookie path is compiled out.
Standard Requirement
Interpretation:
When sending the new ClientHello the client MUST copy the contents of the extension received in the HelloRetryRequest into a "cookie" extension in the new ClientHello..
Relevant Source Code
wolfSSL implements HRR cookie parse/save/write support only when WOLFSSL_SEND_HRR_COOKIE is defined. The tested client build leaves that macro undefined, which turns the cookie parse/write helpers into no-ops and also gates TLSX_COOKIE emission from ClientHello extension serialization.
src/tls13.c:34-39The TLS 1.3 build-options comment documents WOLFSSL_SEND_HRR_COOKIE as default off.
src/tls.c:7506-7510The Cookie extension implementation is compiled only when both WOLFSSL_TLS13 and WOLFSSL_SEND_HRR_COOKIE are defined.
src/tls.c:7552-7560When the macro is enabled, TLSX_Cookie_Write serializes the Cookie extension body into ClientHello or HelloRetryRequest.
src/tls.c:7600-7603When parsing a HelloRetryRequest cookie with the macro enabled, wolfSSL marks hrrSentCookie and stores the cookie through TLSX_Cookie_Use().
src/tls.c:7689-7696When WOLFSSL_SEND_HRR_COOKIE is not defined, the cookie get-size, write, and parse hooks become no-ops.
src/tls.c:17720-17722ClientHello extension serialization only permits TLSX_COOKIE when WOLFSSL_SEND_HRR_COOKIE is defined.
src/tls13.c:6070-6075The client-side HRR acceptance check only considers hrrSentCookie when WOLFSSL_SEND_HRR_COOKIE is defined; otherwise a key_share change can allow the HRR path to continue without retaining the cookie.
Runtime Evidence
Round 1
harness-build/cmake-mingw-examples-psk/examples/client/client.exe.WOLFSSL_SEND_HRR_COOKIEis not defined andWOLFSSL_HRR_COOKIE=undefined.tasks/cand-11762dbda8b8-missing-default-no-macro-user-rerun/runtime-artifacts/tlsattacker-workflow.xml.AA BB CC DD 01 02 03 04and request a changed key_share group.00 1D; the second ClientHello changed key_share to00 17, confirming this was a real HRR retry. However, the second ClientHello hadcookie_present=false.00 2Cand did not contain the expected cookie bytesAA BB CC DD 01 02 03 04.0; wolfSSL exited withwolfSSL_connect error -308, after sending the non-compliant second ClientHello.tasks/cand-11762dbda8b8-missing-default-no-macro-user-rerun/runtime-artifacts/summary.json.Round 2
harness-build/cmake-mingw-examples-psk-hrrcookie.-DWOLFSSL_HRR_COOKIE=yes, which definesWOLFSSL_SEND_HRR_COOKIE.SECP384R1HelloRetryRequest so the selected group differs from the original ClientHello key_share.cookie_present=true.00 2C 00 0A 00 08 AA BB CC DD 01 02 03 04, i.e. a Cookie extension with the exact HRR cookie value.tasks/cand-11762dbda8b8-missing-hrrcookie-enabled-secp384r1/runtime-artifacts/summary.json.Inconsistency Reason
RFC 8446 requires the client to copy a HelloRetryRequest cookie into the new ClientHello. In the no-macro build, wolfSSL accepts the HRR because the key_share changes, but the HRR cookie is not saved or written into the follow-up ClientHello. The enabled-macro control demonstrates that the missing echo is caused by the compiled-out HRR cookie path.
Decision Reason
The current tested build does not define WOLFSSL_SEND_HRR_COOKIE. Static review shows that this compiles HRR cookie parse/save/write hooks into no-ops and prevents TLSX_COOKIE from being emitted in ClientHello. Runtime reproduction with that build observed a second ClientHello after a cookie-bearing HRR with no cookie extension. A control build with WOLFSSL_HRR_COOKIE=yes echoed the same cookie, confirming the behavior is configuration-dependent but real for the default/no-macro build under test.