Question:
NAME Good point about being more explicit. I actually think is valuable to reference an existing encoding of public keys providing also key type and curve, like CREDX in URL Also, there is a discussion about format for public keys in COSE, which if it is specified probably will be referenced by EDHOC instead of CREDX. I would be good if there is a common format used in all these instances. For the time being I propose that we reference CRED_X with empty text string subject name, and keep track of the COSE activity.
We should consider replace the NIST reference with SECG [1] to harmonize with EDHOC [2]. [1] URL [2] URL (edit) ... but the commits in [3] mainly refers to the NIST spec. so I propose we keep it as is for the time being. [2] URL
It looks good to me; we can give more details on one point. For the two HKDF invocations in Section 2.3.1, we can define more explicitly how the public keys are expressed when concatenated to form IKM-Sender and IKM-Recipient. Given a public key, that can simply be: For OKP signature keys, the compressed 'x' coordinate, i.e. what would be expressed in the key parameter -2 of a corresponding COSE Key. For EC2 signature keys, the 'x' coordinate followed by the 'y' coordinate in this order, i.e. what would be expressed in the key parameters -2 and -3 of a corresponding COSE Key. This should be sufficient, i.e. it shouldn't be needed to have a more structured encoding of public keys providing also key type and curve, e.g. like done for CRED_X in URL

The derivation of pairwise keys defined in key-derivation-pairwise is compatible with ECDSA and EdDSA asymmetric keys, but is not <del> compatible with RSA asymmetric keys.  The security of using the same key pair for Diffie-Hellman and for signing is demonstrated in Degabriele. </del> <ins> compatible with RSA asymmetric keys. For the public key translation from Ed25519 (Ed448) to X25519 (X448) specified in key-derivation-pairwise, variable time methods can be used since the translation operates on public information.  Any byte string of appropriate length is accepted as a public key for X25519 (X448) in RFC7748, it is therefore not necessary for security to validate the translated public key (assuming the translation was successful). The security of using the same key pair for Diffie-Hellman and for signing (by considering the ECDH procedure in sec-derivation-pairwise as a Key Encapsulation Mechanism (KEM)) is demonstrated in Degabriele and Thormarker. Applications using ECDH (except X25519 and X448) based KEM in sec- derivation-pairwise are assumed to verify that a peer endpoint's public key is on the expected curve and that the shared secret is not the point at infinity.  The KEM in Degabriele checks that the shared secret is different from the point at infinity, as does the procedure in Section 5.7.1.2 of NIST-800-56A which is referenced in sec- derivation-pairwise. Extending Theorem 2 of Degabriele, Thormarker shows that the same key pair can be used with X25519 and Ed25519 (X448 and Ed448) for the KEM specified in sec-derivation-pairwise.  By symmetry in the KEM used in this document, both endpoints can consider themselves to have the recipient role in the KEM -- as discussed in Section 7 of Thormarker - and rely on the mentioned proofs for the security of their key pairs. Theorem 3 in Degabriele shows that the same key pair can be used for an ECDH based KEM and ECDSA.  The KEM uses a different KDF than in sec-derivation-pairwise, but the proof only depends on that the KDF has certain required properties, which are the typical assumptions about HKDF, e.g., that output keys are pseudorandom.  In order to comply with the assumptions of Theorem 3, received public keys MUST be successfully validated, see Section 5.6.2.3.4 of NIST-800-56A. The validation MAY be performed by a trusted Group Manager.  For Degabriele to apply as it is written, public keys need to be in the expected subgroup.  For this we rely on cofactor DH, Section 5.7.1.2 of NIST-800-56A which is referenced in sec-derivation-pairwise. HashEdDSA variants of Ed25519 and Ed448 are not used by COSE, see Section 2.2 of I-D.ietf-cose-rfc8152bis-algs, and are not covered by the analysis in Thormarker, and hence MUST NOT be used with the public keys used with pairwise keys as specified in this document. </ins> 10.14.


Question: Back to one processing description Observe is now primarily inner Simplified processing Explicit cancellation by intermediary not supported

Observe RFC7641 is an optional feature.  An implementation MAY support RFC7252 and the OSCORE option without supporting RFC7641, in <del> which case the Observe related processing specified in this section, sequence-numbers and processing can be omitted. The Observe option as used here targets the requirements on forwarding of I-D.hartke-core-e2e-security-reqs (Section 2.2.1). This section specifies Observe processing associated to the Partial IV (observe-partial-iv) and Observe processing in the presence of RFC7641-compliant intermediaries (observe-option-processing). In contrast to e.g. block-wise, the Inner and Outer Observe option are not processed independently.  Outer Observe is required to support Observe operations in intermediaries, but the additional use of Inner Observe is needed to protect Observe registrations end-to- end (see observe-option-processing). observe-without-intermed specifies a simplified Observe processing which is applicable in the absence of intermediaries. </del> <ins> which case the Observe related processing can be omitted. </ins> <del> Note that OSCORE is compliant with the requirement that a client must not register more than once for the same target resource (see Section 3.1 of RFC7641) since the target resource for Observe registration is identified by all options in the request that are part of the Cache-Key, including OSCORE. </del> <ins> OSCORE supports a reduced set of RFC7641 operations performed in intermediary nodes as specified in this section.  The use of Observe targets the requirements on forwarding of Section 2.2.1 of I- D.hartke-core-e2e-security-reqs, i.e. that observations go through any intermediate node, as illustrated in Figure 8 of RFC7641). </ins> <del> 4.1.3.4.1. To support proxy operations, the CoAP client using Observe with OSCORE MUST set Outer Observe.  If Observe was only sent encrypted end-to-end, an OSCORE-unaware proxy would not expect several responses to a non-Observe request and notifications would not reach the client.  Moreover, intermediaries are allowed to cancel observations and inform the server; forbidding this may result in processing and transmission of notifications on the server side which do not reach the client. In case of registrations or re-registrations, the CoAP client using Observe with OSCORE MUST set both Inner and Outer Observe to the same value (0).  This allows the server to verify that the observation was requested by the client, thereby avoiding unnecessary processing and transmission of notifications, since such notifications would not benefit the client. An intermediary that supports Observe MUST copy the OSCORE option in the next hop request unchanged.  Although intermediaries are allowed to re-send notifications to other clients, when using OSCORE this does not happen, since requests from different clients will have different cache keys. The Outer Observe option in the CoAP request may be legitimately removed by a proxy or ignored by a server.  In these cases, the server processes the request as a non-Observe request and produce a non-Observe response.  If the OSCORE client receives a response to an Observe request without an Outer Observe value, then it verifies the response as a non-Observe response, as specified in ver-res.  If the OSCORE client receives a response to a non-Observe request with an Outer Observe value, it stops processing the message, as specified in ver-res. </del> <ins> Inner Observe is used by default to protect the value of the Observe option between the endpoints.  Outer Observe is additionally used to support a selected set of intermediate node operations that are useful while maintaining end-to-end security.  Intermediary nodes MUST copy the OSCORE option in the next hop request unchanged. </ins> In order to support Observe processing in OSCORE-unaware intermediaries, for messages with the Observe option the Outer Code <del> SHALL be set to 0.05 (FETCH) for requests and to 2.05 (Content) for </del> <ins> MUST be set to 0.05 (FETCH) for requests and to 2.05 (Content) for </ins> responses. <ins> 4.1.3.4.1. The client MUST set both Inner and Outer Observe to the same value in the request.  In order to support the case of an intermediary node ignoring a registration request (Observe 0) and instead processing a non-Observe request (Section 2 of RFC7641), the server MUST only consider the received message a registration request if both Inner and Outer Observe are set to 0. Clients can re-register observations to ensure that the observation is still active and establish freshness again (RFC7641 Section 3.3.1).  When an OSCORE protected observation is refreshed, not only the ETags, but also the Partial IV (and thus the payload and OSCORE option) change.  The server uses the Partial IV of the new request as the 'request_piv' of new responses. Since intermediaries are not assumed to have a security context with the server, cancellation or re-registration of an observation initiated by an intermediary node is not supported. Cancellation of observation by an intermediary using the Reset message as response to a notification can still be applied. An intermediary node may forward a re-registration message, but if a proxy re-sends an old registration message from a client this will trigger the replay protection mechanism in the server which, depending on action, may result in a termination of the observation in proxy or client.  An OSCORE aware intermediary SHALL NOT initiate re-registrations of observations.  A server MAY respond to a replayed registration request with a cached notification.  The server SHALL NOT respond to a replayed registration request with a message encrypted using the Partial IV of the request. Note that OSCORE is compliant with the requirement that a client must not register more than once for the same target resource (see Section 3.1 of RFC7641) since the target resource for Observe registration is identified by all options in the request that are part of the Cache-Key, including OSCORE. </ins> 4.1.3.4.2. If the server accepts an Observe registration, a Partial IV MUST be


Question: Back to one processing description Observe is now primarily inner Simplified processing Explicit cancellation by intermediary not supported

the order of notifications, the client SHALL maintain a Notification Number for each Observation it registers.  The Notification Number is a non-negative integer containing the largest Partial IV of the <del> received notifications for the associated Observe registration (see replay-protection).  The Notification Number is initialized to the Partial IV of the first successfully received notification response to the registration request.  In contrast to RFC7641, the received Partial IV MUST always be compared with the Notification Number, which thus MUST NOT be forgotten after 128 seconds.  Further details of replay protection of notifications are specified in replay- protection. Clients can re-register observations to ensure that the observation is still active and establish freshness again (RFC7641 Section 3.3.1).  When an OSCORE protected observation is refreshed, not only the ETags, but also the partial IV (and thus the payload and OSCORE option) change.  The server uses the new request's Partial IV as the 'request_piv' of new responses. </del> <ins> received notifications for the associated Observe registration. Further details of replay protection of notifications are specified in replay-notifications. The Inner Observe in a response MUST either have the value of Observe in the original CoAP message or be empty.  The former is used to allow the server to set the Observe values to be received by the client.  In the latter case the overhead of the Observe value is saved and instead the least significant bytes of the Partial IV is used as Observe value, see replay-notifications.  The Outer Observe in the response may be needed for intermediary nodes to support multiple responses to one request.  The client MAY ignore the Outer Observe value. If the client receives a response to an Observe request without an Observe value, then it verifies the response as a non-Observe response, as specified in ver-res.  If the client receives a response to a non-Observe request with an Observe value, then it stops processing the message but keeps the observation alive, as specified in ver-res. </ins> 4.1.3.5.


