PQ Crypta Logo

quiche — 425 (Too Early) in answer to a request sent as early data

The client does not do this, and said so itself — by what it advertised, or by refusing outright. A definite answer about the client, not a failure and not a gap.

PQ CRYPTA PLATFORM

🏠 Main

📰 News

👤 Account

⟨ QUANTUM ERROR PORTAL ⟩

Navigate the Error Dimensions

Jump to an anomaly59

Every one of these is a page: what the server emits, the clause it is judged against, and how each client answered. The full list carries the verdict tallies too.

Unsupported

does not deliver early data to an endpoint that negotiates versions, so it was never answered 425. It offered a GREASE QUIC version first, which this endpoint answered with Version Negotiation (RFC 8999 §6), and it did not re-offer early data on the v1 retry -- so the 0-RTT it intended never reached the wire. Both sides are conformant; the early data is lost between them.

The client does not do this, and said so itself — by what it advertised, or by refusing outright. A definite answer about the client, not a failure and not a gap.

Why the run landed here

quiche's early data is lost to its own version GREASE before the resumption is ever tried.

Same cause as q-zero-rtt-reject: the GREASEd QUIC version in the first flight draws Version Negotiation, the early data goes with it, and the retry carries none. Nothing was replayed because nothing was sent early.

Established separately from the run and recorded beside it, not in it: the verdict above is still only what the server could see. Measured by packet decode of the client's first flight, including coalesced packets; pqcrypta-proxy/src/conformance/listener.rs no_early_data(), 2026-09-19.

What was measured

Client
quiche — Cloudflare quiche, 0.30.0 (1c8e976)
Test
425 (Too Early) in answer to a request sent as early data — q-zero-rtt-replay
Clause
RFC 8470 §5.2 (SHOULD)
Class
discretionary — The RFC permits either behaviour; the report says which was chosen.
Required behaviour
Handle being told the request arrived too early. §5.2 says a user agent "SHOULD retry automatically, but any retries MUST NOT be sent in early data" — so retrying on the 1-RTT keys and handing the 425 back to the caller are both conformant, and the report says which happened. Falling over is not one of the options. This is the only port that *accepts* early data instead of refusing it, which is what makes the 425 exchange possible at all. What it does not check is §4's rule that unsafe methods must never be sent in early data: reading the method would mean QPACK-decoding the request, which this suite deliberately never does. Reaching it needs a session ticket from an earlier connection to this same port, so a client that connects once has none.
Measured
2026-10-27

Reproduce it

The suite is the judge, so the reproduction is to point the same client at the same test and let the server report what it saw.

SESSION=$(curl -sX POST https://conformance.pqcrypta.com/session | jq -r .id)
# then drive quiche at the test URL and read the verdict:
curl -s https://conformance.pqcrypta.com/report/$SESSION.json | jq '.results["q-zero-rtt-replay"]'