14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here.  2.  If A and B are two distinct versions of QUIC, A is said to be "compatible" with B if it is possible to take a first flight of packets from version A and convert it into a first flight of packets much later - in that scenario one endpoint might be aware of the compatibility document while the other may not. <del> 3. </del>  This document specifies two means of performing version negotiation: one "incompatible" which requires a round trip and is applicable to The client initiates a QUIC connection by sending a first flight of QUIC packets with a long header to the server INV.  We'll refer to the version of those packets as the "original version".  The client's <del> first flight includes handshake version information (see hs-vers- info) which will be used to optionally enable compatible version negotation (see compat-vn), and to prevent version downgrade attacks (see downgrade). </del>  Upon receiving this first flight, the server verifies whether it knows how to parse first flights from the original version.  If it parse first flight packets but not enough to fully establish a connection using that version. <del> 3.1. </del>  QUIC connections are shared state between a client and a server INV. The compatible version negotiation mechanism defined in this document across two QUIC connections: one before the Version Negotiation packet, and a distinct connection after. <del> 3.2. </del>  <del> The server starts incompatible version negotiation by sending a VN packet, listing all the versions that it does support. </del>  Upon receiving the VN packet, the client will search for a version it supports in the list provided by the server.  If it doesn't find one, The new first flight will allow the endpoints to establish a connection using the negotiated version.  The handshake of the <del> negotiated version will exchange handshake version information (see hs-vers-info) required to ensure that VN was genuine, i.e. that no attacker injected packets in order to influence the VN process, see downgrade. </del>  <del> 3.3. </del>  When the server can parse the client's first flight using the <del> original version, it can extract the client's handshake version information (see hs-vers-info).  This contains the list of versions that the client thinks its first flight is compatible with. </del>  If the server supports one of the client's compatible versions, and the server also believes that the original version is compatible with load balancers to ensure that packets for a given connection are routed to the same server. <del> 4. </del>  <del> During the handshake, endpoints will exchange handshake version information, which is a blob of data that is defined below.  In QUIC version 1, the handshake version information is transmitted using a new transport parameter, "version_negotiation".  The contents of handshake version information depend on whether the client or server is sending it, and are shown below (using the notation from the "Notational Conventions" section of QUIC): </del>  The content of each field is described below: <del> The version that the client is attempting to use.  This field MUST be equal to the value of the Version field in the long header that carries this data. If the client is sending this first flight in response to a Version Negotiation packet, this field contains the version that the client used in the previous first flight that triggered the version negotiation packet.  If the client did not receive a Version Negotiation packet, this field SHALL be all-zeroes. A variable-length integer specifying the number of Received Negotiation Version fields following it.  If the client is sending this first flight in response to a Version Negotiation packet, the subsequent versions SHALL include all the versions from that Version Negotiation packet in order, even if they are not supported by the client (even if the versions are reserved).  If the client has not received a Version Negotiation packet on this connection, this field SHALL be 0. A variable-length integer specifying the number of Compatible Version fields following it.  The client lists all versions that this first flight is compatible with in the subsequent Compatible Version fields, ordered by descending preference.  Note that the version in the Currently Attempted Version field MUST be included in the Compatible Version list to allow the client to communicate the currently attempted version's preference.  Note that this preference is only advisory, servers MAY choose to use their own preference instead. </del>  <del> The content of each field is described below: </del>  <del> The version that the server chose to use for the connection.  This field MUST be equal to the value of the Version field in the long header that carries this data. A variable-length integer specifying the number of Supported Version fields following it.  The server encodes all versions it supports in the subsequent list, ordered by descending preference. Note that the version in the Negotiated Version field MUST be included in the Supported Version list to allow the server to communicate the negotiated version's preference.  Note that this preference is only advisory, clients MAY choose to use their own </del>  preference instead. <del> Clients MAY include versions following the pattern "0x?a?a?a?a" in their "Compatible Version" list, and the server in their "Supported Version" list.  Those versions are reserved to exercise version negotiation (see the Versions section of QUIC), and will be ignored when parsing these fields.  On the other hand, the "Received Negotiation Version" list MUST be identical to the received Version Negotiation packet, so clients MUST NOT add or remove reserved version from that list. </del>  <del> 5. </del>  Clients MUST ignore any received Version Negotiation packets that contain the version that they initially attempted.  Once a client has reacted to a Version Negotiation packet, it MUST drop all subsequent Version Negotiation packets on that connection. <del> Servers MUST validate that the client's "Currently Attempted Version" matches the version in the long header that carried the handshake version information.  Similarly, clients MUST validate that the server's "Negotiated Version" matches the long header version.  If an endpoint's validation fails, it MUST close the connection.  If the connection was using QUIC version 1, it MUST be closed with a transport error of type "VERSION_NEGOTIATION_ERROR". When a server parses the client's handshake version information, if the "Received Negotiation Version Count" is not zero, the server MUST validate that it could have sent the Version Negotation packet described by the client in response to a first flight of version "Previously Attempted Version".  In particular, the server MUST ensure that there are no versions that it supports that are absent from the Received Negotiation Versions, and that the ordering matches the server's preference.  If this validation fails, the server MUST close the connection.  If the connection was using QUIC version 1, it MUST be closed with a transport error of type "VERSION_NEGOTIATION_ERROR".  This mitigates an attacker's ability to forge Version Negotiation packets to force a version downgrade. If a server operator is progressively deploying a new QUIC version throughout its fleet, it MAY perform a two-step process where it first progressively adds support for the new version, but without enforcing its presence in "Received Negotiation Versions".  Once all servers have been upgraded, the second step is to start enforcing that the new version is present in "Received Negotiation Versions". This opens connections to version downgrades during the upgrade window, since those could be due to clients communicating with both upgraded and non-upgraded servers. If an endpoint receives its peer's Handshake Version Information and fails to parse it (for example, if it is too short), then the endpoint MUST close the connection.  If the connection was using QUIC version 1, it MUST be closed with a transport error of type "TRANSPORT_PARAMETER_ERROR". 6. The server's "Supported Version" list allows it to communicate the full list of versions it supports to the client.  In the case where clients initially attempt connections with the oldest version they support, this allows them to be notified of more recent versions the server supports.  If the client notices that the server supports a version that is more preferable that the one initially attempted by default, the client SHOULD cache that information and attempt the preferred version in subsequent connections. </del>  7. validate the client's IP address before parsing the client's first flight.  This impacts compatible version negotiation because a server who wishes to send a retry packet before parsing the client's first <del> flight won't have parsed the client's handshake version information yet.  If a future document wishes to define compatibility between two versions that support retry, that document MUST specify how version </del>  negotiation (both compatible and incompatible) interacts with retry during a handshake that requires both.  For example, that could be accomplished by having the server send a retry packet first and 11. The security of this version negotiation mechanism relies on the <del> authenticity of the handshake version information exchanged during the handshake.  In QUIC version 1, transport parameters are authenticated ensuring the security of this mechanism.  Negotiation between compatible versions will have the security of the weakest common version. </del>  The requirement that versions not be assumed compatible mitigates the possibility of cross-protocol attacks, but more analysis is still needed here. <del> The presence of the "Attempted Version" and "Negotiated Version" fields mitigates an attacker's ability to forge packets by altering the version. </del> 12. 12.1.

This PR simplifies the document's design. The new simplified design was by NAME . It removes the indication of server versions that everyone seemed to think was useless, but apart from that has very similar properties to the previous design. One important difference is that it is now the client's responsibility to detect VN-packet-based downgrade attacks instead of the server's. .
In , NAME points out that the backticks don't render nicely in the TXT version, so let's remove them
In , NAME mentioned that having the client communicate preference ordering between compatible versions isn't absolutely necessary. This issue tracks whether we want to keep this ordering or not.
During the IETF QUIC WG meeting there was (weak-ish) consensus that this useful to keep.
The strongest argument against this was that it doesn't give the server a full ordering, because it doesn't tell the server where the offered version falls in the preference list. There's a possible answer to that, which is that the client should only offer compatible versions which are more preferred than the currently offered version. However, we should explicitly state that the server makes the actual decision and MAY factor client preferences into that. I suspect most won't.
NAME that's incorrect. The offered version is present in the list.
Ah, thanks for correcting me. Then we're spending bytes to repeat the version number, which we don't expect servers will typically use. Not the end of the world either way.
Consensus established. Closing this issue with no action.
Almost there, but I think we need clarity on the clients verification-and-drop requirements.