Question: Back to one processing description Observe is now primarily inner Simplified processing Explicit cancellation by intermediary not supported

The sending endpoint SHALL write the Code of the original CoAP message into the plaintext of the COSE object (see plaintext).  After that, the sending endpoint writes an Outer Code to the OSCORE <del> message.  With one exeception (see observe-option-processing) the Outer Code SHALL by default be set to 0.02 (POST) for requests and to 2.04 (Changed) for responses.  The receiving endpoint SHALL discard the Outer Code in the OSCORE message and write the Code of the COSE object plaintext (plaintext) into the decrypted CoAP message. </del> <ins> message.  With one exeception (see observe) the Outer Code SHALL by default be set to 0.02 (POST) for requests and to 2.04 (Changed) for responses.  The receiving endpoint SHALL discard the Outer Code in the OSCORE message and write the Code of the COSE object plaintext (plaintext) into the decrypted CoAP message. </ins> The other currently defined CoAP Header fields are Unprotected (Class U).  The sending endpoint SHALL write all other header fields of the


Question: Back to one processing description Observe is now primarily inner Simplified processing Explicit cancellation by intermediary not supported

7.4.1. <del> Additionally to the previous section, the following applies when Observe is supported. 7.4.1.1. A client receiving a notification SHALL compare the Partial IV of a received notification with the Notification Number associated to that Observe registration.  The ordering of notifications after OSCORE processing MUST be aligned with the Partial IV.  The client MAY do so by copying the least significant bytes of the Partial IV into the Observe option, before passing it to CoAP processing.  The client MAY ignore an Outer Observe option value.  If the verification of the response succeeds, and the received Partial IV was greater than the Notification Number, then the client SHALL update the corresponding Notification Number with the received Partial IV.  The client MUST stop processing notifications with a Partial IV which has been previously received.  An application MAY require the client to discard notifications which have Partial IV less than the Notification Number. If messages are processed concurrently, the Partial IV needs to be validated a second time after decryption and before updating the replay protection data.  The operation of validating the Partial IV and updating the replay protection data MUST be atomic. 7.4.1.2. In order to allow intermediaries to re-register their interest in a resource (see 3.3.1 of RFC7641), a server receiving an Observe registration with Token, kid and Partial IV identical to a previously received registration, and which decrypts without error SHALL not treat it as a replay and SHALL respond with a notification.  The notification may be a cached copy of the latest sent notification (with the same Token, kid and Partial IV) or it may be a newly generated notification with a fresh Partial IV. </del> <ins> The following applies additionally when Observe is supported. The Notification Number is initialized to the Partial IV of the first successfully received notification response to the registration request.  A client receiving a notification SHALL compare the Partial IV of a verified notification with the Notification Number associated to that Observe registration.  In contrast to RFC7641, the received Partial IV MUST always be compared with the Notification Number, which thus MUST NOT be forgotten after 128 seconds. If the verification of the response succeeds, and the received Partial IV was greater than the Notification Number, then the client SHALL update the corresponding Notification Number with the received Partial IV.  The operation of validating the Partial IV and updating the replay protection data MUST be atomic.  If the Inner Observe option is empty, then the client SHALL copy the least significant bytes of the Partial IV into the Observe option, before passing it to CoAP processing. If the Partial IV is less than or equal to the Notification Number, then the client SHALL stop processing the response but not cancel the observation. </ins> 7.5.


Question: Back to one processing description Observe is now primarily inner Simplified processing Explicit cancellation by intermediary not supported

7.5.3. <del> To prevent accepting replay of previously received notification responses, the client may perform the following procedure after boot: </del> <ins> To prevent accepting replay of previously received notifications, the client may perform the following procedure after boot: </ins> <del> The client rejects notifications bound to the earlier registration, removes all Notification Numbers and re-registers using Observe. </del> <ins> The client forgets about earlier registrations, removes all Notification Numbers and re-registers using Observe. </ins> 8.


Question: Back to one processing description Observe is now primarily inner Simplified processing Explicit cancellation by intermediary not supported

If Observe is implemented: <del> Replace step 1 in ver-req with: A.  Discard Code and all options marked in fig-option-protection with 'x' in column E, except for Observe, present in the received message. For example, an If-Match Outer option is discarded, Uri-Host Outer option is not discarded, Observe is not discarded. </del> <ins> Insert the following step before step 1 in ver-req: </ins> <del> Replace step 3 in ver-req with: </del> <ins> A.  Check if the Outer Observe option is present and has value zero. </ins> <del> B.  If Observe is present in the received message, and has value 0, check if the Token, kid and Partial IV are identical to a previously received Observe registration.  In this case, replay verification is postponed until step C.  Otherwise verify the 'Partial IV' parameter using the Replay Window, as described in replay-protection. </del> <ins> Insert the following step between step 6 and 7 of ver-req: </ins> <del> Insert the following steps between step 6 and 7 of ver-req: C.  If Observe was present in the received message (in step 1): If the value of Observe in the Outer message is 0: If Observe is present and has value 0 in the decrypted options, discard the Outer Observe.  If the Token, kid and Partial IV are identical to a previously received Observe registration, respond with a notification as described in observe-replay- processing; Otherwise, discard both the Outer and Inner (if present) Observe options and verify the 'Partial IV' parameter using the Replay Window, as described in replay-protection. If the value of Observe in the Outer message is not 0, discard the decrypted Observe option if present. </del> <ins> B.  If Inner Observe is present and has value zero, and Outer option is either not present or has not value 0, then remove the Observe option. </ins> 8.3.


Question: Back to one processing description Observe is now primarily inner Simplified processing Explicit cancellation by intermediary not supported

If Observe is implemented: <del> Replace step 1 of ver-res with: A.  Discard Code and all options marked in fig-option-protection with 'x' in column E, except for Observe, present in the received message. For example, ETag Outer option is discarded, as well as Max-Age Outer option, Observe is not discarded. Insert the following steps between step 2 and 3 of ver-res: B.  If the Observe option is present in the response, but the request was not an Observe registration, then go to 9. </del> <ins> Replace step 6 of ver-res with: </ins> <del> C.  If an Observe option is included or the Notification number for the observation has already been initiated, but the Partial IV is not present in the response, then go to 9. </del> <ins> A.  If Inner Observe is present then: </ins> <del> D.  For Observe notifications, verify the received 'Partial IV' parameter against the corresponding Notification Number as described in replay-protection. </del> <ins> If the request was not an Observe registration, then go to 9. </ins> <del> Replace step 6 of ver-res with: </del> <ins> If the Partial IV was not present in the response, then go to 9. </ins> <del> E.  If the response is a notification, initiate or update the corresponding Notification Number, as described in sequence-numbers. Otherwise, delete the attribute-value pair (Token, {Security Context, PIV}). </del> <ins> If the request was an Observe registration and the Partial IV was present in the response, then verify the received 'Partial IV' parameter against the corresponding Notification Number, and follow the processing described in replay-notifications. Otherwise, delete the attribute-value pair (Token, {Security Context, PIV}). </ins> <del> Replace step 7 of ver-res with: </del> <ins> Replace step 9 of ver-res with: </ins> <del> F.  Add decrypted Code, options and payload to the decrypted request, except for decrypted Observe if present.  The OSCORE option is removed. </del> <ins> B.  In case any of the previous erroneous conditions apply: the client SHALL stop processing the response.  An error condition occurring while processing a response in an observation does not cancel the observation.  A client MUST NOT react to failure by re- registering the observation immediately. </ins> <del> An error condition occurring while processing a response in an observation does not cancel the observation.  A client MUST NOT react to failure in step 5 by re-registering the observation immediately. </del> <ins> Note that the attribute-value attribute-value pair (Token, {Security Context, PIV}) MUST be deleted whenever the Observation is cancelled or "forgotten". </ins> 9.


Question:
I don't know why your commit got included.
I think I do: I modified the commit in order to add the description (to close issues). Now there are 2 identical commits, one is the one above ( 30475e3) that does not close issues, the other is the one in the master branch (7d4cbc2)
Thanks for your contribution Jim

receiving endpoint discards the message, if complying to the policy) may be obtained as part of normal resource discovery. <ins> Applications need to use a padding scheme if the content of a message can be determined solely from the length of the payload.  As an example, the strings "YES" and "NO" even if encrypted can be distinguished from each other as there is no padding supplied by the current set of encryption algorithms.  Some information can be determined even from looking at boundary conditions.  An example of this would be returning an integer between 0 and 100 where lengths of 1, 2 and 3 will provide information about where in the range things are.  Three different methods to deal with this are: 1) ensure that all messages are the same length.  For example using 0 and 1 instead of 'yes' and 'no'.  2) Use a character which is not part of the responses to pad to a fixed length.  For example, pad with a space to three characters.  3) Use the PKCS #7 style padding scheme where m bytes are appended each having the value of m.  For example, appending a 0 to "YES" and two 1's to "NO".  This style of padding means that all values need to be padded. </ins> 8. Privacy threats executed through intermediate nodes are considerably


Question: Replaced Media with Key distributor in on important place. Replaced the DTLS tunnel with TLS according to the latest tunnel draft. A couple of more wording fixes.

