flow control limits set by its peer, and continues to accept and process MAX_STREAM_DATA frames.  An endpoint in the "Send" state generates STREAM_DATA_BLOCKED frames if it is blocked from sending by <del> stream or connection flow control limits data-flow-control. </del>  After the application indicates that all stream data has been sent and a STREAM frame containing the FIN bit is sent, the sending part routed.  This can be used to direct connections to a different server instance. <del> If a server receives a client Initial that can be unprotected but contains an invalid Retry token, it knows the client will not accept </del>  another Retry token.  The server can discard such a packet and allow the client to time out to detect handshake failure, but that could impose a significant latency penalty on the client.  Instead, the lost or when the limit is updated, with care taken to prevent the frame from being sent too often.  An endpoint SHOULD stop sending MAX_STREAM_DATA frames when the receiving part of the stream <del> enters a "Size Known" state. </del>  The limit on streams of a given type is sent in MAX_STREAMS frames.  Like MAX_DATA, an updated value is sent when a packet Examples and a sample decoding algorithm are shown in sample-varint. <del> Versions (versions) and packet numbers sent in the header (packet- encoding) are described using integers, but do not use this encoding. </del>  17. message.  The first CRYPTO frame sent always begins at an offset of 0; see handshake. <del> Note that if the server sends a HelloRetryRequest, the client will send another series of Initial packets.  These Initial packets will continue the cryptographic handshake and will contain CRYPTO frames starting at an offset matching the size of the CRYPTO frames sent in the first flight of Initial packets. </del>  17.2.2.1. restrictions as the first Initial packet.  A client MUST use the same cryptographic handshake message it included in this packet.  A server MAY treat a packet that contains a different cryptographic handshake <del> message as a connection error or discard it. </del>  A client MAY attempt 0-RTT after receiving a Retry packet by sending <del> 0-RTT packets to the connection ID provided by the server.  A client MUST NOT change the cryptographic handshake message it sends in response to receiving a Retry. </del>  A client MUST NOT reset the packet number for any packet number space after processing a Retry packet.  In particular, 0-RTT packets

This should address all of them at once; one per commit for those that I think need action. This is probably OK: This is not expressly forbidden. We do say : Which doesn't really contradict the other. FWIW, I'm not a fan of allowing frames to be copied, implementations really should do that, but it's a consequence of having frame idempotency. This is one I'm not sure about: What is the prevailing advice regarding MTU and tunnels? Clearly when you tunnel you get a smaller MTU, but I haven't seen what happens when IPv6 is tunneled over a network that has a minimum MTU. Most paths don't have that small an MTU, so it might be that things just fail.
I realized that there are some answers here in the description, but probably best to move them to the relevant issues anyways.
NAME said: >
NAME said: with TLS.
NAME said:
NAME said: this true for PATH_CHALLENGE? I thought this quite explicitly shouldn't be copied.
My recommendation is to answer the question, but not change anything. See for an answer.
Very well, please close this issue. Sorry for the confusion.
NAME said: RESET_RECVD.
NAME said:
NAME said:
This looks good to me, with NAME 's nit.

flow control limits set by its peer, and continues to accept and process MAX_STREAM_DATA frames.  An endpoint in the "Send" state generates STREAM_DATA_BLOCKED frames if it is blocked from sending by  <ins> stream flow control limits data-flow-control. </ins> After the application indicates that all stream data has been sent and a STREAM frame containing the FIN bit is sent, the sending part routed.  This can be used to direct connections to a different server instance.  <ins> If a server receives a client Initial that contains an invalid Retry token but is otherwise valid, it knows the client will not accept </ins> another Retry token.  The server can discard such a packet and allow the client to time out to detect handshake failure, but that could impose a significant latency penalty on the client.  Instead, the lost or when the limit is updated, with care taken to prevent the frame from being sent too often.  An endpoint SHOULD stop sending MAX_STREAM_DATA frames when the receiving part of the stream  <ins> enters a "Size Known" or "Reset Recvd" state. </ins> The limit on streams of a given type is sent in MAX_STREAMS frames.  Like MAX_DATA, an updated value is sent when a packet Examples and a sample decoding algorithm are shown in sample-varint.  <ins> Versions (versions), packet numbers sent in the header (packet- encoding), and the length of connection IDs in long header packets (long-header) are described using integers, but do not use this encoding. </ins> 17. message.  The first CRYPTO frame sent always begins at an offset of 0; see handshake.  <ins> Note that if the server sends a TLS HelloRetryRequest (see Section 4.7 of QUIC-TLS), the client will send another series of Initial packets.  These Initial packets will continue the cryptographic handshake and will contain CRYPTO frames starting at an offset matching the size of the CRYPTO frames sent in the first flight of Initial packets. </ins> 17.2.2.1. restrictions as the first Initial packet.  A client MUST use the same cryptographic handshake message it included in this packet.  A server MAY treat a packet that contains a different cryptographic handshake  <ins> message as a connection error or discard it.  Note that including a Token field reduces the available space for the cryptographic handshake message, which might result in the client needing to send multiple Initial packets. </ins> A client MAY attempt 0-RTT after receiving a Retry packet by sending  <ins> 0-RTT packets to the connection ID provided by the server. </ins> A client MUST NOT reset the packet number for any packet number space after processing a Retry packet.  In particular, 0-RTT packets


IPv4 networks.  Assuming the minimum IP header size of 40 bytes for IPv6 and 20 bytes for IPv4 and a UDP header size of 8 bytes, this results in a maximum datagram size of 1232 bytes for IPv6 and 1252 <del> bytes for IPv4.  Thus, modern IPv4 and all IPv6 network paths will be able to support QUIC. </del>  Any maximum datagram size larger than 1200 bytes can be discovered using Path Maximum Transmission Unit Discovery (PMTUD; see pmtud) or

NAME said: >14 "Thus, modern IPv4 and all IPv6 network paths will be able to support QUIC." Generally true, but should be qualified for the presence of arbitrary numbers of tunnels.
This is not one that I have an answer to currently. We could just wave this away as Martin suggests, but I'm not sure that is best. What do tunneling protocols say about ensuring the IPv6 minimum MTU?
I don't know what the IETF tunneling protocols say about MTU, but I don't expect them to violate IPv6 minimum MTU (someone should correct me if I'm wrong). The problem here might not be about what allowances we make for tunneling -- I don't want to create a list of exceptions in this document -- but about wording. I propose changing "will be able to support" to "are expected to support". As long as we are not making assumptions that violate permissions afforded by spec or practice, I think we're good.
Thanks. This is weaker, but truer.

IPv4 networks.  Assuming the minimum IP header size of 40 bytes for IPv6 and 20 bytes for IPv4 and a UDP header size of 8 bytes, this results in a maximum datagram size of 1232 bytes for IPv6 and 1252  <ins> bytes for IPv4.  Thus, modern IPv4 and all IPv6 network paths are expected to be able to support QUIC. </ins> Any maximum datagram size larger than 1200 bytes can be discovered using Path Maximum Transmission Unit Discovery (PMTUD; see pmtud) or


messages) that indicate when an IP packet is dropped because it is larger than the local router MTU.  DPLPMTUD can also optionally use these messages.  This use of ICMP messages is potentially vulnerable <del> to off-path attacks that successfully guess the addresses used on the path and reduce the PMTU to a bandwidth-inefficient value. </del>  An endpoint MUST ignore an ICMP message that claims the PMTU has decreased below QUIC's smallest allowed maximum datagram size. unintelligible, as described in Section 1.1 of DPLPMTUD. QUIC endpoints using PMTUD SHOULD validate ICMP messages to protect <del> from off-path injection as specified in RFC8201 and Section 5.2 of </del>  RFC8085.  This validation SHOULD use the quoted packet supplied in the payload of an ICMP message to associate the message with a corresponding transport connection (see Section 4.6.1 of DPLPMTUD). Destination Connection ID of the received packet, which is initially randomly selected by a client.  Echoing both connection IDs gives clients some assurance that the server received the packet and that <del> the Version Negotiation packet was not generated by an off-path attacker. </del>  Future versions of QUIC could have different requirements for the lengths of connection IDs.  In particular, connection IDs might have In order to prevent tampering by version-unaware middleboxes, Initial packets are protected with connection- and version-specific keys (Initial keys) as described in QUIC-TLS.  This protection does not <del> provide confidentiality or integrity against on-path attackers, but provides some level of protection against off-path attackers. </del>  The client and server use the Initial packet type for any packet that contains an initial cryptographic handshake message.  This includes Clients MUST discard Retry packets that have a Retry Integrity Tag that cannot be validated; see the Retry Packet Integrity section of <del> QUIC-TLS.  This diminishes an off-path attacker's ability to inject a Retry packet and protects against accidental corruption of Retry packets.  A client MUST discard a Retry packet with a zero-length Retry Token field. </del>  The client responds to a Retry packet with an Initial packet that includes the provided Retry Token to continue connection modification in the path taken by packets that comprise a connection. Attackers are additionally categorized as either on-path attackers or <del> off-path attackers; see Section 3.5 of SEC-CONS.  An on-path attacker can read, modify, or remove any packet it observes such that it no longer reaches its destination, while an off-path attacker observes the packets, but cannot prevent the original packet from reaching its intended destination.  Both types of attackers can also transmit arbitrary packets. </del>  Properties of the handshake, protected packets, and connection migration are considered separately. An off-path attacker cannot: <del> Modify any part of a packet </del>  Delay packets Reorder original packets <del> An off-path attacker can modify packets that it has observed and inject them back into the network, potentially with spoofed source and destination addresses. </del>  For the purposes of this discussion, it is assumed that an off-path <del> attacker has the ability to observe, modify, and re-inject a packet into the network that will reach the destination endpoint prior to the arrival of the original packet observed by the attacker.  In other words, an attacker has the ability to consistently "win" a race with the legitimate packets between the endpoints, potentially causing the original packet to be ignored by the recipient. </del>  It is also assumed that an attacker has the resources necessary to affect NAT state, potentially both causing an endpoint to lose its