14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. <ins> In this document, the Maximum Segment Lifetime (MSL) represents the time a QUIC packet can exist in the network.  Implementations can make this configurable, and a RECOMMENDED value is one minute. </ins> 2. <ins> While this document mainly discusses a single QUIC server, it is common for deployments of QUIC servers to include a fleet of multiple server instances.  We therefore define the following terms: This is the set of versions supported by a given server instance. More specifically, these are the versions that a given server instance will use if a client sends a first flight using them. This is the set of versions that a given server instance will send in a Version Negotiation packet if it receives a first flight from an unknown version.  This set will most often be equal to the Acceptaple Versions set, except during short transitions while versions are added or removed (see below). This is the set of QUIC versions that is supported and negotiated by every single QUIC server instance in this deployment.  If a deployment only contains a single server instance, then this set is equal to the Offered Versions set, except during short transitions while versions are added or removed (see below). If a deployment contains multiple server instances, software updates may not happen at exactly the same time on all server instances. Because of this, a client might receive a Version Negotiation packet from a server instance that has already been updated and the client's resulting connection attempt might reach a different server instance which hasn't been updated yet. However, even when there is only a single server instance, it is still possible to receive a stale Version Negotiation packet if the server performs its software update while the Version Negotiation packet is in flight. This could cause the version downgrade prevention mechanism described in downgrade to falsely detect a downgrade attack.  To avoid that, server operators SHOULD perform a three-step process when they wish to add or remove support for a version: When adding support for a new version: The first step is to progressively add support for the new version to all server instances.  This step updates the Acceptable Versions but not the Offered Versions nor the Fully-Deployed Versions.  Once all server instances have been updated, operators wait for at least one MSL to allow any in-flight Version Negotiation packets to arrive. Then, the second step is to progressively add the new version to Offered Versions on all server instances.  Once complete, operators wait for at least another MSL. Finally, the third step is to progressively add the new version to Fully-Deployed Versions on all server instances. When removing support for a version: The first step is to progressively remove the version from Fully- Deployed Versions on all server instances.  Once it has been removed on all server instances, operators wait for at least one MSL to allow any in-flight Version Negotiation packets to arrive. Then, the second step is to progressively remove the version from Offered Versions on all server instances.  Once complete, operators wait for at least another MSL. Finally, the third step is to progressively remove support for the version from all server instances.  That step updates the Acceptable Versions. Note that this opens connections to version downgrades (but only for partially-deployed versions) during the update window, since those could be due to clients communicating with both updated and non- updated server instances. 3. </ins> If A and B are two distinct versions of QUIC, A is said to be "compatible" with B if it is possible to take a first flight of packets from version A and convert it into a first flight of packets much later - in that scenario one endpoint might be aware of the compatibility document while the other may not.  <ins> 4. </ins> This document specifies two means of performing version negotiation: one "incompatible" which requires a round trip and is applicable to The client initiates a QUIC connection by sending a first flight of QUIC packets with a long header to the server INV.  We'll refer to the version of those packets as the "original version".  The client's  <ins> first flight includes Version Information (see vers-info) which will be used to optionally enable compatible version negotation (see compat-vn), and to prevent version downgrade attacks (see downgrade). </ins> Upon receiving this first flight, the server verifies whether it knows how to parse first flights from the original version.  If it parse first flight packets but not enough to fully establish a connection using that version.  <ins> 4.1. </ins> QUIC connections are shared state between a client and a server INV. The compatible version negotiation mechanism defined in this document across two QUIC connections: one before the Version Negotiation packet, and a distinct connection after.  <ins> 4.2. </ins>  <ins> The server starts incompatible version negotiation by sending a Version Negotiation packet.  This packet SHALL include each entry from the server's set of Offered Versions (see server-fleet) in a Supported Version field.  The server MAY add reserved versions (as defined in the Versions section of QUIC) in Supported Version fields. </ins> Upon receiving the VN packet, the client will search for a version it supports in the list provided by the server.  If it doesn't find one, The new first flight will allow the endpoints to establish a connection using the negotiated version.  The handshake of the  <ins> negotiated version will exchange version information (see vers-info) required to ensure that VN was genuine, i.e. that no attacker injected packets in order to influence the VN process, see downgrade. </ins>  <ins> 4.3. </ins> When the server can parse the client's first flight using the  <ins> original version, it can extract the client's Version Information structure (see vers-info).  This contains the list of versions that the client thinks its first flight is compatible with. </ins> If the server supports one of the client's compatible versions, and the server also believes that the original version is compatible with load balancers to ensure that packets for a given connection are routed to the same server.  <ins> 5. </ins>  <ins> During the handshake, endpoints will exchange Version Information, which is a blob of data that is defined below.  In QUIC version 1, the Version Information is transmitted using a new transport parameter, "version_information".  The contents of Version Information are shown below (using the notation from the "Notational Conventions" section of QUIC): </ins> The content of each field is described below:  <ins> The version that the sender has chosen to use for this connection. In most cases, this field will be equal to the value of the Version field in the long header that carries this data. </ins>  <ins> The contents of the "Other Versions" field depends on whether it is sent by the client or by the server. </ins>  <ins> When sent by a client, the "Other Versions" field lists all the versions that this first flight is compatible with, ordered by descending preference.  Note that the version in the "Chosen Version" field MUST be included in this list to allow the client to communicate the chosen version's preference.  Note that this preference is only advisory, servers MAY choose to use their own </ins> preference instead.  <ins> When sent by a server, the "Other Versions" field lists all the Fully-Deployed Versions of this server deployment, see server- fleet. </ins>  <ins> Clients and servers MAY both include versions following the pattern "0x?a?a?a?a" in their "Other Versions" list.  Those versions are reserved to exercise version negotiation (see the Versions section of QUIC), and will never be selected when choosing a version to use. 6. </ins> Clients MUST ignore any received Version Negotiation packets that contain the version that they initially attempted.  Once a client has reacted to a Version Negotiation packet, it MUST drop all subsequent Version Negotiation packets on that connection.  <ins> Both endpoints MUST parse their peer's Version Information during the handshake.  If the Version Information was missing or if parsing it failed (for example, if it is too short or if its length is not divisible by four), then the endpoint MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type "TRANSPORT_PARAMETER_ERROR". If a client has reacted to a Version Negotiation packet, it MUST validate that the server's "Other Versions" field does not contain the client's original version, and that the client would have selected the same negotiated version if it had received a Version Negotiation packet whose Supported Versions field had the same contents as the server's "Other Versions" field.  If any of these checks fail, the client MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type "VERSION_NEGOTIATION_ERROR".  This connection closure prevents an attacker from being able to use forged Version Negotiation packets to force a version downgrade. After the process of version negotiation in this document completes, the version in use for the connection is the version that the server sent in the "Chosen Version" field of its Version Information.  That remains true even if other versions were used in the Version field of long headers at any point in the lifetime of the connection; endpoints MUST NOT change the version that they consider to be in use based on the Version field of long headers as that field could be forged by attackers. </ins> 7. validate the client's IP address before parsing the client's first flight.  This impacts compatible version negotiation because a server who wishes to send a retry packet before parsing the client's first  <ins> flight won't have parsed the client's Version Information yet.  If a future document wishes to define compatibility between two versions that support retry, that document MUST specify how version </ins> negotiation (both compatible and incompatible) interacts with retry during a handshake that requires both.  For example, that could be accomplished by having the server send a retry packet first and 11. The security of this version negotiation mechanism relies on the  <ins> authenticity of the Version Information exchanged during the handshake.  In QUIC version 1, transport parameters are authenticated ensuring the security of this mechanism.  Negotiation between compatible versions will have the security of the weakest common version. </ins> The requirement that versions not be assumed compatible mitigates the possibility of cross-protocol attacks, but more analysis is still needed here.  12. 12.1.


Version Negotiation packets on that connection. Both endpoints MUST parse their peer's Version Information during the <del> handshake.  If the Version Information was missing or if parsing it failed (for example, if it is too short or if its length is not divisible by four), then the endpoint MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type "TRANSPORT_PARAMETER_ERROR". </del>  If a client has reacted to a Version Negotiation packet, it MUST validate that the server's "Other Versions" field does not contain

Section 5 describes Version Downgrade Prevention. If a client receives a VN packet and selects a new attempted version, it will format the "compatible VN" extension and document in it the previously attempted version and the VN parameters. The server who understands the extension will then verify that the VN was not a downgrade attack. This supposes that the server supports the extension. If it does not, the server will ignore the parameter, and will not verify anything. It also will not include that parameter in its parameter set. What should the client do in that scenario? Should it just close the connection with versionnegotiation error?

Version Negotiation packets on that connection. Both endpoints MUST parse their peer's Version Information during the  <ins> handshake.  If parsing the Version Information failed (for example, if it is too short or if its length is not divisible by four), then the endpoint MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type "TRANSPORT_PARAMETER_ERROR". If the Version Information was missing, the endpoints MAY complete the handshake if they have reason to believe the peer might not support this extension.  However, if a client has reacted to a Version Negotiation packet and the Version Information was missing, the client MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type "VERSION_NEGOTIATION_ERROR". </ins> If a client has reacted to a Version Negotiation packet, it MUST validate that the server's "Other Versions" field does not contain