Distributor, this framework utilizes a DTLS-SRTP RFC5764 association between an endpoint and the Key Distributor.  To establish this association, an endpoint will send DTLS-SRTP messages to the Media <del> Distributor which will then forward them to the Media Distributor as </del> <ins> Distributor which will then forward them to the Key Distributor as </ins> defined in I-D.jones-perc-dtls-tunnel.  The Key Encryption Key (KEK) (i.e., EKT Key) is also conveyed by the Key Distributor over the DTLS association to endpoints via procedures defined in PERC EKT [I-


Question: Replaced Media with Key distributor in on important place. Replaced the DTLS tunnel with TLS according to the latest tunnel draft. A couple of more wording fixes.

Media Distributors use DTLS-SRTP RFC5764 directly with a peer Media Distributor to establish HBH keys for transmitting RTP and RTCP <del> packets that peer Media Distributor.  The Key Distributor does not </del> <ins> packets to that peer Media Distributor.  The Key Distributor does not </ins> facilitate establishing HBH keys for use between Media Distributors. 4.5.1. The procedures defined in DTLS Tunnel for PERC I-D.jones-perc-dtls- <del> tunnel establish one or more DTLS tunnels between the Media </del> <ins> tunnel establish one or more TLS tunnels between the Media </ins> Distributor and Key Distributor, making it is possible for the Media Distributor to facilitate the establishment of a secure DTLS association between each endpoint and the Key Distributor as shown


Question: Replaced Media with Key distributor in on important place. Replaced the DTLS tunnel with TLS according to the latest tunnel draft. A couple of more wording fixes.

the DTLS signaling, but will instead forward DTLS packets received from an endpoint on to the Key Distributor (and vice versa) via a tunnel established between Media Distributor and the Key Distributor. <del> This tunnel used to encapsulate the DTLS-SRTP signaling between the Key Distributor and endpoints will also be used to convey HBH key </del> <ins> This tunnel is used to encapsulate the DTLS-SRTP signaling between the Key Distributor and endpoints will also be used to convey HBH key </ins> information from the Key Distributor to the Media Distributor, so no additional protocol or interface is required.


Question: Replaced Media with Key distributor in on important place. Replaced the DTLS tunnel with TLS according to the latest tunnel draft. A couple of more wording fixes.

fingerprint of the DTLS-SRTP certificate used for the call.  This certificate is unique for a given call and a conference.  This allows the Key Distributor to ensure that only authorized users participate <del> in the conference.  Similarly the Key Distributor can create a WeBRTC Identity assertion bound the fingerprint of the unique certificate </del> <ins> in the conference.  Similarly the Key Distributor can create a WebRTC Identity assertion to bind the fingerprint of the unique certificate </ins> used by the Key Distributor for this conference so that the endpoint can validate it is talking to the correct Key Distributor.


Question:
This is much more compatible with extensibility patterns in TLS stacks, and in a way that is very forward-compatible with the forthcoming DTLS 1.3, while still being implementable in pre-1.3 stacks. DTLS 1.3 has a notion of post-handshake handshake messages, like and , which are acknoweldged with an message. The framework described here simply sends as yet another post-handshake message. Depends on
r? NAME
I have a bunch of comments but really I could live with this like you have it now.

This document defines an extension to DTLS-SRTP called SRTP EKT Key Transport which enables secure transport of EKT keying material from <del> one DTLS-SRTP peer to another.  This allows those peers to process EKT keying material in SRTP (or SRTCP) and retrieve the embedded SRTP keying material.  This combination of protocols is valuable because it combines the advantages of DTLS, which has strong authentication of the endpoint and flexibility, along with allowing secure multiparty RTP with loose coordination and efficient communication of per-source keys. </del> <ins> the DTLS-SRTP peer in the server role to the client.  This allows those peers to process EKT keying material in SRTP (or SRTCP) and retrieve the embedded SRTP keying material.  This combination of protocols is valuable because it combines the advantages of DTLS, which has strong authentication of the endpoint and flexibility, along with allowing secure multiparty RTP with loose coordination and efficient communication of per-source keys. </ins> 5.1.


Question:
This is much more compatible with extensibility patterns in TLS stacks, and in a way that is very forward-compatible with the forthcoming DTLS 1.3, while still being implementable in pre-1.3 stacks. DTLS 1.3 has a notion of post-handshake handshake messages, like and , which are acknoweldged with an message. The framework described here simply sends as yet another post-handshake message. Depends on
r? NAME
I have a bunch of comments but really I could live with this like you have it now.

5.2. <del> This document defines a new TLS negotiated extension called "srtp_ekt_key_transport" and a new TLS content type called EKTMessage. Using the syntax described in DTLS RFC6347, the following structures are used: If a DTLS client includes srtp_ekt_key_transport in its ClientHello, then a DTLS server that supports this extensions will includes srtp_ekt_key_transport in its ServerHello message.  If a DTLS client includes srtp_ekt_key_transport in its ClientHello, but does not receive srtp_ekt_key_transport in the ServerHello, the DTLS client MUST NOT send DTLS EKTMessage messages.  Also, the srtp_ekt_key_transport in the ServerHello MUST select one and only one EKTCipherType from the list provided by the client in the srtp_ekt_key_transport in the ClientHello. When a DTLS client sends the srtp_ekt_key_transport in its ClientHello message, it MUST include the SupportedEKTCiphers as the extension_data for the extension, listing the EKTCipherTypes the client is willing to use in preference order, with the most preferred version first.  When the server responds in the srtp_ekt_key_transport in its ServerHello message, it MUST include a SupportedEKTCiphers list that selects a single EKTCipherType to use (selected from the list provided by the client) or it returns an empty list to indicate there is no matching EKTCipherType in the clients list that the server is also willing to use.  The value to be used in the EKTCipherType for future extensions that define new ciphers is the value from the "EKT Ciphers Type" IANA registry defined in iana-ciphers. The figure above defines the contents for a new TLS content type called EKTMessage which is registered in iana-tls-content.  The EKTMessage above is used as the opaque fragment in the TLSPlaintext structure defined in Section 6.2.1 of RFC5246 and the srtp_ekt_message as the content type.  The srtp_ekt_message content type is defined and registered in iana-tls-ext. When the Server wishes to provide a new EKT Key, it can send EKTMessage containing an EKTKey with the new key information.  The client MUST respond with an EKTMessage of type ekt_key_act, if the EKTKey was successfully processed and stored or respond with the the ekt_key_error EKTMessage otherwise. The diagram below shows a message flow of DTLS client and DTLS server using the DTLS-SRTP Key Transport extension. Note that when used in PERC I-D.ietf-perc-private-media-framework, the Server is actually split between the Media Distrbutor and Key Distributor.  The messages in the above figure that are "SRTP packets" will not got to the Key Distributor but the other packets will be relayed by the Media Distributor to the Key Distributor. </del> <ins> This document defines a new TLS negotiated extension and a new TLS handshake message type .  The extension negotiates the cipher to be used in encrypting and decrypting EKTCiphertext values, and the handshake message carries the corresponding key. The diagram below shows a message flow of DTLS 1.3 client and server using EKT configured using the DTLS extensions described in this section.  (The initial cookie exchange and other normal DTLS messages are omitted.) In the context of a multi-party SRTP session in which each endpoint performs a DTLS handshake as a client with a central DTLS server, the extensions defined in this session allow the DTLS server to set a common EKT key among all participants.  Each endpoint can then use EKT tags encrypted with that common key to inform other endpoint of the keys it is using to protect SRTP packet.  This avoids the need for many individual DTLS handshakes among the endpoints, at the cost of preventing endpoints from directly authenticating one another. 5.2.1. To indicate its support for EKT, a DTLS-SRTP client includes in its ClientHello an extension of type listing the EKT ciphers the client supports in preference order, with the most preferred version first.  If the server agrees to use EKT, then it includes a extension in its ServerHello containing a cipher selected from among those advertised by the client. The field of this extension contains an "EKTCipher" value, encoded using the syntax defined in RFC5246: 5.2.2. Once a client and server have concluded a handshake that negotiated an EKT cipher, the server MUST provide to the client a key to be used when encrypting and decrypting EKTCiphertext values.  EKT keys are sent in encrypted handshake records, using handshake type .  The body of the handshake message contains an structure: [[ NOTE: RFC Editor, please replace "TBD" above with the code point assigend by IANA ]] The contents of the fields in this message are as follows: If the server did not provide a extension in its ServerHello, then EKTKey messages MUST NOT be sent by either the client or the server. When an EKTKey is received and processed successfully, the recipient MUST respond with an Ack handshake message as described in Section 7 of I-D.ietf-tls-dtls13.  The EKTKey message and Ack must be retransmitted following the rules in Secton 4.2.4 of RFC6347. Note: To be clear, EKT can be used with versions of DTLS prior to 1.3.  The only difference is that in a pre-1.3 TLS stacks will not have built-in support for generating and processing Ack messages. If an EKTKey message is received that cannot be processed, then the recipient MUST respond with an appropriate DTLS alert. </ins> 5.3.


Question:
This is much more compatible with extensibility patterns in TLS stacks, and in a way that is very forward-compatible with the forthcoming DTLS 1.3, while still being implementable in pre-1.3 stacks. DTLS 1.3 has a notion of post-handshake handshake messages, like and , which are acknoweldged with an message. The framework described here simply sends as yet another post-handshake message. Depends on
r? NAME
I have a bunch of comments but really I could live with this like you have it now.

5.4. <del> The DTLS ekt_key is sent using the retransmissions specified in Section 4.2.4.  of DTLS RFC6347. </del> <ins> The DTLS message is sent using the retransmissions specified in Section 4.2.4. of DTLS RFC6347.  Retransmission is finished with an Ack message or an alert is received. </ins> 6.


Question:
This is much more compatible with extensibility patterns in TLS stacks, and in a way that is very forward-compatible with the forthcoming DTLS 1.3, while still being implementable in pre-1.3 stacks. DTLS 1.3 has a notion of post-handshake handshake messages, like and , which are acknoweldged with an message. The framework described here simply sends as yet another post-handshake message. Depends on
r? NAME
I have a bunch of comments but really I could live with this like you have it now.

7.3. <del> IANA is requested to add srtp_ekt_key_transport as a new extension name to the "ExtensionType Values" table of the "Transport Layer Security (TLS) Extensions" registry with a reference to this specification and allocate a value of TBD to for this.  Note to RFC Editor: TBD will be allocated by IANA. </del> <ins> IANA is requested to add as a new extension name to the "ExtensionType Values" table of the "Transport Layer Security (TLS) Extensions" registry with a reference to this specification and allocate a value of TBD to for this. [[ Note to RFC Editor: TBD will be allocated by IANA. ]] </ins> Considerations for this type of extension are described in Section 5 of RFC4366 and requires "IETF Consensus". 7.4. <del> IANA is requested to add srtp_ekt_message as an new descriptions name to the "TLS ContentType Registry" table of the "Transport Layer Security (TLS) Extensions" registry with a reference to this specification, a DTLS-OK value of "Y", and allocate a value of TBD to for this content type.  Note to RFC Editor: TBD will be allocated by IANA. </del> <ins> IANA is requested to add as a new entry in the "TLS HandshakeType Registry" table of the "Transport Layer Security (TLS) Parameters" registry with a reference to this specification, a DTLS-OK value of "Y", and allocate a value of TBD to for this content type. [[ Note to RFC Editor: TBD will be allocated by IANA. ]] </ins> This registry was defined in Section 12 of RFC5246 and requires "Standards Action".


Question:
We're talking about the key wrap function here. Of course there's a requirement to remove padding, but it's explicitly clear in the AES Key Wrap RFCs. Seems like this text might be wrong now.
Thinking about this a bit, I think I will redo to just make it so decrypt has to remove the pad - I think this is way hold historic text that makes no sense given we use key wrap
Section 2.3 The decryption function returns a plaintext value P that is at least M bytes long, or returns an indication that the decryption operation failed because the ciphertext was invalid (i.e. it was not generated by the encryption of plaintext with the key K). These functions have the property that D(K, E(K, P)) = ( P concatenated with optional padding) for all values of K and P. Each cipher also has a limit T on the number of times that it can be used with any fixed key value. The EKTKey MUST NOT be used more that T times.
I think the goal was to avoid having a length indicator in the encrypted data as the stuff outside this knows the size (and thus how much pad to remove). Thoughts on what we should say here in the draft ? NAME NAME
should we clarify, how the code knows the length of the padding on the decryption side ?
I'm unsure what the question is. I reviewed that section of the current draft and it sounds clear. Perhaps the confusion is over the padding? The AES Key Wrap logic defines how to insert and remove padding. You can see how that's implemented here: URL There is a "with padding" function that inserts required padding per the RFC. So, what's the question?
NAME .. I think the question is on clarifying when the padding gets added and removed. Is it out of enc/dec or inside. We might just need to clarify tht
It's defined in the RFC. I don't think we should be trying to explain it again here.

a ciphertext value C with a length of N bytes. <del> The decryption function returns a plaintext value P that is at least M bytes long, or returns an indication that the decryption operation failed because the ciphertext was invalid (i.e. it was not generated by the encryption of plaintext with the key K). These functions have the property that D(K, E(K, P)) = ( P concatenated with optional padding) for all values of K and P.  Each cipher also has a limit T on the number of times that it can be used with any fixed key value.  The EKTKey MUST NOT be used for encryption more that T times.  Note that if the same EKT packet is retransmitted 3 times, that only counts as 1 encryption. </del> <ins> The decryption function returns a plaintext value P that is M bytes long, or returns an indication that the decryption operation failed because the ciphertext was invalid (i.e. it was not generated by the encryption of plaintext with the key K). These functions have the property that D(K, E(K, P)) = P for all values of K and P.  Each cipher also has a limit T on the number of times that it can be used with any fixed key value.  The EKTKey MUST NOT be used for encryption more that T times.  Note that if the same EKT packet is retransmitted 3 times, that only counts as 1 encryption. </ins> Security requirements for EKT ciphers are discussed in sec.


Question:
We're talking about the key wrap function here. Of course there's a requirement to remove padding, but it's explicitly clear in the AES Key Wrap RFCs. Seems like this text might be wrong now.
Thinking about this a bit, I think I will redo to just make it so decrypt has to remove the pad - I think this is way hold historic text that makes no sense given we use key wrap
Section 2.3 The decryption function returns a plaintext value P that is at least M bytes long, or returns an indication that the decryption operation failed because the ciphertext was invalid (i.e. it was not generated by the encryption of plaintext with the key K). These functions have the property that D(K, E(K, P)) = ( P concatenated with optional padding) for all values of K and P. Each cipher also has a limit T on the number of times that it can be used with any fixed key value. The EKTKey MUST NOT be used more that T times.
I think the goal was to avoid having a length indicator in the encrypted data as the stuff outside this knows the size (and thus how much pad to remove). Thoughts on what we should say here in the draft ? NAME NAME
should we clarify, how the code knows the length of the padding on the decryption side ?
I'm unsure what the question is. I reviewed that section of the current draft and it sounds clear. Perhaps the confusion is over the padding? The AES Key Wrap logic defines how to insert and remove padding. You can see how that's implemented here: URL There is a "with padding" function that inserts required padding per the RFC. So, what's the question?
NAME .. I think the question is on clarifying when the padding gets added and removed. Is it out of enc/dec or inside. We might just need to clarify tht
It's defined in the RFC. I don't think we should be trying to explain it again here.

other aspects of EKT processing.  EKT ciphers are free to use this field in any way, but they SHOULD NOT use other EKT or SRTP fields as an input.  The values of the parameters L, and T MUST be defined by <del> each EKTCipher. </del> <ins> each EKTCipher.  The cipher MUST provide integrity protection. </ins> 2.5.


Question:
NAME asked how to best approach logging from a server's perspective, given that things like version negotiation and stateless retry are not inherently tied to a single connection. We should add some informative guidance on how to best approach this to the spec, depending on how much state you're willing to keep around Some options: low state: keep a separate qlog file for the entire server. This logs vneg, retry, etc.. Then, when a connection is truly accepted, start a new .qlog for the individual connection, containing all events thereafter. The URL can then also contain an event signalling the acceptance of a new connection for later cross-linking between the files. low state: keep a single huge qlog file for everything, using the "groupid" field to allow later de-multiplexing into separate connections (I believe quant does this atm) stateful: if you already track vneg/retry and link them up with the final connection, you can output them in the per-connection qlog file as well Maybe also shortly talk about some of the trade-offs in each option. Also talk about how to approach server-level events like serverlistening and packet_dropped in separate scenarios.
I lean on the side of minimally and clearly identifying the challenges and maybe signpost some features and leave it up to implementers to figure out how to address this. They can always push back later in the specification lifecycle is something is deemed missing.

2.2. <del> For several types of events, it is sometimes impossible to tie them to a specific conceptual QUIC connection (e.g., a packet_dropped event triggered because the packet has an unknown connection_id in the header).  Since qlog events in a trace are typically associated with a single connection, it is unclear how to log these events. Ideally, implementers SHOULD create a separate, individual "endpoint- level" trace file (or group_id value), not associated with a specific connection (for example a "server.qlog" or group_id = "client"), and log all events that do not belong to a single connection to this grouping trace.  However, this is not always practical, depending on the implementation.  Because the semantics of most of these events are well-defined in the protocols and because they are difficult to mis-interpret as belonging to a connection, implementers MAY choose to log events not belonging to a particular connection in any other trace, even those strongly associated with a single connection. Note that this can make it difficult to match logs from different vantage points with each other.  For example, from the client side, it is easy to log connections with version negotiation or retry in the same trace, while on the server they would most likely be logged in separate traces.  Servers can take extra efforts (and keep additional state) to keep these events combined in a single trace however (for example by also matching connections on their four-tuple instead of just the connection ID). </del> <ins> A single qlog event trace is typically associated with a single QUIC connection.  However, for several types of events (for example, a transport-packetdropped event with trigger value of "connection_unknown"), it can be impossible to tie them to a specific QUIC connection, especially on the server. There are various ways to handle these events, each making certain tradeoffs between file size overhead, flexibility, ease of use, or ease of implementation.  Some options include: Log them in a separate endpoint-wide trace (or use a special group_id value) not associated with a single connection. Log them in the most recently used trace. Use additional heuristics for connection identification (for example use the four-tuple in addition to the Connection ID). Buffer events until they can be assigned to a connection (for example for version negotiation and retry events). </ins> 3.


Question:
Also, add structure to the "changes from v1" section.
It would be a simple matter to switch around the packet type codes in long headers, e.g. 0x0 = Retry 0x1 = Handshake 0x2 = 0-RTT 0x3 = Initial so no one ossifies on 0x0 = Initial.
I'm ambivalent on this. It's fairly trivial to have the long header parsed in version-specific fashion, so it's easy to implement, but I'm not sure how much value it has. It also makes reading packets slightly harder.

QUIC version 2 endpoints MUST implement the QUIC version 1 specification as described in QUIC, QUIC-TLS, and RFC9002, with the <del> following changes: </del> <ins> following changes. </ins> <del> The version field of long headers is 0x709a50c4. </del> <ins> 3.1. </ins> <del> The salt used to derive Initial keys in Section 5.2 of QUIC-TLS changes to: </del> <ins> The version field of long headers is 0x709a50c4. </ins> <del> The labels used in QUIC-TLS to derive packet protection keys (Section Section 5.1 of QUIC-TLS), header protection keys (Section Section 5.4 of QUIC-TLS), Retry Integrity Tag keys (Section Section 5.8 of QUIC-TLS), and key updates (Section Section 6.1 of QUIC-TLS) change from "quic key" to "quicv2 key", from "quic iv" to "quicv2 iv", from "quic hp" to "quicv2 hp", and from "quic ku" to "quicv2 ku", to meet the guidance for new versions in Section Section 9.6 of QUIC-TLS of that document. </del> <ins> 3.2. </ins> <del> The key and nonce used for the Retry Integrity Tag (Section 5.8 of QUIC-TLS) change to: </del> <ins> Initial packets use a packet type field of 0b01. 0-RTT packets use a packet type field of 0b10.  Handshake packets use a packet type field of 0b11.  Retry packets use a packet type field of 0b00. 3.3. 3.3.1. The salt used to derive Initial keys in Section 5.2 of QUIC-TLS changes to: 3.3.2. The labels used in QUIC-TLS to derive packet protection keys (Section Section 5.1 of QUIC-TLS), header protection keys (Section Section 5.4 of QUIC-TLS), Retry Integrity Tag keys (Section Section 5.8 of QUIC-TLS), and key updates (Section Section 6.1 of QUIC-TLS) change from "quic key" to "quicv2 key", from "quic iv" to "quicv2 iv", from "quic hp" to "quicv2 hp", and from "quic ku" to "quicv2 ku", to meet the guidance for new versions in Section Section 9.6 of QUIC-TLS of that document. 3.3.3. The key and nonce used for the Retry Integrity Tag (Section 5.8 of QUIC-TLS) change to: </ins> 4.


Question:
The correct term from the VN document would be "original version" but just removing the word initial avoids the confusion
Fewer words means fewer nits

Finally QUIC-VN provides two mechanisms for endpoints to negotiate the QUIC version to use.  The "incompatible" version negotiation <del> method can support switching from any initial QUIC version to any other version with full generality, at the cost of an additional round-trip at the start of the connection.  "Compatible" version negotiation eliminates the round-trip penalty but levies some restrictions on how much the two versions can differ semantically. </del> <ins> method can support switching from any QUIC version to any other version with full generality, at the cost of an additional round-trip at the start of the connection.  "Compatible" version negotiation eliminates the round-trip penalty but levies some restrictions on how much the two versions can differ semantically. </ins> QUIC version 2 is meant to mitigate ossification concerns and exercise the version negotiation mechanisms.  The only change is a


Question:
In we agreed on this. Considering that the decision affects handling of multiple frames, I think it's worth clarifying the general rule in the draft. For discussions regarding specific frames, please refer: MAXSTREAMS, MAXDATA, MAXSTREAMDATA - RESETSTREAM, STOPSENDING - ACK -
If you want to be explicit, perhaps also mention that stream ranges can be retransmitted with different boundaries or partially, if this isn't already covered by some existing text.
NAME While that's possible, I think we should better handle retransmission rules of specific frames in separate PRs. The reason I suggest this having this catch-all sentence is because to me it seems that the concept is sometimes being lost.
I agree that I'd like to discourage this a bit more than this PR does.
NAME NAME Your comments make sense to me. I'll update the PR.
Moved to 13.2, expanding the text to encourage reassembling frames containing up-to-date information. PTAL.
This is implicitly assumed, and, as NAME points out in , not doing so can cause undesired outcomes. There should be normative text in the transport draft requiring this behavior.
So the situation is that if one so far have ACKed: 1,2,3,6,7. Then if 4,5 shows up at the receiver and it is going to ACK those, it must at least send an ACK that contains 4,5 and 7, thus likely acking 4-7? It should not be allowed to send an ACK saying 4, 5 in the above situation as that doesn't indicate the receiver total progress, i.e. all the way to 7? I think requiring Largest Acknowledge to always indicate highest solves some issues and likely simplifies a lot of implementations. But it may result in larger ACK frames as one will have include the full current state between the largest Acknowledged and so far into the past PNs that you need to go. In severe re-ordering cases that could be a lot. Will this cause cause the ACK to be to large to include? Especially maybe in connections with a large delay bandwidth product going full steam encountering a serious hick up in the network. For example if an ACK is required to ack packet 4000 + 1E9 and you have 500 gaps that has arrived the last RTT/4 and really should be included. Resulting in an ACK frame that is at least 1000 bytes large, possibly bigger.
There are a few things this precludes, and we we should understand those before doing this. 1) A very limited implementation(ie: hardware) can't always send only one ACK block without giving up on reordered packets. I don't have such an implementation, but at some point I remember discussing this idea with people who seemed interested in it. 2) One cannot do multipath with QUIC v1 and it means the multipath design will have to use a PN space per path, as described in Christian's draft: URL I think that's likely the right choice for other reasons, but I'm hesitant to make that decision now. 3) An RTT sample can only be taken based on the largest acked. Therefore, if there is a large amount of reordering(ie: 1RTT), you don't get any RTT samples for an RTT. If we care about this, we can probably solve it a different way in the recovery draft, but that likely means using ack delay sometimes and not others. In regards to Martin's comment, I thought we already had text that said ACKs with lower packet numbers than the largest ACK packet number should be ignored, since they're old?
NAME regarding your question. "In regards to Martin's comment, I thought we already had text that said ACKs with lower packet numbers than the largest ACK packet number should be ignored, since they're old?" At least when it comes to ECN, the editors have been working hard to reformulate which has resulted in that there is nothing that applies this from the PN increasing for the ACKs. So to solve the ECN part, I think (re-)introducing that aspect into the text is the simpliest fix for ECN. But there clearly are other aspects here.
NAME The problem doesn't go away if you ignore acks that are lower than largest_acked. The problem is that the receiver sent the acks in the wrong order because packets were received in the wrong order, but ECN counts are going up. But you raise good points. This is a corner case. I think that with the current spec, under these conditions, ECN gets turned off since validation fails. I think that's a reasonable outcome, and I'm fine with it. NAME
ECN Validation as I currently understand it will not fail if the sender to receiver reordering happens as long as the ACKs from the receiver to sender are not reordered. So to my understanding what is missing is a requirement for the sender to no process verfication for out of order ACKs. It will not fail if the largest acknowledge is not increasing as the comparison is done on number of newly ACKed packets versus counts change. The current sentence in Section 13.3.2 (-17): "Counts MUST NOT be verified if the ACK frame does not increase the largest received packet number at the endpoint." Which I interpret to mean that what PN the ACK reference (sender-receiver direction), rather than the PN of the receiver to sender direction. Can NAME or NAME fix that?
I think is enough to address the original problem, so I'd like to close this issue. I think and are enough. NAME sound ok?
Yes, the ECN related issue is resolved. What I don't know if it is resolved fully is the implementation requirements is that a sender MUST be capable of handling an ACK frame with Largest Acknowledged that is smaller than highest received? From my perspective there are good and valid arguments why this may be required, however I think consensus needs to be established on that.
NAME I am not sure if I'm following the context, but my understanding is that a sender MUST be capable of that, because we allow an endpoint to simply retransmit the payload of a packet that is being deemed lost; see .
Just a stray thought: is this requirement really strictly needed? It would complicate trasnmitters that split work into multiple processing units which might not be fully synced on the latest ACK'ed.
NAME what NAME says. Also, a sender needs to be able to simply deal with reordering on the ack path. Did you mean something else?
My concern was primarily about the clearness of this behavior in the specification text. In transport I find the following which indicates this but are not explicit. : To limit receiver state or the size of ACK frames, a receiver MAY limit the number of ACK Ranges it sends. : Largest Acknowledged: A variable-length integer representing the largest packet number the peer is acknowledging; this is usually the largest packet number that the peer has received prior to generating the ACK frame. I think there are strong hints, with the above "usually the largest" indicating that it is not always. I would have made this explicit in 19.3, but then I prefer being more explicit than not. I think it is possible interop issue point. Anywhere else this is more explicit? (I have read github master version) NAME I think there are strong points for allowing an ACK frame to acknowledge only a part of the range between highest received and confirmed to be have been ACKed. The two main reasons I see. high rate flows suffering an packet loss burst so that the number of ACK ranges becomes to large to fit a single QUIC packet. Low complexity receivers ACKing a single range of received packets and doing this for reordered packets.
NAME As suggested by NAME in , might be the correct place. I am advocating for describing the design principle the PR, but we might (or might not) be interested in expanding how ACK could look like.
So results in certain implications, that an ACK could arrive that addresses older state, thus resulting in acknowledging some PNs that was previously unacknowledged. As 13.2 is about retransmissions, I think there are other desing principle aspects of ACKs that probably should be covered, but then earlier in 13.1.
We're in the process of making our implementation accept smaller largest_acked values, so I'm wonder if we're any closer to consensus(one way or the other) on this issue?
I think this is mostly addressed and what's left is OBE. There's text in the draft now that says: "Processing counts out of order can result in verification failure. An endpoint SHOULD NOT perform this verification if the ACK frame is received in a packet with packet number lower than a previously received ACK frame. Verifying based on ACK frames that arrive out of order can result in disabling ECN unnecessarily." This would be adequate, but there's other text (thanks to ) that says old ACKs can be resent. I think we simply add a note about that in the para above, which should be adequate.
Discussed in London: NAME to prepare a PR for those remaining bits
NAME any progress here?
I think the conclusion here is close with no further action, but it'd be good for NAME to confirm.
I've added , which I believe addresses what's left of this issue.
Note that we agreed that proposal-ready would be used when there were approvals for PRs (or at least apparent agreement, as determined by editors).
NAME : Yeah, my bad.
This gets fixed by , so marking this issue as well.
Fixed by .