We weren't being consistent. This should help.
NAME said:
The first here is in the process of being addressed, see . I agree regarding "strong", but also agree regarding what to do about it. My proposal is to let close this issue.
NAME said:
Proposed resolution is URL
This is an improvement. Thanks.

messages) that indicate when an IP packet is dropped because it is larger than the local router MTU.  DPLPMTUD can also optionally use these messages.  This use of ICMP messages is potentially vulnerable  <ins> to attacks by entities that cannot observe packets but might successfully guess the addresses used on the path.  These attacks could reduce the PMTU to a bandwidth-inefficient value. </ins> An endpoint MUST ignore an ICMP message that claims the PMTU has decreased below QUIC's smallest allowed maximum datagram size. unintelligible, as described in Section 1.1 of DPLPMTUD. QUIC endpoints using PMTUD SHOULD validate ICMP messages to protect  <ins> from packet injection as specified in RFC8201 and Section 5.2 of </ins> RFC8085.  This validation SHOULD use the quoted packet supplied in the payload of an ICMP message to associate the message with a corresponding transport connection (see Section 4.6.1 of DPLPMTUD). Destination Connection ID of the received packet, which is initially randomly selected by a client.  Echoing both connection IDs gives clients some assurance that the server received the packet and that  <ins> the Version Negotiation packet was not generated by an entity that did not observe the Initial packet. </ins> Future versions of QUIC could have different requirements for the lengths of connection IDs.  In particular, connection IDs might have In order to prevent tampering by version-unaware middleboxes, Initial packets are protected with connection- and version-specific keys (Initial keys) as described in QUIC-TLS.  This protection does not  <ins> provide confidentiality or integrity against attackers that can observe packets, but provides some level of protection against attackers that cannot observe packets. </ins> The client and server use the Initial packet type for any packet that contains an initial cryptographic handshake message.  This includes Clients MUST discard Retry packets that have a Retry Integrity Tag that cannot be validated; see the Retry Packet Integrity section of  <ins> QUIC-TLS.  This diminishes an attacker's ability to inject a Retry packet and protects against accidental corruption of Retry packets. A client MUST discard a Retry packet with a zero-length Retry Token field. </ins> The client responds to a Retry packet with an Initial packet that includes the provided Retry Token to continue connection modification in the path taken by packets that comprise a connection. Attackers are additionally categorized as either on-path attackers or  <ins> off-path attackers.  An on-path attacker can read, modify, or remove any packet it observes such that it no longer reaches its destination, while an off-path attacker observes the packets, but cannot prevent the original packet from reaching its intended destination.  Both types of attackers can also transmit arbitrary packets.  This definition differs from that of Section 3.5 of SEC- CONS in that an off-path attacker is able to observe packets. </ins> Properties of the handshake, protected packets, and connection migration are considered separately. An off-path attacker cannot:  <ins> Modify packets sent by endpoints </ins> Delay packets Reorder original packets  <ins> An off-path attacker can create modified copies of packets that it has observed and inject those copies into the network, potentially with spoofed source and destination addresses. </ins> For the purposes of this discussion, it is assumed that an off-path  <ins> attacker has the ability to inject a modified copy of a packet into the network that will reach the destination endpoint prior to the arrival of the original packet observed by the attacker.  In other words, an attacker has the ability to consistently "win" a race with the legitimate packets between the endpoints, potentially causing the original packet to be ignored by the recipient. </ins> It is also assumed that an attacker has the resources necessary to affect NAT state, potentially both causing an endpoint to lose its


Section 7.5 of QUIC-TRANSPORT. Once the TLS handshake is complete, this is indicated to QUIC along <del> with any final handshake bytes that TLS needs to send.  TLS also provides QUIC with the transport parameters that the peer advertised during the handshake. </del>  Once the handshake is complete, TLS becomes passive.  TLS can still receive data from its peer and respond in kind, but it will not need error of type 0x16d (equivalent to a fatal TLS missing_extension alert, see tls-errors). <del> While the transport parameters are technically available prior to the completion of the handshake, they cannot be fully trusted until the handshake completes, and reliance on them should be minimized. However, any tampering with the parameters will cause the handshake to fail. </del>  Endpoints MUST NOT send this extension in a TLS connection that does not use QUIC (such as the use of TLS with TCP defined in TLS13).  A

This is OK, but only in a limited fashion.
NAME said: parameters are not delivered until the handshake is complete. In 8.2 it says that the TPs are "available" but "not fully trusted" before completion. The latter is certainly true; but the server can't send 0.5-RTT packets (e.g. a SETTINGS frame) without any indication of the client transport parameters. I would suggest a clarification in 4.1.3 and letting the language in 8.2 stand.
Proposed resolution is
I think the limitations could be a be clearer, but heading in a good direction.I think the changes add clarity.

Section 7.5 of QUIC-TRANSPORT. Once the TLS handshake is complete, this is indicated to QUIC along  <ins> with any final handshake bytes that TLS needs to send.  At this stage, the transport parameters that the peer advertised during the handshake are authenticated; see quic_parameters. </ins> Once the handshake is complete, TLS becomes passive.  TLS can still receive data from its peer and respond in kind, but it will not need error of type 0x16d (equivalent to a fatal TLS missing_extension alert, see tls-errors).  <ins> Transport parameters become available prior to the completion of the handshake.  A server might use these values earlier than handshake completion.  However, the value of transport parameters is not authenticated until the handshake completes, so any use of these parameters cannot depend on their authenticity.  Any tampering with transport parameters will cause the handshake to fail. </ins> Endpoints MUST NOT send this extension in a TLS connection that does not use QUIC (such as the use of TLS with TCP defined in TLS13).  A


Application Data may appear only in the Early Data and Application Data levels.  Handshake and Alert messages may appear in any level. <del> The 0-RTT handshake is only possible if the client and server have </del>  previously communicated.  In the 1-RTT handshake, the client is unable to send protected Application Data until it has received all of the Handshake messages sent by the server.

Though I guess provisioning of a PSK depends on prior communication of a sort, there is no need to be so absolute here.
NAME said:
I will suggest that we strike the "only" here.

Application Data may appear only in the Early Data and Application Data levels.  Handshake and Alert messages may appear in any level.  <ins> The 0-RTT handshake can be used if the client and server have </ins> previously communicated.  In the 1-RTT handshake, the client is unable to send protected Application Data until it has received all of the Handshake messages sent by the server.


Handshake state updates <del> Additional functions might be needed to configure TLS. </del>  4.1.1.

Important enough to call out in this section.
Roman Danyliw said:
I think that we're OK, and the text added in should help avoid any need for this point.
NAME said:
Should we split this bit out into a separate issue? per §4.8 TLS alerts are translated into QUIC connection errors and are not sent natively. (The prose also says "TLS Handshake and Alert messages are carried directly over the QUIC transport".)
I don't think we need to do anything in response to that. Those messages are carried by QUIC.
I will defer to your preference, but I do not agree that "those messages" are carried by QUIC; QUIC does not carry TLS Alert structures.
a nit but lgtm

Handshake state updates  <ins> Additional functions might be needed to configure TLS.  In particular, QUIC and TLS need to agree on which is responsible for validation of peer credentials, such as certificate validation (RFC5280). </ins> 4.1.1.


from the range reserved for CRYPTO_ERROR.  The resulting value is sent in a QUIC CONNECTION_CLOSE frame of type 0x1c. <del> The alert level of all TLS alerts is "fatal"; a TLS stack MUST NOT generate alerts at the "warning" level. </del>  QUIC permits the use of a generic code in place of a specific error code; see Section 11 of QUIC-TRANSPORT.  For TLS alerts, this

This changes the shape of the requirement from one that proscribes the behaviour of a TLS stack to the reaction of QUIC to a warning level alert. This recommends treating them as fatal as QUIC never deliberately closes TLS. This is a normative change that should have no practical effect on implementations.
NAME said:
I'm going to request that we flag this one "design". I think that we want to say: the TLS connection is never closed using TLS mechanisms QUIC can treat any TLS alert as fatal PR created and email in the pipe.
Marking this as design as requested.
Returning to an open state as the chairs directed in their plan.
Closing this now that the IESG have approved the document(s).
I agree that this is a good improvement, especially for folks who can't modify their TLS stack.

from the range reserved for CRYPTO_ERROR.  The resulting value is sent in a QUIC CONNECTION_CLOSE frame of type 0x1c.  <ins> QUIC is only able to convey an alert level of "fatal".  In TLS 1.3, the only existing uses for the "warning" level are to signal connection close; see Section 6.1 of TLS13.  As QUIC provides alternative mechanisms for connection termination and the TLS connection is only closed if an error is encountered, a QUIC endpoint MUST treat any alert from TLS as if it were at the "fatal" level. </ins> QUIC permits the use of a generic code in place of a specific error code; see Section 11 of QUIC-TRANSPORT.  For TLS alerts, this


The keys used for packet protection are computed from the TLS secrets using the KDF provided by TLS.  In TLS 1.3, the HKDF-Expand-Label function described in Section 7.1 of TLS13 is used, using the hash <del> function from the negotiated cipher suite.  Note that labels, which are described using strings, are encoded as bytes using ASCII ASCII without quotes or any trailing NUL byte.  Other versions of TLS MUST provide a similar function in order to be used with QUIC. </del>  The current encryption level secret and the label "quic key" are input to the KDF to produce the AEAD key; the label "quic iv" is used these labels provides key separation between QUIC and TLS; see key- diversity.  The KDF used for initial secrets is always the HKDF-Expand-Label function from TLS 1.3; see initial-secrets.