Version Negotiation packet.  This packet SHALL include each entry from the server's set of Offered Versions (see server-fleet) in a Supported Version field.  The server MAY add reserved versions (as <del> defined in the Versions section of QUIC) in Supported Version fields. </del>  Upon receiving the VN packet, the client will search for a version it supports in the list provided by the server.  If it doesn't find one, QUIC version 1, that connection closure MUST use a transport error of type "VERSION_NEGOTIATION_ERROR". <del> If a client has reacted to a Version Negotiation packet, it MUST validate that the server's "Other Versions" field does not contain the client's original version, and that the client would have selected the same negotiated version if it had received a Version Negotiation packet whose Supported Versions field had the same contents as the server's "Other Versions" field.  If any of these checks fail, the client MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type "VERSION_NEGOTIATION_ERROR".  This connection closure prevents an attacker from being able to use forged Version Negotiation packets to force a version downgrade. </del>  After the process of version negotiation in this document completes, the version in use for the connection is the version that the server

In light of discussion in slack, the problem here is that the validation is based on the negotiated version. Validation needs to be based on the client's selected version. I've also moved text about validating lack of support for the original version to the incompatible VN section, alongside a reminder to validate connection IDs. Security does depend on this, but the client ignores these bad VN packets. That provides more effective defense against attack than what was here originally.
Thanks! Approved modulo two nits

Version Negotiation packet.  This packet SHALL include each entry from the server's set of Offered Versions (see server-fleet) in a Supported Version field.  The server MAY add reserved versions (as  <ins> defined in Section 6.3 of QUIC) in Supported Version fields. Clients will ignore a Version Negotiation packet if it contains the original version attempted by the client.  The client also ignores a Version Negotiation that contains incorrect connection ID fields; see Section 6 of RFC8999. </ins> Upon receiving the VN packet, the client will search for a version it supports in the list provided by the server.  If it doesn't find one, QUIC version 1, that connection closure MUST use a transport error of type "VERSION_NEGOTIATION_ERROR".  <ins> If the client received and acted on a Version Negotiation packet, the client MUST validate the server's "Other Versions" field.  The "Other Versions" field is validated by confirming that the client would have attempted the same version with knowledge of the versions the server supports.  That is, the client would have selected the same version if it received a Version Negotiation packet that listed the versions in the server's "Other Versions" field, plus the negotiated version. If the client would have selected a different version, the client MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type "VERSION_NEGOTIATION_ERROR".  This connection closure prevents an attacker from being able to use forged Version Negotiation packets to force a version downgrade. This validation of "Other Versions" is not sufficient to prevent downgrade.  Downgrade prevention also depends on the client ignoring Version Negotiation packets that contain the original version; see incompat-vn. </ins> After the process of version negotiation in this document completes, the version in use for the connection is the version that the server


VN packet to indicate that the version the client offered is unacceptable, but doesn't allow the client to safely make use of that information to create a new connection with a mutually supported <del> version.  With proper safety mechanisms in place, the VN packet can be part of a mechanism to allow two QUIC implementations to negotiate between two totally disjoint versions of QUIC, at the cost of an extra round trip.  However, it is beneficial to avoid that cost whenever possible, especially given that most incremental versions are broadly similar to the the previous version. This specification describes a simple version negotiation mechanism which optionally leverages similarities between versions and can negotiate between the set of "compatible" versions in a single round trip. </del>  1.1.

The "single round trip" thing isn't really a guarantee given various factors. Setting this up as additional round trips is cleaner and more accurate. I adjusted the paragraph structure to match.
The introduction reads like the draft only defines compatible version negotiation. It probably needs to be written to be more general.
Fair enough.
Thanks, that is a lot clearer

VN packet to indicate that the version the client offered is unacceptable, but doesn't allow the client to safely make use of that information to create a new connection with a mutually supported  <ins> version. With proper safety mechanisms in place, the VN packet can be part of a mechanism to allow two QUIC implementations to negotiate between two totally disjoint versions of QUIC.  This document specifies version negotiation using VN packets, which adds an extra round trip to connection establishment if needed. It is beneficial to avoid additional round trips whenever possible, especially given that most incremental versions are broadly similar to the the previous version.  This specification also defines a simple version negotiation mechanism which leverages similarities between versions and can negotiate between the set of "compatible" versions without additional round trips. </ins> 1.1.


7. <del> The client's first flight SHOULD be sent using the version that the server is most likely to support (in the absence of other information, this will often be the oldest version the client supports). </del>  8.

Though it might be the oldest version that is compatible with the most-preferred version, it isn't just "oldest".

7.  <ins> The client's first connection attempt SHOULD be made using the version that the server is most likely to support.  The client selects the version it believes to be best supported from the versions that are compatible with the client's most preferred version.  Without additional information this could mean selecting the oldest version that the client supports. </ins> 8.


8. <del> QUIC version 1 features retry packets, which the server can send to </del>  validate the client's IP address before parsing the client's first <del> flight.  This impacts compatible version negotiation because a server who wishes to send a retry packet before parsing the client's first flight won't have parsed the client's Version Information yet.  If a future document wishes to define compatibility between two versions that support retry, that document MUST specify how version </del>  negotiation (both compatible and incompatible) interacts with retry during a handshake that requires both.  For example, that could be <del> accomplished by having the server send a retry packet first and validating the client's IP address before starting version negotiation and deciding whether to use compatible version negotiation on that connection (in that scenario the retry packet would be sent using the original version). </del>  9.

Retry packets have a capital R protocols aren't "who" paragraphs are good minor edits for brevity

8.  <ins> QUIC version 1 features Retry packets, which the server can send to </ins> validate the client's IP address before parsing the client's first  <ins> flight.  A server that sends a Retry packet can do so before parsing the client's first flight.  A server that sends a Retry packet therefore might not have processed the client's Version Information before doing so. If a future document wishes to define compatibility between two versions that support retry, that document MUST specify how version </ins> negotiation (both compatible and incompatible) interacts with retry during a handshake that requires both.  For example, that could be  <ins> accomplished by having the server send a Retry packet first and validating the client's IP address before attempting compatible version negotiation.  In that scenario the Retry packet would be sent using the original version. </ins> 9.


version_information <del> permanent (if this document is approved) </del>  This document  12.2. This document registers a new value in the QUIC Transport Error Codes Error negotiating version <del> permanent (if this document is approved) </del>  This document

I just saw a provisional registration for the 0xff73db value (from the current draft). This contains a note suggesting that the value might become permanent. Given how crucial version negotiation could be, I think we should seriously consider taking a codepoint from the 0-63 range.
Agreed, that was the intent but it wasn't clear from the draft. I wrote in to make it clearer.

version_information  <ins> provisional </ins> This document <ins> When this document is approved, it will request permanent allocation of a codepoint in the 0-63 range to replace the provisional codepoint described above. </ins> 12.2. This document registers a new value in the QUIC Transport Error Codes Error negotiating version  <ins> provisional </ins> This document <ins> When this document is approved, it will request permanent allocation of a codepoint in the 0-63 range to replace the provisional codepoint described above. </ins>


During the handshake, endpoints will exchange Version Information, which is a blob of data that is defined below.  In QUIC version 1, the Version Information is transmitted using a new transport <del> parameter, "version_information".  The contents of Version Information are shown below (using the notation from the "Notational Conventions" section of QUIC): </del>  The content of each field is described below: In most cases, this field will be equal to the value of the Version field in the long header that carries this data. <del> The contents of the "Other Versions" field depends on whether it is </del>  sent by the client or by the server. <del> When sent by a client, the "Other Versions" field lists all the </del>  versions that this first flight is compatible with, ordered by <del> descending preference.  Note that the version in the "Chosen Version" field MUST be included in this list to allow the client to communicate the chosen version's preference.  Note that this </del>  preference is only advisory, servers MAY choose to use their own preference instead. <del> When sent by a server, the "Other Versions" field lists all the </del>  Fully-Deployed Versions of this server deployment, see server- <del> fleet.  Note that the version in the "Chosen Version" field is not </del>  necessarily included in this list, because the server operator could be in the process of removing support for this version.  For the same reason, this field MAY be empty. Clients and servers MAY both include versions following the pattern <del> "0x?a?a?a?a" in their "Other Versions" list.  Those versions are reserved to exercise version negotiation (see the Versions section of QUIC), and will never be selected when choosing a version to use. </del>  6. if it is too short or if its length is not divisible by four), then the endpoint MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of <del> type "TRANSPORT_PARAMETER_ERROR". </del>  If the Version Information was missing, the endpoints MAY complete the handshake if they have reason to believe the peer might not Version Negotiation packet and the Version Information was missing, the client MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of <del> type "VERSION_NEGOTIATION_ERROR". </del>  If the client received and acted on a Version Negotiation packet, the <del> client MUST validate the server's "Other Versions" field.  The "Other Versions" field is validated by confirming that the client would have </del>  attempted the same version with knowledge of the versions the server supports.  That is, the client would have selected the same version if it received a Version Negotiation packet that listed the versions <del> in the server's "Other Versions" field, plus the negotiated version. </del>  If the client would have selected a different version, the client MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type <del> "VERSION_NEGOTIATION_ERROR".  This connection closure prevents an </del>  attacker from being able to use forged Version Negotiation packets to force a version downgrade. <del> This validation of "Other Versions" is not sufficient to prevent </del>  downgrade.  Downgrade prevention also depends on the client ignoring Version Negotiation packets that contain the original version; see incompat-vn. After the process of version negotiation in this document completes, the version in use for the connection is the version that the server <del> sent in the "Chosen Version" field of its Version Information.  That </del>  remains true even if other versions were used in the Version field of long headers at any point in the lifetime of the connection; endpoints MUST NOT change the version that they consider to be in use