data, unless priorities specified by the application indicate otherwise (see stream-prioritization). <ins> Even though a sender is encouraged to assemble frames containing up- to-date information every time it sends a packet, it is not forbidden to retransmit frames of lost packets as they are.  A receiver MUST accept packets containing an outdated frame, such as a MAX_DATA frame carrying a smaller maximum data than one found in an older packet. </ins> Upon detecting losses, a sender MUST take appropriate congestion control action.  The details of loss detection and congestion control are described in QUIC-RECOVERY.


Question:
(Note that the issue identifies two issues, but one was already fixed in .)
In , NAME correctly observed that I messed up , but he closed his PR and I'm not able to reopen it without more git wizardry than I'm interested in practicing today. Easier just to fix it in my own branch.
Clients don't send GOAWAY and when a client sends one, the server treats it as HTTPUNEXPECTEDFRAME. By contrast, servers don't send MAXPUSHID but the client treats receiving one as HTTPMALFORMEDFRAME. By contrast, if GOAWAY is sent on !control it's HTTPUNEXPECTEDFRAME, but if MAXPUSHID is sent on !control, it's HTTPWRONGSTREAM. I think the answers here are HTTPUNEXPECTEDFRAME and HTTPWRONGSTREAM respectively, but we should be consistent.
I think you're correct. There are some situations where newer errors would be more appropriate.

