Draft: draft-ietf-quic-transport

Commentary: This defines a new transport parameter and new rules for the server when it generates the Source Connection ID for Initial packets . See for rationale and background . 
 I agree that this is the right fix . However , I think I would prefer to allow the server to reuse the client 's initial DCID when sending the first server initial when there are no retries involved . From a theoretical standpoint , requiring the server to change the CID makes the one offered by the client useless which seems silly - but that is admittedly a very weak argument . From a practical standpoint , that would allow us to deploy this change faster . 
  is correct that that change would speed our deployment by quite a bit . I 'm more concerned about raising the bar too high for implementers that have very simple load balancing infrastructure , so I think this deserves an email to the list if you 're willing , 
 IMO I think it is a good idea to discourage servers from using client - generated data for load balancing etc . , even though we might agree that we do not need to forbid that . Maybe SHOULD NOT ? 
 I 'm not sure we should be discouraging servers from using client - generated connection IDs . We 've been doing that for years and I 'm not sure there is a credible attack here . 
 Discuss this on the issue please . 
 Hi everyone , I 've redone this based on discussion . Please take another look . I do n't think that this benefits from a description of an attack . This is not a change made in response to an attack , but in response to a request to make the protocol easier to analyze for the purposes of proving its security . 
 I have implement it in picoquic as such : 1 ) Always send the handshake CID TP . Not an interop issue since implementations are supposed to ignore unknown TP 2 ) Send the retry CID TP when also sending the ODCID . 3 ) Verify that the client is not sending Retry CID TP 4 ) If the protocol version is newer than " draft 27 " , check that the handshake CID is present , and that the retry CID is present if required . Then check that the values are what is expected . 5 ) When verifying the retry token , check that the retry CID sent by the client is what is expected . That version of picoquic is used in the interop runner , and I have not noticed any issue related to CID checks . But then the tests are bypassed with draft-27 versions . I suppose I could split the  test into verifying that the CID are present if the version is newer than draft-27 , and then check that the CID have the expected value if they are present . That would allow for interop testing with draft 27 . 
 I like deployment plan . I think it would be valuable to get deployment experience of these new transport parameters in draft-27 so that it does n't break interop . Perhaps we should add a temporary subsection to the spec on how to this , with a note that it 'll be removed before publication . It could say something like this : using draft-28 or later , these transport parameters MUST be sent , and received ones MUST be validated . using draft-27 or earlier , these transport parameters SHOULD be sent , and upon receipt : if is present , then validate using draft-28 rules else validate using draft-27 rules Thoughts ? 
 in practice , you can only publish new spec as draft-28 . So what you want is not a new draft , but maybe a note on the implementers ' slack . By the way , I did change my implementation to check the values if they are sent . 
 That sounds good to me , or perhaps on the implementer 's wiki 
 I just a wiki page on . 
 I changed to initialconnectionid . I do n't necessarily like that we are using " original " and " initial " , but I think that 's marginally better than creating the obviously redundant " originalinitial " variant of this . 
 Is it not necessary to authenticate both client CIDs in a Retry scenario ? C - S : Initial SCID = C1 ( attacker modifies to C2 ) , DCID =    Retry SCID = S2 , DCID = C2 ( modified to C1 ) C - S : Initial SCID = C1 , DCID = S2  : Initial SCID = S3 , DCID = C1 .... C - S : Short DCID =    Short DCID = C1 Admittedly , I do n't really understand the threat model here , but the very first packet 's SCID is n't authenticated unless the Initial SCID is in the Token . I do n't think a TP is needed , as the server can reject the 2nd initial if there 's a mismatch in SCID . Relatedly , if it 's written anywhere that the client MUST NOT change its CID during a Retry , it 's not in a place that 's obvious to me . 
 if the attacker modifies the SCID in an Initial that ultimately causes a Retry to be sent , that does n't affect the final state in any way , so there is no harm done . The reason we authenticate the DCID on that packet in the way we do is to verify that the the server is cooperating with the entity that generated the Retry token . Also , the client - chosen DCID value might persist as the server could use that value to determine its choice of connection ID . The client ca n't change its mind , so authenticating a single value is enough . That said , I will take on advisement that we do n't require that the client does n't change its connection ID . Issue inbound . 
 I just a picture . This new figure shows the complete set of messages that determine the connection ID that each peer uses . The explanation describes how the connection IDs in those messages are included in transport parameters . Hopefully this aids in understanding how this is put together . It 's not complicated , but it 's not necessarily clear from reading a set of rules that this is the case . 
 has noted in the past that we do n't authenticate the connection IDs that are exchanging during the handshake . This complicates analysis of header protection ( for details , see the upcoming paper ) . We already authenticate the connection ID that the client first uses if there is a Retry packet sent , but we do n't otherwise authenticate the connection IDs that are signaled in the Source Connection ID field . The question here is whether we should be more careful about authenticating these . also points out in that the ODCID transport parameter is an odd duck . If we use transport parameters to authenticate connection IDs , we might be better served by restoring a fixed header to the transport parameters so that we can more cleanly address that issue . 
 There is also something interesting about the ODCID transport parameter . If no retry happens , then the DCID gets authenticated , however if a retry does happen then an attacker can tamper with the new SCID in the RETRY packet . Also our QUIPS paper is on ePrint and section 3.4 has some relevant details 
 I think we need to see more ( supportive ) discussion in order to justify taking this on . 
 In the interests of both providing defense in depth and for simplifying the analysis of the protocol , I believe that we should consider the ways in which connection IDs are negotiated and the ways in which that negotiation might be more strongly protected . We currently do not validate any choice of any connection ID that is chosen during the handshake , with the exception of the Destination Connection ID the client chooses when a Retry was used . The describes an attack on earlier versions of header protection that relied on the variable position of the packet number length field , the lack of an authenticated length of the connection ID , and the malleability of the encryption used in header protection . We have since fixed the position of the packet number length , which invalidates that attack . The effect of the attack was not severe , but I would rather not have any weaknesses . Note also that two of these weaknesses remain and we only really fixed this problem by accident . The attack described required that a server generate a Retry . The attacker rewrites the Source Connection ID field from that message into a value that the server would then subsequently reuse . This seems to be in tension with the requirement that connection IDs be unpredictable , but I believe the theory is that the requirement only applies to the question of linkability . As long as an attacker is unable to generate another valid connection ID or link valid connection IDs to this original value , a server could reuse the client 's choice . Of course , in this case the value is chosen by the attacker , not the client . A server could authenticate the value it includes in a Retry packet by including it in the token , but let 's assume for now that it does not do that . Whether or not there is a concrete attack out of this , this demonstrates that an attacker can choose a connection ID . That 's not a great position to be in with respect to analysis of the protocol . Right now the values that are negotiated using the Source Connection ID field are not authenticated . It is true that these are ultimately authenticated when they are included in the AAD of a 1 - RTT packet , but that is rather circuitous . You might also say that Handshake packets also cover these , but that relies on even more convoluted logic . What I heard at QUIPS and what I learned from TLS is that formalizing proofs based on such indirect authentication can be extremely challenging . I realize that this is theoretical , but we made concessions in TLS for simplified analysis and as long as the complexity cost is low , the same might be done here . A relatively simple way to authenticate these connection IDs would be to include a transport parameter that includes the value that the endpoint includes in the Source Connection ID field of Initial or Handshake packets . Endpoints then validate this value before declaring the handshake complete . In terms of transport parameter construction , this is simple : endpoints make a choice and stick with it . The only real cost is the extra 21 bytes this takes . That is n't quite enough though . The server gets to choose new connection IDs twice during the handshake if a Retry packet is sent . Authenticating a single connection ID could not authenticate the Source Connection ID from the Retry packet . That 's might be OK on the basis that the value from the Retry wo n't be used after the handshake completes . Not authenticating the choice from Retry is less OK if the server adopts the value that the client uses in its Destination Connection ID field . Now the attacker just chose a connection ID . As this was the specific attack that was used , that needs to be addressed too . Rather than authenticate the Retry also , my suggestion there is to forbid the server from copying the client 's Destination Connection ID when it generates its first Initial packet . That is , the server needs to pick a completely new connection ID . We already do that for Retry packets . Then the attacker has no input into connection ID selection . We could limit the requirement to change connection ID to only the cases where Retry is used . That is require a change if there is a token in the Initial packet . It seems easier to require the change always . 
 My first intuition is that this requirement could be difficult for some people(it certainly requires a change for us ) . However , given Retry and NEWCONNECTIONID both have similar requirements , I think requiring this is fine , at least for us . 
 I 'm not convinced that we need a transport parameter here . As explained by a transport parameter would only protect the connection IDs used after the Retry , i.e. CIDs that are used after a connection has been accepted and an endpoint has created state for this connection . At this point , we could require endpoints to keep track of the SCID that they used , and discard incoming packets that arrive at this connection where the DCID does n't match the SCID they chose . If I 'm not mistaken , this would thwart the attack ( and as a bonus , it would do so earlier than the TP proposed here , since the TP would only be validated after the handshake completes ) . 
 suggests that allowing the server to copy the client 's ODCID when it is not sending a Retry would speed Google deployment . I think that is a reasonable request , but it does complicate things . I 'd like to hear about that . suggests that forcing a change of connection ID at the server ( always ? only when there is no Retry ? ) would be sufficient because all an endpoint needs to do is ensure that the choice they made is retained . I would like to see what thinks of that . ( I will also take this to the list , but here I get to at - mention people :) 
 It would be nice to avoid any unnecessary complication . is this a Google - specific problem , or would this also apply to other deployments ? 
 What are the required attackers capabilities in order to mount this attack ? Clearly , it can be mounted by a MITM , but MITM can do a lot of creative damage during the initial handshake . Can it be mounted by a Man - on - the - side ? In QUIC V1 , we understand that authentication only starts when keys are exchanged . The connection - id attack appears to cause the connection to fail because connection IDs are authenticated in 1 - RTT packets . That 's bad , but there are many ways for MITM to interfere with the connection set up and cause the connection to fail at 1RTT . Do we really want to do something specific about the connection ID ? Is n't that an example of piecemeal solutions that make the design complex without blocking all the holes ? We know the general outline of a stronger solution . It is presented in the authenticated handshake draft : derive a secret from the ESNI key of the server , use that secret to authenticate all initial packets . Doing that will suppress not just the connection ID attack , but also the whole class of " attacks by messing up with initial packets " . I would much rather authenticate the handshake that pile up piecemeal solutions . The working group has decided to push the authenticated handshake work to V2 , and to accept that there may be DOS attacks during the initial handshake . Is the connection ID attack so special that we need to delay V1 for it ? 
 In the design of Google QUIC , the client picks a random connection ID , and the server uses that . ( BTW that 's why it 's called a connection ID , it 's a unique identifier that has a one - to - one mapping with one connection ... ) What that means in practice is that the client uses randomness to generate the connection ID , the load balancer maps that to a given server , and using the same connection ID for the duration of the connection makes sure that all packets reach the same server . So far we 've kept this design for our implementation of IETF drafts . We understand that some server deployments may want to have the server pick its connection ID , but so far we do n't see the value in that outweighing the complexity . Today we do not yet have a good mechanism for a server to ask the load balancer for more connection IDs that will map to it . We have some hacks that we can perform , but I do n't think those hacks will work for the first connection that a server receives . So if this becomes required , we 'll have to build the load balancer protocol before we can deploy the new draft . 
 The problem is not with what you are doing , but a consequence of adding Retry to the protocol . In addressing the problems arising from that we can ask servers to make a small sacrifice in terms of requiring them to generate a new connection ID , something they need to know how to do anyway . Or , we can ask clients to conditionally validate server behaviour . I appreciate that if you have no need to send Retry , this might be an imposition on the server , but from the outside it seems totally doable . I would like to understand less about the strength of your reluctance to offer a new connection ID and more about why it might be difficult to do so . Is this expensive because you have to consult with load balancers ? How are you able to support migration ? 
 Though we tolerate denial of service prior to handshake completion , we do n't tolerate attacks that alter connection properties . This results in the attacker choosing a connection ID that the client will use after the handshake completes . 
 There is also an aspect of downgrade attacks to this : If part of a server farm has a flawed deployment , an attacker could use the SCID to route traffic to that part of the server farm and take advantage of that until the entire fleet has been upgraded . 
 you did not mention how the Google LB does the CID mapping , but if is hashed based rather than stateful , an attacker might be able to overload a single server og subset of servers , no ? And if it is stateful , you have a lot of coordination with fail - overs and offloads ? 
 quote " Or , we can ask clients to conditionally validate server behaviour . " I do n't think we can rely on clients validating server chosen CIDs . My intuition tells me that rogue or careless clients might compromise server infrastructure . I like the idea of keeping the state in the handshake and avoid a TP for that . However , I suspect that a server choosing a new CID from a Retry might move traffic to a separate server in choosing that CID so you can not remember if the resulting server was indeed the intended server . I 'm a bit vague on this , so I might be mistaken . 
 If we are to fix this , my choice would be to document the issue and observe that servers can fix it by tying the retry token to their proposed CID . That would implicitly solve Google 's issue . 
 While I 'm inclined to support statements on this , note that dictating the Initial DCID also dictates the Initial Keys , whether or not the server subsequenty changes . This could reduce the cost of sniffing Initial packets , for what it 's worth . 
 It seems a bit brittle to me , for instance it does n't prevent post - retry adversarial forwarding to a different server with the same token key , which could be used for downgrade as pointed out . It would play out like this : That 's not a very strong attack by any means but still makes me somewhat uncomfortable . That is also kind of OK but difficult to specify as a requirement - how would implementers interpret something like " you must bind the retry token to the proposed CID " ? In practice , they should do something like use the CID as part of the nonce of the ticket encryption , or store it in the stateful token database . Unsurprisingly , I much prefer a mechanism that cryptographically guarantees that the CID is authentic because there is no way for a honest and compliant client to know if the server implements the correct check ( the same argument as for the use of the client 1 - RTT key before checking the client finished ) 
 After skimming the paper and reading MT 's justification a few times , I guess I am still unclear on the threat model : 1 ) Attacker rewrites the SCID of a Retry Packet . This affects the Initial Keys and ca n't be protected by the TP . Server acceptance of the provided CID is a pretty good indication it does n't much care , in which case , meh . If someone picking a CID will take your site down , change the CID ! If we must do something here , perhaps we should just say " servers MUST change their CID if they are sending an ODCID TP ? " -- this would make it easier for Google and minimize the change otherwise . But really the answer is to put in the token . It 's the only way to definitively kill the connection if a MITM is messing with us , and solves the Initial - Key problem . 2 ) Attacker rewrites the SCID of server initial . Does n't Section 5.2 mean that the server would simply discard the remaining Client packets ? Does n't this obviate the need for the TP ? I guess the MITM could successfully rewrite to the original client - chosen DCID , but presumably servers are written to limit the ability of clients or MITMs to just ignore the new CID ? 
 Speaking in terms of design principles , has taught us that pretty much anything that does n't land in the key schedule can be abused by an attacker that makes each endpoint think it has a different value . Specifically to QUIC , everything going on in the CRYPTO stream lands in the transcript thanks to TLS 1.3 , but there are QUIC - specific fields that do n't : in particular the connection IDs and version from long headers . To protect the version , we have , but we do n't have anything for the Source CID . Therefore I 'm supportive of adding a transport parameter that makes sure that it lands in the transcript . On the other hand , requiring the server to always replace the client - chosen initial destination CID does not provide any security benefits in and of itself . There 's nothing preventing the server from determining its replacement CID deterministically from the client - chosen one , for example . This change would be non - trivial for the Google deployment because , unlike migration , it needs to happen synchronously when establishing the connection . If your communication with load balancers is asynchronous , you can delay sending NEWCONNECTIONID frames for migration until you 've received enough connection IDs from your load balancer , but delaying the response to a client 's initial has a performance cost that we 're not willing to pay . 
 from this I infer that pre - caching values is not feasible . Perhaps your load balancers integrate the client address in their decisions . Is that right ? An alternative is to alter the ODCID transport parameter to integrate the SCID from the Retry . Another would be to require that the server perform a check based on the Retry token ( as mentioned ) . 
 I am trying to wrap my head around the " transport parameters " proposal . I am looking at the sequence of the attack : 1 ) Client sends an Initial packet with a specific DCID ( later referred to as ODCID ) 2 ) Server sends a retry packet in which the DCID copies the original SCID of the client , and the SCID is set to the value that the server wants the client to use as the next DCID -- calling this Retry - CID 3 ) Attacker intercepts the retry packet , replaces the DCID by A - CID . 4 ) Client starts a new connection with DCID = A - CID instead of the expected Retry - CID , which possibly opens the possibility of attacks against the server , such as paying games with the load balancer . 5 ) Client includes some new transport parameters in Initial packets 6 ) Attacker possibly intercepts the client packet and messes with the transport parameters . At that point , we have different outcomes based on the defenses implemented by the server : a ) If the server has tied the Retry - CID and the ODCID to the token , the server finds that the incoming client Initial does not meet expectations , and closes the connection with an adequate error code . b ) If the server did not do ( a ) , the server will start establishing the connection , sending the server transport parameters as part of the encrypted extensions , in Handshake packets . The transport parameters include the ODCID . If I understand the proposal correctly , the transport parameters would also include the Retry - CID . The client would then receive these parameters , find out that something is amiss , and close the connection . Given these two choices , it seems that option ( a ) is much better . The Retry mechanism is designed for use under attack . In these scenarios , it is important to minimize the amount of work at the server . If the server has tied Retry - CID to the token , the session is terminated upon the first initial packet , which seems like the desired result . If not doing that , the server will expand resource to compute session keys , signatures , etc . , which means that the DOS attack is more effective . I also think that the server should not rely on the client for protection . The ODCID transport parameter and the proposed Retry - CID parameter allow the client to verify that things are as expected . But suppose for a moment that the attacker is the client itself , and that the goal of the attack is to overwhelm a specific server in the farm by using well chosen DCID . The " attacker - client " will certainly not terminate the connection on Retry - CID mismatch ! Then , I also wonder how servers would implement the Retry - CID transport parameter . It seems that currently many servers implement the ODCID requirement by encoding the ODCID in the token . I assume that server will implement the Retry - CID either by using algorithmic derivation of Retry - CID from ODCID , or by adding the Retry - CID to the token . In both cases , they can implement option ( a ) . So in practice , there is little incremental work for a server if it wants to do ( a ) rather than ( b ) , and there are sizable benefits in terms of reduced DoS surface . The recommendation ought to be , do ( a ) . Now , if servers actually do ( a ) , they will have no problem also sending a Retry - CID transport parameter in the " all clear " case . But that will not be very useful . 
 The problem is not having a server protect itself , that 's fine . The client has a stake in this also . It remains ignorant of whether the server has these protections . 
 it seems that we have agreement on two points a bit of discussion on the third : 1 ) The spec should describe the " munged retry " attack . It can be used to play games with server farms , either by attackers in the middle , or by attackers as client . It can produce a DOS attack of some sort despite the " retry " protection mechanisms . 2 ) The spec should describe how servers can protect themselves by tying the " Retry - CID " to the retry token , and in fact recommend that they do that . 3 ) Adding " retry - CID " as a transport parameter would give assurance to clients that the server is protected against the attack , and allow clients to detect attacks if the server is not protected . I am not sure that ( 3 ) is really needed . I do not really understand the client stake there , except in the general terms of defeating attackers in the middle and encouraging good server implementations . OTOH , if the server does ( 2 ) , it is not very onerous to also do ( 3 ) . But then , what prevents servers that do not care from taking shortcuts , not verify the token , and copy any incoming post - retry DCID in the transport parameter ? 
 I am similarly unconvinced by having that in a transport parameter . That 's why the PR currently does n't include that . As you say , it 's pretty easy to game . That 's why I prefer the changing connection ID . That at least has a hope of being enforced . 
 I think makes a lot of good points . However , tying ODCID to retry - CID could make the production DCID longer than is desirable . Another option might be to have an additional authentication tag ( AAT ) in the handshake packets that is carried along similar to TP , but not necessarily inside the TP machinery . The server or LB could check the AAT at high DoS load without forcing the CID to be long and it could cover other critical parameters as well . If the client needs similar assurances it can not use th AAT directly to do its own checking , but philosophically , the server decides the CIDs going towards the server , and it is the servers responsible to design and check those CIDs with reasonable security bounds for the given deployment . If a server does not check for retry attack CIDs , there are many other things that it might also not check making the connection flawed in some way . 
 I disagree , there are not many other things that the client and server can disagree on after the end of the TLS handshake . The idea to consider connection IDs as an unauthenticated connection parameter ( just like the IP address and UDP port ) that can be used by networking middlebox for DoS / routing is fine , and it 's a possible way to close this discussion , but I urge you to carefully consider the privacy impact for the client . It is somewhat pointless to write a formal proof of packet number encryption if it turns out that an active adversary can inject a 20 - byte long unique identifier that appears in the cleartext of every packet - imagine if China starts doing that to tag incoming QUIC connections to users , if many servers allow them to ( expecting their own middleboxes to do the same thing for legitimate reasons ) . Of course it is already possible to do that with TCP , but QUIC CIDs are much longer than TCP ports and can be use for pervasive monitoring at a fine granularity . If CIDs are truly negotiated between the client and server , the client has the guarantee that the server CID really comes from the server , and knows that no tracking CID has been inserted on the way . 
 I am still wondering why " servers MUST propose a new connection ID in the server Initial if they are going to include an ODCID TP " is insufficient . I believe it solves the Retry case and does n't create problems for Google . If the MITM is rewriting SCID on server Initials , does n't this break the connection anyway ? 
 It 's been a while , but I 'm wondering if this issue relates to old issue regarding 0 - RTT DCID attacks that was moved to quicv2 : 
 LGTM . I like the cleanliness and explicitness of this design . LGTMThanks for all the edits!Thanks for the diagrams , definitely clearer with them .