In , NAME points out that the backticks don't render nicely in the TXT version, so let's remove them

During the handshake, endpoints will exchange Version Information, which is a blob of data that is defined below.  In QUIC version 1, the Version Information is transmitted using a new transport  <ins> parameter, version_information.  The contents of Version Information are shown below (using the notation from the "Notational Conventions" section of QUIC): </ins> The content of each field is described below: In most cases, this field will be equal to the value of the Version field in the long header that carries this data.  <ins> The contents of the Other Versions field depends on whether it is </ins> sent by the client or by the server.  <ins> When sent by a client, the Other Versions field lists all the </ins> versions that this first flight is compatible with, ordered by  <ins> descending preference.  Note that the version in the Chosen Version field MUST be included in this list to allow the client to communicate the chosen version's preference.  Note that this </ins> preference is only advisory, servers MAY choose to use their own preference instead.  <ins> When sent by a server, the Other Versions field lists all the </ins> Fully-Deployed Versions of this server deployment, see server-  <ins> fleet.  Note that the version in the Chosen Version field is not </ins> necessarily included in this list, because the server operator could be in the process of removing support for this version.  For the same reason, this field MAY be empty. Clients and servers MAY both include versions following the pattern  <ins> 0x?a?a?a?a in their Other Versions list.  Those versions are reserved to exercise version negotiation (see the Versions section of QUIC), and will never be selected when choosing a version to use. </ins> 6. if it is too short or if its length is not divisible by four), then the endpoint MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of  <ins> type TRANSPORT_PARAMETER_ERROR. </ins> If the Version Information was missing, the endpoints MAY complete the handshake if they have reason to believe the peer might not Version Negotiation packet and the Version Information was missing, the client MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of  <ins> type VERSION_NEGOTIATION_ERROR. </ins> If the client received and acted on a Version Negotiation packet, the  <ins> client MUST validate the server's Other Versions field.  The Other Versions field is validated by confirming that the client would have </ins> attempted the same version with knowledge of the versions the server supports.  That is, the client would have selected the same version if it received a Version Negotiation packet that listed the versions  <ins> in the server's Other Versions field, plus the negotiated version. </ins> If the client would have selected a different version, the client MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type  <ins> VERSION_NEGOTIATION_ERROR.  This connection closure prevents an </ins> attacker from being able to use forged Version Negotiation packets to force a version downgrade.  <ins> This validation of Other Versions is not sufficient to prevent </ins> downgrade.  Downgrade prevention also depends on the client ignoring Version Negotiation packets that contain the original version; see incompat-vn. After the process of version negotiation in this document completes, the version in use for the connection is the version that the server  <ins> sent in the Chosen Version field of its Version Information.  That </ins> remains true even if other versions were used in the Version field of long headers at any point in the lifetime of the connection; endpoints MUST NOT change the version that they consider to be in use


When the server can parse the client's first flight using the original version, it can extract the client's Version Information structure (see vers-info).  This contains the list of versions that <del> the client thinks its first flight is compatible with. </del>  If the server supports one of the client's compatible versions, and <del> the server also believes that the original version is compatible with </del>  this version, then the server converts the client's first flight to that version and replies to the client as if it had received the converted first flight.  The version used by the server in its reply type TRANSPORT_PARAMETER_ERROR. If the Version Information was missing, the endpoints MAY complete <del> the handshake if they have reason to believe the peer might not support this extension.  However, if a client has reacted to a Version Negotiation packet and the Version Information was missing, the client MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type VERSION_NEGOTIATION_ERROR. </del>  If the client received and acted on a Version Negotiation packet, the client MUST validate the server's Other Versions field.  The Other The client's first connection attempt SHOULD be made using the version that the server is most likely to support.  The client <del> selects the version it believes to be best supported from the versions that are compatible with the client's most preferred version.  Without additional information this could mean selecting the oldest version that the client supports. </del>  8.

This draft talks about clients and servers "thinking" and "believing" things. Those verbs don't necessarily apply to protocol implementations, no matter what new frontiers we're exploring in the machine learning space. Might be worth a pass to rephrase these in terms of client or server capabilities and information. "Know" is a little fuzzier, since an endpoint does in fact possess information at certain points in the process.
So... when my computer says "thinking ...", are you saying it's lying to me?
URL

When the server can parse the client's first flight using the original version, it can extract the client's Version Information structure (see vers-info).  This contains the list of versions that  <ins> the client knows its first flight is compatible with. </ins> If the server supports one of the client's compatible versions, and  <ins> the server also knows that the original version is compatible with </ins> this version, then the server converts the client's first flight to that version and replies to the client as if it had received the converted first flight.  The version used by the server in its reply type TRANSPORT_PARAMETER_ERROR. If the Version Information was missing, the endpoints MAY complete  <ins> the handshake.  However, if a client has reacted to a Version Negotiation packet and the Version Information was missing, the client MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type VERSION_NEGOTIATION_ERROR. </ins> If the client received and acted on a Version Negotiation packet, the client MUST validate the server's Other Versions field.  The Other The client's first connection attempt SHOULD be made using the version that the server is most likely to support.  The client  <ins> selects the version most likely to be supported from the versions that are compatible with the client's most preferred version. Without additional information this could mean selecting the oldest version that the client supports. </ins> 8.


QUIC version 1, that connection closure MUST use a transport error of type TRANSPORT_PARAMETER_ERROR.  If the Version Information was missing, the endpoints MAY complete the handshake.  However, if a client has reacted to a Version Negotiation packet and the Version Information was missing, the <del> client MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type VERSION_NEGOTIATION_ERROR. </del>  If the client received and acted on a Version Negotiation packet, the client MUST validate the server's Other Versions field.  The Other if it received a Version Negotiation packet that listed the versions in the server's Other Versions field, plus the negotiated version. If the client would have selected a different version, the client <del> MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of type VERSION_NEGOTIATION_ERROR.  This connection closure prevents an attacker from being able to use forged Version Negotiation packets to force a version downgrade. </del>  This validation of Other Versions is not sufficient to prevent downgrade.  Downgrade prevention also depends on the client ignoring

Defining an error code for QUICv1 is good, but I think that you need to frame this differently. It probably needs to be framed in terms of a requirement on all QUIC versions. So rather than: You might say something like:
I like this. Can you make it a PR?

QUIC version 1, that connection closure MUST use a transport error of type TRANSPORT_PARAMETER_ERROR. <ins> Every QUIC version that supports version negotiation MUST define a method for closing the connection with a version negotiation error. For QUIC version 1, version negotiation errors are signaled using a transport error of type VERSION_NEGOTIATION_ERROR; see iana-error. </ins> If the Version Information was missing, the endpoints MAY complete the handshake.  However, if a client has reacted to a Version Negotiation packet and the Version Information was missing, the  <ins> client MUST close the connection with a version negotiation error. </ins> If the client received and acted on a Version Negotiation packet, the client MUST validate the server's Other Versions field.  The Other if it received a Version Negotiation packet that listed the versions in the server's Other Versions field, plus the negotiated version. If the client would have selected a different version, the client  <ins> MUST close the connection with a version negotiation error.  This connection closure prevents an attacker from being able to use forged Version Negotiation packets to force a version downgrade. </ins> This validation of Other Versions is not sufficient to prevent downgrade.  Downgrade prevention also depends on the client ignoring


If the server supports one of the client's compatible versions, and the server also knows that the original version is compatible with <del> this version, then the server converts the client's first flight to that version and replies to the client as if it had received the converted first flight.  The version used by the server in its reply is refered to as the "negotiated version".  The server MUST NOT reply with a version that is not present in the client's compatible versions, unless it is the original version. </del>  If the server does not find a compatible version, it will use the original version if it supports it, and if it doesn't then the server