This was a pretty serious omission, even if it was obvious enough that no one ever noticed when implementing it.
NAME said:
The Context thing should be addressed by . The 4 bits should be "Unused" to match the transport spec. I'll fix that.
NAME said:
Oh, so many things to unpack from a short comment... Yes, Context should be explicitly empty. I'll create a PR for this and the other, below. The TLS transcript is integrated into the derivation of the keys that we use, so we don't need to include it again. As an aside, EAP-TLS1.3 use of 0x0D in the exporter is counter to the intended use of the field. They already have all the fixed key separation necessary through the use of the exporter label. The field is intended to capture variable, contextual information such as identities or other things that are not already folded into the handshake. I agree that using a different span of the handshake transcript for key derivation would be massively disruptive, that is why I would oppose doing that. As with Context, so too with Length, though that requires a little more text to address. That's in the PR too. Note: I had to decide between NMAX and NMIN and chose N_MAX. Though the values are the same for all of the AEADs we use, that isn't guaranteed. I'm sure that an AEAD with variable-length nonce could manage, but no sense in being imprecise. I want nothing to do with Derive-Secret. That's too far into TLS internals.
I think that the separation that we have now is good and that we do not need to change the design. Regarding IV length, as stated in the PR review comment, we are using TLS cipher-suites. Therefore I think we should be using what is defined in TLS 1.3 (i.e. ) rather than specifying a different rule.

The keys used for packet protection are computed from the TLS secrets using the KDF provided by TLS.  In TLS 1.3, the HKDF-Expand-Label function described in Section 7.1 of TLS13 is used, using the hash  <ins> function from the negotiated cipher suite.  All uses of HKDF-Expand- Label in QUIC use a zero-length Context. Note that labels, which are described using strings, are encoded as bytes using ASCII ASCII without quotes or any trailing NUL byte. Other versions of TLS MUST provide a similar function in order to be used with QUIC. </ins> The current encryption level secret and the label "quic key" are input to the KDF to produce the AEAD key; the label "quic iv" is used these labels provides key separation between QUIC and TLS; see key- diversity. <ins> Both "quic key" and "quic hp" are used to produce keys, so the Length provided to HKDF-Expand-Label along with these labels is determined by the size of keys in the AEAD or header protection algorithm.  The Length provided with "quic iv" is the minimum length of the AEAD nonce, or 8 bytes if that is larger; see AEAD. </ins> The KDF used for initial secrets is always the HKDF-Expand-Label function from TLS 1.3; see initial-secrets.


The same number of bytes are always sampled, but an allowance needs to be made for the endpoint removing protection, which will not know <del> the length of the Packet Number field.  In sampling the packet ciphertext, the Packet Number field is assumed to be 4 bytes long (its maximum possible encoded length). </del>  An endpoint MUST discard packets that are not long enough to contain a complete sample.

Though people will undoubtedly rely on pseudocode to understand this, there is no reason why we can't also use prose.
NAME said:
That's just an oops. There is a paragraph that almost defines this in prose. It just needs a little push and we don't need to rely exclusively on pseudocode.

The same number of bytes are always sampled, but an allowance needs to be made for the endpoint removing protection, which will not know  <ins> the length of the Packet Number field.  The sample of ciphertext is taken starting from an offset of 4 bytes after the start of the Packet Number field.  That is, in sampling packet ciphertext for header protection, the Packet Number field is assumed to be 4 bytes long (its maximum possible encoded length). </ins> An endpoint MUST discard packets that are not long enough to contain a complete sample.


Once an endpoint successfully receives a packet with a given packet number, it MUST discard all packets in the same packet number space with higher packet numbers if they cannot be successfully unprotected <del> with either the same key, or - if there is a key update - the next packet protection key (see key-update).  Similarly, a packet that appears to trigger a key update, but cannot be unprotected successfully MUST be discarded. </del>  Failure to unprotect a packet does not necessarily indicate the existence of a protocol error in a peer or an attack.  The truncated

This is a little pedantic, but it's more correct. Also fix reference format.
NAME said:

Once an endpoint successfully receives a packet with a given packet number, it MUST discard all packets in the same packet number space with higher packet numbers if they cannot be successfully unprotected  <ins> with either the same key, or - if there is a key update - a subsequent packet protection key; see key-update.  Similarly, a packet that appears to trigger a key update, but cannot be unprotected successfully MUST be discarded. </ins> Failure to unprotect a packet does not necessarily indicate the existence of a protocol error in a peer or an attack.  The truncated


avoid replay attacks on the protocol. Of the frames defined in QUIC-TRANSPORT, the STREAM, RESET_STREAM, <del> and CONNECTION_CLOSE frames are potentially unsafe for use with 0-RTT as they carry application data.  Application data that is received in 0-RTT could cause an application at the server to process the data multiple times rather than just once.  Additional actions taken by a server as a result of processing replayed application data could have unwanted consequences.  A client therefore MUST NOT use 0-RTT for application data unless specifically requested by the application that is in use. </del>  An application protocol that uses QUIC MUST include a profile that defines acceptable use of 0-RTT; otherwise, 0-RTT can only be used to

So it could be unsafe for use in 0-RTT.
NAME said:
STOP_SENDING can be sent in 0-RTT. It should be in the list.

avoid replay attacks on the protocol. Of the frames defined in QUIC-TRANSPORT, the STREAM, RESET_STREAM,  <ins> STOP_SENDING, and CONNECTION_CLOSE frames are potentially unsafe for use with 0-RTT as they carry application data.  Application data that is received in 0-RTT could cause an application at the server to process the data multiple times rather than just once.  Additional actions taken by a server as a result of processing replayed application data could have unwanted consequences.  A client therefore MUST NOT use 0-RTT for application data unless specifically requested by the application that is in use. </ins> An application protocol that uses QUIC MUST include a profile that defines acceptable use of 0-RTT; otherwise, 0-RTT can only be used to


The process of creating new packet protection keys for receiving packets could reveal that a key update has occurred.  An endpoint MAY <del> perform this process as part of packet processing, but this creates a timing signal that can be used by an attacker to learn when key updates happen and thus the value of the Key Phase bit in certain packets.  Endpoints MAY instead defer the creation of the next set of receive packet protection keys until some time after a key update completes, up to three times the PTO; see old-keys-recv. </del>  Once generated, the next set of packet protection keys SHOULD be retained, even if the packet that was received was subsequently Phase bit alone can be used to select keys. An endpoint MAY allow a period of approximately the Probe Timeout <del> (PTO; see QUIC-RECOVERY) after receiving a packet that uses the new key generation before it creates the next set of packet protection keys.  These updated keys MAY replace the previous keys at that time. With the caveat that PTO is a subjective measure - that is, a peer could have a different view of the RTT - this time is expected to be long enough that any reordered packets would be declared lost by a peer even if they were acknowledged and short enough to allow for subsequent key updates. </del>  Endpoints need to allow for the possibility that a peer might not be able to decrypt packets that initiate a key update during the period

Some of this is just forward reference, but it does need a little more context. Also, there was a missing word.
This also no?
NAME said:
I'll roll this into the change for as it relates to the same basic text. I like the "promoting" idea, though I'm not going to go back and rewrite everything to use it. Here, the important thing is to have words for current, next, and "subsequent next" to avoid making this more confusing than necessary. I think that I got it.
NAME said:
I can see an obvious missing word in there at a minimum. I can see some opportunities for clarification here though, so I'll give it a go. Breaking the ordering dependencies between sections is tricky though. It might just be that we need a little redundancy.
This is a big help; thank you!

The process of creating new packet protection keys for receiving packets could reveal that a key update has occurred.  An endpoint MAY  <ins> generate new keys as part of packet processing, but this creates a timing signal that could be used by an attacker to learn when key updates happen and thus leak the value of the Key Phase bit. Endpoints are generally expected to have current and next receive packet protection keys available.  For a short period after a key update completes, up to the PTO, endpoints MAY defer generation of the next set of receive packet protection keys.  This allows endpoints to retain only two sets of receive keys; see old-keys-recv. </ins> Once generated, the next set of packet protection keys SHOULD be retained, even if the packet that was received was subsequently Phase bit alone can be used to select keys. An endpoint MAY allow a period of approximately the Probe Timeout  <ins> (PTO; see QUIC-RECOVERY) after promoting the next set of receive keys to be current before it creates the subsequent set of packet protection keys.  These updated keys MAY replace the previous keys at that time.  With the caveat that PTO is a subjective measure - that is, a peer could have a different view of the RTT - this time is expected to be long enough that any reordered packets would be declared lost by a peer even if they were acknowledged and short enough to allow a peer to initiate further key updates. </ins> Endpoints need to allow for the possibility that a peer might not be able to decrypt packets that initiate a key update during the period


Future analyses and specifications MAY relax confidentiality or integrity limits for an AEAD. <del> These limits were originally calculated using assumptions about the limits on TLS record size.  The maximum size of a TLS record is 2^14 bytes.  In comparison, QUIC packets can be up to 2^16 bytes.  However, it is expected that QUIC packets will generally be smaller than TLS records.  Where packets might be larger than 2^14 bytes in length, smaller limits might be needed. </del> Any TLS cipher suite that is specified for use with QUIC MUST define limits on the use of the associated AEAD function that preserves margins for confidentiality and integrity.  That is, limits MUST be

We changed the limits listed here to be based on the maximum packet size, so the note a few paragraphs up citing the appendix is all we need here.
NAME said:
A few things here... The text in DTLS is a copy of this text, so similarities are no accident. However, the text has diverged, so drawing an analogy doesn't seem necessary (and I don't want a downref, even if it were informational). The numbers we are using from TLS is the target advantage probability. QUIC has a larger limit on packet size than TLS has on record size. Larger sizes affects the limits, which is what you see there. The note you quote is old and it should have been removed when we changed the numbers. As noted the analysis for DTLS would be helpful, but not definitive. As you say, the number of blocks in a packet can have an effect (though not for ChaCha20Poly1305 apparently). So l've a PR for the note, but I don't see any other action here.
I have an action item (to pester the DTLS 1.3 authors to reduce the divergence), but I agree there's no other action for this document.

