Original text:
Data is protected using a number of encryption levels: <del> Plaintext </del>  Early Data (0-RTT) Keys level.  For instance, an implementation might bundle a Handshake message and an ACK for some Handshake data into the same packet. <del> Each encryption level has a specific list of frames which may appear in it.  The rules here generalize those of TLS, in that frames associated with establishing the connection can usually appear at any encryption level, whereas those associated with transferring data can only appear in the 0-RTT and 1-RTT encryption levels: CRYPTO frames MAY appear in packets of any encryption level except 0-RTT. CONNECTION_CLOSE MAY appear in packets of any encryption level other than 0-RTT. </del>  PADDING frames MAY appear in packets of any encryption level.  ACK frames MAY appear in packets of any encryption level other than 0-RTT, but can only acknowledge packets which appeared in that packet number space. <del> STREAM frames MUST ONLY appear in the 0-RTT and 1-RTT levels. </del>  <del> All other frame types MUST only appear at the 1-RTT levels. </del>  Because packets could be reordered on the wire, QUIC uses the packet type to indicate which level a given packet was encrypted under, as 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 <del> function described in Section 7.1 of TLS13) is used, using the hash </del>  function from the negotiated cipher suite.  Other versions of TLS <del> MUST provide a similar function in order to be used 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 to derive the IV, see aead.  The header protection key uses the "quic <del> hp" label, see header-protect).  Using these labels provides key </del>  separation between QUIC and TLS, see key-diversity. The KDF used for initial secrets is always the HKDF-Expand-Label in hexadecimal notation.  Future versions of QUIC SHOULD generate a new salt value, thus ensuring that the keys are different for each version of QUIC.  This prevents a middlebox that only recognizes one <del> version of QUIC from seeing or modifying the contents of handshake packets from future versions. </del>  The HKDF-Expand-Label function defined in TLS 1.3 MUST be used for Initial packets even where the TLS versions offered do not include All QUIC packets other than Version Negotiation and Retry packets are protected with an AEAD algorithm AEAD.  Prior to establishing a shared secret, packets are protected with AEAD_AES_128_GCM and a key <del> derived from the destination connection ID in the client's first </del>  Initial packet (see initial-secrets).  This provides protection against off-path attackers and robustness against QUIC version unaware middleboxes, but not against on-path attackers. The "extension_data" field of the quic_transport_parameters extension contains a value that is defined by the version of QUIC that is in use.  The quic_transport_parameters extension carries a <del> TransportParameters when the version of QUIC defined in QUIC- </del>  TRANSPORT is used. The quic_transport_parameters extension is carried in the ClientHello 9.1.  A small ClientHello that results in a large block of handshake messages from a server can be used in packet reflection attacks to amplify the traffic generated by an attacker. attacker cannot forge them.  Put together, these defenses limit the level of amplification. <del> 9.2. </del>  QUIC, TLS, and HTTP/2 all contain messages that have legitimate uses in some contexts, but that can be abused to cause a peer to expend implementations SHOULD track redundant packets and treat excessive volumes of any non-productive packets as indicative of an attack. <del> 9.3. </del>  Header protection relies on the packet protection AEAD being a pseudorandom function (PRF), which is not a property that AEAD payloads and packet numbers MUST be free from side-channels that would reveal the packet number or its encoded size. <del> 9.4. </del>  In using TLS, the central key schedule of TLS is used.  As a result of the TLS handshake messages being integrated into the calculation