Section 3.3 states: If the server supports one of the client's compatible versions, and the server also believes that the original version is compatible with this version, then the server converts the client's first flight to that version and replies to the client as if it had received the converted first flight. The version used by the server in its reply is refered to as the "negotiated version". The server MUST NOT reply with a version that is not present in the client's compatible versions, unless it is the original version. I am looking at implementing that, and I am really puzzled. Take for example Martin Duke's V2 draft, which merely changes the Initial salt. Reprocess the first flight would mean try to parse it with the new salt, and that would fail. Or the "authenticated handshake" draft, which require adding a secret into the Initial AAD, but that secret is only present if the first flight was designed for authenticated handshake. I think that the draft needs to be much more precise about this "compatible version" process. It seems that there are three levels: packets, which should be parsed and formatted according to the version number in the long header, or for 1RTT packets the version number negotiated during the handshake. frames, which generally should be treated independently of the packet format -- unless the target version includes new parameters transport parameters and maybe TLS extensions In Martin Duke's V2 draft, we have a simple case of merely changing the packet format without changing the semantic of frames or parameters, so that's easy. In the authenticated exchange draft, the peers could update from V1 to V-authenticated, but only if they manage to retrieve the required secret from the TLS extensions or the transport parameter. Is that what reprocess means? The more I think of it, the more I believe that the "upgrade from V1 to Vx" process should be defined as part of the Vx specification. For example, Vx spec might say something like "when upgrading from V1 to Vx, find the Transport Parameter X, Y and Z and use them to initialize Vx parameters A, B and C." Maybe that's part of what a "compatible upgrade" is.
Hi NAME where does the word "reprocess" come from? I don't see it anywhere in the draft. The draft uses the word "convert". For example in Martin Duke's v2 draft, you would convert a v1 initial to v2 by decrypting it with v1 initial keys, setting the version to v2, and re-encrypting it with v2 initial keys. Then you'd be able to process that new synthetic v2 initial. Of course as an optimization your code can skip the re-encryption and just use the parsed result but the concept is to define a conversion between versions. In the current design, it's totally possible for the "upgrade from V1 to Vx" process to be described in the Vx draft, but it's not required - that allows us to make two versions compatible even if they were developed concurrently in isolation.
NAME gentle ping on this - did the latest update to the draft clarify this for you?
The spec says: If the server supports one of the client's compatible versions, and the server also believes that the original version is compatible with this version, then the server converts the client's first flight to that version and replies to the client as if it had received the converted first flight. The version used by the server in its reply is refered to as the "negotiated version". (Typo: Should be referred, I think) The text works, but it relies on the server also believes. My point is that in order to believe, the server has to be able to convert the initial Vi input into the selected Vx. You may or may not want to outline that. I would prefer if you did.
Sounds good, I'll write up an editorial PR to address this.
In it talks about the server picking a compatible version and then converting the first flight. As noted in the definition of compatible, it is not sufficient that the transform exist, it also has to succeed. In the example given, there might be reasons that a conversion could fail (such as the inclusion of information that is optional and cannot be transformed). In other words, the version might be compatible but the handshake is not. There are three possible outcomes I see here: This eliminates that version from the set of compatible options. The server is free to try another compatible version or just give up and use the offered version. I don't like this much as it implies a denial of service attack on a server that is willing to try multiple compatible versions. The server can regard all attempts at compatible versions to have failed and it could send a Version Negotiation packet in response. I am happier with this, but only marginally. It could hide a genuine error on the part of the client. That error manifests as a performance bug. As clients should not ever offer a handshake that includes a compatible version that can't be used, this suggests option 3... The server regards this as a fatal error. The server uses a signal appropriate to the original version to indicate handshake failure. Ideally, any version that has other versions compatible with it defines an error code for this purpose.
Can you elaborate on that? In my mental model, one of the reasons why conversion could fail is that the client is offering an extension which only works with the original, but not the upgraded version. In that case conversion would fail, even though the two versions are compatible in general. I think this would rule out 3. the client didn’t do anything wrong, and therefore shouldn’t receive an error.
My view is that either the conversion process should describe how to discard that data or the client should not include it.
I agree with NAME here. If the conversion hits something that it doesn't know how to convert, which seems possible if you consider the range of options that might exist, then that's an error. Either client shouldn't have included it, or the server is ignorant of how the conversion should operate. In most cases I can think of, stuff that is only valid for the original version can just be thrown away when converting. Concrete example of a case that might fail. Say that we change the rules for Initial packets in QUICv2 to make the minimum size of the DCID 10 bytes (up from 8 in v1). A client that offers a QUICv1 Initial with an 8-byte DCID would be valid in v1, but it is invalid in v2. Thus, the rule might be that the client always provide at least 10 bytes in its DCID. If the client didn't do that, but offered v2 as compatible, it has a bug and the connection shouldn't proceed.
I agree with you, though I'm not sure what you're asking in terms of changes to the draft - what's missing? Should we define the concept of conversion better to explain that a conversion cannot fail - or is this about how the server should react when the client sent something that it knew would fail?
in Section 3.3 seems to just assume that this conversion process works:

If the server supports one of the client's compatible versions, and the server also knows that the original version is compatible with  <ins> this version, and the client's first flight is compatible with this version, then the server converts the client's first flight to that version and replies to the client as if it had received the converted first flight.  Note that this conversion process cannot fail by definition of the first flight being compatible.  The version used by the server in its reply is refered to as the "negotiated version". The server MUST NOT reply with a version that is not present in the client's compatible versions, unless it is the original version. </ins> If the server does not find a compatible version, it will use the original version if it supports it, and if it doesn't then the server


much later - in that scenario one endpoint might be aware of the compatibility document while the other may not.  4. This document specifies two means of performing version negotiation:

