t-hybrid-share-length
· draft-kwiatkowski-tls-ecdhe-mlkem §3.1.2, RFC 8446 §6.2, RFC 9001 §4.8 · correctness · layer tls · udp/4517 · MUST
Passing this means: Rejected something invalid, with the code the RFC names.
Anomaly type: transport
How each client answered
| Client | Version | Verdict | What happened |
|---|---|---|---|
| curl | ngtcp2/1.11.0 | Not run | Not attempted. |
| quinn | noq fork | Inconclusive | The handshake did not complete, which it could not have done with half the shared secret missing, but nothing arrived to say the client rejected the length deliberately. A close that was never sent and one that was lost look the same from here. |
| aioquic | 1.3.0 | Not run | Not attempted. |
| chromium | build 1223 | Pass | Responded correctly: aborted the handshake with TLS alert 80 rather than illegal_parameter. §3.1.2 requires the abort and RFC 9001 §4.8 permits replacing the alert over QUIC, so the code is reported and not judged -- though note that a truncated share also breaks the key schedule, so this abort does not on its own show the length was what the client objected to. |
| quic-go | quic-go v0.61.0 | Pass | Responded correctly: aborted with illegal_parameter (alert 47) over a server share of the wrong length for X25519MLKEM768, which is the check §3.1.2 asks the client to make and the code it names. |
| quiche | 0.30.0 | Pass | Responded correctly: aborted the handshake with TLS alert 80 rather than illegal_parameter. §3.1.2 requires the abort and RFC 9001 §4.8 permits replacing the alert over QUIC, so the code is reported and not judged -- though note that a truncated share also breaks the key schedule, so this abort does not on its own show the length was what the client objected to. |
| neqo | 0.31.1 | Pass | Responded correctly: aborted with illegal_parameter (alert 47) over a server share of the wrong length for X25519MLKEM768, which is the check §3.1.2 asks the client to make and the code it names. |
| picoquic | 8162550 | Inconclusive | The handshake ended (aborted by peer: the endpoint encountered an internal error and cannot continue with the connection) without a CONNECTION_CLOSE carrying a TLS alert. The share was certainly not used, but nothing shows whether its length was what the client objected to. |
| ngtcp2 | 3c23148 | Pass | Responded correctly: aborted the handshake with TLS alert 80 rather than illegal_parameter. §3.1.2 requires the abort and RFC 9001 §4.8 permits replacing the alert over QUIC, so the code is reported and not judged -- though note that a truncated share also breaks the key schedule, so this abort does not on its own show the length was what the client objected to. |
| lsquic | 4.9.4 | Inconclusive | The handshake did not complete, which it could not have done with half the shared secret missing, but nothing arrived to say the client rejected the length deliberately. A close that was never sent and one that was lost look the same from here. |
| xquic | 2060a44 | Pass | Responded correctly: aborted the handshake with TLS alert 40 rather than illegal_parameter. §3.1.2 requires the abort and RFC 9001 §4.8 permits replacing the alert over QUIC, so the code is reported and not judged -- though note that a truncated share also breaks the key schedule, so this abort does not on its own show the length was what the client objected to. |
| msquic | 2.7.0 | Not run | Not attempted. |
What the clause requires
Abort rather than proceed. §3.1.2 is explicit: "For all groups, the client MUST check if the ciphertext length matches the selected group, and abort with an illegal_parameter alert if it fails." The port sends 1,088 bytes where X25519MLKEM768 fixes the server share at 1,120 — the ML-KEM ciphertext whole and the 32-byte X25519 tail removed. It parses cleanly as an opaque vector, so the only thing wrong with it is its length for the group it is named with. Neither outcome lets a client derive our keys, because the shared secret needs both halves. What separates them is where it notices: a client that checks the length rejects this at the ServerHello, while one that does not carries a truncated share into decapsulation and fails later and less clearly. What is judged is the abort, not the alert value. RFC 9001 §4.8 lets a QUIC endpoint replace any alert with a generic one, so the code a client chooses is reported and not scored — and a handshake that ends with no CONNECTION_CLOSE at all is inconclusive rather than a failure, because a close that was never sent cannot be told from one that was lost.
Judged against RFC 8446, RFC 9001.
Run this one yourself
Every test is reachable from your own client. Nothing here needs an account.
curl -s https://conformance.pqcrypta.com/catalog.json \
| jq '.tests[] | select(.id == "t-hybrid-share-length")'
What this suite is · The full grid · All clients · All tests · Findings