Reviewer comments:
In , NAME suggests that we could allow RESETSTREAM in 0-RTT. That seems slightly wrong, because why would someone send something then give up without receiving anything in return, but that is actually possible in the presence of packet loss. And changing your mind is perfectly acceptable. But RESETSTREAM doesn't really cover it. Streams can get blocked, requests can go out with additional flow control credits, and maybe even STOPSENDING makes sense. And my analysis suggests that the risk from replay is not made worse from any frame type that doesn't produce application-visible changes. So this removes the restrictions, aside from the natural restrictions that exist for frames (for instance, there are no cases where ACK, CRYPTO, and even PATHRESPONSE make sense to send in 0-RTT).
Thede rules seem to get more and more complex. As I mentioned in the discussion on the issue, I’d prefer to allow all frames in 0-RTT. For example, what’s the harm of sending a PING in 0-RTT?
OK, big changes here based on doing more analysis. Please re-review.
As NAME notes, there is a reasonable argument on the issue that most frame types should simply be permitted. Would it make more sense to invert the list and instead state only where frames are prohibited?
Proposed shortening of replay section As described in Section 8 of {{!TLS13}}, use of TLS early data comes with an exposure to replay attack. The use of 0-RTT in QUIC is similarly vulnerable to replay attack. Endpoints MUST implement and use the replay protections described in {{!TLS13}}, however it is recognized that these protections are imperfect. Therefore, additional consideration of the risk of replay are needed. The QUIC transport protocol is not vulnerable to replay attacks and does tolerate replayed frames because all frames are idempotent and because no state is carried across connections. Applications might carry state across connections and can be confused by STREAM frame content under 0-RTT keys and also by other content such as flow control credits. Servers can be configured to reject old 0-RTT packets but it is not perfect nor guaranteed. Only application protocols can define semantics that are acceptable for 0-RTT sessions, if any. A copied 0-RTT session is cheap to establish and can be exploited to expend excessive server resources. Applications MUST account for this overhead before accepting 0-RTT connections. QUIC extensions SHOULD describe how replay attacks affect their operation. Applications MUST prohibit extensions where efficient replay mitigation strategies cannot be provided.
I am not sure if this is accurate. IIUC their is nothing that mandates the client to switch to using 1-RTT when it receives ServerFinished. In fact, on a lossy network, a client would benefit from using 0-RTT packets until it receives an ACK for ClientFinished. In such case, it would be natural to observe these frames in a 0-RTT packet. I think we should either forbid them or clarify that there are allowed, instead of suggesting (IMO incorrectly) that it’s impossible. Originally posted by NAME in URL
To be clear, this was in reference to text that mentioned that certain frames couldn't be sent in 0-RTT. That would only be true if we made this a requirement.
This actually is already addressed in the TLS draft, as NAME pointed out in another thread: , "Though an endpoint might retain older keys, new data MUST be sent at the highest currently-available encryption level." If you have 1-RTT keys, you MUST use them. There's currently no server verification that you do so, however.
I think this should be stated in transport as well as TLS, along with a statement that a server MAY/SHOULD/MUST ignore 0RTT packets that have higher packet numbers than the first received 1RTT packet. The first is editorial I believe, the latter is borderline design. If we decided it was valid to close the connection if a 0RTT packet was received with a higher packet number than 1RTT, then that's definitely not editorial, but I think it may be a good way to enforce proper behavior.
NAME Agreed. I think that this should be a MAY/SHOULD close the connection with PROTOCOL_VIOLATION rather than "ignore", because that aligns the handling with how we agreed to handle other misuse of 0-RTT packets (see URL).
NAME said it right at the mike: this is a key update scenario, from 0-RTT to 1-RTT key. Treat it the same way as peer continuing using old key after key update.
I think the only verifiable requirement is "must not ack 1RTT packet in 0RTT packet". The server can definitely detect that, and send a connection close with reason PROTOCOL VIOLATION when it happens. This would effectively force the client to switch to 1RTT soon.
NAME exceeding the initial flow control / max streams from the remembered TP's is also detectable.
NAME detection with flow control would require special case code in stream processing, as in "check against the current window but if 0-RTT check against the initial window". Could be done, but that would be another wart. Also, in many cases the 0-RTT data sent is well below the initial flow control window, so it will not be a very efficient test.
NAME It's actually something that can be implemented in a clear and concise way. The only thing you need to have are objects representing limits for each type of packets. When processing 0-RTT packets, the logic would refer to the limits declared by TP of the previous connection. When processing 1-RTT packets, the logic would refer to the limits declared by current TP and the max frames.
Since QUIC provides 0-RTT support, it really should.
forbids a RESETSTREAM frame being sent in a 0-RTT packet. I do not see a reason why we should prohibit that even though we allow FIN to be sent. RESETSTREAM is just another way of closing a stream. I think that we should allow RESETSTERAM to be sent using a 0-RTT packet. FWIW, my assumption is that we simply missed to clarify that RSTSTREAM is allowed when we split the frame into RST and STOP_SENDING.
Do we really need any special rules for allowed frame types in 0-RTT packets? I don't see any justification for treating 0-RTT and 1-RTT different in that regard.
NAME My understanding is that 0-RTT is a temporary state that provides less protection (i.e. not forward-secret and also replay-able). It makes sense to require clients to switch to 1-RTT ASAP. I think that the current approach of limiting the capability to the transmission of stream data is one way of accomplishing that.
If RESETSTREAM is to be permitted, shouldn't it also be permitted to send STOPSENDING on locally initiated bidirectional streams?
I don't understand why we would consider e.g. flow control updates worthy of higher protection than application data. Note that there's a real use case for sending flow control updates in 0-RTT packets: A client might anticipate a large response when it sends a request in 0-RTT request, and it can save one roundtrip by granting a lot of flow control credit for that response.
NAME I'm not sure if that's true. A client can always use transport parameters to specify it's limits; I doubt if there's a benefit in updating the limits using a 0-RTT packet. And in case of anticipating a large response, the anticipation would be that the transmission of the response would span across multiple round-trips (because of congestion control). Everything would work fine if the client's initial limit is large enough to cover what can be sent in the first round-trip (or several round-trips). Asking for permission to send BLOCKED frames in 0-RTT packets might make sense, though I am not sure if we'd need that in practice. I think we can expect a server allowing 0-RTT to provide enough window to let the client actually use 0-RTT.
There's generally good reason to keep the initial window small, since we don't have any mechanism to update the transport parameters. That depends very much on the concrete values used. Right, I hadn't even thought about BLOCKED. I think it proves my point here: If we don't allow those frame types in 0-RTT, we'll need a lot of special code just for keeping those frames out of 0-RTT packets (and to delay transmission until you have 1-RTT keys). Equivalently, on the receiver side, you'd need to implement checks that the payload of 0-RTT packets only contain valid frames. I don't see any reason for special casing anything here, so we should just allow all frame types in 0-RTT packets.
I can imagine an application protocol oriented around using streams as message framing that might have small initial limits to support proportionately large numbers of in-flight streams, but occasionally request large responses by issuing MAXSTREAMDATA alongside the request. Supporting such a pattern in 0-RTT seems useful.
I agree with NAME I think we should just have the same rules for 0-RTT and 1-RTT packets.
Acks cannot be sent in 0rtt packets atm, are you proposing changing that as well NAME
I’m on board with all other frame types though. I guess acks cannot logically be sent in 0rtt naturally, so maybe that’s not really a big deal
I agree that it makes sense to treat 0-RTT and 1-RTT the same since all frames the same. I'd still like to keep the handshake frames to the bare minimum.
I agree with loosening the restrictions. As with TLS 1.3, it's up to the application layer to restrict what things can't be done in 0-RTT. Those should generally be things which have effects outside the connection itself, and at the QUIC layer, nothing the client sends does.
I have been skimming through the QUIC transport and QUIC TLS draft a few times. It is really difficult to decipher which frames can be sent where. Some packet types mention permitted frames in transport, but does not do that for all packet types. QUIC TLS has a list of frames for different packet types, but it is not clear if that cover all frame types. QUIC TLS does suggest that CRYPTO frames can be sent in 1-RTT by stating that only 0-RTT cannot contain crypto, but is not clear about how or why that would happen, although I suspect it has to do with client auth - which is explicitly not permitted post handshake without any explanation. It could also be rekeying, but I think that is derived locally from session key.
This is useful for , for example.
Bring the discussion back from . I'm thinking about NAME comment there and I think that it would be easier if we were able to permit any frame type in 0-RTT (except CRYPTO, which has nothing to carry). In thinking about this, the main concern is whether there is any replay risk associated with any of these frames. Going through each, I didn't find anything. Though replay does result in spurious state being created, it's all transient and connection-bound, not application state. In general, all connection-level control messages affect only connection state, which goes away when the connection goes away. And replayed 0-RTT always results in the connection being thrown out as the full handshake cannot successfully complete twice. There might be some application-level significance to resetting streams in addition to carrying stream data, particularly when you consider the potential for selective replay. An attacker with sufficient knowledge of the contents of packets could replay some packets and not others to effect changes. But while the signals that a server application might receive are different, they are not outside of the range of possible signals that a client accepts as possible when sending the 0-RTT. That is, if the server receives a partial stream rather than a complete stream, that is a potential outcome that the client has to accept as a possibility even when there is no attack. If there are lasting application-layer effects from a RESETSTREAM (or STOPSENDING), then this might cause problems. But the application actively chooses to accept those risks by triggering these actions before the handshake is complete. In addition, RESETSTREAM is a poor carrier for state-changing action because its semantics are better suited to abandoning state-changing effects, not creating them. It would be a poor choice in protocol design to carry any application-layer signal with RESETSTREAM that implied a need for some action. HTTP does this with CONNECT in a way, but that is only to match with a TCP RST and comes with no real expectation of it being reliable. In the end, I conclude that we should permit all frames in 0-RTT and 1-RTT. While there is some increased risk here, I think that this is best left to the 0-RTT profile for the protocol that uses QUIC. For HTTP, where the only application-layer effect RESET_STREAM can have is to cancel requests, the result is to reduce exposure to replay. Other protocols will need to make their own assessment about safety, but I don't anticipate problems. I'll adjust to match.
I think this is an improvement but I am a bit anxious. What happens to special frames related to connection migration that might affect a server view of a remembered client. What about tokens stored for future use - perhaps when looking towards v2 where things get more symmetrical. What about path migration and validation. What about 100 coalesced 0-RTT packets forcing 3x amp path validation, or something, in each - is that a possibility? (EDIT: no because you should protect against repeat 0-RTT, but perhaps it gets more important now) I like the simplicity of all frames - but black listing frames in a 0-RTT receive handler is not hard either - iff valid frames are clearly document. There could be a lot of hidden complexity in 0-RTT that we do not fully appreciate yet.
NAME The problem with 0-RTT in QUIC is that, unlike TLS 1.3 (that has maxearlydatasize), there is no limit in the amount of data that the client can send using the 0-RTT key. IIUC, currently, it's entirely up to the client to decide when it switches from 0-RTT to 1-RTT keys. As we know, Initial and 0-RTT packets can be replayed against different servers within a server cluster that does not (cannot) implement the use-only-once rule for the session tickets. I am concerned that widening how 0-RTT packets can be used might lead to additional exposure to the attack surface. An attack would go like this: an attacker creates a legitimate connection and obtains a session ticket the attacker reconnects using the session ticket, and exchanges lots of information with the server (involving MAXDATA, MAX_STREAMS, etc.). However, the attacker sticks to using 0-RTT for packets it emits, even after the handshake is complete. simultaneously, the attacker creates many QUIC connections using the same Initial packet as that of step 2, and then sends the copied 0-RTT packets. The server will handle those and commit state. Because the client never responds with an 1-RTT ACK, the connection will eventually die. However, a client can create a connection with huge PTO (by delaying Initial packets) to have enough time to let the server accept many packets. IMO it is preferable to allow less frames in 0-RTT packets, because it narrows the attack vector. PS. Anyways I think it's worth clarifying how to minimize stream-related states being created by 0-RTT replay attacks; left my comment URL
NAME QUIC uses for that purpose. You can't receive a flow control update, so whatever value you have for that determines how much 0-RTT you can send. In thinking through this, I realized that the client can't send 0-RTT after receiving 1-RTT from the server. A client won't have the keys until it has the entire handshake flight from the server, at which point it has to switch to 1-RTT keys. So this all comes down to the same calculus we have in TLS/TCP, after you have spent a little bit of time on the question of RESET_STREAM and its effect on long-term application state.
NAME My understanding is that an attacker acting as a client can receive flow control updates (in 1-RTT packets), and use the updated value for emitting additional 0-RTT packets. Something like following: client obtains to a server and obtains session ticket and TP client reconnects, sends 0-RTT packets containing a STREAM frame (id=0, off=TP.initialmaxdata-1, len=1) server sends handshake messages and a 1-RTT packet that contains MAXDATA (maximumdata=TP.initalmaxdata3), because it observes the client reaching the limit client sends a 0-RTT packet containing a STREAM frame (id=0, off=TP.initialmaxdata3-1, len=1) server sends another 1-RTT packet containing MAXDATA... client sends a 0-RTT packet containing a yet another STREAM frame...
At the point the client has 1-RTT keys for receiving, it will have the ability to send using 1-RTT keys. It can (and should) send its Finished too. Why would it send with 0-RTT keys?
Because the client here is an attacker. However, I'm not seeing as much threat related to this specific change -- this is something the client can do regardless (generating many connections and causing state to be allocated for each). So the attack here is to artificially create a large batch of (hopefully work-intensive) 0-RTT packets which are legitimate given a particular session ticket. Then open a large set of parallel connections using the same session ticket and dump all those 0-RTT packets into each connection. To guard against this, TLS 1.3 recommends . This defense is the same for QUIC, and lives in the TLS layer.
Is the concern here about a denial of service attack on the server? That is, the extra frames that it might receive, which aren't really limited in any way by flow control or other such limitations, might cause it to do too much work? This doesn't sound that interesting to me. There is always a risk when you accept 0-RTT that the client or data is bad. As NAME points out, you shouldn't be accepting the same 0-RTT multiple times. The recommendations in TLS 1.3 provide some tips on how to avoid that. But even if your server configuration doesn't allow you to detect that and stop it, the work you expend on 0-RTT packets is a cost that you take on. And you take on that work with the understanding of the associated risk of replay. Clients can always send far more stuff than you are prepared to process; servers just need to make the call. For instance, rejecting 0-RTT would be my first response to increasing server load. If a client chooses to send 0-RTT when 1-RTT keys are available to it, maybe we can allow servers to cut them off. That's maybe hard to police, but simple things like exceeding initial flow control might be detectable. Even if the server has provided more credit, the client should still be operating within the initial window for 0-RTT.
I like that defense. Just to sanity check, there shouldn't be a case in which the TLS handshake takes an extra round-trip and 0-RTT is accepted, right? Assuming that's true, saying that 0-RTT data MUST NOT exceed the initial connection flow control window (even if MAX_DATA frames are received in 1-RTT) and a pointer to the TLS 1.3 anti-replay protections seem like sufficient mitigation here.
Correct. TLS only takes an extra round trip with HelloRetryRequest, which results in 0-RTT being automatically rejected.
NAME The difference between a DoS using 1-RTT packets and 0-RTT packets is that the latter requires far less CPU cost on the attacker-side. This is because an attacker can just retransmit the same packets from different source tuples, whereas in 1-RTT case, an attacker needs to do expensive crypto operations (especially DH) for each connection it establishes. Therefore my preference goes to limiting the capability of 0-RTT. I like (maybe more than the approach I described in URL), because it clearly limits what a client can do using 0-RTT for streams. The remaining question is what we should do for non-stream-related frames. I still think that it makes sense to disallow the use of any non-stream-related frame in 0-RTT packets, considering the fact that: the frames allowed by 0-RTT and 1-RTT packets are nevertheless going to be different (CRYPTO, ACK) in practice there's no reason to send non-stream-related frames in 0-RTT packets potential security issues related to replay
FWIW, I think that is about formalizing a poorly-enforced constraint that we might have assumed already existed. It's not directly a solution to the problem were discussing. I personally don't think that the cost of processing frames is significant enough to build additional defenses for. Generic anti-DoS measures should suffice. But clearly that's not a universally held viewpoint. I think we should discuss this in Tokyo.
If I understand our correctly, this attack is only possible for a limited amount of time, namely 3 PTO after the server received the Client Initial:
NAME 3 PTO is not going to defend the server here, because an attacker can control the value. It can delay the Initial packets that it sends (carrying ACKs) so that PTO becomes huge.
If I understand correctly, the server switches to 1-RTT right after receiving the Client Initial, doesn't it? That means that PTO will have its initial value, and not be client-controlled. Obviously, this could be a problem on long RTT connections, so maybe that rule about dropping packets needs to be changed.
In the scenario that we are discussing (yeah the thread is getting long), the attacker sends the Initial packet that contains an ACK to the server's Initial. That means that if an attacker can for example send the ACK after 3 seconds (3 seconds of RTO!) to have an open window of additional 9 seconds to perform an attack.
I am concerned with the attack in which the 0-RTT data is replayed by a third party, maybe also with a replayed "retry token". Do we want more than 3 packets there? Do we really want to allow sending a large flow control window of data? Also, 0-RTT may very well be rejected by the server. Sending something that changes connection state looks weird, because all these frames can be dropped.
Tokyo proposal: limit allowed frames to stuff we know are useful. This leaves CONNECTIONCLOSE, NEWCONNECTIONID, PATHCHALLENGE, PATHRESPONSE, PING, and RETIRECONNECTIONID out for the moment, but if we identify a need, we would do the analysis regarding safety under replay attack and make a decision. This means that extensions would need to make their own assessment about safety. Note that ACK, CRYPTO, and NEWTOKEN are not allowed for other, existing reasons. What would be allowed: STREAM, RESETSTREAM, STOPSENDING, MAXDATA, MAXSTREAMDATA, MAXSTREAMID, DATABLOCKED, STREAMDATABLOCKED, STREAMIDBLOCKED, and PADDING. Still open debate between taking this and the PR that has been proposed.
I think we need a complementary analysis on expected server behavior. For example, if MAX DATA increase, does that mean sending that much data right now, or does that mean sending a small amount now, and wait until handshake complete to send more?
The congestion controller and the limitations on how many bytes can be sent to an unvalidated address are separate from flow control. What frames are permitted in 0-RTT has no bearing on those limits.
NAME to be clear - with , are you referring to the comment from Tokyo above, or the revised ?
This is an issue that never really resolved in Tokyo. It is that I was referring to. See also voluminous list discussion on the topic.
LGTM, one nit.Generally looks good. Just need to make sure CONNECTION_CLOSE is allowed everywhere.