QUIC Stream ID for a client-initiated bidirectional stream encoded as a variable-length integer.  A client MUST treat receipt of a GOAWAY frame containing a Stream ID of any other type as a connection error <del> of type HTTP_MALFORMED_FRAME. </del> <ins> of type HTTP_WRONG_STREAM. </ins> Clients do not need to send GOAWAY to initiate a graceful shutdown; they simply stop making new requests.  A server MUST treat receipt of


Question:
I find this pretty hard to read, but assuming I am reading it corectly, it basically says that if you read any packet or write any packet that has a frame other than ACK or padding, then you reset the timer. The text about "other packet has not been acknowledged or lost" doesn't make sense unless you have some very complicated timer scheme, because the packet won't be acknowledge or lost until after it is sent, at which point I have already reset the timer.
Yeah, this is opaque. I think that the logic is something like: when receiving a packet, restart the idle timer when sending an ACK-eliciting packet. if you haven't sent other ACK-eliciting packets since the idle timer was started, restart the idle timer That is, if you send 10 packets, only the first of those restarts the timer. This clearly needs to be reworded.
I'd suggest one change to the second bullet, Martin. "when sending an ACK-eliciting packet. if you haven't sent other ACK-eliciting packets since the idle timer was restarted due to a received packet, restart the idle timer" And yes, that text is not clear.
I like the look of the wording change in ac59e11. Is there something blocking it from being applied?
Nothing. I just neglected to open the pull request. That happens sometimes. Lots of changes in flight...
I think this looks good, but NAME has more familiarity with this code than I do, so I'm adding him as well.

