Stale ECH GREASE buffer corrupts HRR transcript
Categories
(NSS :: Libraries, defect, P2)
Tracking
(nss 3.126)
| Tracking | Status | |
|---|---|---|
| nss | --- | 3.126 |
People
(Reporter: jschanck, Assigned: jschanck)
Details
(Whiteboard: [nss-nofx])
Attachments
(1 file)
I encountered this while trying to write tests for mlkem1024 support in Firefox. Here's Claude's summary.
Affected component
lib/ssl/ — TLS 1.3 server, ECH HRR GREASE / stateless HRR cookie path.
Steps to reproduce
- Configure an NSS TLS 1.3 server that supports only a key-exchange group the client does not place first, so the server must send an HRR (e.g. a P-256-only or ML-KEM-1024-only server against a client that prefers X25519).
- Have the client offer an ECH extension — including default ECH GREASE, which is enabled by default in Firefox and other modern clients (SSL_EnableTls13GreaseEch).
- Complete the handshake on a single server socket (i.e. the normal stateless-cookie HRR recovery path; no fresh socket between CH1 and CH2).
Expected
Handshake completes: HRR requesting the server's group, client resends with the correct key share, connection established.
Actual
- Debug builds: assertion failure
Assertion failure: !ss->ssl3.hs.greaseEchBuf.len, at tls13con.c:2761
#04: tls13_ConstructHelloRetryRequest (tls13con.c:2762)
- Release builds: no crash and no memory unsafety, but the handshake fails (transcript-hash mismatch → bad Finished MAC / decrypt-error alert). The connection never completes.
Root cause
tls13_SendHelloRetryRequest (lib/ssl/tls13con.c) sets ss->ssl3.hs.greaseEchBuf to the 8-byte ECH HRR GREASE signal whenever ss->xtnData.ech is set, then constructs and sends the HRR. It never clears the buffer afterward.
The signal is preserved in the HRR cookie. On the second ClientHello, tls13_RecoverHashState (lib/ssl/tls13hashstate.c:303) calls tls13_ConstructHelloRetryRequest with the cookie's signal to rebuild the transcript:
if (cookieGreaseEchSignal) {
PORT_Assert(!ss->ssl3.hs.greaseEchBuf.len); /* tls13con.c:2761 */
rv = sslBuffer_Append(&ss->ssl3.hs.greaseEchBuf,
cookieGreaseEchSignal, TLS13_ECH_SIGNAL_LEN);
...
}
| Assignee | ||
Comment 1•2 months ago
|
||
Pushed by jschanck@mozilla.com:
https://hg.mozilla.org/projects/nss/rev/a9224ff7ae27
clear greaseEchBuf after constructing HRR. r=djackson
| Assignee | ||
Updated•1 month ago
|
Description
•