Two versions might be compatible in the sense that one can convert the Initial Packet from one into the other. But one version might not have the features necessary for an application. There are two ways to mediate this that I can see: 1) The client excludes compatible versions that are inadequate for the app from its TP. This means the QUIC API will need a way for applications to control the advertised versions. 2) Servers understand what capabilities are needed and will not select an advertised compatible version that does not support them. For incompatible VN, if the server can identify the application based on IP and port, it might scrub irrelevant versions from its VN packet, though I don't know if that's a good idea or not.
When MsQuic implemented this extension, we exposed a configuration option to the app for it to specify its "desired version list". My expectation is that a client would include all acceptable QUIC versions here, and then adapt (if necessary) their protocol layer accordingly. Though, this might get harry, for instance, if they need to then choose a different ALPN based on the negotiated QUIC version (we don't currently support that).
NAME you're describing an implicit assumption of the draft: the list of supported versions are specific to an application, not just to an implementation. Perhaps we can add a sentence to make that more obvious, such as Servers don't need to do anything here, it's the client's responsibility to know what it wants to do with a given connection, not the server's.
Yes NAME that works for me. The real issue is that this not totally internal to the QUIC implementation and there needs to be an API for the application to manage this.
I agree that such an API is reasonable (Google QUICHE provides one for example) but I think that's out of scope for this document though.
I agree you shouldn't define the API, but it would be good to say, "hey, dummy, don't just advertise every compatible version the QUIC implementation supports"
Note that the relationship between version selection and ALPN is similar to the aftereffects of HTTP/2, which made the cipher selection and ALPN selection within TLS interdependent. That was a pain. It doesn't affect this draft per se, but I do hope we don't paint ourselves into that particular corner again.

much later - in that scenario one endpoint might be aware of the compatibility document while the other may not. <ins> When a client creates a QUIC connection, its goal is to use an application layer protocol.  Therefore, when considering which versions are compatible, clients will only consider versions that support the intended application layer protocol. </ins> 4. This document specifies two means of performing version negotiation:


version such that commonly deployed versions are compatible with it. For example, a successor to QUIC version 1 may wish to design its transport parameters in a way that does not preclude compatibility. <del> Additionally, frames in QUIC version 1 do not use a self-describing encoding, so unrecognized frame types cannot be parsed or ignored (see the Extension Frames section of QUIC); this means that new versions that wish to be very similar to QUIC version 1 and compatible with it should avoid introducing new frames in initial packets. </del> 11.

In : This is not an issue. If v2 defines a new frame type that can appear in Initial-equivalent packets, then to be compatible with v1 (in both directions) that frame type could simply be optional in v2. The lack of a self-describing encoding is not an issue as the parsing of the v2 packet is done with knowledge of all the core frame types in v2. Sure, you can't introduce an extension frame here, but that's true of v1 on its own. The only way in which a version might become incompatible is if it includes new information that can't be inferred from the other version or doesn't have a valid default. I think that the intent of this was to say that if there is any need for the Initial flight to carry new information that is only consumed by a compatible version, then there is no way for QUIC version 1 to carry that new information by using new frames. Instead, it has to use a field in v1 that would be ignored by a v1 endpoint. As v1 defines no real extension points of this sort, the options in this case are limited. I think that this text can be removed. Maybe you could talk about the problem of carrying version-specific information in other versions.
This makes sense. This text was somewhat vestigial from earlier designs of this mechanism.

version such that commonly deployed versions are compatible with it. For example, a successor to QUIC version 1 may wish to design its transport parameters in a way that does not preclude compatibility.  11.


5. During the handshake, endpoints will exchange Version Information, <del> which is a blob of data that is defined below.  In QUIC version 1, the Version Information is transmitted using a new transport parameter, version_information.  The contents of Version Information are shown below (using the notation from the "Notational Conventions" section of QUIC): </del>  The content of each field is described below:

I think that the answer is "no" (see also Betteridge's Law) in that the format is version-specific, but is pretty obtuse about this: The first sentence reads as an absolute; the second is clearly narrowly scoped. But then nothing is said about other versions. As I mentioned with error codes in , I think that the way this needs to be phrased is as a requirement on QUIC versions that support version negotiation. The requirement is that those protocols need to define a way to carry certain information. You can then define that information in the abstract when articulating that requirement; again see . The concrete form you choose for v1 then only needs to apply to v1.
The intention was for the handshake version information to be invariant, and for how it is conveyed to be version-specific. But I agree that we should state that versions need an authenticated way to exchange handshake version information.
It needs to go further than that. I think that you need to list, concretely, what information is being authenticated. And you need to explain the consequences, namely: And then in Section 4, say precisely what information needs to be authenticated in order to achieve this goal, with a concrete definition for how the information is carried in QUIC version 1 transport parameters.
That works for me.

5. During the handshake, endpoints will exchange Version Information,  <ins> which consists of a chosen version and a list of other versions.  Any version of QUIC that supports this mechanism MUST provide a mechanism to exchange Version Information in both directions during the handshake, such that this data is authenticated. In QUIC version 1, the Version Information is transmitted using a new transport parameter, version_information.  The contents of Version Information are shown below (using the notation from the "Notational Conventions" section of QUIC): </ins> The content of each field is described below:


will perform incompatible version negotiation instead, see incompat- vn. <del> For the duration of the compatible version negotiation process, clients MUST use the same 5-tuple (source and destination IP addresses and UDP port numbers).  During that time, clients MUST also use the same Destination Connection ID, except if the server explicitly instructs the client to use a different Destination Connection ID (for example, a QUIC version 1 server can accomplish this by sending an INITIAL packet with a Source Connection ID that differed from the client's Destination Connection ID).  This allows load balancers to ensure that packets for a given connection are routed to the same server. </del>  5.

indicates that the address tuple used for the first flight remain stable. This is probably OK, but I think that this is unnecessary. What seems particularly risky here is anticipating the rules about connection IDs that might apply to both versions: My preference here is to drop this text entirely and leave it to the negotiated version to specify these rules. Once you have performed whatever mapping/transformation that is defined, then the first flight complies with the requirements of the negotiated version and you are subject to the rules of that version. Trying to manage the intersection of both sets of rules is complicated. Better not to chase down that rabbit hole (I've been there). FWIW, I fully expect v2 to also specify address tuple stability during the handshake. However, if it does not and a client can send a v2 first flight on multiple tuples (leaving aside the implausibility of expecting those datagrams to arrive at the same place), then that won't be naturally compatible with v1 and you won't be able to start with v2 in that way and expect to be able to negotiate v1 out of that. This is no different than your new, optional frame example.
I think we need to state something about 5-tuple stability here, because if version A requires 5-tuple stability and version B requires 5-tuple stability, neither of those documents specifies that the two halves of the handshake (the first half using A, and the second half using B) need 5-tuple stability between them.
I don't think that you need to say anything about that specifically. You might use it as an example in a sentence like:
Fair enough, that works for me.

will perform incompatible version negotiation instead, see incompat- vn.  <ins> Note that, after the first flight is converted to the negotiated version, the handshake completes in the negotiated version.  The entire handshake (including the converted first flight) needs to conform to the rules of the negotiated version.  For instance, if the negotiated version requires that the 5-tuple remain stable for the entire handshake (as QUIC version 1 does), then this applies to the entire handshake, including the first flight. </ins> 5.


fleet.  Note that the version in the Chosen Version field is not necessarily included in this list, because the server operator could be in the process of removing support for this version.  For <del> the same reason, this field MAY be empty. </del>  Clients and servers MAY both include versions following the pattern 0x?a?a?a?a in their Other Versions list.  Those versions are reserved

The draft says: Server-Sent Other Versions: When sent by a server, the Other Versions field lists all the Fully-Deployed Versions of this server deployment, see Section 2. Note that the version in the Chosen Version field is not necessarily included in this list, because the server operator could be in the process of removing support for this version. For the same reason, this field MAY be empty. But the syntax is: What does the draft exactly mean by "this field MAY be empty"?
The "Other Versions" field contains a list of versions, whose length can be zero. That text exists to remind people that the list of Fully-Deployed Versions can be empty, and that shouldn't cause handshake failures.
The text is far from clear, because the sentence mixes references to "Other Versions" and "Chosen version". Stating "For the same reason, the Other Versions field MAY be empty" would remove the ambiguity.
Thanks for clarifying, I've written that up as .

fleet.  Note that the version in the Chosen Version field is not necessarily included in this list, because the server operator could be in the process of removing support for this version.  For  <ins> the same reason, the Other Versions field MAY be empty. </ins> Clients and servers MAY both include versions following the pattern 0x?a?a?a?a in their Other Versions list.  Those versions are reserved


if it received a Version Negotiation packet that listed the versions in the server's Other Versions field, plus the negotiated version. If the client would have selected a different version, the client <del> MUST close the connection with a version negotiation error.  This connection closure prevents an attacker from being able to use forged Version Negotiation packets to force a version downgrade. </del>  This validation of Other Versions is not sufficient to prevent downgrade.  Downgrade prevention also depends on the client ignoring

Q1) Other Versions can be empty. In that case, should validation fail? Q2) What does this "negotiated version" refer to? (I guess "it selects a mutually supported version and sends a new first flight with that version") Q3) Why don't we check Chosen Version at all?
Q1: correct. I've written to make that explicit in the spec. Q2: the term "negotiated version" is defined in Sections 4.2 and 4.3 Q3: see
Relating to Q3. is about compatible nego. I'm asking the case of incompatible nego here.
Chosen Version is used to pick the version in both compatible and incompatible VNs, and also when the server uses the version that the client started with.
OK. So, I feel that the following sentence should include something like "Chosen Version MUST be checked .... If a mismatch is found, the connection MUST be closed with VERSIONNEGOTIATIONERROR".
NAME since you were the motivation to replace verification with negotiation, do you have thoughts here? NAME points out that when implementing this the client needs to pick the new version based on long headers before it sees the transport parameters
I think that "negotiated" is correct in this context (incompatible) even though it is really just the client selecting from a list, that's still negotiating a version (for which the outcome is a negotiated version). Christian is right about the process, but that doesn't mean we can't call it negotiation. The process is negotiation. The transport parameter captures the outcome of that URL the information necessary to validate that outcome. If we hadn't named the Version Negotiation packet something else, we might have more flexibility in how things are named [^1], but that's a done deal. [^1]: Well, I guess we'd have the same amount of flexibility, except with different words.
I am a bit puzzled here. Suppose that the client started with version 1, is receiving the transport parameters with chosen version X in handshake packet of version Y. There are four possible combination. My understanding is that only two are correct. handshake  selected version 2 -----------------------: ----------- version 1 error version 2 correct Am I wrong?
NAME that will depend on how the QUICv2 draft defines compatible VN from v1 to v2. I think we should define it in such a way that makes your table correct, but that's a design topic for that draft.
I understand that it is pretty hard to reason about this in the abstract, but I do believe that we could have some kind of invariant specification here. The basic idea is that we will have: a client flight in which the client uses version A and proposes version B (and maybe C and D) a negotiation happening when the server parses the transport parameters (or equivalent) received in the first flight and selects version B or remains with A a server flight in which packets are carried as specified in version A or B. The invariant matrix would be: packet header  selected version B --: -- version A error version B correct I would expect that the "erroneous" combinations result in a Version negotiation error.
I don't think we have invariants for this. For example, you had proposed that the server might have a first flight of ACKs in version A until it can parse the entire ClientHello. I don't think there's value in being prescriptive here, any invariant we come up with will rely on assumptions that might be broken by future versions of QUIC.
Maybe what we want is some kind of guidelines on what reprocessing means, and the implication on packet parsing, etc. In any case, the server will transition from sending version A to sending version B. If version B is somehow preferred, we want that to happen before the handshake is complete. Both Kazu & I had to work this out for V1->V2, which makes me think some kind of guide will be useful. Maybe under the heading of "implementation experience".
That makes sense. I'm closing this issue in favor of URL since that's where the transition is defined.

if it received a Version Negotiation packet that listed the versions in the server's Other Versions field, plus the negotiated version. If the client would have selected a different version, the client  <ins> MUST close the connection with a version negotiation error.  In particular, if the client reacted to a Version Negotiation packet and the server's Other Versions field is empty, the client MUST close the connection with a version negotiation error.  These connection closures prevent an attacker from being able to use forged Version Negotiation packets to force a version downgrade. </ins> This validation of Other Versions is not sufficient to prevent downgrade.  Downgrade prevention also depends on the client ignoring


entire handshake (as QUIC version 1 does), then this applies to the entire handshake, including the first flight.  5. During the handshake, endpoints will exchange Version Information,

After pushback from NAME I think this covers the main point with a whole lot less text.
As discussed in URL, there are various levels of partial support for this standard, different for client and server, and there ought to be normative language around these capabilities. There are certain modes that MUST be supported along with multiple versions, and others that are just performance improvements. AFAICT, for any server that supports >1 versions, there are two possible levels of support: Send the TP and support incompatible negotiation Support compatible negotiation For a client, it's more complicated: NAME proposes: No support: do not the send nor parse the TP. If you get a VN packet, fail the QUIC connection Downgrade prevention only: send the TP with only one other version, also parse and validate the TP. If you get a VN packet, fail the QUIC connection. This protects against intermediaries that are rewriting the version field on Initial packets. In v1/v2, these attacks will be detected by the authenticated version field in subsequent handshake packets, but that is not generalizable to all versions of QUIC. Compatible only: downgrade prevention and be prepared to accept an upgrade Incompatible only: advertise only one version, so there's downgrade prevention when trying again with new version after a VN packet. Full: downgrade prevention, compatible VN and incompatible VN
LGTM

entire handshake (as QUIC version 1 does), then this applies to the entire handshake, including the first flight. <ins> Note also that the client can disable compatible version negotiation by only including the Chosen Version in the Other Versions field of the Version Information Transport Parameter. </ins> 5. During the handshake, endpoints will exchange Version Information,


from version B.  As an example, if versions A and B are absolutely equal in their wire image and behavior during the handshake but differ after the handshake, then A is compatible with B and B is <del> compatible with A. </del>  Version compatibility is not symmetric: it is possible for version A to be compatible with version B and for B not to be compatible with

This is NAME 's proposed text to fix this issue.
LGTM. I am going to merge this on the basis of it being David's text and my approval.
LGTM
Section 9 is pretty clear that 'compatible versions' might not have commonly usable 0-RTT packets. But Section 3 defines 'compatible' as a translatable first flight. 0-RTT is part of the first flight, so one of these definitions has to change.
That doesn't necessarily follow. You can translate a first flight in a way that 0-RTT is rejected and the 0-RTT packets are just dropped and the handshake will still succeed. I'm not sure I see an inconsistency here.
Having read sec 3 a few times now, I see the subtlety in your point. 0-RTT could fall under the third paragraph as something that can't be included to be compatible. I still don't really like the definition. I'll think on it some more, but I'd prefer something like "A is said to be 'compatible' with B if the first flight of A contains all the information minimally necessary to complete a first flight of B." So to be compatible with v1 , vx needs to contain a TLS 1.3 client hello including TPs for version negotiation and all the other required v1 TPs. For v1 to be compatible with vx, v_x must not have any additional information to complete its first fligth besides the client hello at the v1 TPs. Whether or not there's 0-RTT in the flight doesn't matter. We are drifting into the editorial, but if you like that definition I'm happy to write a PR.
I'm not sure "minimally necessary" is well-defined. How about something like:

from version B.  As an example, if versions A and B are absolutely equal in their wire image and behavior during the handshake but differ after the handshake, then A is compatible with B and B is  <ins> compatible with A.  Note that the conversion of the first flight can be lossy: some data such as QUICv1 0-RTT packets could be ignored during conversion and retransmitted later. </ins> Version compatibility is not symmetric: it is possible for version A to be compatible with version B and for B not to be compatible with


When a client creates a QUIC connection, its goal is to use an application layer protocol.  Therefore, when considering which versions are compatible, clients will only consider versions that <del> support the intended application layer protocol. </del>  4.

Mix recommendations of NAME and NAME
LGTM
The document currently says: However, as we see with HTTP over TCP, clients routinely offer "h2", "http/1.1" and are content with either selection. Particularly if ALPN tokens map 1:1 to QUIC versions as specified in H3, the client's goal might be to use any of a collection of application-layer protocols. Perhaps tweak this to "...support one of the intended application layer protocols."? The first statement might or might not need to be expanded as well.
Perhaps we add a sentence after the ones you quoted along the lines of "For example, if the client's first flight advertises multiple ALPN tokens and multiple compatible versions, the server needs to ensure that the ALPN token that it selects can run over the QUIC version that it selects."

When a client creates a QUIC connection, its goal is to use an application layer protocol.  Therefore, when considering which versions are compatible, clients will only consider versions that  <ins> support one of the intended application layer protocols.  For example, if the client's first flight advertises multiple Application Layer Protocol Negotiation (ALPN) RFC7301 tokens and multiple compatible versions, the server needs to ensure that the ALPN token that it selects can run over the QUIC version that it selects. </ins> 4.


if it is too short or if its length is not divisible by four), then the endpoint MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of <del> type TRANSPORT_PARAMETER_ERROR. </del>  Every QUIC version that supports version negotiation MUST define a method for closing the connection with a version negotiation error.