Future analyses and specifications MAY relax confidentiality or integrity limits for an AEAD.  Any TLS cipher suite that is specified for use with QUIC MUST define limits on the use of the associated AEAD function that preserves margins for confidentiality and integrity.  That is, limits MUST be


and destination addresses, source and destination UDP ports, and the Destination Connection ID field.  The flow label generation MUST be designed to minimize the chances of linkability with a previously <del> used flow label, as this would enable correlating activity on multiple paths; see migration-linkability. </del>  A possible implementation is to compute the flow label as a cryptographic hash function of the source and destination addresses,

The text was probably backwards, but rather than invert it, remove the indirect reference to the subject of the claim and be explicit.
Erik Kline said:

and destination addresses, source and destination UDP ports, and the Destination Connection ID field.  The flow label generation MUST be designed to minimize the chances of linkability with a previously  <ins> used flow label, as a stable flow label would enable correlating activity on multiple paths; see migration-linkability. </ins> A possible implementation is to compute the flow label as a cryptographic hash function of the source and destination addresses,


bytes for IPv4.  Thus, modern IPv4 and all IPv6 network paths are expected to be able to support QUIC.  Any maximum datagram size larger than 1200 bytes can be discovered using Path Maximum Transmission Unit Discovery (PMTUD; see pmtud) or Datagram Packetization Layer PMTU Discovery (DPLPMTUD; see dplpmtud). fragmented or dropped (RFC8085). If a QUIC endpoint determines that the PMTU between any pair of local <del> and remote IP addresses has fallen below the smallest allowed maximum </del>  datagram size of 1200 bytes, it MUST immediately cease sending QUIC packets, except for those in PMTU probes or those containing CONNECTION_CLOSE frames, on the affected path.  An endpoint MAY

URL the path doesn't provide extra headroom. Includes some rewording of the text.
Éric Vyncke said:
We wanted some space for things like extension headers/options and maybe for tunnels. See which is in response to your peer Erik. And yeah, 1200 is a nice number.
Based on the discussion here and the linked issue, I don't think we need to do anything here.
Erik Kline said:
Seems reasonable to mention. Obviously many paths support a larger MTU and so will support more extensions (or options), but it's worth noting that there isn't a ton of space available.

bytes for IPv4.  Thus, modern IPv4 and all IPv6 network paths are expected to be able to support QUIC. <ins> This requirement to support a UDP payload of 1200 bytes limits the space available for IPv6 extension headers to 32 bytes or IPv4 options to 52 bytes if the path only supports the IPv6 minimum MTU of 1280 bytes.  This affects Initial packets and path validation. </ins> Any maximum datagram size larger than 1200 bytes can be discovered using Path Maximum Transmission Unit Discovery (PMTUD; see pmtud) or Datagram Packetization Layer PMTU Discovery (DPLPMTUD; see dplpmtud). fragmented or dropped (RFC8085). If a QUIC endpoint determines that the PMTU between any pair of local  <ins> and remote IP addresses cannot support the smallest allowed maximum </ins> datagram size of 1200 bytes, it MUST immediately cease sending QUIC packets, except for those in PMTU probes or those containing CONNECTION_CLOSE frames, on the affected path.  An endpoint MAY


connection ID to be routed back to the endpoint and to be identified by the endpoint upon receipt.  Connection IDs MUST NOT contain any information that can be used by an external observer (that is, one that does not cooperate with the issuer) to correlate them with other connection IDs for the same

Éric Vyncke said:
We say it, but it comes a lot later. Too late, I think.

connection ID to be routed back to the endpoint and to be identified by the endpoint upon receipt. <ins> Multiple connection IDs are used so that endpoints can send packets that cannot be identified by an observer as being for the same connection without cooperation from an endpoint; see migration- linkability. </ins> Connection IDs MUST NOT contain any information that can be used by an external observer (that is, one that does not cooperate with the issuer) to correlate them with other connection IDs for the same


4.7. QUIC uses a probe timeout (PTO; see pto), with a timer based on TCP's <del> RTO computation.  QUIC's PTO includes the peer's maximum expected acknowledgment delay instead of using a fixed minimum timeout.  QUIC does not collapse the congestion window until persistent congestion (persistent-congestion) is declared, unlike TCP, which collapses the congestion window upon expiry of an RTO.  Instead of collapsing the congestion window and declaring everything in-flight lost, QUIC allows probe packets to temporarily exceed the congestion window whenever the timer expires. In doing this, QUIC avoids unnecessary congestion window reductions, </del>  obviating the need for correcting mechanisms such as F-RTO (RFC5682). Since QUIC does not collapse the congestion window on a PTO expiration, a QUIC sender is not limited from sending more in-flight timer expires.  This is more aggressive than TCP's RTO mechanism when application-limited, but identical when not application-limited. <del> A single packet loss at the tail does not indicate persistent congestion, so QUIC specifies a time-based definition to ensure one or more packets are sent prior to a dramatic decrease in congestion window; see persistent-congestion. </del>  4.8. Acknowledgment-based loss detection implements the spirit of TCP's Fast Retransmit (RFC5681), Early Retransmit (RFC5827), FACK (FACK), <del> SACK loss recovery (RFC6675), and RACK (RACK).  This section provides an overview of how these algorithms are implemented in QUIC. </del>  A packet is declared lost if it meets all the following conditions:

and part of
Alissa Cooper said:
NAME said:
Good point, also 4.7 currently has TLP in the title, but doesn't use it anywhere else in the section, so I'll add some text on TLP too. URL
Please also update the RACK reference to version 14. draft-ietf-tcpm-rack-14
The version update is part of the toolchain we use, so the newest version of RACK should be referenced automatically.

4.7. QUIC uses a probe timeout (PTO; see pto), with a timer based on TCP's  <ins> RTO computation; see RFC6297.  QUIC's PTO includes the peer's maximum expected acknowledgment delay instead of using a fixed minimum timeout. Similar to the RACK-TLP loss detection algorithm for TCP (RACK), QUIC does not collapse the congestion window when the PTO expires, since a single packet loss at the tail does not indicate persistent congestion.  Instead, QUIC collapses the congestion window when persistent congestion is declared; see persistent-congestion.  In doing this, QUIC avoids unnecessary congestion window reductions, </ins> obviating the need for correcting mechanisms such as F-RTO (RFC5682). Since QUIC does not collapse the congestion window on a PTO expiration, a QUIC sender is not limited from sending more in-flight timer expires.  This is more aggressive than TCP's RTO mechanism when application-limited, but identical when not application-limited.  <ins> QUIC allows probe packets to temporarily exceed the congestion window whenever the timer expires. </ins> 4.8. Acknowledgment-based loss detection implements the spirit of TCP's Fast Retransmit (RFC5681), Early Retransmit (RFC5827), FACK (FACK),  <ins> SACK loss recovery (RFC6675), and RACK-TLP (RACK).  This section provides an overview of how these algorithms are implemented in QUIC. </ins> A packet is declared lost if it meets all the following conditions:


Abstract This document defines the properties of the QUIC transport protocol <del> that are expected to remain unchanged over time as new versions of the protocol are developed. </del>  Note to Readers

This reconciles the abstract with the content
Éric Vyncke said:
The abstract hasn't kept pace with the text. It can be made clearer.

Abstract This document defines the properties of the QUIC transport protocol  <ins> that are common to all versions of the protocol. </ins> Note to Readers


RESET_STREAM frame instead of retransmitting the data. An endpoint SHOULD copy the error code from the STOP_SENDING frame to <del> the RESET_STREAM frame it sends, but MAY use any application error </del>  code.  An endpoint that sends a STOP_SENDING frame MAY ignore the error code in any RESET_STREAM frames subsequently received for that stream. non-probing packet with a new largest packet number on its preferred address, the server begins sending non-probing packets to the client exclusively from its preferred IP address.  It SHOULD drop packets <del> for this connection received on the old IP address, but MAY continue </del>  to process delayed packets. The addresses that a server provides in the preferred_address

Barry Leiba said:
The other reference was: — Section 3.5 — An endpoint SHOULD copy the error code from the STOPSENDING frame to the RESETSTREAM frame it sends, but MAY use any application error code. I'm OK with changing to "can".
I don't think we need to do this; I've suggested changes on the PR.
Ok, let's merge this one, and I'll make a separate PR for the second comment.

RESET_STREAM frame instead of retransmitting the data. An endpoint SHOULD copy the error code from the STOP_SENDING frame to  <ins> the RESET_STREAM frame it sends, but can use any application error </ins> code.  An endpoint that sends a STOP_SENDING frame MAY ignore the error code in any RESET_STREAM frames subsequently received for that stream. non-probing packet with a new largest packet number on its preferred address, the server begins sending non-probing packets to the client exclusively from its preferred IP address.  It SHOULD drop packets  <ins> for this connection received on the old IP address, but can continue </ins> to process delayed packets. The addresses that a server provides in the preferred_address


Attackers could replay tokens to use servers as amplifiers in DDoS attacks.  To protect against such attacks, servers MUST ensure that replay of tokens is prevented or limited.  Servers SHOULD ensure that <del> tokens sent in Retry packets are only accepted for a short time. Tokens that are provided in NEW_TOKEN frames (frame-new-token) need to be valid for longer, but SHOULD NOT be accepted multiple times in a short period.  Servers are encouraged to allow tokens to be used only once, if possible; tokens MAY include additional information about clients to further narrow applicability or reuse. </del>  8.2.

They only need to be good for one RTT. Of course, the server doesn't really know what the RTT is, so this isn't something firm, and I don't want to explain ALL of that, but this should do.
Roman Danyliw said:

Attackers could replay tokens to use servers as amplifiers in DDoS attacks.  To protect against such attacks, servers MUST ensure that replay of tokens is prevented or limited.  Servers SHOULD ensure that  <ins> tokens sent in Retry packets are only accepted for a short time, as they are returned immediately by clients.  Tokens that are provided in NEW_TOKEN frames (frame-new-token) need to be valid for longer, but SHOULD NOT be accepted multiple times.  Servers are encouraged to allow tokens to be used only once, if possible; tokens MAY include additional information about clients to further narrow applicability or reuse. </ins> 8.2.