definitions) is closed.  A connection enters the draining state when the idle timeout expires. <del> Each endpoint advertises its own idle timeout to its peer.  The idle timeout starts from the last packet received.  In order to ensure that initiating new activity postpones an idle timeout, an endpoint restarts this timer when sending a packet.  An endpoint does not postpone the idle timeout if another packet has been sent containing frames other than ACK or PADDING, and that other packet has not been acknowledged or declared lost.  Packets that contain only ACK or PADDING frames are not acknowledged until an endpoint has other frames to send, so they could prevent the timeout from being refreshed. </del> <ins> Each endpoint advertises its own idle timeout to its peer.  An enpdpoint restarts any timer it maintains when a packet from its peer is received and processed successfully.  The timer is also restarted when sending a packet containing frames other than ACK or PADDING (an ACK-eliciting packet, see QUIC-RECOVERY), but only if no other ACK- eliciting packets have been sent since last receiving a packet. Restarting when sending packets ensures that connections do not prematurely time out when initiating new activity. </ins> The value for an idle timeout can be asymmetric.  The value advertised by an endpoint is only used to determine whether the


Question:
In the recovery draft, RTT is briefly spelled out in section 5 but is used in several earlier sections. SRTT and PTO are not explained at all, it seems. TLP is spelled out. RTO has a section of its own but it referenced before that. The recovery doc cannot be a tutorial on transmission theory, but it would be helpful to list the key acronyms and possibly reference an RFC with more details. There are already sections summarising key variables in pseudocode. There are references at the end, but the reader would have to go through them all.
Yes, thanks for the note. I'm planning to do a cleanup of that doc soon.
I fixed defined RTT earlier in .