Should an endpoint be required to reject a transport parameter that contains 0?
Sure.
CC with ?
That's what I currently have in my implementation :)
Off topic but what if version 0 is included in Supported Version of a VN packet?
That would make the VN packet malformed. I'd suggest either dropping such packets or ignoring the zero.
OK. I modified my client to drop such packets as same as the case of the original version included.
I considered treating it as an error, but as it is an unauthenticated packet, it's better to drop it. I've done the same for ours.

if it is too short or if its length is not divisible by four), then the endpoint MUST close the connection; if the connection was using QUIC version 1, that connection closure MUST use a transport error of  <ins> type TRANSPORT_PARAMETER_ERROR.  If an endpoint receives a Chosen Version equal to zero, or any Other Version equal to zero, it MUST treat it as a parsing failure. </ins> Every QUIC version that supports version negotiation MUST define a method for closing the connection with a version negotiation error.


The server MUST NOT reply with a version that is not present in the client's compatible versions, unless it is the original version. <del> If the server does not find a compatible version, it will use the original version if it supports it, and if it doesn't then the server will perform incompatible version negotiation instead, see incompat- vn. </del>  Note that, after the first flight is converted to the negotiated version, the handshake completes in the negotiated version.  The by only including the Chosen Version in the Other Versions field of the Version Information Transport Parameter.  5. During the handshake, endpoints will exchange Version Information, the version in use for the connection is the version that the server sent in the Chosen Version field of its Version Information.  That remains true even if other versions were used in the Version field of <del> long headers at any point in the lifetime of the connection; endpoints MUST NOT change the version that they consider to be in use based on the Version field of long headers as that field could be forged by attackers. </del>  7.