Revised text:
Data is protected using a number of encryption levels:  <ins> Initial Keys </ins> Early Data (0-RTT) Keys level.  For instance, an implementation might bundle a Handshake message and an ACK for some Handshake data into the same packet.  <ins> Some frames are prohibited in different encryption levels, others cannot be sent.  The rules here generalize those of TLS, in that frames associated with establishing the connection can usually appear at any encryption level, whereas those associated with transferring data can only appear in the 0-RTT and 1-RTT encryption levels: </ins> PADDING frames MAY appear in packets of any encryption level. <ins> CRYPTO and CONNECTION_CLOSE frames MAY appear in packets of any encryption level except 0-RTT. </ins> ACK frames MAY appear in packets of any encryption level other than 0-RTT, but can only acknowledge packets which appeared in that packet number space.  <ins> All other frame types MUST only be sent in the 0-RTT and 1-RTT levels. </ins>  <ins> Note that it is not possible to send the following frames in 0-RTT for various reasons: ACK, CRYPTO, NEW_TOKEN, PATH_RESPONSE, and RETIRE_CONNECTION_ID. </ins> Because packets could be reordered on the wire, QUIC uses the packet type to indicate which level a given packet was encrypted under, as 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  <ins> function described in Section 7.1 of TLS13 is used, using the hash </ins> function from the negotiated cipher suite.  Other versions of TLS  <ins> 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 to derive the IV, see aead.  The header protection key uses the "quic  <ins> hp" label, see header-protect.  Using these labels provides key </ins> separation between QUIC and TLS, see key-diversity. The KDF used for initial secrets is always the HKDF-Expand-Label in hexadecimal notation.  Future versions of QUIC SHOULD generate a new salt value, thus ensuring that the keys are different for each version of QUIC.  This prevents a middlebox that only recognizes one  <ins> version of QUIC from seeing or modifying the contents of packets from future versions. </ins> The HKDF-Expand-Label function defined in TLS 1.3 MUST be used for Initial packets even where the TLS versions offered do not include All QUIC packets other than Version Negotiation and Retry packets are protected with an AEAD algorithm AEAD.  Prior to establishing a shared secret, packets are protected with AEAD_AES_128_GCM and a key  <ins> derived from the Destination Connection ID in the client's first </ins> Initial packet (see initial-secrets).  This provides protection against off-path attackers and robustness against QUIC version unaware middleboxes, but not against on-path attackers. The "extension_data" field of the quic_transport_parameters extension contains a value that is defined by the version of QUIC that is in use.  The quic_transport_parameters extension carries a  <ins> TransportParameters struct when the version of QUIC defined in QUIC- </ins> TRANSPORT is used. The quic_transport_parameters extension is carried in the ClientHello 9.1. <ins> As described in Section 8 of TLS13, use of TLS early data comes with an exposure to replay attack.  The use of 0-RTT in QUIC is similarly vulnerable to replay attack. Endpoints MUST implement and use the replay protections described in TLS13, however it is recognized that these protections are imperfect. Therefore, additional consideration of the risk of replay is needed. QUIC is not vulnerable to replay attack, except via the application protocol information it might carry.  The management of QUIC protocol state based on the frame types defined in QUIC-TRANSPORT is not vulnerable to replay.  Processing of QUIC frames is idempotent and cannot result in invalid connection states if frames are replayed, reordered or lost.  QUIC connections do not produce effects that last beyond the lifetime of the connection, except for those produced by the application protocol that QUIC serves. TLS session tickets and address validation tokens are used to carry QUIC configuration information between connections.  These MUST NOT be used to carry application semantics.  The potential for reuse of these tokens means that they require stronger protections against replay. A server that accepts 0-RTT on a connection incurs a higher cost than accepting a connection without 0-RTT.  This includes higher processing and computation costs.  Servers need to consider the probability of replay and all associated costs when accepting 0-RTT. Ultimately, the responsibility for managing the risks of replay attacks with 0-RTT lies with an application protocol.  An application protocol that uses QUIC MUST describe how the protocol uses 0-RTT and the measures that are employed to protect against replay attack.  An analysis of replay risk needs to consider all QUIC protocol features that carry application semantics. Disabling 0-RTT entirely is the most effective defense against replay attack. QUIC extensions MUST describe how replay attacks affects their operation, or prohibit their use in 0-RTT.  Application protocols MUST either prohibit the use of extensions that carry application semantics in 0-RTT or provide replay mitigation strategies. 9.2. </ins> A small ClientHello that results in a large block of handshake messages from a server can be used in packet reflection attacks to amplify the traffic generated by an attacker. attacker cannot forge them.  Put together, these defenses limit the level of amplification.  <ins> 9.3. </ins> QUIC, TLS, and HTTP/2 all contain messages that have legitimate uses in some contexts, but that can be abused to cause a peer to expend implementations SHOULD track redundant packets and treat excessive volumes of any non-productive packets as indicative of an attack.  <ins> 9.4. </ins> Header protection relies on the packet protection AEAD being a pseudorandom function (PRF), which is not a property that AEAD payloads and packet numbers MUST be free from side-channels that would reveal the packet number or its encoded size.  <ins> 9.5. </ins> In using TLS, the central key schedule of TLS is used.  As a result of the TLS handshake messages being integrated into the calculation