result is smaller than the min_rtt, the RTT should be used, but the ack delay field should be ignored. <del> A sender calculates both smoothed RTT and RTT variance similar to those specified in RFC6298, see on-ack-received. </del> <ins> A sender calculates both smoothed RTT (SRTT) and RTT variance (RTTVAR) similar to those specified in RFC6298, see on-ack-received. </ins> A sender takes an RTT sample when an ACK frame is received that acknowledges a larger packet number than before (see on-ack-


Question:
While we allow the consumer to start using new CIDs anytime, there are consequences of consuming them excessively, as discussed in starting from this comment. The text clarifies that excessive consumption is not what the issuer needs to support.
NAME For HTTP3, it is natural to assume that the connections would not survive for very long time. In such case, capping the number of total connection IDs is a practical countermeasure against excessive issuance of CIDs. Implementations need not to be as complicated as capping the frequency.
I don't want to put this in the draft. It tells endpoints not to change connection IDs based on some unspecified (scary!) constraints that may or may not be present in a peer. I realize that there might be a limited supply in some implementations, but artificial constraints on the rate of use is not the way I would address the problem. Refusing or slowing issuance of new connection IDs if someone retires too many is a better approach. In other words, implementations should deal with this on their own.
NAME If that's the concern, do you think clarifying that the issue can "refuse or slow issuance of new connection IDs" in section 5.1.1 would be fine? The problem I have with current text is that section 5.1.1 only says that the issuer SHOULD issue new CIDs as the consumer retires them. I think we need to clarify that doing that without limitation could be dangerous.
NAME Moved the clarification to the issuer side. PTAL.
One low-level observation: CID's need to be looked up in a hash table or similar. For a busy server multiplexing many connections, it want this table in fast cache, also to reject invalid CID's fast. You may be able to handle 5000 connections efficiently, but if you are required to handle 8x5000 this can degrade performance, especially on rejection. You can counter this by cryptographically mapping multiple CID's a single internal CID but that is not the simplest approach. Therefore, choosing a minimum number of CID's should be done with care. Would 2 or 3 not be sufficient for most use cases?
NAME > Unfortunately, this is a design change, and a new one. just to be clear, are you referring to my comment on a limit of eight, or something earlier?
NAME I think we should have a separate discussion around a sensible default. Part of the idea here was to make sure that we were very unlikely to run out, even around lost/retransmitted packets on different paths. Choosing a very low number brings with it other potential issues which probably should hold up this change?
NAME yes, I realised this relates to maxconnectionids.
I'm going with editorial then.
While I can see why you'd limit the frequency of issuing new connection IDs, I don't think you should limit the number of total connection IDs per connection.Unfortunately, this is a design change, and a new one. From an abundance of caution, we'll need an issue for this, and chair assessment of consensus.I'm not convinced this is a design change -- there was previously a SHOULD, and this adds additional text (including a MAY) around when you might choose to violate the SHOULD. However, no mandatory behavior is added, changed, or removed.A few nits, but this looks good to me. That said, this issue will need consensus.

available and unused connection IDs.  While each endpoint independently chooses how many connection IDs to issue, endpoints SHOULD provide and maintain at least eight connection IDs.  The <del> endpoint SHOULD do this by always supplying a new connection ID when a connection ID is retired by its peer or when the endpoint receives a packet with a previously unused connection ID.  Endpoints that initiate migration and require non-zero-length connection IDs SHOULD provide their peers with new connection IDs before migration, or risk the peer closing the connection. </del> <ins> endpoint SHOULD do this by supplying a new connection ID when a connection ID is retired by its peer or when the endpoint receives a packet with a previously unused connection ID.  However, it MAY limit the frequency or the total number of connection IDs issued for each connection to avoid the risk of running out of connection IDs (see reset-token). An endpoint that initiates migration and requires non-zero-length connection IDs SHOULD ensure that the pool of connection IDs available to its peer allows the peer to use a new connection ID on migration, as the peer will close the connection if the pool is exhausted. </ins> 5.1.2.


Question:
I suspect these are uncontroversial.
All three Mart[ie]ns now agree, no further objections allowed.
LGTM, with the one change altered.

Data is protected using a number of encryption levels: <del> Plaintext </del> <ins> Initial Keys </ins> Early Data (0-RTT) Keys


Question:
I suspect these are uncontroversial.
All three Mart[ie]ns now agree, no further objections allowed.
LGTM, with the one change altered.

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 function from the negotiated cipher suite.  Other versions of TLS <del> MUST provide a similar function in order to be used QUIC. </del> <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


Question:
I suspect these are uncontroversial.
All three Mart[ie]ns now agree, no further objections allowed.
LGTM, with the one change altered.

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> <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


Question:
I suspect these are uncontroversial.
All three Mart[ie]ns now agree, no further objections allowed.
LGTM, with the one change altered.

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> <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


Question:
Another attempt to group related concepts in this section which hopefully (This is technically design, because previously-required server behavior is now only recommended.)
Why do I have to explicitly cancel after GOAWAY? Given that GOAWAY already tells the client this, what's the point?
GOAWAY tells the client that those requests aren't going to be serviced, but the streams will continue to exist. If the cleanup period is significant, having the streams open is a bad idea. However, attaching SHOULD to this is unnecessary, I think that we might instead just note that clients are free to do as they please with streams that won't be answered.
Discussed in Tokyo; this doesn't need to be required server behavior, but recommended (or RECOMMENDED) as a method to clean up state. Should have a reminder cross-reference to request rejection.
Lgtm now

Servers SHOULD NOT increase the QUIC MAX_STREAM_ID limit after sending a GOAWAY frame. <del> Once GOAWAY is sent, the server MUST reject requests sent on streams with an identifier greater than or equal to the indicated last Stream ID.  Clients MUST NOT send new requests on the connection after receiving GOAWAY, although requests might already be in transit.  A new connection can be established for new requests. If the client has sent requests on streams with a Stream ID greater than or equal to that indicated in the GOAWAY frame, those requests are considered rejected (request-cancellation).  Clients SHOULD cancel any requests on streams above this ID.  Servers MAY also reject requests on streams below the indicated ID if these requests were not processed. </del> <ins> Clients MUST NOT send new requests on the connection after receiving GOAWAY; a new connection MAY be established to send additional requests. Some requests might already be in transit.  If the client has already sent requests on streams with a Stream ID greater than or equal to that indicated in the GOAWAY frame, those requests will not be processed and MAY be retried by the client on a different connection. The client MAY cancel these requests.  It is RECOMMENDED that the server explicitly reject such requests (see request-cancellation) in order to clean up transport state for the affected streams. </ins> Requests on Stream IDs less than the Stream ID in the GOAWAY frame <del> might have been processed; their status cannot be known until they are completed successfully, reset individually, or the connection terminates. </del> <ins> might have been processed; their status cannot be known until a response is received, the stream is reset individually, or the connection terminates.  Servers MAY reject individual requests on streams below the indicated ID if these requests were not processed. </ins> Servers SHOULD send a GOAWAY frame when the closing of a connection is known in advance, even if the advance notice is small, so that the


Question:
I believe UNEXPECTED_FRAME is the preferred type.
I actually prefer the wording in duplicate push section and wonder if we should port that to PUSH_PROMISE too

A client MUST NOT send a DUPLICATE_PUSH frame.  A server MUST treat the receipt of a DUPLICATE_PUSH frame as a connection error of type <del> HTTP_MALFORMED_FRAME. </del> <ins> HTTP_UNEXPECTED_FRAME. </ins> The DUPLICATE_PUSH frame carries a single variable-length integer that identifies the Push ID of a resource that the server has


Question:
Builds on .
Initial packets need to be in 1200 byte datagrams for DoS amplification reasons. We have an exception for the case where an ACK for a Handshake packet has been received from the peer. In that case, we remove the requirement to pad. That condition is extraordinarily obscure, especially if we are suggesting that endpoints not send any more Initial packets once they have Handshake keys. Removing this text is the right answer.
+1 to the proposed resolution.

can be mounted using spoofed source addresses.  In determining this limit, servers only count the size of successfully processed packets. <del> Clients MUST ensure that UDP datagrams containing Initial packets are sized to at least 1200 bytes, adding padding to packets in the datagram as necessary.  Once a client has received an acknowledgment for a Handshake packet it MAY send smaller datagrams.  Sending padded datagrams ensures that the server is not overly constrained by the amplification restriction. </del> <ins> Clients MUST ensure that UDP datagrams containing only Initial packets are sized to at least 1200 bytes, adding padding to packets in the datagram as necessary.  Sending padded datagrams ensures that the server is not overly constrained by the amplification restriction. </ins> Packet loss, in particular loss of a Handshake packet from the server, can cause a situation in which the server cannot send when


Question:
I realise this may be a bit out of context for this PR, but I can't find any clear definition of when the handshake is complete other than this being magically spawned from the inner workings of TLS.
Previous discussions have established the CFIN is HoL blocking, partially because even though it's not strictly necessary, if client auth is in use, it's critical to receive the client's entire Handshake flight before the server processes 1RTT packets. I don't think the current TLS text is sufficiently clear(and normative) about that. Section 4.1.1 has: "Important: Until the handshake is reported as complete, the connection and key exchange are not properly authenticated at the server. Even though 1-RTT keys are available to a server after receiving the first handshake messages from a client, the server cannot consider the client to be authenticated until it receives and validates the client's Finished message. The requirement for the server to wait for the client Finished message creates a dependency on that message being delivered. A client can avoid the potential for head-of-line blocking that this implies by sending a copy of the CRYPTO frame that carries the Finished message in multiple packets. This enables immediate server processing for those packets." URL
I agree, perhaps this section needs to say something along the lines of:
How is this not a duplicate of ?
Nevermind, I can fix this easily.

though 1-RTT keys are available to a server after receiving the first handshake messages from a client, the server cannot consider the client to be authenticated until it receives and validates the <del> client's Finished message. </del> <ins> client's Finished message.  A server MUST NOT process 1-RTT packets until the handshake is complete.  A server MAY buffer or discard 1-RTT packets that it cannot read. </ins> The requirement for the server to wait for the client Finished message creates a dependency on that message being delivered.  A


Question:
This was always intended (and also written in the description of FRAMEENCODINGERROR), but didn't show up in the text somehow.
I agree with NAME about the MUSTs that you shuffled around are statements of fact, not interoperability requirements, but the addition is fine.

contain frames. QUIC payloads MUST contain at least one frame, and MAY contain <del> multiple frames and multiple frame types. </del> <ins> multiple frames and multiple frame types.  Frames MUST fit within a single QUIC packet and MUST NOT span a QUIC packet boundary. </ins> <del> Frames MUST fit within a single QUIC packet and MUST NOT span a QUIC packet boundary.  Each frame begins with a Frame Type, indicating its type, followed by additional type-dependent fields: </del> <ins> Each frame begins with a Frame Type, indicating its type, followed by additional type-dependent fields: </ins> The frame types defined in this specification are listed in frame- types.  The Frame Type in ACK, STREAM, MAX_STREAMS, STREAMS_BLOCKED,


Question:
This was always intended (and also written in the description of FRAMEENCODINGERROR), but didn't show up in the text somehow.
I agree with NAME about the MUSTs that you shuffled around are statements of fact, not interoperability requirements, but the addition is fine.

the frame.  These frames are explained in more detail in frame- formats. <ins> An endpoint MUST treat the receipt of a frame of unknown type as a connection error of type FRAME_ENCODING_ERROR. </ins> All QUIC frames are idempotent in this version of QUIC.  That is, a valid frame does not cause undesirable side effects or errors when received more than once.


Question:
…are: require unlinkability by stating: "SHOULD NOT expose linkability" suggest use of encryption when embedding expiration time in the token
Thanks NAME !
My understanding is that tokens provided by NEW_TOKEN frames should not leak information that allows observers correlate the newly established connection with the previous connection. Such information include the time when the token was issued, RTT, server name (when SNI is not used or Encrypted SNI is used), or even the size of the token. However, the draft seems to be vague about the requirement. I think it might be worth clarifying the principle in the draft. "a token SHOULD include an expiration time" (section 8.1.2) - I think we should change this to "a token SHOULD be associated an expiration time", considering the fact that we are talking about "stateful" design (stateless design is mentioned briefly in one of the following paragraphs). In a stateful design, an opaque identifier is the only thing that a server should be allowed to send. "In a stateless design, a server can use encrypted and authenticated tokens to pass information to clients" - I think we might prefer using "SHOULD" rather than "can".
I think the current text is fine: "include" translates to "put into the token and encrypt" in my mind. Reading that a token is "associated" with an expiration time would give me pause.
Would you mind clarifying where the "and encrypt" comes from? My point is that that is the way it should be, however the text does not seem to clarify that.
I don't recall how I arrived at it -- perhaps some common sense. Now that I have implemented it, it seems only natural. Perhaps we should simply add "and encrypt" to the text instead of changing to "associated with," which is less clear?
I'm happy to know that we share the common sense :+1: As stated in the opening comment, my "editorial" preference goes to stating the principle that any information in an NEW_TOKEN token (other than the opaque lookup key used in a stateful design) SHOULD be encrypted. If that is to be met, I think adding "and encrypt" would be fine.
I agree with NAME -- I think stating this explicitly as a SHOULD is sensible.
(For the chairs, and triage purposes). This suggests a normative requirement that I don't think that we need, or that is already implied by existing text. There would be new normative text. I believe that is still editorial on the basis that the requirement is already implied, but will defer to your judgment.
FWIW, what I am shooting for is a change like URL
NAME and others, is kazuhoNAME kind of the change you were envisioning?
I was asked to move here. I miss the point, that the server SHOULD NOT construct the same token multiple times because this leads to additional scenarios where tracking by a network observer becomes feasible. The referenced PR does not fix this problem.
NAME I think we are in agreement that unlinkability between tokens is required. IMO the phrase "SHOULD NOT expose linkability" in the proposed text captures the concept, though I might agree that "i.e., ..." needs improvement.
NAME NAME change would be adequate, and I agree with NAME that this is effectively editorial. Do the chairs want to mark this issue as ?
NAME Yes, I agree with you on the phrase "Should NOT expose likability". To address my concern, I suggest to include "This includes that the server constructs each time a different token when issuing tokens to clients from the same source address." after line 1560 of #kazuho/base-draftsNAME
Marking this as editorial
Looks good, modulo the minor suggestions.

connections.  Servers MAY discard any Initial packet that does not carry the expected token. <ins> A token SHOULD be constructed for the server to easily distinguish it from tokens that are sent in Retry packets as they are carried in the same field. The token MUST NOT include information that would allow it to be linked by an on-path observer to the connection on which it was issued.  For example, it cannot include the connection ID or addressing information unless the values are encrypted. </ins> Unlike the token that is created for a Retry packet, there might be some time between when the token is created and when the token is <del> subsequently used.  Thus, a token SHOULD include an expiration time. The server MAY include either an explicit expiration time or an issued timestamp and dynamically calculate the expiration time.  It is also unlikely that the client port number is the same on two </del> <ins> subsequently used.  Thus, a token SHOULD have an expiration time, which could be either an explicit expiration time or an issued timestamp that can be used to dynamically calculate the expiration time.  A server can store the expiration time or include it in an encrypted form in the token. It is unlikely that the client port number is the same on two </ins> different connections; validating the port is therefore unlikely to be successful. <del> A token SHOULD be constructed for the server to easily distinguish it from tokens that are sent in Retry packets as they are carried in the same field. </del> If the client has a token received in a NEW_TOKEN frame on a previous connection to what it believes to be the same server, it SHOULD include that value in the Token field of its Initial packet.


Question:
draft-ietf-quic-tls currently mentions AEADAES256CCM, however there is no way to use that AEAD in TLS 1.3 - TLSAES256CCMSHA256 does not appear in the . If I understand this correctly, the presence of AEADAES256CCM in the document was an editorial oversight.
Thanks. This was extremely confusing: you meant CCM, but wrote GCM in tons of places.

Before a TLS ciphersuite can be used with QUIC, a header protection algorithm MUST be specified for the AEAD used with that ciphersuite. This document defines algorithms for AEAD_AES_128_GCM, <del> AEAD_AES_128_CCM, AEAD_AES_256_GCM, AEAD_AES_256_CCM (all AES AEADs are defined in AEAD), and AEAD_CHACHA20_POLY1305 CHACHA.  Prior to TLS selecting a ciphersuite, AES header protection is used (hp-aes), matching the AEAD_AES_128_GCM packet protection. </del> <ins> AEAD_AES_128_CCM, AEAD_AES_256_GCM (all AES AEADs are defined in AEAD), and AEAD_CHACHA20_POLY1305 CHACHA.  Prior to TLS selecting a ciphersuite, AES header protection is used (hp-aes), matching the AEAD_AES_128_GCM packet protection. </ins> 5.4.2.


Question:
draft-ietf-quic-tls currently mentions AEADAES256CCM, however there is no way to use that AEAD in TLS 1.3 - TLSAES256CCMSHA256 does not appear in the . If I understand this correctly, the presence of AEADAES256CCM in the document was an editorial oversight.
Thanks. This was extremely confusing: you meant CCM, but wrote GCM in tons of places.

5.4.3. This section defines the packet protection algorithm for <del> AEAD_AES_128_GCM, AEAD_AES_128_CCM, AEAD_AES_256_GCM, and AEAD_AES_256_CCM.  AEAD_AES_128_GCM and AEAD_AES_128_CCM use 128-bit AES AES in electronic code-book (ECB) mode.  AEAD_AES_256_GCM, and AEAD_AES_256_CCM use 256-bit AES in ECB mode. </del> <ins> AEAD_AES_128_GCM, AEAD_AES_128_CCM, and AEAD_AES_256_GCM. AEAD_AES_128_GCM and AEAD_AES_128_CCM use 128-bit AES AES in electronic code-book (ECB) mode.  AEAD_AES_256_GCM uses 256-bit AES in ECB mode. </ins> This algorithm samples 16 bytes from the packet ciphertext.  This value is used as the input to AES-ECB.  In pseudocode:


Question:
I must have missed this when making the PR to remove the version negotiation text. Thanks NAME !
I wasn’t aware that there was an issue. Sorry for that!
No worries, thanks for doing this!
We can probably remove big chunks of section "8.1. Protocol and Version Negotiation" since we don't do version negotiation anymore in v1.
Fixed with . Thanks NAME

8.1. <del> The QUIC version negotiation mechanism is used to negotiate the version of QUIC that is used prior to the completion of the handshake.  However, this packet is not authenticated, enabling an active attacker to force a version downgrade. To ensure that a QUIC version downgrade is not forced by an attacker, version information is copied into the TLS handshake, which provides integrity protection for the QUIC negotiation.  This does not prevent version downgrade prior to the completion of the handshake, though it means that a downgrade causes a handshake failure. </del> QUIC requires that the cryptographic handshake provide authenticated protocol negotiation.  TLS uses Application Layer Protocol Negotiation (ALPN) RFC7301 to select an application protocol.  Unless


Question:
As of , the client MUST use the same handshake message.
NAME That's quite complicated, and I'm not sure if we've chosen the right design here. I'd like to keep this PR editorial though. I opened to discuss this.
In URL, NAME points out that after a Retry, all 0-RTT packets sent in the first flight are still valid, although they will probably have been dropped by the server (unless there's significant reordering). That means that a client SHOULD retransmit all 0-RTT packets in the second flight. We now have two different scenarios: In the case of a HelloRetryRequest, the client is prohibited from sending 0-RTT, and has to cancel retransmissions for all outstanding 0-RTT packets. In the case of Retry, the 0-RTT packets from the first flight are declared lost (without any effect on the cwnd though) and retransmitted. Considering that Retry adds a roundtrip anyway (and thereby limits the usefulness of 0-RTT), and that we only expect it to be used by a server that's under attack (which makes it likely to refuse 0-RTT later in the handshake), does it really make sense to send 0-RTT in that case?
NAME I am not sure if I agree with the observation. The transport draft states that a server MAY send Retry packets in response to Initial and 0-RTT packets. A server can either discard or buffer 0-RTT packets that it receives (). Notice that the server is allowed to "buffer" 0-RTT packets. I am not sure if I like this ambiguity (because I think most if not all of us will be dropping 0-RTT packets that carry the original DCID when sending a Retry), but IMO the draft is clear.
NAME thanks for pointing that out. My point is that we should change the draft (i.e. this is a design issue, not an editorial issue). The reason a server (or a LB) performs a Retry is that it either has reasons to suspect that the client isn't reachable at the 2-tuple it sent the packet from, or that it is under load, and either uses the Retry to redirect traffic to a different backend server, or just to buy itself some time Under both circumstances, a server wouldn't want to allocate additional state for buffering 0-RTT packets. I'm therefore suggesting to change the draft such that: A server that performs a Retry MUST discard 0-RTT packets. A client MUST NOT use 0-RTT after a Retry was performed. Does that make sense to you?
Yeah, I can envision a server that considers buffering some number of packets to be cheaper than doing a TLS handshake. For such servers, delaying the TLS handshake until client proves it's existence but buffering the 0-RTT packets in the meantime would make sense. That said, I'd be fine with this, assuming that the discarded 0-RTT packets are the ones that carry the original DCID. I would prefer not having this requirement. Once the client is known to exist, a server needs to communicate with the client. Use of 0-RTT helps reduce the server load, because when used, average lifetime of connections becomes 1-RTT less. That leads us to having less concurrent connections.
When our implementation does Retry, it's because we've hit a memory pressure limit and we want to protect ourselves from attack. If a client supplies us with a valid token, we will accept 0-RTT still, but we won't buffer it from the previous Initial (without a token). So, if the client gets a Retry and still wants to do 0-RTT, they need to retransmit it, with the new CID, in a new packet (with a new packet number). I don't see why that design should be prevented.
Ok, I see that there's value in doing 0-RTT after a Retry, and furthermore, there seem to be good reasons (prevention of tampering by middle boxes) to disallow 0-RTT after a HelloRetryRequest in TLS 1.3, as NAME pointed out OOB. Since we can assume that most (all?) server implementation will drop 0-RTT packets when sending a Retry, the only reasonable thing to do for a client is to treat all 0-RTT packets as lost and retransmit them. Considering that, it would make sense to require servers to drop all Retry packets from the first flight, as NAME suggests.
NAME Thank you for suggesting a path forward. I think my weak preference goes to something slightly different. I think we are in agreement that most if not all the servers would not buffer the 0-RTT packets carrying the original DCIDs when they send Retrys. It makes sense to acknowledge the fact in the specification and suggest clients to retransmit 0-RTT data it has already sent. What I am not sure is if there is a reason to forbid servers from buffering such 0-RTT packets. From client's point of view, sending 0-RTT data once per connection is an optimization. Retransmitting 0-RTT data when the server sends a Retry is further optimization. If we think that way, servers that buffer 0-RTT packets when sending a Retry has increased chance of utilizing 0-RTT data. Compared to that, there is no reason to mandate servers to drop 0-RTT packets. To summarize, I think all we need to clarify is that servers responding with Retries are likely to discard 0-RTT packets that carry the original DCIDs and therefore that retransmitting 0-RTT data makes sense. But nothing more.
What if client takes action on Retry, and the old 0-RTT state lingers - wouldn't that make servers more vulnerable to DDoS attacks from packet sniffers?
This also bears on . If the DCID doesn't change, then the server won't be able to differentiate the first flight of 0-RTT packets, which you're proposing to drop, from the second flight of 0-RTT packets which it accepts. The current text says that the server MAY buffer and process them later; you're saying that servers probably won't. I think that's fine, but some might -- hence, I favor NAME suggestion to retain the permission to buffer but the caution to the client that the packets were quite possibly lost/dropped. In terms of actual spec change, I think that means this text in : ...becomes a SHOULD instead of a MAY.
It seems like you have sorted this out. I have no problem with using "SHOULD" over "MAY" here. Note that the reason we have this distinction is logical separation of the mechanism of Retry and 0-RTT acceptance. Retry strictly precedes the connection attempt. No point in blocking 0-RTT if you have to Retry. HelloRetryRequest is different in that certain characteristics it might cause to reset affect whether the 0-RTT works. Retry is required to use the same ClientHello, so there is no need to have the two interact; you can treat a Retry almost as a loss event for the first Initial and everything works fine.
So, the effect of not changing the handshake message is that all previously-sent 0-RTT data is still valid, but has potentially/probably been lost rather than queued. Clients obviously MUST NOT reuse the packet number for different data, but in their not-resetting, they also can't change the data that they've already sent in those packets. They'll need to retransmit it, because otherwise there's a potential DoS attack by delaying/replaying a 0-RTT packet by one RTT against a server that does Retries.This PR looks good to me as an editorial improvement. Regarding NAME point, the transport draft explicitly states that a server sending a Retry can buffer 0-RTT packets that carried the original DCID, and process them after receiving a response to the Retry. To put it differently, I think we are clear on the semantics and that there are ways to implement this without having security concerns. That said, I understand that NAME has opened a design issue () to discuss if that is the design we want to have.LGTM

have been lost or discarded by the server.  A client MAY attempt to resend data in 0-RTT packets after it sends a new Initial packet. <del> A client MUST NOT reset the packet number it uses for 0-RTT packets. The keys used to protect 0-RTT packets will not change as a result of responding to a Retry packet unless the client also regenerates the cryptographic handshake message.  Sending packets with the same packet number in that case is likely to compromise the packet </del> <ins> A client MUST NOT reset the packet number it uses for 0-RTT packets, since the keys used to protect 0-RTT packets will not change as a result of responding to a Retry packet.  Sending packets with the same packet number in that case is likely to compromise the packet </ins> protection for all 0-RTT packets because the same key and nonce could be used to protect different content.