Paragraph (version A):
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in BCP
14 RFC2119 RFC8174 when, and only when, they appear in all capitals,
as shown here.
Paragraph (version B):
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
BCP 14 RFC2119 RFC8174 when, and only when, they appear in all
capitals, as shown here.
Paragraph (version B):
An endpoint might need to stop accepting previously issued connection
IDs in certain circumstances.  Such an endpoint can cause its peer to
retire connection IDs by sending a NEW_CONNECTION_ID frame with an
increased Retire Prior To field.  The endpoint SHOULD continue to
accept the previously issued connection IDs until they are retired by
the peer.  If the endpoint can no longer process the indicated
connection IDs, it MAY close the connection.
Paragraph (version B):
A client that supports only this version of QUIC MUST abandon the
current connection attempt if it receives a Version Negotiation
packet, with the following two exceptions.  A client MUST discard any
Version Negotiation packet if it has received and successfully
processed any other packet, including an earlier Version Negotiation
packet.  A client MUST discard a Version Negotiation packet that
lists the QUIC version selected by the client.
Paragraph (version A):
Note that multiple QUIC packets - even of different encryption levels
- may be coalesced into a single UDP datagram (see packet-coalesce),
and so this handshake may consist of as few as 4 UDP datagrams, or
any number more.  For instance, the server's first flight contains
packets from the Initial encryption level (obfuscation), the
Handshake level, and "0.5-RTT data" from the server at the 1-RTT
encryption level.
Paragraph (version A):
tls-0rtt-handshake shows an example of a connection with a 0-RTT
handshake and a single packet of 0-RTT data.  Note that as described
in packet-numbers, the server acknowledges 0-RTT data at the 1-RTT
encryption level, and the client sends 1-RTT packets in the same
packet number space.
Paragraph (version B):
tls-0rtt-handshake shows an example of a connection with a 0-RTT
handshake and a single packet of 0-RTT data.  Note that as described
in packet-numbers, the server acknowledges 0-RTT data in 1-RTT
packets, and the client sends 1-RTT packets in the same packet number
space.
Paragraph (version B):
Upon first receiving an Initial or Retry packet from the server, the
client uses the Source Connection ID supplied by the server as the
Destination Connection ID for subsequent packets, including any 0-RTT
packets.  This means that a client might have to change the
connection ID it sets in the Destination Connection ID field twice
during connection establishment: once in response to a Retry, and
once in response to an Initial packet from the server.  Once a client
has received a valid Initial packet from the server, it MUST discard
any subsequent packet it receives with a different Source Connection
ID.
Paragraph (version B):
The choice each endpoint makes about connection IDs during the
handshake is authenticated by including all values in transport
parameters; see transport-parameters.  This ensures that all
connection IDs used for the handshake are also authenticated by the
cryptographic handshake.
Paragraph (version B):
absence of the initial_source_connection_id transport parameter
from either endpoint,
Paragraph (version B):
absence of the original_destination_connection_id transport
parameter from the server,
Paragraph (version B):
absence of the retry_source_connection_id transport parameter from
the server after receiving a Retry packet,
Paragraph (version B):
a mismatch between values received from a peer in these transport
parameters and the value sent in the corresponding Destination or
Source Connection ID fields of Initial packets.
Paragraph (version B):
If a zero-length connection ID is selected, the corresponding
transport parameter is included with a zero-length value.
Paragraph (version B):
fig-auth-cid shows the connection IDs that are used in a complete
handshake.  The exchange of Initial packets is shown, plus the later
exchange of 1-RTT packets that includes the connection ID established
during the handshake.
Paragraph (version B):
fig-auth-cid-retry shows a similar handshake that includes a Retry
packet.
Paragraph (version B):
For the handshakes in fig-auth-cid and fig-auth-cid-retry the client
sets the value of the initial_source_connection_id transport
parameter to "C1".  In fig-auth-cid-retry, the server sets
original_destination_connection_id to "S1",
retry_source_connection_id to "S2", and initial_source_connection_id
to "S3".  In fig-auth-cid, the server sets
original_destination_connection_id to "S1",
initial_source_connection_id to "S3", and does not include
retry_source_connection_id.  Each endpoint validates the transport
parameters set by their peer, including the client confirming that
retry_source_connection_id is absent if no Retry packet was
processed.
Paragraph (version A):
A server MUST include the original_connection_id transport parameter
(transport-parameter-definitions) if it sent a Retry packet to enable
validation of the Retry, as described in packet-retry.
Paragraph (version B):
Endpoints use transport parameters to authenticate the negotiation of
connection IDs during the handshake; see cid-auth.
Paragraph (version B):
A client MUST NOT use remembered values for the following parameters:
ack_delay_exponent, max_ack_delay, initial_source_connection_id,
original_destination_connection_id, preferred_address,
retry_source_connection_id, and stateless_reset_token.  The client
MUST use the server's new values in the handshake instead, and absent
new values from the server, the default value.
Paragraph (version A):
Prior to validating the client address, servers MUST NOT send more
than three times as many bytes as the number of bytes they have
received.  This limits the magnitude of any amplification attack that
can be mounted using spoofed source addresses.  In determining this
limit, servers only count the size of successfully processed packets.
Paragraph (version B):
Prior to validating the client address, servers MUST NOT send more
than three times as many bytes as the number of bytes they have
received.  This limits the magnitude of any amplification attack that
can be mounted using spoofed source addresses.  For the purposes of
avoiding amplification prior to address validation, servers MUST
count all of the payload bytes received in datagrams that are
uniquely attributed to a single connection.  This includes datagrams
that contain packets that are successfully processed and datagrams
that contain packets that are all discarded.
Paragraph (version B):
A server can also use a Retry packet to defer the state and
processing costs of connection establishment.  Requiring the server
to provide a different connection ID, along with the
original_destination_connection_id transport parameter defined in
transport-parameter-definitions, forces the server to demonstrate
that it, or an entity it cooperates with, received the original
Initial packet from the client.  Providing a different connection ID
also grants a server some control over how subsequent packets are
routed.  This can be used to direct connections to a different server
instance.
Paragraph (version B):
A token issued with NEW_TOKEN MUST NOT include information that would
allow values to be linked by an observer to the connection on which
it was issued, unless the values are encrypted.  For example, it
cannot include the previous connection ID or addressing information.
A server MUST ensure that every NEW_TOKEN frame it sends is unique
across all clients, with the exception of those sent to repair losses
of previously sent NEW_TOKEN frames.  Information that allows the
server to distinguish between tokens from Retry and NEW_TOKEN MAY be
accessible to entities other than the server.
Paragraph (version A):
There is no need for a single well-defined format for the token
because the server that generates the token also consumes it.  A
token could include information about the claimed client address (IP
and port), a timestamp, and any other supplementary information the
server will need to validate the token in the future.
Paragraph (version B):
There is no need for a single well-defined format for the token
because the server that generates the token also consumes it.  Tokens
sent in Retry packets SHOULD include information that allows the
server to verify that the source IP address and port in client
packets remains constant.
Paragraph (version B):
Tokens sent in NEW_TOKEN frames MUST include information that allows
the server to verify that the client IP address has not changed from
when the token was issued.  Servers can use tokens from NEW_TOKEN in
deciding not to send a Retry packet, even if the client address has
changed.  If the client IP address has changed, the server MUST
adhere to the anti-amplification limits found in validate-handshake.
Note that in the presence of NAT, this requirement might be
insufficient to protect other hosts that share the NAT from
amplification attack.
Paragraph (version A):
An endpoint restarts its idle timer when a packet from its peer is
received and processed successfully.  The idle timer is also
restarted when sending the first ack-eliciting packet (see QUIC-
RECOVERY) after receiving a packet.  Restarting when sending packets
ensures that connections do not prematurely time out when initiating
new activity.  Only restarting when sending after receipt of a packet
ensures the idle timeout is not excessively lengthened past the time
the peer's timeout has expired.  An endpoint might need to send
packets to avoid an idle timeout if it is unable to send application
data due to being blocked on flow control limits; see flow-control.
Paragraph (version A):
An endpoint that sends packets near the end of the idle timeout
period risks having those packets discarded if its peer enters the
draining state before the packets arrive.  If a peer could time out
within a Probe Timeout (PTO; see Section 6.6 of QUIC-RECOVERY), it is
advisable to probe the path with an ack-eliciting packet to ensure
the connection is still responsive before sending any data that
cannot be retried safely.  Note that it is likely that only
applications or application protocols will know what information can
be retried.
Paragraph (version B):
A client will always know whether the server has Handshake keys
(see discard-initial), but it is possible that a server does not
know whether the client has Handshake keys.  Under these
circumstances, a server SHOULD send a CONNECTION_CLOSE frame in
both Handshake and Initial packets to ensure that at least one of
them is processable by the client.
Paragraph (version B):
Sending a CONNECTION_CLOSE of type 0x1d in an Initial or Handshake
packet could expose application state or be used to alter application
state.  A CONNECTION_CLOSE of type 0x1d MUST be replaced by a
CONNECTION_CLOSE of type 0x1c when sending the frame in Initial or
Handshake packets.  Otherwise, information about the application
state might be revealed.  Endpoints MUST clear the value of the
Reason Phrase field and SHOULD use the APPLICATION_ERROR code when
converting to a CONNECTION_CLOSE of type 0x1c.
Paragraph (version B):
CONNECTION_CLOSE frames sent in multiple packet types can be
coalesced into a single UDP datagram; see packet-coalesce.
Paragraph (version A):
All other packets are protected with keys derived from the
cryptographic handshake.  The type of the packet from the long header
or key phase from the short header are used to identify which
encryption level - and therefore the keys - that are used.  Packets
protected with 0-RTT and 1-RTT keys are expected to have
confidentiality and data origin authentication; the cryptographic
handshake ensures that only the communicating endpoints receive the
corresponding keys.
Paragraph (version B):
Data sent in CRYPTO frames is retransmitted according to the rules
in QUIC-RECOVERY, until all data has been acknowledged.  Data in
CRYPTO frames for Initial and Handshake packets is discarded when
keys for the corresponding packet number space are discarded.
Paragraph (version B):
One way to construct a probe for the path MTU is to coalesce (see
packet-coalesce) a Handshake packet (packet-handshake) with a short
header packet in a single UDP datagram.  If the UDP datagram reaches
the endpoint, the Handshake packet will be ignored, but the short
header packet will be acknowledged.  If the UDP datagram causes an
ICMP message to be sent, the first part of the datagram will be
quoted in that message.  If the the source connection ID is within
the quoted portion of the UDP datagram, that could be used for
routing.
Paragraph (version B):
The Initial packet contains a long header as well as the Length and
Packet Number fields.  The first byte contains the Reserved and
Packet Number Length bits.  Between the SCID and Length fields, there
are two additional fields specific to the Initial packet.
Paragraph (version B):
Like Initial packets (see discard-initial), data in CRYPTO frames for
Handshake packets is discarded - and no longer retransmitted - when
Handshake protection keys are discarded.
Paragraph (version B):
A server acknowledges the use of a Retry packet for a connection
using the retry_source_connection_id transport parameter; see
transport-parameter-definitions.  If the server sends a Retry packet,
it also subsequently includes the value of the Source Connection ID
field from the Retry packet in its retry_source_connection_id
transport parameter.
Paragraph (version B):
If the client received and processed a Retry packet, it MUST validate
that the retry_source_connection_id transport parameter is present
and correct; otherwise, it MUST validate that the transport parameter
is absent.  A client MUST treat a failed validation as a connection
error of type PROTOCOL_VIOLATION.
Paragraph (version B):
The value of the Destination Connection ID field from the first
Initial packet sent by the client; see cid-auth.  This transport
parameter is only sent by a server.
Paragraph (version A):
The maximum packet size parameter is an integer value that limits
the size of packets that the endpoint is willing to receive.  This
indicates that packets larger than this limit will be dropped.
The default for this parameter is the maximum permitted UDP
payload of 65527.  Values below 1200 are invalid.  This limit only
applies to protected packets (packet-protected).
Paragraph (version B):
The maximum UDP payload size parameter is an integer value that
limits the size of UDP payloads that the endpoint is willing to
receive.  UDP packets with payloads larger than this limit are not
likely to be processed by the receiver.
Paragraph (version B):
The default for this parameter is the maximum permitted UDP
payload of 65527.  Values below 1200 are invalid.
Paragraph (version B):
The value that the endpoint included in the Source Connection ID
field of the first Initial packet it sends for the connection; see
cid-auth.
Paragraph (version B):
The value that the the server included in the Source Connection ID
field of a Retry packet; see cid-auth.  This transport parameter
is only sent by a server.
Paragraph (version B):
A client MUST NOT include any server-only transport parameter:
original_destination_connection_id, preferred_address,
retry_source_connection_id, or stateless_reset_token.  A server MUST
treat receipt of any of these transport parameters as a connection
error of type TRANSPORT_PARAMETER_ERROR.
Paragraph (version B):
The Retire Prior To field counts connection IDs established during
connection setup and the preferred_address transport parameter; see
retiring-cids.  The Retire Prior To field MUST be less than or equal
to the Sequence Number field.  Receiving a value greater than the
Sequence Number MUST be treated as a connection error of type
FRAME_ENCODING_ERROR.
Paragraph (version B):
An endpoint that receives a NEW_CONNECTION_ID frame with a sequence
number smaller than the Retire Prior To field of a previously
received NEW_CONNECTION_ID frame MUST send a corresponding
RETIRE_CONNECTION_ID frame that retires the newly received connection
ID, unless it has already done so for that sequence number.
Paragraph (version B):
The application or application protocol caused the connection to
be closed.