jiebi/CodeConvo huggingface dataset:
Change:
accidentally targeted an older branch that was since merged into master. This just takes the same change and redirects it to the main branch.

Discussion:
A "HpkeKeyConfig" structure carrying the configuration information associated with the HPKE public key.  Note that this structure contains the "config_id" field, which applies to the entire <del> ECHConfigContents.  Sites MUST NOT publish two differet"ECHConfigContents" values with the same "HpkeKeyConfig" value. </del> <ins> ECHConfigContents.  Sites MUST NOT publish two different "ECHConfigContents" values with the same "HpkeKeyConfig" value. The RECOMMENDED technique for choosing "config_id" is to choose a random byte.  This process is repeated if this config_id matches that of any valid ECHConfig, which could include any ECHConfig that has been recently removed from active use. </ins> The longest name of a backend server, if known.  If this value is not known it can be set to zero, in which case clients SHOULD use

The "HpkeKeyConfig" structure contains the following fields: <del> An opaque identifier for the given HPKE key configuration.  This </del> <ins> A one-byte identifier for the given HPKE key configuration.  This </ins> is used by clients to indicate the key used for ClientHello encryption.

"payload", as computed above. If optional configuration identifiers (see optional-configs)) are <del> used, "config_id" SHOULD be set to a randomly generated eight bytes. Unless specified by the application using (D)TLS or externally configured on both sides, implementations MUST compute the field as specified in encrypted-client-hello. </del> <ins> used, "config_id" SHOULD be set to a randomly generated byte.  Unless specified by the application using (D)TLS or externally configured on both sides, implementations MUST set the field as specified in encrypted-client-hello. </ins> 6.1.1.

The client then modifies the "encrypted_client_hello" extension in ClientHelloOuter as follows: <del> "config_id" is replaced with the empty string. </del> <ins> "config_id" is unchanged and contains the "config_id" corresponding to the client's chosen ECHConfig. </ins> "cipher_suite" is unchanged and contains the client's chosen HPKE cipher suite.

RFC8701 "encrypted_client_hello" extension in the first ClientHello as follows: <del> Set the "config_id" field to a random eight byte string. </del> <ins> Set the "config_id" field to a random byte. </ins> Set the "cipher_suite" field to a supported HpkeSymmetricCipherSuite.  The selection SHOULD vary to exercise