The currently states: Let's assume the following scenario: the server supports both v1 and v2, and is configured to perform compatible negotiation from 1 to 2 when possible client sends a QUIC v1 initial with "Other Versions" = (1, 2) the server decides to switch to v2, and sends its initial ServerHello as v2, followed by a v2 handshake packet with the first half of the certificate - the transport parameters will follow in a later packet when the client receives the v2 handshake packet, it technically doesn't yet know the "negotiated version" because it hasn't yet parsed the transport parameters Conceptually, this sounds like a terminology issue with the VN draft: at that point in time the client does know that the server wants to use v2, because it's parsed a v2 ServerHello - but I think we need a name for that in the VN draft so that the v2 draft can refer to it for the MUST above. cc NAME NAME -- the more I think about it the more I think that to "use instead of validate" is making the spec and implementation writing a lot harder - the idea makes sense in theory, but in practice it complicates the handshake. Maybe we go back to something like "the negotiated version is the one seen in long headers, and the Chosen Version in the TP exists to validate that it matches after the fact"
I agree. Let's get the terminology right.
This WFM. FWIW, my implementation at the client uses long header packets to "negotiate" the version at the client; the transport parameters are used at the server. Validation at the server is not necessary, but the validation based on a chosen version is right for the client.
My reading of the current editors' draft is that this is a no-op: AFAICT, the term "negotiated version" refers to whatever is the version field of the first server flight. If the editors agree, please close this issue.
I'm reading editor's draft. It says that both peers MUST parse Version Information. This is good. However, a client MUST validate Version Information only on incompatible version negotiation ("acted on a Version Negotiation packet"). I think the same validation should be done on compatible version negotiation.
Can you elaborate? What validation should the client do if it hasn't reacted to a VN packet?
I think that Chosen Version MUST be the same as the version in the Initial packet from the server.
That doesn't quite work - sometimes you might use some packets of the original version (see and ). The security property we want is to ensure that after the handshake, the server's "Chosen Version" is the one used by the connection. That property is guaranteed by this text from the end of Section 6:
NAME So, why does a server have to send back Version Information (which is not validated at all) for compatible negotiation?
This exists to prevent an attacker from modifying the version: since the authenticity of version information is protected during the handshake, it guarantees that, once the handshake is complete, the client is using the version that the server chose.
Do you mean that a client should check if Chosen Version is the same as using version when handshake is complete?
Yes, that's one way of implementing this
The exchange with a successful negotiation may look like: The discussion of issue shows the value of having the server switch to the new version as soon as the negotiation completes. But then, the client can only decrypt the server response if it verifies that "version = B" is an expected response, and then starts using the version B encryption keys, etc. There is very little protection there. Are we worried that third parties might spoof a successful negotiation?
I'm not sure I understand the problem here. The version will be retroactively blessed when the handshake completes, just like the rest of the handshake negotiation.
+1 to what NAME said. NAME this is addressed in :
Yes, I get that the whole posture is "best effort until the handshake is complete, detection of issues during the completion", and that the final verification will detect spoofing and terminate the connection. So this is basically one more avenue for injecting spoofed packets during the handshake, causing the connection to crash. We may or may not want to mention that.
It's already trivial to cause a handshake failure by injecting spoofed packets, this doesn't make it any worse. So I don't think we absolutely need to mention this but I wouldn't oppose an addition to Security Considerations if you want to write a PR.
I am implementing that right now, and I am trying to understand when to accept this "automatic" negotiation. This may be a V1 only issue, but I suspect we will find it with other versions as well. The basic protection is that packets received with the wrong version are considered bogus, and are just ignored. I need to create an exception to that rule when negotiation is in progress, accept packet if the version would be accepted after successful negotiation, and do as if the negotiation had already succeeded. The obvious restriction is to only do that on the client, before the handshake is complete. But that still opens a large time window for attacks. Restricting to "TP negotiation not complete yet" is a bit better than "handshake not complete yet", but still leaves a large window. Restricting to "this is the first packet from the server" does not work, because the server could be sending initial acknowledgements. Reasoning such as "no crypto frame received yet" might work, but the existence of "crypto frames" is version dependent.
NAME what problem are you trying to solve? As long as initial receive keys are present, it's trivial for an attacker to make the handshake fail. The version field doesn't change that in any way, and doesn't offer any protection. Or am I misunderstanding something here?
There is indeed a denial-of-service window lasting as long as initial packets are accepted. It stops when the handshake keys are computed, at which point picoquic stops processing initial packets. I am trying to ensure that supporting version negotiation does not extend that window. But yes, I fully get the general point. If we want to protect against packet injection during the handshake, we have to use some crypto. Maybe derive a token from ECH, or something like that.
Thanks, I totally agree with your goal. So far I don't see any vector by which this draft extends the DoS window, but adding text to Security Considerations (or perhaps to Considerations for Future Versions) could help ensure we avoid this pitfall in the future.
As we've merged this into the quicv2 draft, is there anything else to say in VN?
Between what we have in the QUICv2 draft and PR here, this should be covered. So I'm going to close this with no action. Please reopen/comment if you disagree.
I am reading the draft, and I have doubts on how this is supposed to affect encryption keys. Suppose a classic exchange: the client sends a couple of initial packets, the server parses them and acknowledges them, the server then sends initial and handshake packets. I think we have the following constraints: 1) The server will only complete the compatible version negotiation after receiving "enough" of the client's initial packets, i.e., enough to parse the QUIC transport parameters. 2) The server transport parameters are sent as encrypted extensions. The client will only receive them after receiving "enough" handshake packets. 3) The client could learn that the server has chosen a new version at any point during the handshake, by receiving a new version field in a long header packet -- Initial or handshake. So we get possible variations: 1) Server receives client first flight with V1, may reply with V1 ACK until the flight has been received, but uses V2 for the reminder of the handshake, i.e., sends server hello in a V2 Initial packet, sends the encrypted parameters and the reminder of the server first flight in V2 handshake packets. Upon reception and successful decryption of initial V2 packet, the client switches to V2. 2) Same but server sends all Initial packets using V1, all handshake packets using V2. Client switches to V2 upon reception and successful decryption of V2 handshake packet. 3) Server keeps using V1 for initial and handshake packets, switches to V2 for 1RTT packets. Client keeps using V1 until the handshake completes, switches to V2 for 1RTT packets. Variation 3 is the easiest to implement, but I suspect that "the server converts the client's first flight to that version and replies to the client as if it had received the converted first flight" actually implies variation 1. That variation requires that the client makes a pretty expensive decision, recomputing the encryption keys using the new version's parameters upon receiving a packet with a "negotiated" version in the version header. Since the encryption key of initial packets is well known, this is yet another avenue for third parties to send poisoned packets and cause the client to fail the connection, but I suppose that will not stop us because there are many such attacks already. In any case, the current text is not very explicit. I think that we will save a lot of interop issues by being more explicit, maybe presenting the expected flow of packets.
I agree that timing of key installation is severe. From the anti-ossification point of view, V2 should be used as much as possible. So, variant 1 is ideal but it is hard to implement it.
I am doing a thought experiment, hypothesizing a V3 version of QUIC in which the handshake changes radically. Instead of using just Initial and Handshake packets, the Handshake would also use Zero RTT packets, because we magically found a way to always have a Resume Token available, or maybe a shared password. In the new V3 version we would have: From client: Initial packet carry Client Hello and some unencrypted parameters. From client: Zero RTT packets carry encrypted handshake parameters From server: Zero RTT packets carry Server Hello and unencrypted extensions. From server: Handshake packets carry reminder of server flight From client: Handshake packet carry Client's Fin. Maybe V3 is designed to prevent third parties from spoofing the server. In the transition phase, we would want something like: From client: Initial V1 packet carry Client Hello and all parameters. From server: Zero RTT V3 packets carry Server Hello and unencrypted extensions. etc... That would preserve the key "defense from spoofing" when the negotiation succeeds. But it does require something like variation .
The current text in the draft was written with Google's implementation in mind, where the server will never send a packet until it has received the full client hello. Therefore the intent was: client sends first flight in v1 if some of those packets get lost, the client retransmits all of them once server receives the full client hello, it can decide to perform compatible VN with v2 all server packets are then sent with v2 This issue makes me realize that some implementations may wish to acknowledge initial packets before receiving the full client hello, which I hadn't thought of. If the client hello ever becomes more than a handful of packets, this might be useful. I would prefer variation 1 (server sends initial acks of client's first flight in v1 but everything else in v2, including the server hello) as that would match our implementation model, and has the property of switching to the newer version ASAP. I agree that we should be clearer, though I'm not sure if that belongs in this draft since this draft intends to be mostly version agnostic. Perhaps that's something that needs to be added to the QUICv2 draft in the section when it declares itself compatible with QUICv1?
Yes, it would be nicer if we add VN scenarios to the V2 draft instead of the VN draft.
I think you cannot pass the burden to every new version draft. You have to be very explicit about what is expected. On the implementation part: picoquic uses picotls. When initial or handshake packets are received, picoquic passes the content of the "crypto" frames to picotls. Picotls does its own thing according to the TLS 1.3 logic. At some point it will callback into picoquic for events like "handshake secret is now available" or "transport parameter option has been received". In my tests, the order of events on the client was: set zero RTT encode secret (when sending the client hello) receive the server initial packet with new version set (which causes client to declare negotiation successful) set handshake encode secret (when receiving the server hello extensions) set handshake decode secret (when receiving the server hello extensions) process the transport options (when receiving the server first flight) set the 1rtt encode secret (after receiving the server first flight) set the 1rtt decode secret (father receiving the server first flight) On the server, the order is: set the zero RTT decode secret (when receiving the client hello) process the transport options (when receiving the client hello) and do the negotiation set handshake encode secret (after composing the server hello) set handshake decode secret (after composing the server hello) send the server initial packet with new version set (which causes client to declare negotiation successful) set the 1rtt encode secret (after sending the server first flight) set the 1rtt decode secret (father receiving the client finished) In the specific case of the V1 to V2 "reprocessing" means replacing the initial key computed with the V1 initial secret by one that uses the V2 secret. However, on the client side, we have to do this reprocessing in a speculative manner, upon receiving a first long header packet with version = V2.
There is something weird happening with 0-RTT. See issue
I don't understand, how can this draft be explicit about future versions that don't exist yet? Is that a problem?
LGTM

The server MUST NOT reply with a version that is not present in the client's compatible versions, unless it is the original version.  <ins> Clients will be made aware of compatible version negotiation by seeing a change in the QUIC long header Version field.  It is possible for the server to initially send packets with the original version before switching to the negotiated version (for example, this can happen when the client's Version Information structured spans multiple packets; in that case the server might acknowledge the first packet in the original version and later switch to a different negotiated version). </ins> Note that, after the first flight is converted to the negotiated version, the handshake completes in the negotiated version.  The by only including the Chosen Version in the Other Versions field of the Version Information Transport Parameter. <ins> If the server does not find a compatible version, it will use the original version if it supports it, and if it doesn't then the server will perform incompatible version negotiation instead, see incompat- vn. </ins> 5. During the handshake, endpoints will exchange Version Information, the version in use for the connection is the version that the server sent in the Chosen Version field of its Version Information.  That remains true even if other versions were used in the Version field of  <ins> long headers at any point in the lifetime of the connection.  In particular, since during compatible version negotiation the client is made aware of the negotiated version by the QUIC long header version (see compat-vn), clients MUST validate that the server's Chosen Version is equal to the negotiated version; if they do not match, the client MUST close the connection with a version negotiation error. This prevents an attacker's ability to influence version negotiation by forging the Version long header field. </ins> 7.