QUIC Version 2
Extracted elements (27)
Clients initiating a connection with version 2 to combat middlebox ossification must be reasonably certain the server supports it, or accept a round-trip penalty. A server issuing a version 2 session ticket signals intent to maintain version 2 support for the ticket's lifetime.
QUIC version 2 is not intended to deprecate version 1, and the two are defined as mutually compatible versions under RFC 9368. Servers are encouraged to support both simultaneously to maximize compatibility, especially for HTTP/3 via Alt-Svc.
QUIC version 2's primary purpose is to combat ossification: middleboxes that assume long headers always encode version 1, or that the version 1 Initial key derivation is version-invariant, will not correctly process version 2 packets, forcing them to handle QUIC generically.
The wire version number 0x6b3343cf is randomly chosen rather than being the integer 2, and the Long Header packet type bits differ from version 1. Both choices are intentional anti-ossification measures rather than strict requirements for any new QUIC version.
All ALPN codepoints specified to operate over QUIC version 1 can also operate over QUIC version 2, including "h3" (HTTP/3) and "doq" (DNS over QUIC). All QUIC extensions defined for version 1 also work with version 2 unless otherwise stated.
The Alt-Svc mechanism (RFC 7838) does not currently distinguish between QUIC versions, meaning HTTP servers advertising "h3" should support QUIC version 1 because some clients only implement that version.
After switching to a negotiated version following a Retry, the server MUST include the relevant transport parameters to validate the server sent the Retry and the connection IDs used in the exchange, as described in RFC 9000 Section 7.3.
Any QUIC endpoint that supports QUIC version 2 MUST send, process, and validate the version_information transport parameter specified in RFC 9368 to prevent version downgrade attacks.
Both endpoints MUST send Handshake and 1-RTT packets using the negotiated version. An endpoint MUST drop packets using any other version. Endpoints have no need to generate keying material to decrypt or authenticate such packets.
Clients MUST NOT use a session ticket or NEW_TOKEN token from a QUIC version 1 connection to initiate a QUIC version 2 connection, and vice versa. Tokens from compatible version negotiation are attributed to the negotiated version.
Endpoints that support both QUIC versions 1 and 2 SHOULD support compatible version negotiation to avoid a round trip, since version 2 meets the RFC 9368 definition of a compatible version with version 1.
HTTP servers SHOULD support multiple QUIC versions to reduce the probability of incompatibility and the cost associated with version negotiation or TCP fallback, since Alt-Svc does not currently distinguish between QUIC versions.
If the server sends a Retry packet during compatible negotiation, it MUST use the original version. The client MUST NOT use a different version in the subsequent Initial packet containing the Retry token.
QUIC version 2 endpoints MUST implement the QUIC version 1 specification as described in RFC 9000, RFC 9001, and RFC 9002, except for the specific differences enumerated in Section 3.
Servers MUST validate the originating version of any session ticket or token and not accept one issued from a different version. A rejected ticket falls back to a full TLS handshake; a rejected token leaves the client address unverified.
The client MUST NOT send 0-RTT packets using the negotiated version, even after processing a packet of that version from the server. Servers can accept 0-RTT and process 0-RTT packets from the original version.
The server MUST NOT discard its original version Initial receive keys until it successfully processes a Handshake packet with the negotiated version.
The server MUST send all CRYPTO frames using the negotiated version. The server cannot send CRYPTO frames until it has processed the client's transport parameters.
HKDF labels for packet protection keys, header protection keys, Retry Integrity Tag keys, and key updates change from the "quic *" prefix to "quicv2 *": "quicv2 key", "quicv2 iv", "quicv2 hp", and "quicv2 ku".
The client learns the negotiated version by observing the first long header Version field that differs from the original version. Receipt of a CRYPTO frame from the server in the original version indicates the negotiated version equals the original version.
IANA has added two entries to the "QUIC Versions" registry: 0x6b3343cf (permanent, RFC 9369) as the QUIC version 2 wire value, and 0x709a50c4 (provisional, RFC 9369) as the QUIC v2 draft codepoint.
Support for QUIC version 2 can help an observer fingerprint both client and server devices, since version 2 support reveals implementation-specific characteristics.
The mandatory version_information transport parameter mechanism guards against version downgrade attacks. However, downgrades between versions 1 and 2 carry no security implication because both versions have identical security properties.
QUIC version 2 reassigns all Long Header packet type bits: Initial=0b01, 0-RTT=0b10, Handshake=0b11, Retry=0b00. All four values differ from their QUIC version 1 counterparts.
The Initial packet salt for key derivation changes to 0x0dede3def700a6db819381be6e269dcbf9bd2ed9 (first 20 bytes of sha256sum of "QUICv2 salt"), replacing the version 1 salt used in RFC 9001 Section 5.2.
The Retry Integrity Tag uses a new secret (sha256sum of "QUICv2 retry secret"), key 0x8fb4b01b56ac48e260fbcbcead7ccc92, and nonce 0xd86969bc2d7c6d9990efb04a, derived with labels "quicv2 key" and "quicv2 iv".
The Version field in QUIC version 2 long headers is 0x6b3343cf, derived as the first four bytes of the sha256sum of "QUICv2 version number". This replaces the version 1 value of 0x00000001.