window of 10 times the maximum datagram size (max_datagram_size), limited to the larger of 14720 bytes or twice the maximum datagram size.  This follows the analysis and recommendations in RFC6928, <del> increasing the byte limit to account for the smaller 8 byte overhead of UDP compared to the 20 byte overhead for TCP. </del>  If the maximum datagram size changes during the connection, the initial congestion window SHOULD be recalculated with the new size.

and the 20-byte overhead too. (If this is superseded, that's cool. Low hanging fruit...)
Éric Vyncke said:

window of 10 times the maximum datagram size (max_datagram_size), limited to the larger of 14720 bytes or twice the maximum datagram size.  This follows the analysis and recommendations in RFC6928,  <ins> increasing the byte limit to account for the smaller 8-byte overhead of UDP compared to the 20-byte overhead for TCP. </ins> If the maximum datagram size changes during the connection, the initial congestion window SHOULD be recalculated with the new size.


Indicates that x is optional (and has length of L) <del> Indicates that x is repeated zero or more times (and that each instance is length L) </del>  This document uses network byte order (that is, big endian) values. Fields are placed starting from the high-order bits of each byte.

Not repetitions, which might be read to mean one or more occurrences. This change will conflict, but the conflict is easy to resolve.
NAME said:
It is zero or more occurrences is correct and will adjust the text accordingly.

Indicates that x is optional (and has length of L)  <ins> Indicates that zero or more instances of x are present (and that each instance is length L) </ins> This document uses network byte order (that is, big endian) values. Fields are placed starting from the high-order bits of each byte.


case where state is lost, so this approach is suboptimal. A single static key can be used across all connections to the same <del> endpoint by generating the proof using a second iteration of a preimage-resistant function that takes a static key and the connection ID chosen by the endpoint (see connection-id) as input. An endpoint could use HMAC RFC2104 (for example, HMAC(static_key, connection_id)) or HKDF RFC5869 (for example, using the static key as input keying material, with the connection ID as salt).  The output of this function is truncated to 16 bytes to produce the Stateless Reset Token for that connection. </del>  An endpoint that loses state can use the same method to generate a valid Stateless Reset Token.  The connection ID comes from the packet

The second iteration piece is cruft and confusing.
NAME said:
I think that's an oops. I'll cut that. It's just the PRF part we need.

case where state is lost, so this approach is suboptimal. A single static key can be used across all connections to the same  <ins> endpoint by generating the proof using a pseudorandom function that takes a static key and the connection ID chosen by the endpoint (see connection-id) as input.  An endpoint could use HMAC RFC2104 (for example, HMAC(static_key, connection_id)) or HKDF RFC5869 (for example, using the static key as input keying material, with the connection ID as salt).  The output of this function is truncated to 16 bytes to produce the Stateless Reset Token for that connection. </ins> An endpoint that loses state can use the same method to generate a valid Stateless Reset Token.  The connection ID comes from the packet


carry. An endpoint received transport parameters that were badly <del> formatted, included an invalid value, was absent even though it is mandatory, was present though it is forbidden, or is otherwise in error. </del>  The number of connection IDs provided by the peer exceeds the advertised active_connection_id_limit.

Error because you were going to violate the transport parameters we negotiated. You know you were! YOU KNOW IT!
NAME said:
I guess we were missing future tense, which would have made this sentence really fun.

carry. An endpoint received transport parameters that were badly  <ins> formatted, included an invalid value, omitted a mandatory transport parameter, included a forbidden transport parameter, or were otherwise in error. </ins> The number of connection IDs provided by the peer exceeds the advertised active_connection_id_limit.


discard packets that are received on a different network path. The Source and Destination Connection ID fields are the primary means <del> of protection against off-path attack during the handshake.  These are required to match those set by a peer.  Except for an Initial and stateless reset packets, an endpoint only accepts packets that include a Destination Connection ID field that matches a value the endpoint previously chose.  This is the only protection offered for Version Negotiation packets. </del>  The Destination Connection ID field in an Initial packet is selected by a client to be unpredictable, which serves an additional purpose.

NAME said:
I believe that we are perfectly OK for the handshake. We can cite Section 8.1 (again) for this (it's the third paragraph primarily). This is deliberately not specified other places. Mostly because it is hard, but also because any definition would be unnecessarily constraining. I don't agree with Fernando that this absolutely needs specification.

discard packets that are received on a different network path. The Source and Destination Connection ID fields are the primary means  <ins> of protection against off-path attack during the handshake; see validate-handshake.  These are required to match those set by a peer. Except for an Initial and stateless reset packets, an endpoint only accepts packets that include a Destination Connection ID field that matches a value the endpoint previously chose.  This is the only protection offered for Version Negotiation packets. </ins> The Destination Connection ID field in an Initial packet is selected by a client to be unpredictable, which serves an additional purpose.


IP header to influence the sender's rate.  RFC3168 discusses manipulations and their effects in more detail. <del> An on-the-side attacker can duplicate and send packets with modified ECN fields to affect the sender's rate.  If duplicate packets are discarded by a receiver, an off-path attacker will need to race the duplicate packet against the original to be successful in this </del>  attack.  Therefore, QUIC endpoints ignore the ECN field on an IP packet unless at least one QUIC packet in that IP packet is successfully processed; see ecn.

This might conflict, but I think it supersedes the other "off-path" tweaks.
NAME said:

IP header to influence the sender's rate.  RFC3168 discusses manipulations and their effects in more detail.  <ins> A limited on-path attacker can duplicate and send packets with modified ECN fields to affect the sender's rate.  If duplicate packets are discarded by a receiver, an attacker will need to race the duplicate packet against the original to be successful in this </ins> attack.  Therefore, QUIC endpoints ignore the ECN field on an IP packet unless at least one QUIC packet in that IP packet is successfully processed; see ecn.


An endpoint MAY enter the draining state from the closing state if it receives a CONNECTION_CLOSE frame, which indicates that the peer is <del> also closing or draining.  In this case, the draining state SHOULD end when the closing state would have ended.  In other words, the endpoint uses the same end time, but ceases transmission of any packets on this connection. </del>  10.2.3.

No need for a SHOULD here. (No issue yet.)
Murray might have more choice words.

An endpoint MAY enter the draining state from the closing state if it receives a CONNECTION_CLOSE frame, which indicates that the peer is  <ins> also closing or draining.  In this case, the draining state ends when the closing state would have ended.  In other words, the endpoint uses the same end time, but ceases transmission of any packets on this connection. </ins> 10.2.3.


measurement and use of the latency spin bit is further discussed in QUIC-MANAGEABILITY. <del> The spin bit is an OPTIONAL feature of this version of QUIC.  A QUIC stack that chooses to support the spin bit MUST implement it as specified in this section. </del>  Each endpoint unilaterally decides if the spin bit is enabled or disabled for a connection.  Implementations MUST allow administrators

Rob Wilton said:
This was talked about on the IESG telechat 2020-01-07. The action item is to add clarity for what an endpoint that does not support the spin bit should do. Note that this is distinct from an endpoint that supports spin bit but chooses to disable it. The discussion leaned towards an editorial change to the text in Section 17.4, for instance in paragraph 3. IIUC no other changes are needed to resolve this discuss, but we should confirm this via email.
I don't get this. The following text seems abundantly clear: Or is it this? Where we don't say that optional == disable it? If that is all, I'm going to hold my tongue.
NAME -- this is good now. Thanks!

measurement and use of the latency spin bit is further discussed in QUIC-MANAGEABILITY.  <ins> The spin bit is an OPTIONAL feature of this version of QUIC.  An endpoint that does not support this feature MUST disable it, as defined below. </ins> Each endpoint unilaterally decides if the spin bit is enabled or disabled for a connection.  Implementations MUST allow administrators


a per-connection basis.  Even when the spin bit is not disabled by the administrator, endpoints MUST disable their use of the spin bit for a random selection of at least one in every 16 network paths, or <del> for one in every 16 connection IDs.  As each endpoint disables the spin bit independently, this ensures that the spin bit signal is disabled on approximately one in eight network paths. </del>  When the spin bit is disabled, endpoints MAY set the spin bit to any value, and MUST ignore any incoming value.  It is RECOMMENDED that

NAME notes: requiring the disabling of the spin bit on a fraction of connections is useful. This may be worth a sentence of explanation. My understanding is that this exists both to protect the ability of endpoints to opt out and to ensure that monitoring is robust when the opt-out is exercised.
Also to ensure that if the functionality is removed/changed in a future version of QUIC, we're only changing the percentage of traffic that enables it versus creating something new.

a per-connection basis.  Even when the spin bit is not disabled by the administrator, endpoints MUST disable their use of the spin bit for a random selection of at least one in every 16 network paths, or  <ins> for one in every 16 connection IDs, in order to ensure that QUIC connections that disable the spin bit are commonly observed on the network.  As each endpoint disables the spin bit independently, this ensures that the spin bit signal is disabled on approximately one in eight network paths. </ins> When the spin bit is disabled, endpoints MAY set the spin bit to any value, and MUST ignore any incoming value.  It is RECOMMENDED that


6.2. <del> Version Negotiation packets are designed to allow future versions of QUIC to negotiate the version in use between endpoints.  Future versions of QUIC might change how implementations that support multiple versions of QUIC react to Version Negotiation packets when attempting to establish a connection using this version. </del>  A client that supports only this version of QUIC MUST abandon the current connection attempt if it receives a Version Negotiation lists the QUIC version selected by the client. How to perform version negotiation is left as future work defined by <del> future versions of QUIC.  In particular, that future work will ensure robustness against version downgrade attacks; see version-downgrade. </del>  6.2.1.

Remove a sentence (apparently) about handling version negotiation packets from the section that's supposed to be about sending them. Clarify that the handling of version negotiation packets is meant to be specified only by standards-track documents (since it is in some sense a cross-version invariant rather than version-specific behavior). In particular, those documents will not necessarily be specifications for a future version of QUIC. New versions of QUIC specified prior to the existence of a version negotiation mechanism are to respond to Version Negotiation packets in the same manner as v1.
Pushed fixups for both points raised.
NAME said:
Responded via email.
My mistake; I haven't responded to this DISCUSS yet. I will do so shortly.
Martin did so (shortly): see URL
NAME said:
This is a common question, but I'm still reluctant to say anything. The best reference I can offer is either or . The former currently doesn't really do anything to address this problem, and I've only a promise to look into this, not even a real commitment to do something. My personal draft is maybe better as the latest version directly addresses the problem, but that had only a lukewarm reception when I presented it and I don't like downrefs to drafts, especially those that aren't working group items.
I guess might have some bearing here as well.
It might be done by including information from VN packets in transport parameters of the eventually-selected version, so the endpoints can validate that they selected the proper version after the fact. That's the most obvious approach. One could also imagine dedicated frame types, something not specific to QUIC, etc.
I had something along the lines of Mike's thought in mind; "There are multiple mechanisms available by which such authentication could occur, including using transport parameters and the TLS transcript hash to provide mutual agreement on the contents of the version negotiation packet, but no such mechanism is currently defined."
I'm still reluctant to say that.
I'm labelling this as editorial, since the request was to "add some indication", which doesn't sound like normative text. If someone would like to argue for adding such text, please prepare a PR.
I propose close with no action. I'm fine without the MUST even, but I can see the argument that it is useful in requiring authentication. I don't see the point in talking about what an endpoint might do; we have to define that in a future spec. Similar to , is it worth stating that future standards-track spec will describe how to do this authentication?
Okay. While I'm not opposed to mentioning it, I did look at this text and choose not to propose a change for it as part of .
One suggestion, but this is good. Excision performed in the service of brevity. We have no information, but that indicates more that we have time to work on a solution. I am confident that we have enough of an escape valve that we will be able to define new versions securely. As is the working group (who I am certain will speak up if they disagree). If only we hadn't already discussed this at length. I think that we know the answer in the general sense, just not in the specific sense of being able to define the bits and manage operational concerns and other protocol design constraints. The working group reached that confidence. I don't know how much effort I'm able to devote now to helping you reach that state. Perhaps other participants would like to offer their help now.

6.2.  <ins> Version Negotiation packets are designed to allow for functionality to be defined in the future that allows QUIC to negotiate the version of QUIC to use for a connection.  Future standards-track specifications might change how implementations that support multiple versions of QUIC react to Version Negotiation packets received in response to an attempt to establish a connection using this version. </ins> A client that supports only this version of QUIC MUST abandon the current connection attempt if it receives a Version Negotiation lists the QUIC version selected by the client. How to perform version negotiation is left as future work defined by  <ins> future standards-track specifications.  In particular, that future work will ensure robustness against version downgrade attacks; see version-downgrade. </ins> 6.2.1.


An application-level error on the individual stream. <del> The term "payload data" is defined in Section 6.4 of SEMANTICS. </del>  Finally, the terms "resource", "message", "user agent", "origin server", "gateway", "intermediary", "proxy", and "tunnel" are defined the header field section, sent as a single HEADERS frame (see frame-headers), <del> optionally, the payload data, if present, sent as a series of DATA </del>  frames (see frame-data), and optionally, the trailer field section, if present, sent as a single HEADERS frame. Header and trailer field sections are described in Sections 6.3 and <del> 6.5 of SEMANTICS; the payload data is described in Section 6.4 of </del>  SEMANTICS. Receipt of an invalid sequence of frames MUST be treated as a A response MAY consist of multiple messages when and only when one or more interim responses (1xx; see Section 15.2 of SEMANTICS) precede a final response to the same request.  Interim responses do not contain <del> payload data or trailers. </del>  An HTTP request/response exchange fully consumes a client-initiated bidirectional QUIC stream.  After sending a request, a client MUST the inclusion of invalid characters in field names or values. <del> A request or response that includes payload data can include a Content-Length header field.  A request or response is also malformed if the value of a Content-Length header field does not equal the sum of the DATA frame lengths that form the payload data.  A response that is defined to have no payload, as described in Section 6.4 of SEMANTICS, can have a non-zero Content-Length field, even though no </del>  content is included in DATA frames. Intermediaries that process HTTP requests or responses (i.e., any 7.2.1. DATA frames (type=0x0) convey arbitrary, variable-length sequences of <del> bytes associated with HTTP request or response payload data. </del>  DATA frames MUST be associated with an HTTP request or response.  If a DATA frame is received on a control stream, the recipient MUST

… avoiding confusion with individual frame payloads (editorial). This is related to the Semantics issue URL
NAME has created URL on http-core Semantics draft, which describes how the term "payload" is overloaded when considered with the H2 and H3 docs. Roy's has a proposal to change that term in Semantics, which impacts the HTTP/3 draft. But he was kind enought to submit PR URL, which demonstrates the impact of that change. This issue is mainly for visibility and tracking purposes.
With or without NAME suggestion. I need to do the same for h2, so it is good to see URL suggestion

An application-level error on the individual stream.  <ins> The term "content" is defined in Section 6.4 of SEMANTICS. </ins> Finally, the terms "resource", "message", "user agent", "origin server", "gateway", "intermediary", "proxy", and "tunnel" are defined the header field section, sent as a single HEADERS frame (see frame-headers),  <ins> optionally, the content, if present, sent as a series of DATA </ins> frames (see frame-data), and optionally, the trailer field section, if present, sent as a single HEADERS frame. Header and trailer field sections are described in Sections 6.3 and  <ins> 6.5 of SEMANTICS; the content is described in Section 6.4 of </ins> SEMANTICS. Receipt of an invalid sequence of frames MUST be treated as a A response MAY consist of multiple messages when and only when one or more interim responses (1xx; see Section 15.2 of SEMANTICS) precede a final response to the same request.  Interim responses do not contain  <ins> content or trailers. </ins> An HTTP request/response exchange fully consumes a client-initiated bidirectional QUIC stream.  After sending a request, a client MUST the inclusion of invalid characters in field names or values.  <ins> A request or response that is defined as having content when it contains a Content-Length header field (Section 6.4.1 of SEMANTICS), is malformed if the value of a Content-Length header field does not equal the sum of the DATA frame lengths received.  A response that is defined as never having content, even when a Content-Length is present, can have a non-zero Content-Length field even though no </ins> content is included in DATA frames. Intermediaries that process HTTP requests or responses (i.e., any 7.2.1. DATA frames (type=0x0) convey arbitrary, variable-length sequences of  <ins> bytes associated with HTTP request or response content. </ins> DATA frames MUST be associated with an HTTP request or response.  If a DATA frame is received on a control stream, the recipient MUST


Examples and a sample decoding algorithm are shown in sample-varint.  Versions (versions), packet numbers sent in the header (packet- encoding), and the length of connection IDs in long header packets (long-header) are described using integers, but do not use this

With one exception.
Rob Wilton said:
The one case where non-optimal encodings are forbidden is URL Otherwise, there is no restriction. Yes, 3 can be encoded in 8 bytes. But it is worth noting. (I thought that we had.)

Examples and a sample decoding algorithm are shown in sample-varint. <ins> Values do not need to be encoded on the minimum number of bytes necessary, with the sole exception of the Frame Type field; see frames. </ins> Versions (versions), packet numbers sent in the header (packet- encoding), and the length of connection IDs in long header packets (long-header) are described using integers, but do not use this


The next two bits (those with a mask of 0x30) of byte 0 contain a packet type.  Packet types are listed in long-packet-types. <del> The lower four bits (those with a mask of 0x0f) of byte 0 are type-specific. </del>  The QUIC Version is a 32-bit field that follows the first byte. This field indicates the version of QUIC that is in use and

So I rewrote the sentence instead.
packet-type-specific?
Rob Wilton said:
In this case, you can simply do "type specific", since type-specific is not an adjective before a noun (like "type-specific bits"). But this is good too.

The next two bits (those with a mask of 0x30) of byte 0 contain a packet type.  Packet types are listed in long-packet-types.  <ins> The semantics of the lower four bits (those with a mask of 0x0f) of byte 0 are determined by the packet type. </ins> The QUIC Version is a 32-bit field that follows the first byte. This field indicates the version of QUIC that is in use and


risk that differing semantics are attributed to the same codepoint by different implementations. <del> Use of the first available codepoint in a range is reserved for allocation using the Standards Action policy; see Section 4.9 of RFC8126.  The early codepoint assignment process EARLY-ASSIGN can be used for these values. </del>  For codepoints that are encoded in variable-length integers (integer- encoding), such as frame types, codepoints that encode to four or

Not sure if this is design. It probably is.
Because that is where contention occurs.
Amanda from IANA says: I believe that the original idea was that we privilege the first unassigned value in each range of values that has a different length encoding for varints. But as we are also using these rules for non-varint encodings, that sort of rulemaking is likely confusing. I'm proposing that this be made simply "first unassigned codepoint". PR to follow. (This will affect more than just -transport, but the text change only occurs there, so I think we're OK.)
This is good.

risk that differing semantics are attributed to the same codepoint by different implementations.  <ins> Use of the first unassigned codepoint is reserved for allocation using the Standards Action policy; see Section 4.9 of RFC8126.  The early codepoint assignment process EARLY-ASSIGN can be used for these values. </ins> For codepoints that are encoded in variable-length integers (integer- encoding), such as frame types, codepoints that encode to four or


Endpoints communicate in QUIC by exchanging QUIC packets.  Most packets contain frames, which carry control information and <del> application data between endpoints.  QUIC authenticates all packets and encrypts as much as is practical.  QUIC packets are carried in UDP datagrams (UDP) to better facilitate deployment in existing systems and networks. </del>  Application protocols exchange information over a QUIC connection via streams, which are ordered sequences of bytes.  Two types of stream

Éric Vyncke said:
This is deliberate. Everything is authenticated (absent some unused fields in Retry packets and Version Negotiation, which has a big TBD on it). As much as possible is encrypted. I'm going to propose no action here.
Well, it's not deliberate that he has trouble parsing it, so I don't think that's the right way to justify a no-action. This is an editorial comment. Something like "QUIC authenticates all packets; as much of each packet as practical is also encrypted." would make the same statement with less possibility of misunderstanding. As a native speaker, I don't find the current text confusing, but I also realize that our audience includes those from different backgrounds; I'm not opposed to making an editorial change here.

Endpoints communicate in QUIC by exchanging QUIC packets.  Most packets contain frames, which carry control information and  <ins> application data between endpoints.  QUIC authenticates the entirety of each packet and encrypts as much of each packet as is practical. QUIC packets are carried in UDP datagrams (UDP) to better facilitate deployment in existing systems and networks. </ins> Application protocols exchange information over a QUIC connection via streams, which are ordered sequences of bytes.  Two types of stream


4. <del> It is necessary to limit the amount of data that a receiver could buffer, to prevent a fast sender from overwhelming a slow receiver, or to prevent a malicious sender from consuming a large amount of memory at a receiver.  To enable a receiver to limit memory commitment to a connection and to apply back pressure on the sender, streams are flow controlled both individually and as an aggregate.  A QUIC receiver controls the maximum amount of data the sender can send on a stream at any time, as described in data-flow-control and fc- credit. </del>  Similarly, to limit concurrency within a connection, a QUIC endpoint controls the maximum cumulative number of streams that its peer can

Barry Leiba said:
receiver/client is an invalid comparison here, so this is a bit of a confusing question. The point is to ensure that a receiver can limit what space it commits for buffering.
With the suggestions, this is a fine, if small, improvement.

4.  <ins> Receivers need to limit the amount of data that they are required to buffer, in order to prevent a fast sender from overwhelming them or a malicious sender from consuming a large amount of memory.  To enable a receiver to limit memory commitments for a connection, streams are flow controlled both individually and across a connection as a whole. A QUIC receiver controls the maximum amount of data the sender can send on a stream as well as across all streams at any time, as described in data-flow-control and fc-credit. </ins> Similarly, to limit concurrency within a connection, a QUIC endpoint controls the maximum cumulative number of streams that its peer can


versions without retaining state.  Though either the Initial packet or the Version Negotiation packet that is sent in response could be lost, the client will send new packets until it successfully receives <del> a response or it abandons the connection attempt.  As a result, the client discards all state for the connection and does not send any more packets on the connection. </del>  A server MAY limit the number of Version Negotiation packets it sends.  For instance, a server that is able to recognize packets as

There was a sentence in this section that seems to be specifying how to handle a version negotiation packet, not how to send one, and as such is out of place.
I can see how this duplicates text from the next section and so is safe to remove. Thanks for separating and providing independent justification. I missed the justification before.

versions without retaining state.  Though either the Initial packet or the Version Negotiation packet that is sent in response could be lost, the client will send new packets until it successfully receives  <ins> a response or it abandons the connection attempt. </ins> A server MAY limit the number of Version Negotiation packets it sends.  For instance, a server that is able to recognize packets as


between packets, any limits on packet size will also limit the space available for a reason phrase. <del> A human-readable explanation for why the connection was closed. This can be zero length if the sender chooses not to give details beyond the Error Code.  This SHOULD be a UTF-8 encoded string RFC3629. </del>  The application-specific variant of CONNECTION_CLOSE (type 0x1d) can only be sent using 0-RTT or 1-RTT packets; see frames-and-spaces.

Though we recommend the use of text in UTF-8, we don't provide all of the machinery necessary for true internationalization, like multiple translations and all that mess. Be very explicit about that. (This is a recurring problem; we had the same problem with HTTP/2 and it might be worth updating BCP 18 for this.)
NAME said:
I hope not. How can we qualify this to avoid any implication that it does?
BCP 18 says: That really does sound like it covers this field. Would it be enough to say that the field SHOULD begin with a language tag if it is not empty?
This is a great example of red-tape. In any case, I think we can explicitly disavow anything here and say that the content of the field is not-defined and while it might be a good idea to make it something that can be rendered as text, it is for diagnostic purposes and does not need to be comprehensible to anyone other than the entity that generated it.
see URL (As an individual, I don't see any action required to fix something last spoken about, with little interest, ~4 years ago)
For a more substantial discussion, please see URL
In case my intention isn't clear (again as an individual), the WG discussed this previously and found a resolution reflected in the current text. I'm not seeing any new information in the meantime to warrant revisiting that decision. I am concerned that a change at this stage is disruptive to existing implementations and deployments of QUIC.
For clarity, I do not plan to take a position on the question since I am not much of an authority on the matter; I have asked the ART ADs if they can weigh in. I think we have somewhat recently marked a field as being "for debugging purposes" or "not intended to be displayed to the user" but don't remember it clearly enough to have search terms to actually find it as an example.
I think NAME 's fix in makes it so that this is not necessarily "human readable". I think that fixes this issue by defining the field differently (though still accurately), so I'm going to merge that and close this issue.
Sorry to come in later, after Jana already closed this, but I think the result is fine. I sent the following reply to Ben K: It's generally true that we don't worry about language tagging for strings that aren't expected to be directly handled by end users. The failures caused by not knowing the intended language involve semantic issues (trying to do translation or other semantic interpretation of the strings), case mapping (such as handling "i" to "I" in English, vs Turkish), sorting ("ä" sorts after "a" in German and after "z" in Swedish, and Spanish actually eliminated "ch" as a single letter in 1994 to avoid such trouble), and comparisons. The strings in question here have none of those issues. So I would let this go, under the general assumption, which we make in very many other places in our protocol suites, that making it UTF-8 allows implementations to swap in German or Swedish or Turkish or Chinese versions of the messages, that installations will choose which language to operate in, and that language tagging really won't be needed.
Thanks for the additional information Barry.
I think this is much clearer. Also, I might argue that it doesn't need to be human-readable, since there is no expectation here about how this information is to be consumed.

between packets, any limits on packet size will also limit the space available for a reason phrase.  <ins> Additional diagnostic information for the closure.  This can be zero length if the sender chooses not to give details beyond the Error Code.  This SHOULD be a UTF-8 encoded string RFC3629, though the frame does not carry information, such as language tags, that would aid comprehension by any entity other than the one that created the text. </ins> The application-specific variant of CONNECTION_CLOSE (type 0x1d) can only be sent using 0-RTT or 1-RTT packets; see frames-and-spaces.


QUIC can use the session resumption feature of TLS 1.3.  It does this by carrying NewSessionTicket messages in CRYPTO frames after the <del> handshake is complete.  Session resumption is the basis of 0-RTT, but can be used without also enabling 0-RTT. </del>  Endpoints that use session resumption might need to remember some information about the current connection when creating a resumed

Resumption is not quite the basis of 0-RTT, since it is also allowed to pre-provision an external PSK and other parameters and do 0-RTT that way. This also allows a rewording to avoid implying that 0-RTT would need to be enabled by configuration, since it is supposed to just be "on by default".
NAME said:
Having just reviewed all instances of 0-RTT, I'm not seeing anything that I disagree with in terms of tone and posture. Most of the language does treat 0-RTT as a normal part of the protocol, though it is very careful to highlight the risks. I think that is entirely appropriate. Short of being provided with specific problems or recommendations, I propose no action here.
How do you feel about s/Session resumption is the basis of 0-RTT, but can be used without also enabling 0-RTT./Session resumption can be used to enable 0-RTT, and can also be used when 0-RTT is disabled./ (recalling that we had another change to clarify that 0-RTT can be used independently of resumption, if sufficient information is configured alongside the external PSK)? To clarify, the concern here is that if 0-RTT is something that you "enable", then there would be some precursor state where 0-RTT is disabled by default. Disabled by default may not mesh very well with "normal part of the protocol". Thank you for reviewing the other instances; I only happened to notice this one place in Section 4.5 but was not specifically looking for others.
It's a fine point, but I wouldn't object to making that change in line with other 0-RTT changes. I think that the chances of ever seeing non-resumption 0-RTT are so remote as to be irrelevant, but we can still be accurate.

QUIC can use the session resumption feature of TLS 1.3.  It does this by carrying NewSessionTicket messages in CRYPTO frames after the  <ins> handshake is complete.  Session resumption can be used to provide 0-RTT, and can also be used when 0-RTT is disabled. </ins> Endpoints that use session resumption might need to remember some information about the current connection when creating a resumed


routing of packets across multiple network paths will also allow activity on those paths to be linked by entities other than the peer. <del> A client might wish to reduce linkability by employing a new connection ID and source UDP port when sending traffic after a period of inactivity.  Changing the UDP port from which it sends packets at the same time might cause the packet to appear as a connection migration.  This ensures that the mechanisms that support migration are exercised even for clients that do not experience NAT rebindings or genuine migrations.  Changing port number can cause a peer to reset its congestion control state (see migration-cc), so the port SHOULD only be changed infrequently. </del>  An endpoint that exhausts available connection IDs cannot probe new paths or initiate migration, nor can it respond to probes or attempts

... is good for linkability.
Éric Vyncke said:
I don't think that is appropriate in the general case. However, in , we say this: We could point to privacy addresses as an option here. That is not a bad idea as IPv6 clients can't rely on NAT to the same extent that IPv4 clients do.
Using "optionally" inside "might wish to" seems overly wishy-washy. How about "employing a new connection ID, source UDP port, and/or IP address (see {{?RFC4941}})...."?

routing of packets across multiple network paths will also allow activity on those paths to be linked by entities other than the peer.  <ins> A client might wish to reduce linkability by switching to a new connection ID, source UDP port, or IP address (see RFC4941) when sending traffic after a period of inactivity.  Changing the address from which it sends packets at the same time might cause the server to detect a connection migration.  This ensures that the mechanisms that support migration are exercised even for clients that do not experience NAT rebindings or genuine migrations.  Changing address can cause a peer to reset its congestion control state (see migration-cc), so addresses SHOULD only be changed infrequently. </ins> An endpoint that exhausts available connection IDs cannot probe new paths or initiate migration, nor can it respond to probes or attempts


Additional connection IDs are communicated to the peer using NEW_CONNECTION_ID frames (frame-new-connection-id).  The sequence number on each newly issued connection ID MUST increase by 1.  The <del> connection ID randomly selected by the client in the Initial packet and any connection ID provided by a Retry packet are not assigned sequence numbers unless a server opts to retain them as its initial connection ID. </del>  When an endpoint issues a connection ID, it MUST accept packets that carry this connection ID for the duration of the connection or until

The value the client puts in the Destination Connection ID field is not random, but unpredictable. But we could be clearer and just say what this refers to. The second error here was that the server can't use the value it puts in Retry. Rather than talk about retaining the values, I'm striking that clause.
Rob Wilton said:
This refers to the one instance where the connection ID does need to be randomly generated; see URL

Additional connection IDs are communicated to the peer using NEW_CONNECTION_ID frames (frame-new-connection-id).  The sequence number on each newly issued connection ID MUST increase by 1.  The  <ins> connection ID that a client selects for the first Destination Connection ID field it sends and any connection ID provided by a Retry packet are not assigned sequence numbers. </ins> When an endpoint issues a connection ID, it MUST accept packets that carry this connection ID for the duration of the connection or until


If the sender wants to elicit a faster acknowledgment on PTO, it can skip a packet number to eliminate the acknowledgment delay. <del> When the PTO timer expires, an ack-eliciting packet MUST be sent.  An endpoint SHOULD include new data in this packet.  Previously sent data MAY be sent if no new data can be sent.  Implementations MAY use alternative strategies for determining the content of probe packets, including sending new or retransmitted data based on the application's priorities. </del>  It is possible the sender has no new or previously-sent data to send. As an example, consider the following sequence of events: new

Despite how the diff appears at first glance, I've only changed the first two sentences.
NAME said:
This changes the emphasis slightly, but in a good way.

If the sender wants to elicit a faster acknowledgment on PTO, it can skip a packet number to eliminate the acknowledgment delay.  <ins> An endpoint SHOULD include new data in packets that are sent on PTO expiration.  Previously sent data MAY be sent if no new data can be sent.  Implementations MAY use alternative strategies for determining the content of probe packets, including sending new or retransmitted data based on the application's priorities. </ins> It is possible the sender has no new or previously-sent data to send. As an example, consider the following sequence of events: new


countermeasures, QUIC server implementations should assume that attackers can cause them to generate arbitrary UDP payloads to arbitrary destinations.  QUIC servers SHOULD NOT be deployed in <del> networks that also have inadequately secured UDP endpoints. </del>  Although it is not generally possible to ensure that clients are not co-located with vulnerable endpoints, this version of QUIC does not

This is already something we recommend separately, but this is a SHOULD and the extra is useful.
Roman Danyliw said:
It might not be entirely realistic, in that the person deploying a server might not be aware of unsecure endpoints around them, but it's better to have the caution present than say nothing.
I think that it is moderately realistic for most deployments. There aren't so many UDP-based protocols out there in common usage. Besides, conducting an audit, if you did not already know, would be healthy. From another angle, a reason to include this is that if you have a firewall, deploy a QUIC server behind that firewall, and don't know what else is behind that firewall, then us writing this text makes it clear where fault lies if something bad happens.
This is not an editorial issue. I think that it is an excellent question, and definitely the sort of question I would expect the IESG to press on. FWIW, I think that this response would be totally unreasonable if this were TCP instead of UDP, which implies that there is a degree of subjectivity involved in the decision. The working group position suggests no action, but I want to confirm that NAME is satisfied with that response. As this was only a comment, not DISCUSS, I'm going to assume that this is OK unless I'm told otherwise.
Would it help to more tightly scope the definition of "networks"? One absurd reading is that QUIC should not be deployed on Internet facing networks because there is not a 0% chance of some unsecured UDP listening host somewhere.
I think we might be able to say "networks without ingress filtering [BCP38]". Servers are only vulnerable to these attacks if they (or their network) permit source address spoofing.
WfMq
I think the addition of BCP 38 makes it much more pointed and realistic. Overall, this is an important cautionary note. We decided that instead of trying to fix this in the protocol, it made sense to force those deploying QUIC to consider the implications of the environment in which they are doing it.
NAME could you comment on the proposed resolution?
Thanks for the refined text. The reference to ingress filtering makes it clearer. Consider this COMMENT resolved.

countermeasures, QUIC server implementations should assume that attackers can cause them to generate arbitrary UDP payloads to arbitrary destinations.  QUIC servers SHOULD NOT be deployed in  <ins> networks that do not deploy ingress filtering BCP38 and also have inadequately secured UDP endpoints. </ins> Although it is not generally possible to ensure that clients are not co-located with vulnerable endpoints, this version of QUIC does not


certificate and can therefore read these 1-RTT packets. A sender SHOULD restart its PTO timer every time an ack-eliciting <del> packet is sent or acknowledged, when the handshake is confirmed (Section 4.1.2 of QUIC-TLS), or when Initial or Handshake keys are </del>  discarded (Section 4.9 of QUIC-TLS).  This ensures the PTO is always set based on the latest estimate of the round-trip time and for the correct packet across packet number spaces.

Ian is right, we would lose the Initial discard condition. Drop the Handshake key drop condition.
NAME -- you're right, but I think that only applies to Initial here, since hs confirmed is the same as hs keys getting dropped. Take a look at the new text.
NAME said:
Yes, this should be only about handshake confirmation. Thanks for catching this!

certificate and can therefore read these 1-RTT packets. A sender SHOULD restart its PTO timer every time an ack-eliciting  <ins> packet is sent or acknowledged, or when Initial or Handshake keys are </ins> discarded (Section 4.9 of QUIC-TLS).  This ensures the PTO is always set based on the latest estimate of the round-trip time and for the correct packet across packet number spaces.


All transmissions in QUIC are sent with a packet-level header, which indicates the encryption level and includes a packet sequence number (referred to below as a packet number).  The encryption level <del> indicates the packet number space, as described in QUIC-TRANSPORT. Packet numbers never repeat within a packet number space for the lifetime of a connection.  Packet numbers are sent in monotonically increasing order within a space, preventing ambiguity. </del>  This design obviates the need for disambiguating between transmissions and retransmissions; this eliminates significant

Roman Danyliw said:
I believe the mapping from encryption level to PNS is detailed in section 12.3 of transport: URL
I can't find the text being commented on.
NAME text is in the first paragraph of URL
It might be useful to point to the specific section in -transport that NAME mentioned in his comment. Anyone care to propose a PR?

All transmissions in QUIC are sent with a packet-level header, which indicates the encryption level and includes a packet sequence number (referred to below as a packet number).  The encryption level  <ins> indicates the packet number space, as described in Section 12.3 of QUIC-TRANSPORT.  Packet numbers never repeat within a packet number space for the lifetime of a connection.  Packet numbers are sent in monotonically increasing order within a space, preventing ambiguity. </ins> This design obviates the need for disambiguating between transmissions and retransmissions; this eliminates significant


A client MUST expand the payload of all UDP datagrams carrying Initial packets to at least the smallest allowed maximum datagram size of 1200 bytes by adding PADDING frames to the Initial packet or <del> by coalescing the Initial packet; see packet-coalesce.  Similarly, a server MUST expand the payload of all UDP datagrams carrying ack- eliciting Initial packets to at least the smallest allowed maximum datagram size of 1200 bytes.  Sending UDP datagrams of this size ensures that the network path supports a reasonable Path Maximum Transmission Unit (PMTU), in both directions.  Additionally, a client that expands Initial packets helps reduce the amplitude of amplification attacks caused by server responses toward an unverified client address; see address-validation. </del>  Datagrams containing Initial packets MAY exceed 1200 bytes if the sender believes that the network path and peer both support the size

This seems to have caused problems, so address it.
This text in seems to cause confusion for implementors: since it leaves it unclear what the Initial packet can be coalesced with to pad it. Specifically, some implementations use zeros or other (random) data, which seems to surprise some implementors. (, which is referred to, also doesn't seem to clarify this.)
My understanding is that transport draft does not say anything about padding outside QUIC packet. Because a receiver is required to ignore invalid long packets, zero padding outside QUIC packet just works. So this is "OK because it is not explicitly disallowed" category.
I agree, but it has tripped up implementers (again). I wonder if a wording can be found that doesn't do that.
I'd be happy to see a bit more explicit text to clarify this, since as you said, it's come up a few times as non-obvious.
Maybe something like: "An Initial that is padded by coalescing could be coalesced with valid or even invalid QUIC packets; the latter MUST be ignored as described in Section XYZ."

A client MUST expand the payload of all UDP datagrams carrying Initial packets to at least the smallest allowed maximum datagram size of 1200 bytes by adding PADDING frames to the Initial packet or  <ins> by coalescing the Initial packet; see packet-coalesce.  Initial packets can even be coalesced with invalid packets, which a receiver will discard.  Similarly, a server MUST expand the payload of all UDP datagrams carrying ack-eliciting Initial packets to at least the smallest allowed maximum datagram size of 1200 bytes. Sending UDP datagrams of this size ensures that the network path supports a reasonable Path Maximum Transmission Unit (PMTU), in both directions.  Additionally, a client that expands Initial packets helps reduce the amplitude of amplification attacks caused by server responses toward an unverified client address; see address- validation. </ins> Datagrams containing Initial packets MAY exceed 1200 bytes if the sender believes that the network path and peer both support the size