7.2.  I-D.ietf-tls-sni-encryption lists several requirements for SNI encryption.  In this section, we re-iterate these requirements and assess the ESNI design against them. <del> 7.2.1. </del>  Since the SNI encryption key is derived from a (EC)DH operation between the client's ephemeral and server's semi-static ESNI key, the

Since OCSP is the server name, ESNI should probably enforce OCSP stapling (similar to ) or any other way of encrypted OCSP checks. Ignoring OCSP status checks entirely makes it hard to revoke a certificate, even if it's only valid for a few months.
NAME what behavior do you expect here? Would clients fail hard if server don't send stapled responses? It's good to view ESNI as part of the leaky boat problem. It plugs one hole, but not all of them. Implementations probably should do something about cleartext OCSP if they want all holes plugged.
Thank you for the changes. LGTM.

7.2. <ins> ESNI requires encrypted DNS to be an effective privacy protection mechanism.  However, verifying the server's identity from the Certificate message, particularly when using the X509 CertificateType, may result in additional network traffic that may reveal the server identity.  Examples of this traffic may include requests for revocation information, such as OCSP or CRL traffic, or requests for repository information, such as authorityInformationAccess.  It may also include implementation- specific traffic for additional information sources as part of verification. Implementations SHOULD avoid leaking information that may identify the server.  Even when sent over an encrypted transport, such requests may result in indirect exposure of the server's identity, such as indicating a specific CA or service being used.  To mitigate this risk, servers SHOULD deliver such information in-band when possible, such as through the use of OCSP stapling, and clients SHOULD take steps to minimize or protect such requests during certificate validation. 7.3. </ins> I-D.ietf-tls-sni-encryption lists several requirements for SNI encryption.  In this section, we re-iterate these requirements and assess the ESNI design against them.  <ins> 7.3.1. </ins> Since the SNI encryption key is derived from a (EC)DH operation between the client's ephemeral and server's semi-static ESNI key, the


Hello, with a different ephemeral key share, as the terminating server will fail to decrypt and verify the ESNI value. <del> 7.2.2. </del>  This design depends upon DNS as a vehicle for semi-static public key distribution.  Server operators may partition their private keys

Hello, with a different ephemeral key share, as the terminating server will fail to decrypt and verify the ESNI value.  <ins> 7.3.2. </ins> This design depends upon DNS as a vehicle for semi-static public key distribution.  Server operators may partition their private keys


by sending different Resource Records containing ESNIRecord and ESNIKeys values with different keys using a short TTL. <del> 7.2.3. </del>  This design requires servers to decrypt ClientHello messages with ClientEncryptedSNI extensions carrying valid digests.  Thus, it is

by sending different Resource Records containing ESNIRecord and ESNIKeys values with different keys using a short TTL.  <ins> 7.3.3. </ins> This design requires servers to decrypt ClientHello messages with ClientEncryptedSNI extensions carrying valid digests.  Thus, it is


server.  This attack is bound by the number of valid TCP connections an attacker can open. <del> 7.2.4. </del>  As more clients enable ESNI support, e.g., as normal part of Web browser functionality, with keys supplied by shared hosting

server.  This attack is bound by the number of valid TCP connections an attacker can open.  <ins> 7.3.4. </ins> As more clients enable ESNI support, e.g., as normal part of Web browser functionality, with keys supplied by shared hosting


ESNI extensions (see grease-extensions), which helps ensure the ecosystem handles the values correctly. <del> 7.2.5. </del>  This design is not forward secret because the server's ESNI key is static.  However, the window of exposure is bound by the key lifetime.  It is RECOMMENDED that servers rotate keys frequently. <del> 7.2.6. </del>  This design permits servers operating in Split Mode to forward connections directly to backend origin servers, thereby avoiding unnecessary MiTM attacks. <del> 7.2.7. </del>  Assuming ESNI records retrieved from DNS are validated, e.g., via DNSSEC or fetched from a trusted Recursive Resolver, spoofing a

ESNI extensions (see grease-extensions), which helps ensure the ecosystem handles the values correctly.  <ins> 7.3.5. </ins> This design is not forward secret because the server's ESNI key is static.  However, the window of exposure is bound by the key lifetime.  It is RECOMMENDED that servers rotate keys frequently.  <ins> 7.3.6. </ins> This design permits servers operating in Split Mode to forward connections directly to backend origin servers, thereby avoiding unnecessary MiTM attacks.  <ins> 7.3.7. </ins> Assuming ESNI records retrieved from DNS are validated, e.g., via DNSSEC or fetched from a trusted Recursive Resolver, spoofing a


client validates the server certificate against the public name before retrying. <del> 7.2.8. </del>  This design has no impact on application layer protocol negotiation. It may affect connection routing, server certificate selection, and client certificate verification.  Thus, it is compatible with multiple protocols. <del> 7.3. </del>  Note that the backend server has no way of knowing what the SNI was, but that does not lead to additional privacy exposure because the

client validates the server certificate against the public name before retrying.  <ins> 7.3.8. </ins> This design has no impact on application layer protocol negotiation. It may affect connection routing, server certificate selection, and client certificate verification.  Thus, it is compatible with multiple protocols.  <ins> 7.4. </ins> Note that the backend server has no way of knowing what the SNI was, but that does not lead to additional privacy exposure because the


nonce re-use since the client's ESNI key share, and thus the value of Zx, does not change across ClientHello retries.)  [[TODO: label swapping fixes a bug in the spec, though this may not be the best way to deal with HRR.  See https://github.com/tlswg/ draft-ietf-tls-esni/issues/121 and https://github.com/tlswg/draft- ietf-tls-esni/pull/170 for more details.]]  The client then creates a ClientESNIInner structure: A random 16-octet value to be echoed by the server in the

I got a little tripped up on this point! Maybe you have a better way to explain it.
Thanks, NAME

nonce re-use since the client's ESNI key share, and thus the value of Zx, does not change across ClientHello retries.) <ins> Note that ESNIContents will not be directly transmitted to the server in the ClientHello.  The server will instead reconstruct the same object by obtaining its values from ClientEncryptedSNI and ClientHello. </ins> [[TODO: label swapping fixes a bug in the spec, though this may not be the best way to deal with HRR.  See https://github.com/tlswg/ draft-ietf-tls-esni/issues/121 and https://github.com/tlswg/draft- ietf-tls-esni/pull/170 for more details.]] <ins> Same value as ClientEncryptedSNI.record_digest. Same value as ClientEncryptedSNI.key_share. Same nonce as ClientHello.random. </ins> The client then creates a ClientESNIInner structure: A random 16-octet value to be echoed by the server in the