ClientHelloOuter also contains the "encrypted_client_hello" extension.  If not, it MUST abort the handshake with a "missing_extension" alert.  Otherwise, it checks that <del> ClientECH.cipher_suite is unchanged, and that ClientECH.config_id and ClientECH.enc are empty.  If not, it MUST abort the handshake with an "illegal_parameter" alert. </del> <ins> ClientECH.cipher_suite and ClientECH.config_id are unchanged, and that ClientECH.enc is empty.  If not, it MUST abort the handshake with an "illegal_parameter" alert. </ins> Finally, it decrypts the new ClientECH.payload as a second message with the previous HPKE context:
Change:
Having looked at this, I have a preference for a construction where the outer ClientHello has a placeholder with empty extension data, rather than a placeholder that has an empty payload field. Zeroing out the payload field is not easier in our implementation. It is somewhat more difficult to implement. This is a preference only; anything can be implemented. But this version is preferable.
The position of the ECH extension is not authenticated as part of ClientHelloOuterAAD. This means that it is possible to construct multiple different ClientHello messages that will all be accepted. This probably isn't that interesting, but it might be worth noting.
If we want to fix this (I don't care either way), we can remove the fields prepended to ClientHelloOuterAAD, leave the ECH extension in, and say the AAD is computed by replacing ClientECH.payload with the empty string.
That seems like a reasonable proposal. NAME what do you think? (NAME might also have thoughts on this.)
I can live with either a placeholder or text in the draft that explains the limitation. Extension order doesn't carry any semantics, so I don't see malleability as a real risk. I'd lean toward the placeholder, but only slightly. More so if we were planning to change the AAD anyway.
This seems like a good idea to me.
If we don't really care about this issue, why specify it? Does this add complexity or reduce it?
We don't know of any way this can be a problem, but that doesn't mean there is none. Plus, malleability is generally not great. I don't think this moves the complexity needle in a meaningful way.
I guess it exposes an active distinguishing attack, though I suspect this style of attack has plenty of vectors: Attacker rewrites CH to move the ECH extension to another spot and forwards to server Server responds with SH..Finished. Attacker forwards that to client unmodified If this was negotiating CHOuter, this would break the transcript and the client would reject. If this was negotiating CHInner, the client won't notice and proceed
Yep, nice! Let's definitely make this change, then.

Discussion:
"ClientECH.cipher_suite", "ClientECH.config_id", and "ClientECH.enc" fields of the payload of the "encrypted_client_hello" extension.  The last parameter, "outer_hello", is computed by serializing <del> ClientHelloOuter with the "encrypted_client_hello" extension removed. Note this does not include the four-byte header included in the Handshake structure. </del> <ins> ClientHelloOuter with the "encrypted_client_hello" extension set to the empty string, i.e., the "extension_data" list has zero length. Note this serialization does not include the four-byte header included in the Handshake structure. </ins> <del> Note the decompression process in encoding-inner forbids </del> <ins> The decompression process in encoding-inner forbids </ins> "encrypted_client_hello" in OuterExtensions.  This ensures the unauthenticated portion of ClientHelloOuter is not incorporated into ClientHelloInner.
Change:
URL don't give both servers a cookie. That is, if a client-facing server forwards the ClientHello, it can't do so statelessly without coordinating with the backend. This is a consequence of moving to a single HelloRetryRequest, but it's a minor one. In most cases, there will be state established anyway just to get the connection forwarded. DTLS might not work that way, but it's still likely reasonable to assume state. No longer builds on .
I guess the dust is still settling on the rest of the HRR mess, but a6b6b67ca710d023962b8b950a2d26f2806d7aac LGTM.
+1 -- NAME can we cherry-pick a6b6b67 into a separate PR?
I would be happy for you to take that and merge it.
Or, I will just rebase -i here.
I was thinking about and the discussion on server HRR checks started by URL, and I'm not sure HRR cookies even work in split mode right now. First off, suppose we don't merge something like . The current text says: This means if you get a cookied HRR only good for ClientHelloInner, there's no requirement to stick the cookie in ClientHelloOuter! But now the client-facing server can't see the cookie, so it can't be stateless. It would seem like fixes this, but now we have a more fundamental problem: whose cookie? Suppose the client-facing server wishes to handle HRR statelessly. It decrypts the first ClientHelloInner and forwards it to the backend server. If the backend server responds with HRR, the client-facing server must forward the HRR as-is, or the transcript breaks. But the client-facing server has no opportunity to bind its state (echhrrkey) into the HRR cookie. (Perhaps there isn't even one. If there is, it's encrypted with the backend server's key anyway. Either way, it's fixed now.) The simplest solution to all this is to only support stateful client-facing servers in split mode, unless the client-facing and backend servers can coordinate enough to share one cookie. I don't know if that would satisfy everyone. I could imagine doing something horrific to URL, akin to what we did to URL, but that sounds really messy.
Let's mark this as an "OPEN ISSUE" in the draft.
Done. URL

Discussion:
not decrypt the second ClientHello's ClientECH.payload value, if there is one. <del> [[OPEN ISSUE: If the client-facing server implements stateless HRR, it has no way to send a cookie, short of as-yet-unspecified integration with the backend server.  Stateful HRR on the client- facing server works fine, however.  See issue https://github.com/tlswg/draft-ietf-tls-esni/issues/333.]] </del> <ins> Note that a client-facing server that forwards the first ClientHello cannot include its own "cookie" extension if the backend server sends a HelloRetryRequest.  This means that the client-facing server either needs to maintain state for such a connection or it needs to coordinate with the backend server to include any information it requires to process the second ClientHello. </ins> 7.2.
Change:
ClientHello is already a defined structure. No need to wrap it in an opaque byte array. This avoids needing to fill in an extra length prefix in front.
Isn't the length prefix there in order to prevent ossification?
Could you elaborate? I don't see how this relates to ossification. Note AAD values aren't parsed or even sent over the wire. Rather, the requirement on them is injectivity.
If the thinking is one might want to change what goes in the AAD later, the length prefix doesn't do anything. You'd need an actual distinguishing field like a type or version. We get that via labels and such when setting up the ECH context itself. By the time we've settled on speaking a particular ECH-like protocol, the AAD structure is fixed.
Thanks for the clarification. I was confused about the specifics of how this prefix was used.
Can probably just say instead of leading with , which is almost always unnecessary.

Discussion:
last parameter, "outer_hello", is computed by serializing ClientHelloOuter with the "encrypted_client_hello" extension set to the empty string, i.e., the "extension_data" list has zero length. <del> Note this serialization does not include the four-byte header included in the Handshake structure. </del> <ins> This serialization uses the ClientHello structure from Section 4.1.2 of RFC8446, which does not include the four-byte header included in the Handshake structure. </ins> The decompression process in encoding-inner forbids "encrypted_client_hello" in OuterExtensions.  This ensures the
Change:
Also see URL
LGTM -- thanks!
I suggest dropping the references to Ben's individual alt-svc in DNS draft.. it hasn't been adopted and its future is murky. actual alt-svc (the non dns kind) actually requires the use of the plaintext SNI. As those are both cachable and connections to new IP addresses (less linkable) you could consider updating it with mike bishop's URL (also an individual draft atm)
NAME also suggested that the reference might not be needed in URL so I made to actually remove it.

Discussion:
the query domain name.  That is, if a client queries example.com, the ESNI TXT Resource Record might be: <del> Servers MUST ensure that, if multiple A, AAAA or ALTSVC I-D.schwartz- httpbis-dns-alt-svc records are returned for a domain with ESNI support, all the servers pointed to by those records are able to handle the keys returned as part of a ESNI TXT record for that domain. </del> <ins> Servers MUST ensure that, if multiple A or AAAA records are returned for a domain with ESNI support, all the servers pointed to by those records are able to handle the keys returned as part of a ESNI TXT record for that domain. </ins> Alt-Svc records may be used to inform the client of the plaintext (fronting) SNI.  If present, clients SHOULD use its value in the SNI
Change:
The second ClientHello after HelloRetryRequest reuses the HPKE context and calls Seal/Open a second time. To avoid needing to unnecessarily retain the enc value, and discourage servers from mistakenly recreating the HPKE context, we made it use the empty string but forgot to update the syntax to match.

Discussion:
"ECHConfigContents.cipher_suites" list. The HPKE encapsulated key, used by servers to decrypt the <del> corresponding "payload" field. </del> <ins> corresponding "payload" field.  This field is empty in ClientHelloOuters sent in response to HelloRetryRequest. </ins> The serialized and encrypted ClientHelloInner structure, encrypted using HPKE as described in real-ech.
Change:
While padding is "described below", it's pretty far away now. We also recommend the padding scheme whether or not the value is non-zero. The text about wildcard names also applies in both cases and seems to describe when the server name may exceed the max. This rephases things a bit.

Discussion:
that of any valid ECHConfig, which could include any ECHConfig that has been recently removed from active use. <del> The longest name of a backend server, if known.  If this value is not known it can be set to zero, in which case clients SHOULD use the inner ClientHello padding scheme described below.  That could happen if wildcard names are in use, or if names can be added or removed from the anonymity set during the lifetime of a particular ECH configuration. </del> <ins> The longest name of a backend server, if known.  If not known, this value can be set to zero.  It is used to compute padding (padding) and does not constrain server name lengths.  Names may exceed this length if, e.g., the server uses wildcard names or added new names to the anonymity set. </ins> The non-empty name of the client-facing server, i.e., the entity trusted to update the ECH configuration.  This is used to correct
Change:
cc/ NAME
I don't think we need to also bump echouterextensions but just in case... S
ECHConfig is defined as but the text below it says The intention was to bump ECHConfig.version from 0xfe0a to 0xfe0b for draft-11, but this got missed by URL (I wrote the PR, so I apologize for my part in missing this.) How do folks think we should resolve this? Do we need to cut a new draft with the ambiguity fixed?
Oh whoops, nice catch! Using definitely won't work since the format and corresponding ClientECH extension has changed. I suppose all the implementors could just agree to mentally fix this typo when reading the draft, but may as well cut draft-12. Draft numbers are cheap.
We could try to pick up some editorial changes, too, like those suggested in .
I'd also personally be pretty happy to have in there, but also fine to skip it for what's supposed to be a small bugfix draft snapshot.
+1 I've not checked recent editorial changes but they're probably fine too. S
I'd be happy to take in draft-12 as well, though I'm inclined to think this should strictly be a bugfix/editorial draft. I'd say let's wait until Chris W. gets off back from PTO and let him make the call. Unless we're in a hurry, in which case we could ping one of the other authors to merge our changes and cut a draft.
Closing as resolved.

Discussion:
IANA is requested to create the following three entries in the existing registry for ExtensionType (defined in RFC8446): <del> encrypted_client_hello(0xfe0a), with "TLS 1.3" column values set </del> <ins> encrypted_client_hello(0xfe0b), with "TLS 1.3" column values set </ins> to "CH, HRR, EE", and "Recommended" column set to "Yes". ech_outer_extensions(0xfd00), with the "TLS 1.3" column values set
Change:
To be included with . Note that this is a wire-breaking change that should have landed in draft-11, but didn't.
NAME since this will go into the next version of the draft, can we bump everything to the next version here?
Done.
Thanks!
ECHConfig is defined as but the text below it says The intention was to bump ECHConfig.version from 0xfe0a to 0xfe0b for draft-11, but this got missed by URL (I wrote the PR, so I apologize for my part in missing this.) How do folks think we should resolve this? Do we need to cut a new draft with the ambiguity fixed?
Oh whoops, nice catch! Using definitely won't work since the format and corresponding ClientECH extension has changed. I suppose all the implementors could just agree to mentally fix this typo when reading the draft, but may as well cut draft-12. Draft numbers are cheap.
We could try to pick up some editorial changes, too, like those suggested in .
I'd also personally be pretty happy to have in there, but also fine to skip it for what's supposed to be a small bugfix draft snapshot.
+1 I've not checked recent editorial changes but they're probably fine too. S
I'd be happy to take in draft-12 as well, though I'm inclined to think this should strictly be a bugfix/editorial draft. I'd say let's wait until Chris W. gets off back from PTO and let him make the call. Unless we're in a hurry, in which case we could ping one of the other authors to merge our changes and cut a draft.
Closing as resolved.

Discussion:
IANA is requested to create the following three entries in the existing registry for ExtensionType (defined in RFC8446): <del> encrypted_client_hello(0xfe0b), with "TLS 1.3" column values set </del> <ins> encrypted_client_hello(0xfe0c), with "TLS 1.3" column values set </ins> to "CH, HRR, EE", and "Recommended" column set to "Yes". ech_outer_extensions(0xfd00), with the "TLS 1.3" column values set
Change:
The requirement to check the ClientHello for an inner ClientECH doesn't make sense because the entire section is already conditioned by observing an inner ClientECH. Also clarify that the client-facing vs. backend server dispatch happens at the initial ClientHello. Switching roles mid-connection will not work very well.

Discussion:
7. Servers that support ECH play one of two roles, depending on the <del> payload of the "encrypted_client_hello" extension in the ClientHello: </del> <ins> payload of the "encrypted_client_hello" extension in the initial ClientHello: </ins> If "ClientECH.type" is "outer", then the server acts as a client- facing server and proceeds as described in client-facing-server to

server overwrites the payload of the "encrypted_client_hello" extension with the following string: <del> As above, the payload of "encrypted_client_hello" is expected to be a "ClientECH" with "ClientECH.type" is "inner".  If this is not the case, the backend server MUST abort the handshake with an "illegal_parameter" alert. Note that, in case of HelloRetryRequest, the backend server confirms ECH acceptance twice: first In HelloRetryRequest, as described here; and then in the subsequent ServerHello, as described above. </del> <ins> In the subsequent ServerHello message, the backend server sends the accept_confirmation value as described in backend-server. </ins> 8.
Change:
There are two reasons for this. First, the algorithm in Appendix B for decoding the EncodedClientHelloInner doesn't actually enforce this. Second, aborting on duplicated extensions is slightly stricter than RFC 8446 requires. It states that "[t]here MUST NOT be more than one extension of the same type in a given extension block", but doesn't specify what the receiver does in this case.

Discussion:
"encrypted_client_hello" appears in OuterExtensions. <del> OuterExtensions contains duplicate values. </del> The extensions in ClientHelloOuter corresponding to those in OuterExtensions do not occur in the same order.
Change:
Just some minor nits I picked up during a slow pass of the spec.
LGTM pending one nit.

Discussion:
"ECHConfigContents.cipher_suites" list. The HPKE encapsulated key, used by servers to decrypt the <del> corresponding "payload" field.  This field is empty in ClientHelloOuters sent in response to HelloRetryRequest. </del> <ins> corresponding "payload" field.  This field is empty in a ClientHelloOuter sent in response to HelloRetryRequest. </ins> The serialized and encrypted ClientHelloInner structure, encrypted using HPKE as described in real-ech.

Next, the client determines the length L of encrypting EncodedClientHelloInner with the selected HPKE AEAD.  This is typically the sum of the plaintext length and the AEAD tag length. <del> The client fills in a "encrypted_client_hello" extension with the outer variant of ClientECH with following values: </del> <ins> The client fills in an "encrypted_client_hello" extension with the outer variant of ClientECH with the following values: </ins> "config_id", the identifier corresponding to the chosen ECHConfig structure;

generates a random PSK identity with the same length.  It also generates a random, 32-bit, unsigned integer to use as the "obfuscated_ticket_age".  Likewise, for each inner PSK binder, the <del> client generates random string of the same length. </del> <ins> client generates a random string of the same length. </ins> <del> If the server replies with a "pre_shared_key" extension in its </del> <ins> Per the rules of real-ech, the server is not permitted to resume a connection in the outer handshake.  If ECH is rejected and the client-facing server replies with a "pre_shared_key" extension in its </ins> ServerHello, then the client MUST abort the handshake with an "illegal_parameter" alert.

a "decode_error" alert if it is invalid.  It otherwise ignores the extension and MUST NOT use the retry keys. <del> [[OPEN ISSUE: if the client sends a GREASE "encrypted_client_hello" extension, should it also send a GREASE "pre_shared_key" extension? If not, GREASE+ticket is a trivial distinguisher.  See issue #384.]] </del> Offering a GREASE extension is not considered offering an encrypted ClientHello for purposes of requirements in client-behavior.  In particular, the client MAY offer to resume sessions established
Change:
Handling server response discusses how to dispatch between accept/reject, but the retry flow is specifically the reject bit.

Discussion:
The DNS name of the client-facing server, i.e., the entity trusted to update the ECH configuration.  This is used to correct <del> misconfigured clients, as described in handle-server-response. </del> <ins> misconfigured clients, as described in rejected-ech. </ins> Clients MUST ignore any "ECHConfig" structure whose public_name is not parsable as a dot-separated sequence of LDH labels, as defined

report such connections as successful to the application.  It additionally MUST ignore all session tickets and session IDs presented by the server.  These connections are only used to trigger <del> retries, as described in handle-server-response.  This may be implemented, for instance, by reporting a failed connection with a dedicated error code. </del> <ins> retries, as described in rejected-ech.  This may be implemented, for instance, by reporting a failed connection with a dedicated error code. </ins> 6.1.5.

all, it will ignore it as required by Section 4.1.2 of RFC8446. Provided the server can present a certificate valid for the public name, the client can safely retry with updated settings, as described <del> in handle-server-response. </del> <ins> in rejected-ech. </ins> Unless ECH is disabled as a result of successfully establishing a connection to the public name, the client MUST NOT fall back to using

Depending on whether the client is configured to accept the proxy's certificate as authoritative for the public name, this may trigger <del> the retry logic described in handle-server-response or result in a connection failure.  A proxy which is not authoritative for the public name cannot forge a signal to disable ECH. </del> <ins> the retry logic described in rejected-ech or result in a connection failure.  A proxy which is not authoritative for the public name cannot forge a signal to disable ECH. </ins> 9.