receipt of a second ClientHello message with a ClientECH value, servers set up their HPKE context and decrypt ClientECH as follows: <del> It is an error for the client to offer ECH before the HelloRetryRequest but not after.  Likewise, it is an error for the client to offer ECH after the HelloRetryRequest but not before.  If the client-facing server accepts ECH for the first ClientHello but not the second, or it accepts ECH for the second ClientHello but not the first, then the client MUST abort the handshake with an "illegal_parameter" alert. </del>  [[OPEN ISSUE: Should we be using the PSK input or the info input?  On the one hand, the requirements on info seem weaker, but maybe

It is an error for the client to offer ECH after HRR but not before. Likewise, it is an error for the client to offer ECH before HRR but not after. This change ensures the server aborts in this case.
Suppose we hit one of the messy HRR cases (URL), where the HRR is valid for the outer ClientHello, but not the inner ClientHello. The client then cannot construct a valid inner ClientHello. How would that square with this text? Are you envisioning the client just generates a random ECH extension, or...?
I don't think this is a new problem. I see the PR as clarifying existing behavior. Can you please propose text for the HRR nightmare in ? :-)
Ah, you're right. Sorry, I misread this PR as introducing this requirement. In principle, we only need the server to require ECH in CH2 if it decided to accept ECH on CH1. That would allow the client to not send ECH the second time, but maybe we don't want to do that, depending on what we do for ... Do we know what we want to do for ? Simplest seems to be saying clients MUST align them. (Though how does that work with later HRR-sensitive extensions? Are funny ECH-adding proxies a thing?) Or maybe it's just a SHOULD? Or maybe we come up with some other protocol trick so ECH acceptance is visible at HRR (which would probably reopen the don't-stick-out can of worms yet again). Of these, only the MUST avoids collision with this PR's (existing) client requirement.
Yeah, that's my preference. This logic is already complicated enough. The primary pain point I see is enumerating (and prescribing) what is a HRR-sensitive field.
Same, with that pain point being the big question in my head. Whether an HRR is valid for a ClientHello isn't an implementation decision, so in theory it's enumerable. But more extensions may come in later. And in the other direction, even a very strong SHOULD means we need to pick a client behavior for the weird case and allow for it in server behavior.
Regardless of where we land on , this PR seems appropriate to me.
In a normal ECHO handshake with HelloRetryRequest there are 4 ClientHellos sent: ClientHelloOuter1, ClientHelloInner1, ClientHelloOuter2, ClientHelloInner2. Encryption of ClientHelloInner2 is bound to echohrrkey so the server must have the ECHOConfig used for ClientHelloInner1 in order to process ECHO the second time. And by the time the client receives encrypted handshake traffic it is not useful to signal if ClientHelloInner1 was successfully decrypted, what matters is to know if ECHO is globally successful or not. So one aspect that I find not explained enough is whether the server replying with HRR should use ClientHelloInner1 in the transcript, or instead always takes ClientHelloOuter1 (data on the wire) regardless of the first decryption status. The ECHO status accept/reject can be conveyed based on distinction ClientHello2 inner/outer only. This point impacts the number of transcripts the client may have to try, i.e. can be sure the combination (ClientHelloInner1, ClientHelloOuter2) is never valid.
Hi NAME the spec has changed quite a bit since this question was first posed. In particular, we've landed , which changes the server behavior so that it provides an explicit signal of ECH acceptance in its SH. Hence, no more trial decryption. I'm wondering if your question still applies? I believe what to do in case of HRR is well-specified at this point. There is no such ECH accdeptance signal provided in the HRR, so to determine if ECH was accepted, the client must wait until the SH. Until that point, the client needs to compute two transcripts in parallel: one assuming the ClientHelloOuter was used, and another assuming the ClientHelloInner was used.
I don't think resolves this. If the client has different HRR-relevant preferences (key share and cipher suite) between CHInner and CHOuter, I believe HRR is still a mess because the HRR message doesn't contain a signal for whether ECH was accepted. Though I suppose it is a little less complex now that you don't need to go as far as trial decrypting. Different HRR-relevant preferences means the HRR may be good for one ClientHello but not the other, yet the client needs to manage that state and defer the actual error-handling to when ECH acceptance is known. An option where the HRR message included an ECH acceptance signal would close this, but then we have sticking out woes. The draft touches on this, but somewhat vaguely. URL We've been intending that our implementation would always match inner and outer preferences for HRR-sensitive fields, to avoid this case. But having this odd complexity cliff hidden in the spec is poor. I'd advocate we either require or at least strongly recommend clients do this.
suggests to add the following text to the HRR section: after. Likewise, it is an error for the client to offer ECH after the HelloRetryRequest but not before. If the client-facing server accepts ECH for the first ClientHello but not the second, or it accepts ECH for the second ClientHello but not the first, then it MUST abort the handshake with an "illegal_parameter" alert. I think this solves the problem, at least partially. It ensures that the HRR path aligns with ECH acceptance/rejection.
That doesn't address the problem. This is about complexity for the client, not the server. Yes, the server needs to enforce consistency between the two modes, but it is easy for it to do this. Imagine you're the client and your CHOuter has: keyshares = {X25519} supportedgroups = {X25519, P-256, P-384} ciphersuites = {TLSAES128GCMSHA256, TLSAES256GCMSHA384} And your CHInner has: keyshares = {P-256} supportedgroups = {X25519, P-256, P-384} ciphersuites = {TLSAES256GCMSHA384, TLSCHACHA20POLY1305SHA256} Now consider how you have to respond to each of these HRRs. Remember that at the time you process the HRR, you don't know if ECH was accepted. ciphersuite = TLSAES256GCMSHA384; keyshare = P-384 ciphersuite = TLSAES128CCMSHA256; keyshare = P-521 ciphersuite = TLSCHACHA20POLY1305SHA256; keyshare = X25519 ciphersuite = TLSAES128GCMSHA256; keyshare = P-256 ciphersuite = TLSCHACHA20POLY1305SHA256; keyshare = X25519 1 is valid for both ClientHellos. This is the easy case and you can compute new CHInner and CHOuter values. 2 is valid for neither ClientHello. If you can detect this, you can error immediately. 3 is valid for neither ClientHello, but for messy reasons. The key share is valid for CHOuter but the cipher suite is not. The cipher suite is valid for CHInner but the key share is not. (Recall that a key share in HRR is allowed if it is in CH.supportedgroups and not CH.keyshares. If it were in CH.keyshares, you shouldn't have sent HRR.) 4 is valid for only CHOuter, so you can't error. It is not possible to compute a CHInner, so I guess you drop the extension? But you still need to make a note to raise an error later if you see SH which claims it did accept ECH. 5 is valid for only CHInner, so you can't error. It is not possible to compute a CHOuter, but you have to, so I guess you send something garbage? But you still need to make a note to raise an error if you see SH which claims it rejected ECH. This is a huge mess. The client can avoid this mess by always matching keyshares, supportedgroups, and cipher_suites between CHInner and CHOuter. That means it can process HRR without knowing which CH to use. It is not obvious in the spec that you should do this, and the spec allows you to not do this.
I see, I wasn't thinking about client complexity. Thanks for laying out the various edge cases. I would favor being stricter about how the keyshares, supportedgroups, and ciphersuites are chosen. At the very least, we should guide implementations towards ensuring they are the same in the CHInner and CHOuter. An alternative would be to add an ECH signal to HRR. We can't do the same trick we did with the URL, as this would stick out. But maybe there's another way? I thought of using HRR.sessionid, but that could get messy.
I think there is still ambiguity in the design about what CH is used by the client-facing server in its own transcript when forwarding CHInner to the backend server. Or else the combination (ECH accepted before HRR, ECH rejected after HRR) can be explicitly forbidden, but I don't see why/how.
Incidentally, this is addressed by URL This adds the following to client-facing server behavior: after. Likewise, it is an error for the client to offer ECH after the HelloRetryRequest but not before. If either of these conditions occurs, then the client-facing server MUST abort the handshake with an "illegal_parameter" alert. It's not hard for the client-facing server to enforce this. It just needs to remember if an HRR was triggered and whether ECH was offered in in the first CH.
Ok that will do it. Assuming "ECH not offered" is same as "ECH not accepted", due to greasing.
With merged, I wonder if the ESNIKeys struct should just be renamed to something not specific to ESNI, but something more like "generic TLS config in DNS" so that it can be more cleanly reused by unrelated features. "ServerConfiguration" comes to mind from the early TLS 1.3 days.
If we were to re-use these keys for other purposes, that seems fine. However, I'm not sure we want to do that. Semi-static keys, for example, should ideally be separate.
The keys yes, but I imagine the extensions field can hold "arbitrary" data, so while the keys would be ESNI-specific, you could also include extensions that have nothing to do with ESNI.
Thinking about this some more, this would also require changing the "_esni." prefix to something else. In any case I can see how this might be out of scope for this spec. In the end it's a matter of deciding whether future TLS extensions that need similar DNS records, should be able to reuse the same structure (so no additional TXT record with its own prefix would be required), or if they should define their own structure (and have a separate TXT record). I'm happy to close this if it goes too much out of scope.
Right, I think it's verging on being out of scope. What do others think? NAME NAME
My preference goes to keeping the name as-is, considering the fact that the role of ESNIKeys is (at least for the moment) to negotiate properties between the client and the fronting server (not the hidden server), and that the only property we need to negotiate between the two is the information necessary for ESNI protection. It is true that the DNS record can covey properties related to the hidden server (as you know, I've argued for using it to carry the server certificate chain). But IMO that's a change of concept, and I prefer keeping the concept simple for the time being.
Ok.

receipt of a second ClientHello message with a ClientECH value, servers set up their HPKE context and decrypt ClientECH as follows:  <ins> If the client offered ECH in the first ClientHello, then it MUST offer ECH in the second.  Likewise, if the client did not offer ECH in the first ClientHello, then it MUST NOT not offer ECH in the second. </ins> [[OPEN ISSUE: Should we be using the PSK input or the info input?  On the one hand, the requirements on info seem weaker, but maybe


negotiating ECH, including servers which do not implement this specification.  7.2. When the client-facing server accepts ECH, it forwards the

negotiating ECH, including servers which do not implement this specification. <ins> 7.1.1. It is an error for the client to offer ECH before the HelloRetryRequest but not after.  Likewise, it is an error for the client to offer ECH after the HelloRetryRequest but not before.  If either of these conditions occurs, then the client-facing server MUST abort the handshake with an "illegal_parameter" alert. </ins> 7.2. When the client-facing server accepts ECH, it forwards the


If the server sends an "encrypted_client_hello" extension, the client MUST check the extension syntactically and abort the connection with <del> a "decode_error" alert if it is invalid. </del>  Offering a GREASE extension is not considered offering an encrypted ClientHello for purposes of requirements in client-behavior.  In

The intent was that the server always sends the retry keys (it cannot distinguish stale keys from GREASE when the client is actually trying to connect to the public name), while the client just ignores them, but I did a poor job of describing this, so add a key sentence. This addresses .
(EDITED.) To recap the discussion on , your point is that the client-facing server needn't attempt to distinguish GREASE from non-GREASE based on outer SNI, because if the outer SNI != public name, then the client knows to ignore the retry config and continue as usual. I think this is weird because if rejection was the intent, then the client is supposed to abort with "ech_required". So the server only knows that non-GREASE was intended once it receives this signal.
I mean, yeah, that's how this was designed and is what we merged to the spec. :-) This formulation, in particular, does not break if the client tries to connect to the public name (it's a perfectly valid URL) without knowing the ECH config (maybe it the HTTPS record didn't get through Do53) but still sends GREASE (because the intent is that every client can GREASE). It seems to me breaks this. Do you have an alternate formulation which keeps this working? Connecting to the public name is especially important if the public name is a non-throwaway domain. The only requirement on the public name is that it's some name which knows about and serves the client-facing server's config. (I.e. this particular backend server is the same entity as the client-facing server.) doesn't relax this requirement, since the public name continues to be the entity trusted to replace, and possibly disable, ECH on config mismatch.
I don't see this as an issue. If the client sends GREASE, it doesn't expect to use ECH, so it won't abort. The text here only requires that the client check the extension if present, and ignore it if absent.
I don't have an alternative formulation. I was evnisioning the public name only being verified on the ECH rejection path, or when neither real nor dummy ECH was offered to the client-facing server. I'm fine with rejection not being known until "ech_required". I support this PR as the resolution to .
NAME and I were sitting down and thinking and we realized the following scenario can happen: URL is on URL, which supports ECH URL has an HTTPS record, an A record, AAAA record pointing at the IP for URL A user of a browsers latest release that supports ECH and greases the extension is using a resolver that doesn't resolve HTTPS records This results in an ECH request being made with URL, and a rejection of the ECH. So now the question is what the client should do and what should servers expect? Try again, with the outer SNI the one matching the one in the new config Use the connection authoritatively for URL since the connection has already revealed the issue.
The intention was the latter, but the text could probably be clearer. I don't think there's much point in trying again since the name has already been revealed. See URL
NAME is this still an issue now that is merged?
I think the client behavior remains equally unspecified. In particular the lengthy argument NAME and I had about server enforcement of the client behavior I think isn't changed.
Care to file a PR, presuming the latter behavior is intended?
A proposed resolution is here: .
NAME a proposed fix has been merged. See .
I think this text works.

If the server sends an "encrypted_client_hello" extension, the client MUST check the extension syntactically and abort the connection with  <ins> a "decode_error" alert if it is invalid.  It otherwise ignores the extension and MUST NOT use the retry keys. </ins> Offering a GREASE extension is not considered offering an encrypted ClientHello for purposes of requirements in client-behavior.  In


10.8.6. This design permits servers operating in Split Mode to forward <del> connections directly to backend origin servers, thereby avoiding unnecessary MiTM attacks. </del>  <del> 10.8.7. Assuming ECH records retrieved from DNS are authenticated, e.g., via DNSSEC or fetched from a trusted Recursive Resolver, spoofing a server operating in Split Mode is not possible.  See plaintext-dns for more details regarding plaintext DNS. </del>  Authenticating the ECHConfigs structure naturally authenticates the included public name.  This also authenticates any retry signals from <del> the server because the client validates the server certificate against the public name before retrying. </del>  <del> 10.8.8. </del>  This design has no impact on application layer protocol negotiation. It may affect connection routing, server certificate selection, and client certificate verification.  Thus, it is compatible with <del> multiple protocols. </del>  10.9.

We use a mix of sentence case and title case in the document. The RFC style guide says to use title case. This PR aligns with that. URL Additionally, the ESNI criteria document has changed slightly since the comparison against criteria section was written. I've aligned the titles with the final wording in RFC8744. RFC8744 has also merged "Proper security context" and "Split server spoofing", so I've done the same here. "Support Multiple Protocols" also now talks about transport protocols and ALPN, so I've added a few words about that.

10.8.6. This design permits servers operating in Split Mode to forward  <ins> connections directly to backend origin servers.  The client authenticates the identity of the backend origin server, thereby avoiding unnecessary MiTM attacks. </ins>  <ins> Conversely, assuming ECH records retrieved from DNS are authenticated, e.g., via DNSSEC or fetched from a trusted Recursive Resolver, spoofing a client-facing server operating in Split Mode is not possible.  See plaintext-dns for more details regarding plaintext DNS. </ins> Authenticating the ECHConfigs structure naturally authenticates the included public name.  This also authenticates any retry signals from  <ins> the client-facing server because the client validates the server certificate against the public name before retrying. </ins>  <ins> 10.8.7. </ins> This design has no impact on application layer protocol negotiation. It may affect connection routing, server certificate selection, and client certificate verification.  Thus, it is compatible with  <ins> multiple application and transport protocols.  By encrypting the entire ClientHello, this design additionally supports encrypting the ALPN extension. </ins> 10.9.


"encrypted_client_hello" extension and proceeds with the handshake as usual, per RFC8446, Section 4.1.2. <del> If it supports ECH but does not recognize the configuration specified by the client, then it ignores the extension and </del>  terminates the handshake using the ClientHelloOuter.  This is referred to as "ECH rejection".  When ECH is rejected, the server sends an acceptable ECH configuration in its EncryptedExtensions message. <del> If it supports ECH and recognizes the configuration, then it attempts to decrypt the ClientHelloInner.  It aborts the handshake if decryption fails; otherwise it forwards the ClientHelloInner to the backend, who terminates the connection.  This is referred to as "ECH acceptance". </del>  Upon receiving the server's response, the client determines whether or not ECH was accepted and proceeds with the handshake accordingly.

The spec describes an optional trial decryption mode, but most of the text contradicts it. This PR fixes the text up and tries to unify their processing models. In doing so, it flips the error handling from decrypterror to fallback to be consistent. This, combined with the ClientHelloOuterAAD change, plugs an active sticking out attack for free. It also makes easier because GREASE configid collisions with real configids are now harmless. Along the way, NAME and NAME observed that we're not authenticating the ECHConfig at all. (It used to be authenticated by way of the configid, which was a digest.) Instead, just pass the ECHConfig into the info field of the HPKE context. They also noticed the server rule about PSKs on ClientHelloOuter didn't work with GREASE. Instead, we can simply remove it.
This matches the acceptance signal length, and we've already accepted that probability of collision.

"encrypted_client_hello" extension and proceeds with the handshake as usual, per RFC8446, Section 4.1.2.  <ins> If it supports ECH but cannot decrypt the extension, then it </ins> terminates the handshake using the ClientHelloOuter.  This is referred to as "ECH rejection".  When ECH is rejected, the server sends an acceptable ECH configuration in its EncryptedExtensions message.  <ins> If it supports ECH and decrypts the extension, it forwards the ClientHelloInner to the backend, who terminates the connection. This is referred to as "ECH acceptance". </ins> Upon receiving the server's response, the client determines whether or not ECH was accepted and proceeds with the handshake accordingly.


"ECHConfig.cipher_suites" list. The configuration identifier, equal to "Expand(Extract("", <del> config), "tls13 ech config id", Nh)", where "config" is the </del>  "ECHConfig" structure and "Extract", "Expand", and "Nh" are as specified by the cipher suite KDF.  (Passing the literal """" as the salt is interpreted by "Extract" as no salt being provided.)

"ECHConfig.cipher_suites" list. The configuration identifier, equal to "Expand(Extract("",  <ins> config), "tls ech config id", Nh)", where "config" is the </ins> "ECHConfig" structure and "Extract", "Expand", and "Nh" are as specified by the cipher suite KDF.  (Passing the literal """" as the salt is interpreted by "Extract" as no salt being provided.)


Note that the HPKE functions Deserialize and SetupBaseS are those which match "ECHConfig.kem_id" and the AEAD/KDF used with "context" are those which match the client's chosen preference from <del> "ECHConfig.cipher_suites". </del>  The value of the "encrypted_client_hello" extension in the ClientHelloOuter is a "ClientECH" with the following values:

Note that the HPKE functions Deserialize and SetupBaseS are those which match "ECHConfig.kem_id" and the AEAD/KDF used with "context" are those which match the client's chosen preference from  <ins> "ECHConfig.cipher_suites".  The "info" parameter to SetupBaseS is the concatenation of "tls ech", a zero byte, and the serialized ECHConfig. </ins> The value of the "encrypted_client_hello" extension in the ClientHelloOuter is a "ClientECH" with the following values:


"payload", as computed above.  6.2. This section describes a deterministic padding mechanism based on the

"payload", as computed above. <ins> If optional configuration identifiers (see optional-configs)) are used, the "config_id" field MAY be empty or randomly generated. 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. </ins> 6.2. This section describes a deterministic padding mechanism based on the


of the first ClientHelloInner via the derived ech_hrr_key by modifying HPKE setup as follows: <del> Clients then encrypt the second ClientHelloInner using this new HPKE context.  In doing so, the encrypted value is also authenticated by ech_hrr_key.  The rationale for this is described in flow-hrr-hijack. </del>  Client-facing servers perform the corresponding process when decrypting second ClientHelloInner messages.  In particular, upon

of the first ClientHelloInner via the derived ech_hrr_key by modifying HPKE setup as follows:  <ins> The "info" parameter to SetupPSKS is the concatenation of "tls ech", a zero byte, and the serialized ECHConfig.  Clients then encrypt the second ClientHelloInner using this new HPKE context.  In doing so, the encrypted value is also authenticated by ech_hrr_key.  The rationale for this is described in flow-hrr-hijack. </ins> Client-facing servers perform the corresponding process when decrypting second ClientHelloInner messages.  In particular, upon


servers set up their HPKE context and decrypt ClientECH as follows: ClientHelloOuterAAD is computed from the second ClientHelloOuter as <del> described in authenticating-outer. </del>  If the client offered ECH in the first ClientHello, then it MUST offer ECH in the second.  Likewise, if the client did not offer ECH

servers set up their HPKE context and decrypt ClientECH as follows: ClientHelloOuterAAD is computed from the second ClientHelloOuter as  <ins> described in authenticating-outer.  The "info" parameter to SetupPSKR is computed as above. </ins> If the client offered ECH in the first ClientHello, then it MUST offer ECH in the second.  Likewise, if the client did not offer ECH


extension will result in a new ClientHello to process, so even the client's TLS version preferences may have changed. <del> The ClientECH value is said to match a known ECHConfig if there exists an ECHConfig that can be used to successfully decrypt ClientECH.payload.  This matching procedure should be done using one of the following two checks: </del>  <del> Compare ClientECH.config_id against identifiers of known ECHConfig and choose the one that matches. </del>  <del> Use trial decryption of ClientECH.payload with known ECHConfig and choose the one that succeeds. </del>  Some uses of ECH, such as local discovery mode, may omit the ClientECH.config_id since it can be used as a tracking vector.  In <del> such cases, trial decryption should be used for matching ClientECH to known ECHConfig.  Unless specified by the application using (D)TLS or externally configured on both sides, implementations MUST use the first method. If the ClientECH value does not match any known ECHConfig structure, it MUST ignore the extension and proceed with the connection, with the following added behavior: It MUST include the "encrypted_client_hello" extension in its EncryptedExtensions with the "retry_configs" field set to one or more ECHConfig structures with up-to-date keys.  Servers MAY supply multiple ECHConfig values of different versions.  This allows a server to support multiple versions at once. If offered, the server MUST ignore the "pre_shared_key" extension in the ClientHello. Note that an unrecognized ClientECH.config_id value may be a GREASE ECH extension (see grease-extensions), so it is necessary for servers to proceed with the connection and rely on the client to abort if ECH was required.  In particular, the unrecognized value alone does not indicate a misconfigured ECH advertisement (misconfiguration). Instead, servers can measure occurrences of the "ech_required" alert to detect this case. </del>  <del> Once a suitable ECHConfig is found, the server verifies that the ECHConfig supports the cipher suite indicated by ClientECH.cipher_suite and that the version of ECH indicated by the client matches the ECHConfig.version.  If not, then the server MUST abort with an "illegal_parameter" alert.  Otherwise, the server decrypts ClientECH.payload, using the private key skR corresponding to ECHConfig, as follows: </del>  ClientHelloOuterAAD is computed from ClientHelloOuter as described in <del> authenticating-outer.  If decryption fails, the server MUST abort the connection with a "decrypt_error" alert.  Otherwise, the server reconstructs ClientHelloInner from EncodedClientHelloInner, as described in encoding-inner. </del>  Upon determining the ClientHelloInner, the client-facing server then forwards the ClientHelloInner to the appropriate backend server,

extension will result in a new ClientHello to process, so even the client's TLS version preferences may have changed.  <ins> First, the server collects a set of candidate ECHConfigs.  This set is determined by one of the two following methods: </ins>  <ins> Compare ClientECH.config_id against identifiers of known ECHConfigs and select the one that matches, if any, as a candidate. </ins>  <ins> Collect all known ECHConfigs as candidates, with trial decryption below determining the final selection. </ins> Some uses of ECH, such as local discovery mode, may omit the ClientECH.config_id since it can be used as a tracking vector.  In  <ins> such cases, the second method should be used for matching ClientECH to known ECHConfig.  See optional-configs.  Unless specified by the application using (D)TLS or externally configured on both sides, implementations MUST use the first method. The server then iterates over all candidate ECHConfigs, attempting to decrypt the "encrypted_client_hello" extension: </ins>  <ins> The server verifies that the ECHConfig supports the cipher suite indicated by the ClientECH.cipher_suite and that the version of ECH indicated by the client matches the ECHConfig.version.  If not, the server continues to the next candidate ECHConfig. Next, the server decrypts ClientECH.payload, using the private key skR corresponding to ECHConfig, as follows: </ins> ClientHelloOuterAAD is computed from ClientHelloOuter as described in  <ins> authenticating-outer.  The "info" parameter to SetupBaseS is the concatenation "tls ech", a zero byte, and the serialized ECHConfig. If decryption fails, the server continues to the next candidate ECHConfig.  Otherwise, the server reconstructs ClientHelloInner from EncodedClientHelloInner, as described in encoding-inner.  It then stops consider candidate ECHConfigs. </ins> Upon determining the ClientHelloInner, the client-facing server then forwards the ClientHelloInner to the appropriate backend server,


ClientHelloInner.  The client-facing server forwards all other TLS messages between the client and backend server unmodified.  7.1.1. In case a HelloRetryRequest (HRR) is sent, the client-facing server

ClientHelloInner.  The client-facing server forwards all other TLS messages between the client and backend server unmodified. <ins> Otherwise, if all candidate ECHConfigs fail to decrypt the extension, the client-facing server MUST ignore the extension and proceed with the connection using ClientHelloOuter.  This connection proceeds as usual, except the server MUST include the "encrypted_client_hello" extension in its EncryptedExtensions with the "retry_configs" field set to one or more ECHConfig structures with up-to-date keys. Servers MAY supply multiple ECHConfig values of different versions. This allows a server to support multiple versions at once. Note that decryption failure could indicate a GREASE ECH extension (see grease-extensions), so it is necessary for servers to proceed with the connection and rely on the client to abort if ECH was required.  In particular, the unrecognized value alone does not indicate a misconfigured ECH advertisement (misconfiguration). Instead, servers can measure occurrences of the "ech_required" alert to detect this case. </ins> 7.1.1. In case a HelloRetryRequest (HRR) is sent, the client-facing server


extension but CH1 does not, then the server MUST abort the handshake with an "illegal_parameter" alert. <del> Suppose the "encrypted_client_hello" extension is sent in both CH1 and CH2, If the configuration identifier (see ech-configuration) differs between CH1 and CH2, then the server MUST abort with an "illegal_parameter" alert. </del>  [[OPEN ISSUE: If the client-facing server implements stateless HRR, it has no way to send a cookie, short of as-yet-unspecified

extension but CH1 does not, then the server MUST abort the handshake with an "illegal_parameter" alert.  <ins> If the "encrypted_client_hello" extension is sent in CH2, the server follows the procedure in client-facing-server to decrypt the extension, but it uses the previously-selected ECHConfig as the set of candidate ECHConfigs.  If decryption fails, the server aborts the connection with a "decrypt_error" alert rather than continuing the handshake with the second ClientHelloOuter. </ins> [[OPEN ISSUE: If the client-facing server implements stateless HRR, it has no way to send a cookie, short of as-yet-unspecified


The non-empty name of the client-facing server, i.e., the entity trusted to update the ECH configuration.  This is used to correct misconfigured clients, as described in handle-server-response.  A list of extensions that the client must take into consideration when generating a ClientHello message.  These are described below

[Edit: deleted "Fixes" line for ]
From , we also talked about IP addresses and such. Do we still want to do that? Whether the client validation is SHOULD or MUST (TBH I kinda prefer MUST, given the implications on private services... if it's a SHOULD, we should talk about why so implementations can make an informed decision), we do also need to say what values are valid for the server.
OK, switched to a MUST. Added IP addresses as well. I'm calling out to for IPv4/IPv6 parsing. I'd like to avoid any ambiguities that might creep in if I were allowed to define the grammar, like allowing octal numbers in an IPv4 address, e.g. != . For hostname parsing, I'm borrowing from so we can parse IDNs.
I think that is a mistake.
Why is that?
I think IP addresses are a mistake because they can introduce parsing ambiguities (as pointed out above), and sometimes those cause problems (URL). Also, SNI is really limited to hostname (as NAME has pointed out before, referencing AGL's post), and having the two mismatch in their capabilities bothers me.
Agreed that the capability mismatch between SNI and ECHConfig.publicname is odd. However, there is already a capability mismatch between ECHConfig.publicname and names allowable on server certificates. At least in theory, the server's certificate might not have a hostname. That being said, I don't have a strong opinion either way. If we do decide to disallow IP addresses, I think we'd still want the client to look for them so it can reject those ECHConfigs that use IP addresses. This is about stopping wacky values from bubbling up to the application.
The client sending the ECH or the server receiving it? Current TLS stacks don't seem to check, on either side. (At least OpenSSL and its major forks)
I was referring to the client, but yeah, scratch that idea. If public_name can only be a hostname, the client should only validate that it looks like a hostname.
I don't think the capability mismatch between SNI and ECHConfig.publicname is a fatal. We can move ECHConfig.publicname up an abstraction level. I think we should do this whether we allow IPs or not. The public name isn't "put this in ClientHelloOuter.servername" but "the name you are trying to connect to in the outer handshake". In particular, this encompasses both ClientHelloOuter.servername and certificate verification. To fill in ClientHelloOuter.servername, you use the rules in RFC6066: servername is the name you are trying to connect to, provided it's a DNS name. Under this model, it is perfectly coherent for "the name you are trying to connect to" to be an IP address, if we want to do that. If we wish to do that then, yeah, we'll need to spell out the syntax here. That syntax clearly does already exist (URLs, etc.), but not in TLS. I don't particular care whether we do it, though. How about this: Right now, IP addresses are implicitly not okay by way of CHOuter.servername = ECHConfig.publicname. So let's not introduce them in this PR and merely iron out the DNS name validation. This PR adds to, but does not We then rework the text to redefine public_name as above. This is a prerequisite to allowing IPs, but I think it's worth doing either way. We decide the IP question (interim?) and with the result. (Sorry, I think some of this confusion is my fault. I filed two related, but separate, discussion points in , which was confusing. My comment in URL was most in reaction to "; that we shouldn't close it out without resolving both points.)
I think I'd mostly be against supporting IP addresses in ECHConfig.publicname. I suspect including an IP address in URL would break some things. The comment below is from OpenSSL's ssl/statem/extensionssrvr.c: / Although the intent was for servername to be extensible, RFC 4366 was not clear about it; and so OpenSSL among other implementations, always and only allows a 'hostname' name types. RFC 6066 corrected the mistake but adding new name types is nevertheless no longer feasible, so act as if no other SNI types can exist, to simplify parsing. Also note that the RFC permits only one SNI value per type, i.e., we can only have a single hostname. / Separately, we could land ourselves with yet more confusion related to the address to which one ought send a ClientHello, (the address in the ECHConfig or in the URL or the A/AAAA of one of the names involved, and which to prefer if some things have DNSSEC etc etc.). Cheers, S.
NAME Right, I think it's unambiguous, whatever we do with IP addresses, they won't go in ClientHelloOuter.servername. Any use of this, if we want it, would be for public name verification, not the servername value. See my comment above with how to think about public_name.
SGTM, folks. Just dropped the parts about IP addresses.
Looks like I was a little overzealous removing the IP address text. We still need to check that publicname is not an IPv4 address because dotted-decimal IPv4 addresses would slip through the cracks of hostname validation. This is bad because a malicious/misconfigured DNS would cause the ECH client to break 's rule on the contents of "servername": (Re-added this IPv4 check in the last commit.)
I would rather make "validate the host name" be a SHOULD and remove all these requirements.
ECH implementations not validating that string risks surprising behavior for a lot of applications, and potentially more attack surface to private services than before. Have you looked at the discussion in issue , in particular: Sadly, the thing that makes that work (logic earlier in the application) doesn't apply here. See URL
Can you explain your concerns in more detail? I think the application should be responsible for validation.
The application should never see the value of ECHConfig.public_name, right?
See , specifically URL and URL Well, there are several things going on here: First, different systems may differently divide the "TLS" part and the "application" part. The spec mostly captures behavior of the overall client system, because that's all we can usefully talk about. (For example, ECH specifies a retry flow that involves making a new connection. At the level of many TLS libraries, including OpenSSL + derivatives, the caller makes connections. So instead the TLS library can expose APIs and document the caller's responsibilities as part of enabling ECH. Other interfaces may be create their own connections and handle this internally.) So whether it's the application or TLS, at the implementation level, isn't a hard deciding factor. Second, with that said, yes, I expect that the majority of TLS application interfaces will treat the ECHConfigList as an opaque blob. That is a good division of responsibilities because the TLS half already needs to process individual ECHConfigs in the ECHConfigList and select one based on its internal capabilities. Having to thread through application-specific DNS validation seems like it'd be complex. (But this is just my view as an implementor. The spec merely describes the overall behavior of the client system. How you choose to layer it is an implementation decision.) Finally, there's the question of whether TLS as a spec should have opinions here or if it should punt to some upper layer spec profile, as we did with 0-RTT. I don't think that's warranted here. RFC6066 already decided what can go in server_name, so TLS already is plenty opinionated on the shape of strings meant to be DNS names. Thus, IMO, the simplest and most practical story is to have TLS handle this, rather than thread it up through all the layers.
I am willing to accept that I am in the rough here.
As noted in URL, I don't think we should be putting IP addresses in .
In the interest of dealing with one problem at a time, this PR no longer attempts to spell out how to recognize IP addresses. Roughly: The client MUST validate as a LDH hostname. The client SHOULD exclude IP address literals, which may come in many strange forms, or else it may send a non-compliant "servername" extension. If we care to make excluding IP addresses a MUST, let's work out the details in another PR. Same goes for if we want to explicitly support IP address literals — we still need to validate them to protect server applications from receiving IP addresses in non-standard notations, e.g. octal.
I think there are a couple things going on here: ECHConfig.publicname, as currently written, is described as what goes in CHOuter.servername. That wasn't right and we should have made it outer reference identity. I believe NAME is going to do a separate PR after this goes through. SNI or reference identity, we need to define what the type of the thing that goes in ECHConfig.publicname and what validation the client does. In particular, without validation, it gives the network more control over what goes into CHOuter.servername than would otherwise be the case. Normally, in a typical HTTPS client, TLS can just assume the hostname has passed whatever checks earlier in the stack (URL parsing, DNS lookup, etc.) and so checks in TLS are not load-bearing. The public name breaks this because the TLS layer is fabricating a hostname on its own. So we should have TLS validate it before running too far with it. This PR addresses (2).
Following up on NAME comment, I was indeed planning on clarifying that ECHConfig.publicname is a reference identity, and planned on renaming this to something other than to match. Basically: may be either a name or IP address, validated according to the rules in this PR, and clients will use that identity when constructing the ClientHello per the normal rules. (If it's a name, put it in "servername," else don't put it in that name.) I think we can probably land this PR as-is. Is everyone else OK with this plan?
It's a nit, but I don't think I've ever seen a use of the term "identity" that didn't eventually cause confusion. I think public_name was better TBH. Sorry if I missed the discussion but: Are one or more IPv4/IPv6 addresses allowed and if so with what syntax? If only 1 is allowed, why? (Syntax still needs a reference.) I don't know how an IP address here ought be handled if it differs from those in the SVCB address hints fields. (Not to mention the origin's A/AAAA records.) Lastly, I forget why we even want an IP address there at all. Thanks, S.
I assumed there's at most one identity in this field, be it a name or address, but NAME can clarify. Also, I think the identity here only pertains to how the client-facing server is authenticated. If a server uses an IP-address certificate for the rejection path then it might specify the single IP address of that certificate. (Clients don't use SVCB hints for this, so they're orthogonal.)
There can be many SANs even if those are IP addresses. So I think you mean that you want exactly one IP address here and if one is here that MUST match one SAN iPaddress from the cert? Personally I don't think that's useful enough to support but maybe I missed why it was really good. TBH, I doubt implementers will notice that orthogonality. And those deploying even less would be my guess. If one is allowed put a single IP address in an ECHConfig and others in SVCB hints then someone needs to say what to do when those aren't the same. S.
True, but I'm just commenting on parity with what's there right now. (ECHConfig.public_name is just one name.) We may change that later if people want it? I don't see a reason to, though. Yeah, that's what I'm thinking. Hmm, yeah, we may be able to clarify this, but given that we don't discuss anything about the SVCB record (beyond the config) currently, it may not be needed.
Currently, this PR explicitly states that the client SHOULD ignore the ECHConfig if its contains an IP address. Unfortunately, what constitutes a textual representation of an IPv4 address is pretty underspecified, so I didn't manage to come up with a foolproof validation algorithm, otherwise I would make it a MUST. If we want to allow IP addresses, let's figure it out in another PR.
So I don't think that we need to worry about IPv6 here. That will never match LDH. The IPv4 thing is unfortunate. I think that the risk is that the public name is passed to a certificate validation library that subsequently treats the name as an IP address (matching against an ipAddress SAN rather than dNSName SAN) when doing fallback process. If there is any potential for confusion about this string (or look-alikes if we consider the octal mess) then it might happen that there is variation in what certificates are considered OK. That leads to a reliance on the certification authorities being careful about issuance for names that look like IP addresses. We don't want that. Either way, I don't like "SHOULD" here. It retains the potential confusion. If one client component is sloppy and doesn't bother other components are then forced to contend with that choice. I think that I've come around to NAME viewpoint on this. It's reasonable to require a domain name for fallback in all cases, even where a server is identified by IP address alone. I think that means prohibiting IPv4 addresses, just to avoid the potential confusion. That is, if the name contains exactly 4 labels that are only digits, then the record is invalid. IPv6 addresses will look after themselves as they aren't valid LDH A-labels. Note: I don't know if there are rules that might allow 172.0.2.2045 to be registered, which is clearly not an IP address. I believe that the main protection we have against valid DNS names appearing to be IPv4 addresses is the gTLD registration rules (from URL Section 2.2.1.3.1 clause 1.2.1 this is currently assured as only a-z is permitted from the ASCII range).
NAME can you drill into this? I must be misunderstanding you (and maybe the problem), but are you suggesting that strings which look like IP addresses might be parsed incorrectly by the thing validating certificates against such look-alike addresses? They also have to be careful about names that aren't actually domain names ("DROP TABLES" or whatever). How is this a substantially new requirement? Prohibiting IP addresses here seems overly restrictive. Given that it doesn't seem challenging to support, and does not, to my knowledge, introduce any new requirements for CAs or certificate validation APIs, I'd like to hear more reasons why we ought to definitely rule them out. And as NAME says, we should hash this out in a separate issue and PR. In the interest of making forward progress, I'm going to merge this PR as-is, and we can discuss more in .
In most cases, I don't anticipate problems: there will be one certificate validator used during fallback and that will make a single determination. IP address lookalikes in that case probably won't be a problem. However, in cases where there are multiple components involved, there might be IP address lookalikes that pass one validator but not another. That might be used to attack clients.
Given how IPv4 literals can get in some applications, I suspect the TLS library classifying and rejecting IPv4 literals in a way that ensures the calling application always interprets it as a DNS name is hopeless. I'm now inclined to say we should: Do and say publicname is exclusively DNS. If anyone adds IP in the future, the expectation will be a separate extension and thus not require any parsing to pick semantics. The exclusively-DNS publicname field is validated according to DNS rules and leave it at that. That at least avoids completely unbounded DNS control on the ClientHello. Concede that we can't reliably exclude IPv4 literals at this layer. Call this out and say that clients MUST NOT validate the string as IP addresses. If your verifier has separate APIs for configuring DNS vs IP names for subjectAltName, feel free to pass the string as a DNS input and move on. If your verifier's API takes a more URL-like hostname, you should use whatever logic you used to distinguish DNS vs. IP and fail the verification if you think the string is an IP. (Effectively that verifier believes "DNS:1.2.3.4" is never valid because it has no way to spell it.) This does mean the DNS can cause ClientHelloOuter to violate the RFC6066 prohibition on IPv4 literals, but since RFC6066 failed to specify what syntax it was prohibiting, the meaning of that rule is somewhat unclear.
In , there's been a lot of discussion around how and whether or not IP addresses should be allowed as a reference identity of the client-facing server. This issue tracks sorting this particular question out. NAME suggested in the case the reference identity is an IP address. (Whether or not this address is in the ECHConfig is separate.) NAME suggested . (Whether or not this allows the outer SNI to be empty is separate.) So there seems to be two questions we need to sort out, in relation to : Should the ECHConfig be allowed to supply IP addresses? And if so, how do client stacks validate them? Should clients be allowed to validate servers using IP addresses as a reference identity? (If yes, then the ClientHelloOuter.SNI must be allowed to be empty/omitted.) I think (2) should be 'yes', given that's currently possible today introduces no new complexity. I think it should be feasible to spell out the requirements to make (1) feasible, so I also think that should be 'yes'. What do others think?
Yes and yes. RFC 8738 using reverse-IP notation, which seems like a halfway-reasonable option. An "empty" public name seems a little more flexible (doesn't require servers to carry certificates for each other's IP addresses), and ought to be easy enough to support on clients.
NAME to clarify this: You're suggesting that if ECHConfig is empty then the client should use the IP address of the client-facing server as the reference identity, right? That seems like a reasonable way around the language we might need to specify what is a valid address in ECHConfig. (If the reference identity is not empty, then it MUST be a name, otherwise it's the IP address, and clients should connect and validate based on that identity accordingly.)
NAME Correct. NAME previously raised a concern that this could complicate client implementations: the TLS stack can no longer make use of a connected socket given solely on the ECHConfig and inner reference identity; it also needs the remote IP in some cases. This is true, but I think the remote IP is essentially always "at hand" so perhaps it can be passed in unconditionally without too much difficulty.
I don't think that's true when the client is using a proxy, depending on how much of DNS is done on the client and how much is done on the proxy. If the client does the SVCB lookup itself but asks the proxy to look up TargetName, as the SVCB draft , the client won't have the remote IP of the client-facing server available. (Are there weird networks that rewrite addresses at the DNS level? That would also break with this idea.)
To try and sharpen NAME point: will the client always have access to the client-facing server IP? I don't see how this won't always be true, since the client connects to something, but maybe I'm misunderstanding the proxy scenario.
NAME is correct about the behavior when using a SOCKS5 or HTTP CONNECT proxy in domain-oriented mode. The proxy performs A/AAAA resolution and TCP connection establishment, and does not provide this information back to the client, so the client doesn't know which server IP it is using. That does suggest that "empty" won't work.
Oh! I see. The proxy is the one establishing the transport connection.
There's probably at least three modes here, if not more: Proxy gets the origin DNS name and takes over the whole DNS lookup. Client doesn't do SVCB at all. The only way to salvage SVCB-based features is to invent a header for the proxy to tell the client what SVCB path it followed in the CONNECT response. Client does SVCB lookup and gives TargetName to the proxy. Client does the whole lookup and gives the IP address to the proxy. The one that breaks empty names is (2). Though, given that proxies today are often used to access internal services (i.e. without the proxy, you may not even be able to resolve the name), I expect (1) to be the default for existing schemes. Whereas (3) might make sense for other kinds of proxy use cases. (I'm actually not entirely sure when you'd want (2) despite the spec recommendation... maybe if you're relying on the proxy to rewrite IPs, but the proxy needs to a DNS name to do so?)
This is presumably not the right forum for this topic, but mode (2) is the one that gives you correct Happy Eyeballs, geo-DNS, etc.
I seem to recall some DNS IPv6 transition thing that maybe has that property. S.
Yes, there are transition technologies that rewrite addresses. Clients get a v6 address because they only have v6, but the server address is v4. As for the general proxy problem, there is no value in any design that does not involve the client having the ECHConfig. It can't use the public IP (because it doesn't know it always), but it can still populate servername according to the value of publicname. I might have missed something there though. From David's , option 1 is a bit silly (it adds unnecessary latency), but it also gives you the best locality if your goal is to use the proxy egress as the client network location (option 2 as Ben only works if you care about the network location of the client, at which point you might as well not use a proxy). The only difference between 2 and 3 there is whether the proxy needs to perform its own name resolution, which might differ from the client (and cause problems as a result; but that's mostly just a case of insisting that clients don't choose option 2). I don't understand why it's so hard to require the use of a domain name. It shouldn't be "". Adding other forms of reference identity adds complexity to what is already a morass of horrifying complexity, so we should insist on justification for every addition. And I'm not seeing any concrete arguments in favour of the complex option. So my answer is No to both questions.
I don't agree with Martin's characterization of the proxy behaviors, but I don't think this is the place to discuss that topic anyway. To me, the main advantage of supporting IP reference identities is for origins that are not using a large-scale hosting provider, and thus cannot rely on a widely shared . Domain names are typically more closely linked to an organization than IP addresses (especially with VM hosting), and more expensive to change. An IP address ensures that the client does not populate the outer SNI, and supports a configuration where the default certificate only contains an IP address SAN. This minimizes the information visible to an adversary unless they can also identify the service that runs on this IP address (e.g. by scanning the whole DNS). An alternative to IP address in would be a flag in the ECHConfig indicating that the specified reference identity is in the default certificate (which is implicitly true for IP reference identities). This would allow clients to omit the SNI, improving small services' privacy against a passive adversary, but active adversaries could fetch the default certificate to learn the .
For everyone's consideration, we now have as an alternate solution to this problem (thanks to NAME which does two things: (1) avoids overloading a single field for two types of values (names and addresses), and (2) punts IP address validation to a future change. While I sympathize with Martin's view, it seems overly restrictive to just prohibit IP addresses outright. This change allows us to sort that out in a future change, and should make everyone happy. Thoughts?
Re , the idea is largely me going "oops, I'm sorry for the mess". :-) When I filed , I was mostly interested in the client validation. But most places with DNS strings have a semi-overlap with IP literal syntax, and RFC6066 already prohibits of IP literals. (Without declaring an actual syntax being prohibited!) So it seemed hard to resolve those questions without going one way or another on IPs. So I brought up that question too as a seemingly minor (hah) side question on the main issue. That side question has turned out to be way more messy than I anticipated. Since there isn't a strong need for IPs as public identities, but also unease to completely close that door, I propose we tweak the encoding so it's easy enough to add later (reuse the extension mechanism we're already putting in), but not actually bother in this draft.
Isn't it the case that the extension scheme would allow us to add IP addresses later, even without ?
There's lots of different ways we can accomplish this, and it'll come down to personal taste. For example: Make publicname optional in the main ECHConfig (and waste the two byte length field), and allow an extension to specify the IP address. Move publicname to a mandatory extension (as 426 does), and allow future extensions to specify addresses override the name. etc. Given the bikeshed that's happening here, it seems prudent to at least separate these things (names and addresses). If we can agree on that, then we just need to decide where we put those bits. does the job one way. If someone wants to propose an alternative PR to put the bits somewhere else, please do so!
If we're really talking about a bikeshed, then the "no change" option works for me. It's fewer bits on the wire (by 4), it is less complicated to enforce it being mandatory, and we already have it implemented. I do think that public_name being optional has some impact here. It means that you don't have a reference identity for fallback handling. I think that's probably legitimate. There might be cases where fallback is not needed.
Hmm... how do you see this working if a future extension wants to specify IP addresses as a fallback but the publicname is not allowed to be optional? I agree that there will be cases where fallback is not needed. DNS-SD is one of them. And in that case, removing the publicname field (or allowing it to be empty, or whatever) will be needed. I think addresses that pretty nicely.
Ahh, I misunderstood. It's not that the extension is mandatory to use, but it is mandatory to understand when present. Let's be really crisp about the words we use. Of course, an empty value is an equally good way to indicate that the value isn't operative. It's one byte in the less-common case to save 4 bytes in the common case. The question occurs to me: is there any possibility that you could have both a publicname extension and this hypothetical ipreference_identity extension? What would that mean? I want to be really open about my priors here: I think that extensibility along this axis is an anti-feature for ECH. The mandatory-to-understand extensions are part of what really confirmed that for me. I think that the current format would be improved by removing the extensions block.
Unclear -- I think it'd be up to the hypothetical extension to define how those things interact. I hear you. If we didn't care about IP addresses for the fallback certificate, much of this would be simplified. (And admittedly the desire to remove the extensions block would increase for me, too.) I'm going to take this to the list, since we don't seem to be getting anywhere without consensus on that point.
The draft already defines a notion of "mandatory". Although does both (let's call the other one "required"?), which I think is the minimal encoding change because... I don't think we should open that can of worms. Even though not having a fallback flow is really the server's decision, I think the client has a stake in this too. It's useful to nudge the ecosystem towards things that work well. If a server deploys without fallback, underestimating the predictability of DNS caching, it will break rarely in some clients. That sort of thing is bad UX and increases the pressure for clients to adopt insecure fallbacks. Unless there is a clear need, I don't think we should allow that. (Otherwise not setting it up is deceptively attractive for a naive server since they make fewer decision.) The extensibility story for ECH is a little funny. You send an ECHConfigList and the client ignores any ECHConfigs it can't understand. So if we say today's ECH clients require a publicname extension, future ECH clients can still support a publicip extension that relaxes the publicname requirement. Today's ECH clients will just ignore the publicip-using configs, which is the desired behavior. But I should say I have no stake in this IP mess and do not care whether we allow those. Just pick something that everyone's happy with, please. was an attempt to punt this out of the draft while keeping all the existing semantics unchanged (hence required extension; the correct reading is that it is purely an encoding change).
That point about making it hard NOT to provide a fallback makes me more inclined to reject . If the effect is just a change in encoding, it's a less efficient encoding and one that is harder to validate properly. If the effect is to make it optional under certain conditions, you have just argued effectively for why that has negative consequences.
It's really a different point and maybe deserves it's own issue but since I'm not logged into github and email works... The "critical" bit in x.509 extensions IMO didn't work. IIRC we really designed it for the basicConstraints extension, as that had to be understood by relying parties, but the result was that we more or less only had one shot at introducing any critical extensions - unless I'm forgetting stuff (which is entirely possible:-) pretty much all later attempts to add new critical extensions failed as they'd break deployed clients. We'd have been better off adding the is-a-ca flag and anything else we knew to be critical the TBSCertificate. (Again IIRC, we put both critical and non-critical stuff into extensions because the UniqueID fields in TBSCertificate that were added in x.509v2 hadn't been useful so there was a reluctance to put new fields in there at that point.) I don't see why criticality is different for ECH extensions. My bet is that any new critical extension will need a new TLS extension code point once the first ECH RFC is issued. So I'd remove the extensions fields we've defined and if not then at least get rid of the idea of criticality. Cheers, S.
NAME I filed to discuss ECHConfig.extensions -- let's try and keep this issue focused on the IP address question(s).
Addressed in , closing.
Some edge cases around the publicname: What if the public name is some random string which is not a valid DNS name? (What's the right terminology here? Same from RFC6066?) Does the client reject the ECHConfig? My feeling is yes. Imagine you have some random service accessible on a private address. Today, it can assume it'll never see in the servername field. Even if an attacker pointed at that private address, the attacker is constrained by valid DNS strings. But the public name is never directly queried in DNS. Is a server deployment allowed to use an IP certificate for the ECH rejection identity? (That was actually the original idea for the fallback flow.) If so, how do they specify it? Do they use the ASCII serialization of the IPv4 or IPv6 address? Note that IP addresses do not go in server name, so the client would need to recognize this and leave server_name empty. NAME
I imagined the outer name would be set from the config similar to how an application sets the inner name. That is, one provides a string to and, internally, the library determines whether or not that string is a valid domain name (and thus goes in the server name) or is an IP address (and thus is used to verify the IP-based cert that might come back from the server). ASCII serialization of addresses seems fine here, if one just takes that string and passes it to the function (or equivalent).
Well, OpenSSL and derivatives have a lower-level API and just take the server name as an opaque string. :-) But yeah, that seems a reasonable model. Whatever we pick, we should write it down. What do you think should happen if the public name is neither a valid DNS name, nor a valid IP address? Like . ECHConfig parse error would be my inclination.
Yeah, that seems like a configuration error on behalf of the server.
That seems like it's already an unsafe assumption, right? Malicious clients could send SQL-injection strings to vulnerable servers without ECH. I suppose ECH introduces some asymmetry; one malicious DNS server could cause N clients to send the malicious payload.
Backing up a step, if we care to protect applications from malicious/malformed DNS hostnames, it seems prudent to validate all incoming server_name values on the server, whether they came from ClientHelloInner/ClientHelloOuter or even a non-ECH ClientHello. (Assuming we're using the RFC6066 HostName definition.)
NAME yeah, that's basically what I was thinking the function would do. Would you have cycles to prep a PR to resolve this issue?
It depends. Services listening on private addresses often make a lot of assumptions. These assumptions are pretty questionable, but we put in effort to anyway because that is reality. Yes, any server listening on a network should tolerate arbitrary input and behave well. Nonetheless, the reality is private services are often buggy. Where we break soft assumptions that might have previously (mostly) worked, we should at least think about it. Here, it seems there's no point in breaking the assumption.
Ah, servers at private addresses was not even on my radar. I support client validation of ECHConfig.publicname at parse time AND server validation of all ClientHello* servername extensions. NAME Happy to do a PR.
(I don't think the ECH spec should say anything about server validation here. The server looks at whichever ClientHello it selects and does whatever it would normally do with the server name in the selected one.)
There doesn't seem to be a standard that reflects actual current practice. Chrome and Firefox accept SNIs with underscores, which are not allowed in valid DNS names (URL).
Yep, thanks for raising that, Carrick. Perhaps we should make hostname validation a SHOULD rather than MUST?
The issue doesn't sound like a MUST vs. a SHOULD but rather what they SHOULD or MUST do. I guess we could say "do whatever you usually do with the SNI."
Oh and yeah, SHOULD seems like a better idea than MUST since there are conflicting opinions about the right way to go about it.
It's a little tricky due to what layers we're talking about. Chrome doesn't particularly validate the SNI at the TLS level. Rather, we leave that to URL parsing and DNS logic earlier in the pipeline. If we've gotten far enough to make a TLS connection, we assume we're happy with the string we're passing to SNI and certificate validation. I imagine this is reasonably common: OpenSSL likewise treats the setservername API as an opaque byte string. ECH breaks this assumption by bypassing all the earlier layers. Suddenly a TLS-level construct (ECHConfig) is fabricating a DNS name on its own, and now TLS needs to pick up all the validation.
Technically couldn't DNS logic validate the DNS name in the ECHConfig?
Hi folks, PR is a little more complete now, if you get a chance :)
To close the loop on this: it could, but we're treating the ECH parts of SVCB as opaque to DNS. [edit: I miswrote "opaque to TLS" at first] I think that's desirable because TLS may introduce new ECH extensions or ECH versions that the DNS stack may not be aware of. Also, any validation on the URL parsing / DNS query path happens in the process of making a request to the DNS server at all, whereas any validation here would be a check afterwards on the result. Whatever we do, it'll end up looking like someone, DNS or TLS, implementing a check we need to write down.
To come back to this: because SNI does not support IP addresses, IP certs must be the server's default-cert, i.e. they must be served to requests that omit the SNI. Thus, we merely need a way to tell clients to omit . My suggestion is to allow to be empty, meaning "omit outer SNI".
Keeping in mind that the client uses to authenticate the server's , the client now needs to be aware of which IP address it's connecting to. I suppose this isn't a protocol concern, but it's more ergonomic when the ECHConfig contains all the information TLS needs to do ECH.
OK. As I mentioned yesterday, I think should probably be an X.509 .
I do not think GeneralName will work. There's somewhat a mismatch between what the application thinks of as identities and how those identities are encoded into X.509. GeneralName is part of the latter. What does a browser certificate verifier, which only believes in things that fit in a URL, do if it's told the identity is now an EDIPartyName? What SNI, etc., does that translate into, given that our identity-to-TLS-config algorithm takes an HTTPS origin, not an X.509 name? (Note that the type field in SNI is fiction. There is and will be .) More importantly, this glomming too many things into an already overloaded issue. If you want to pursue this, can you please fork GeneralName into a separate topic? The status quo in the existing text is that the public name is clearly only good for DNS or DNS+IP, depending on how much you believe in URL syntax. We already have a need to better specify that case, including client validation. Let's fix that, and then we can separate tackle more complex cases.
Strongly disagree. GeneralName was a reasonable guess at a thing to do 20 years ago but is no longer a structure that ought be leveraged - we have no need for EDI nor X.400 names for ECH and even tempting someone to write code for ORAddress handling is risky - there's >1 can of worms there all of which are best avoided. S.
Agree with Stephen. Using GeneralName is like hunting butterflies with an elephant gun. :)
Addressed in , closing.
This seems like it would prohibit URL NAME NAME would this be a problem for the DNS-SD case?High-level, I think that we need to agree on what this value is for first. Editorially, I think that this text needs more space to move. Trying to cram all this stuff into a single paragraph isn't doing us any favours. Make a new section for this. It's certainly important enough to do properly. My sense is that the right answer to the underlying issues is that this is a reference identity rather than something we put in servername in ClientHelloOuter. In that case, the fallback is achieved by establishing a connection and validating that the entity providing the updated configuration is able to answer for this reference identity. You then construct ClientHelloOuter in such a way as to ensure that you are able to successfully connect to that reference identity if ClientHelloInner cannot be accepted. If this is just a name, then this is over-specified. If the goal is to describe what goes in ClientHelloOuter server_name, none of the validation is necessary. If the server wants you to put junk in the field, then I don't see how that junk would be any more identifying than an identifying DNS name. You really only need special IP address rules if you intend for this to be a reference identity. The Server Name Indication (SNI) extension in TLS has a provision to provide names other than host names[1]. None have even been defined to my knowledge, but it's there. OpenSSL (and possibly others) have had a long-standing bug[2] (fixed in master) that means that different types of names will cause an error. To be clear: I live in a glass house and am not throwing stones; these things happen. However, it means that a huge fraction of the TLS deployment will not be able to accept a different name type should one ever be defined. (This issue might have been caused by the fact that the original[3] spec didn't define the extension in such a way that unknown name types could be skipped over.) Therefore we (i.e. BoringSSL, and thus Google) are proposing to give up on this and implement our parser such that the SNI extension is only allowed to contain a single host name value. (This is compatible with all known clients.) We're assuming that since this is already the de-facto reality that there will be little objection. I'm sending this mostly to record the fact so that, if someone tries to define a new name type in the future, they won't waste their time. If the community wishes to indicate a different type of name in the future, a new extension can be defined. This is already effectively the case because we wouldn't fight this level of incompatibility when there's any other option. (I think the lesson here is that protocols should have a single joint, and that it should be kept well oiled. For TLS, that means that extensions should have minimal extensionality in themselves and that we should generally rely on the main extensions mechanism for these sorts of things.) [1] URL [2] URL – note that the data pointer is not updated. [3] URL Cheers AGL Adam Langley EMAIL URL

The non-empty name of the client-facing server, i.e., the entity trusted to update the ECH configuration.  This is used to correct misconfigured clients, as described in handle-server-response. <ins> This value MUST NOT begin or end with an ASCII dot and MUST be parsable as a dot-separated sequence of LDH labels, as defined in RFC5890, Section 2.3.1.  Clients MUST ignore any "ECHConfig" structure whose "public_name" does not meet these criteria.  Note that these criteria are incomplete; they incidentally rule out textual representations of IPv6 addresses (see RFC3986, Section 3.2.2), but do not exclude IPv4 addresses in standard dotted-decimal or other non-standard notations such as octal and hexadecimal (see RFC3986, Section 7.4).  If "public_name" contains a literal IPv4 or IPv6 address, the client SHOULD ignore the "ECHConfig" to avoid sending a non-compliant "server_name" extension on the ClientHelloOuter (see RFC6066, Section 3). </ins> A list of extensions that the client must take into consideration when generating a ClientHello message.  These are described below


"psk_key_exchange_modes" from the ClientHelloInner into the ClientHelloOuter.  [[OPEN ISSUE: We currently require HRR-sensitive parameters to match in ClientHelloInner and ClientHelloOuter in order to simplify client- side logic in the event of HRR.  See https://github.com/tlswg/draft-

This should probably land after . cc NAME
I don't know the answer to this question, but, from the TLS 1.3 RFC: I noticed this while testing with a pre-baked ClientHello that had both extensions. The ECH draft clearly required that the extension be removed, but I wondered about .
Given URL, URL, and URL, I'd say quite the opposite.
Ah, I see text has been added saying it must appear in the ClientHelloOuter. Thanks for the references. I was working from draft-10.
Here's a fun case. Suppose the client talks to a 0-RTT-capable, ECH-capable server. It'll send earlydata + presharedkey in ClientHelloInner, wrap that in some ClientHelloOuter, and follow it up with early data records. Now the server rejects ECH and handshakes with the ClientHelloOuter. But the client has already sent early data, so the server needs to know to skip past it. I believe this means we need to require the client mirror ClientHelloInner.earlydata in ClientHelloOuter, even though it's not actually offering to resume anything. Sending earlydata without presharedkey is slightly weird (if tolerated at all), so we might even want to recommend a fake outer presharedkey. We almost_ don't care about this: the client may as well stop the handshake at server Finished and skip the client Finished flight anyway, for purposes of the recovery flow. However: What's not what the draft currently says If the server rejects ECH, handshakes with ClientHelloOuter, and sends HelloRetryRequest, we do care about the client's second flight getting through. That second case is extra fun because the client-facing server must look for the second ClientHello too.
Wasn't this already the outcome from ? (That is, if the inner CH has a PSK, then the outer one ought have a dummy PSK, too.) As for mirroring earlydata, why can the server not just ignore the application data (as if it received earlydata and decided to ignore it)? Taking a quick look back at RFC8446, the server behavior where clients send application data without early_data is not defined, so are you concerned about that, or something else?
Well, I think we only got as far as MAY in , but yeah I think this is another reason. Regarding ignoring application data, our server implementation only skips early data if there was an early_data extension that we rejected. I believe that matches RFC8446 since it doesn't say to skip application data in general, just that case. And, yeah, that's the concern.
Since this is behavior for the client-facing server, which supports ECH, can't we specify the desired behavior in this spec? That is, we might say that a client-facing server which rejects ECH MUST ignore any early data sent by the server, or something. Would that work?
We could, but then it'd break the nice property that a plain RFC8446 server will handshake ClientHelloOuter without any fuss. This property is great for rollback safety. (Otherwise any ECH server deployment needs to be two-stage, and introduces a lower bound that you cannot rollback beyond.) And elsewhere we've tried to avoid contradicting RFC8446. Yet another option would be to tell the client to retry on certain kinds of errors if it offered 0-RTT in ClientHelloInner, but that's a bit more fuss since retries are often outside the TLS stack. (Besides, the fact that you offer 0-RTT in ClientHelloInner is all but public anyway. While we don't have a cleartext 0-RTT marker[], it's pretty obvious from timing that some post-ClientHello record came before ServerHello.) [] In TCP... I want to say QUIC does, but I could be misremembering.
True! This is fun. :-)
I'm not sure why ignoring stuff is fuss. What's the alternative? To terminate the handshake if the server receives early data? Wouldn't that be more fuss? If RFC8446 doesn't specify what to do in this situation, I'm not sure why specifying it is in contradiction to RFC8446 (as opposed to expanding on it).
I think RFC8446 does say what to do in this situation. Section 5.2 says at the bottom: URL The default for the record layer is that decryption errors are fatal (as it should be). Early data skipping is an exception to this described in section 4.2.10, and the exception only applies when the server declines an earlydata extension. Oh no, the goal is to ignore stuff. That's what makes the recovery flow work. The issue is that, in RFC8446, servers only ignore the early data if there was an earlydata extension in ClientHello which they declined. Otherwise, it's just a fatal decryption error. In order to meet that condition, ClientHelloOuter needs the early_data extension whenever ClientHelloInner does.
ACK -- thanks for closing the loop!

"psk_key_exchange_modes" from the ClientHelloInner into the ClientHelloOuter. <ins> When the client offers the "early_data" extension in ClientHelloInner, it MUST also include the "early_data" extension in ClientHelloOuter.  This allows servers that reject ECH and use ClientHelloOuter to safely ignore any early data sent by the client per RFC8446, Section 4.2.10. </ins> [[OPEN ISSUE: We currently require HRR-sensitive parameters to match in ClientHelloInner and ClientHelloOuter in order to simplify client- side logic in the event of HRR.  See https://github.com/tlswg/draft-


ClientHelloInner. The list of HPKE KDF and AEAD identifier pairs clients can use for <del> encrypting ClientHelloInner. </del>  The client-facing server advertises a sequence of ECH configurations to clients, serialized as follows.

Not sure if this is needed, but I guess it would be another way to generate failures;-)
Good clarification! This was already somewhat in the real-ech section, so I just replaced this with a forward pointer there.

ClientHelloInner. The list of HPKE KDF and AEAD identifier pairs clients can use for  <ins> encrypting ClientHelloInner.  See real-ech for how clients choose from this list. </ins> The client-facing server advertises a sequence of ECH configurations to clients, serialized as follows.


Deprecating MD5 and SHA-1 signature hashes in TLS 1.2 <del> draft-ietf-tls-md5-sha1-deprecate-04 </del>  Abstract <del> The MD5 and SHA-1 hashing algorithms are steadily weakening in strength and their deprecation process should begin for their use in TLS 1.2 digital signatures.  However, this document does not deprecate SHA-1 in HMAC for record protection.  This document updates RFC 5246 and RFC 7525. </del>  1.

NAME thanks, updated with the additional changes.
NAME NAME NAME Feel free to merge when you get a chance
Great! Now on to Daniel's comments.

Deprecating MD5 and SHA-1 signature hashes in TLS 1.2  <ins> draft-ietf-tls-md5-sha1-deprecate-05 </ins> Abstract  <ins> The MD5 and SHA-1 hashing algorithms are increasingly vulnerable to attack and this document deprecates their use in TLS 1.2 digital signatures.  However, this document does not deprecate SHA-1 in HMAC for record protection.  This document updates RFC 5246 and RFC 7525. </ins> 1.


recommendation to use stronger language deprecating use of both SHA-1 and MD5.  The prior text did not explicitly include MD5 or SHA-1; and this text adds guidance to ensure that these algorithms have been <del> deprecated.. </del>  Section 4.3:

recommendation to use stronger language deprecating use of both SHA-1 and MD5.  The prior text did not explicitly include MD5 or SHA-1; and this text adds guidance to ensure that these algorithms have been  <ins> deprecated. </ins> Section 4.3:


recommended) as defined by RFC8447.  The following entries are to be updated: <del> Other entries of the resgistry remain the same. </del>  9. Concerns with TLS 1.2 implementations falling back to SHA-1 is an <del> issue.  This draft updates the TLS 1.2 specification to deprecate </del>  support for MD5 and SHA-1 for digital signatures.  However, this document does not deprecate SHA-1 in HMAC for record protection.

recommended) as defined by RFC8447.  The following entries are to be updated:  <ins> Other entries of the registry remain the same. </ins> 9. Concerns with TLS 1.2 implementations falling back to SHA-1 is an  <ins> issue.  This document updates the TLS 1.2 specification to deprecate </ins> support for MD5 and SHA-1 for digital signatures.  However, this document does not deprecate SHA-1 in HMAC for record protection.


2. <del> Clients MUST NOT include MD5 and SHA-1 in the signature_algorithms extension.  If a client does not send a signature_algorithms extension, then the server MUST abort the handshake and send a handshake_failure alert, except when digital signatures are not used (for example, when using PSK ciphers). </del>  3.

cc NAME NAME NAME
I believe this I-D should still include the "update: 5246 (if approved)" header, even though we took out the 5246 OLD/NEW section. We are still proposing that 5246 be changed to require signature_algorithms extension be sent and that MD5/SHA1 never be sent. In other words, I think you can merge this PR assuming there are no conflicts.
Verifying that this is okay on list, but Daniel suggested the following change for s6: Add the following immediately bfore the OLD/NEW, i.e., right after "due to MD5 and SHA-1 being deprecated.": In Section 7.1.4.1: the following text is removed: If the client supports only the default hash and signature algorithms (listed in this section), it MAY omit the signature_algorithms extension.
Resulted in a number of changes - see .
I think you also need to update the abstract and introduction sections, as they both mention "This document updates ..." (same as URL). Will probably conflict with URL so we should merge that first.I believe this can be merged as is. I.e., don't remove the "udpates" header, change the abstract, or intro.

2.  <ins> Clients MUST include the signature_algorithms extension.  Clients MUST NOT include MD5 and SHA-1 in this extension. </ins> 3.


4. Servers MUST NOT include MD5 and SHA-1 in ServerKeyExchange messages. <del> If a client receives a MD5 or SHA-1 signature in a ServerKeyExchange message it MUST abort the connection with the illegal_parameter alert. </del>  5.

4. Servers MUST NOT include MD5 and SHA-1 in ServerKeyExchange messages.  <ins> If no other signature algorithms are available (for example, if the client does not send a signature_algorithms extension), the server MUST abort the handshake with a handshake_failure alert or select a different cipher suite. </ins> 5.


6. <del> RFC5246, The Transport Layer Security (TLS) Protocol Version 1.2, suggests that implementations can assume support for MD5 and SHA-1 by their peer.  This update changes the suggestion to assume support for SHA-256 instead, due to MD5 and SHA-1 being deprecated. In Section 7.4.1.4.1: the text should be revised from: OLD: "Note: this is a change from TLS 1.1 where there are no explicit rules, but as a practical matter one can assume that the peer supports MD5 and SHA- 1." NEW: "Note: This is a change from TLS 1.1 where there are no explicit rules, but as a practical matter one can assume that the peer supports SHA-256." 7. </del> The document updates the "TLS SignatureScheme" registry to change the recommended status of SHA-1 based signature schemes to N (not recommended) as defined by RFC8447.  The following entries are to be

6.  The document updates the "TLS SignatureScheme" registry to change the recommended status of SHA-1 based signature schemes to N (not recommended) as defined by RFC8447.  The following entries are to be


[RFC5246][RFC8447][RFC-to-be] <del> 8. </del>  Concerns with TLS 1.2 implementations falling back to SHA-1 is an issue.  This document updates the TLS 1.2 specification to deprecate support for MD5 and SHA-1 for digital signatures.  However, this document does not deprecate SHA-1 in HMAC for record protection. <del> 9. </del>  The authors would like to thank Hubert Kario for his help in writing the initial draft.  We are also grateful to Daniel Migault, Martin

[RFC5246][RFC8447][RFC-to-be]  <ins> 7. </ins> Concerns with TLS 1.2 implementations falling back to SHA-1 is an issue.  This document updates the TLS 1.2 specification to deprecate support for MD5 and SHA-1 for digital signatures.  However, this document does not deprecate SHA-1 in HMAC for record protection.  <ins> 8. </ins> The authors would like to thank Hubert Kario for his help in writing the initial draft.  We are also grateful to Daniel Migault, Martin