stored or transported, as compared to the less efficient text-based form of the original vocabulary.  The root of the CDDL specification provided by this document is the rule "coswid" (as defined in tagged):

Addressed the following comments: [Per IETF 110] Add text on the order of native CDDL approach for handling version is used. If a future version of SWID is published which alters the semantics of exists fields, a future version of CoSWID SHOULD (MUST?) use a different tag to represent it. [daw: A new paragraph was added to section 2 detailing how index values are used to support revisions and extensions.] [Per IETF 110] see -16. Use ISO SWID reference for the IANA registry and if desired, used [SEMVER] as an informal reference in the text [daw: This has been done in section 4.1.] [daw: The FIXME markers have been replaced with actual text.] [daw: Section 7 now details the construction of a signed CoSWID. A SHOULD sign requirement was also added to section 7.] [Per IETF 110] We discussed adding language on the order of "This document specifies a data format and an associated integrity mechanism agnostic of a deployment. Application which choose to use CoSWID will need to specify explicit guidance which security properties are needed and under which circumstances." > ** [-15] Section 6. Per "When an authoritative tag is signed, the software [daw: Authenticating the signer is the software provider will require a match between a CoSWID entity and the signer. We are working out a means to do this.] 2 [daw: Not sure which tags this applies to? Signing? All of section 2?] [daw: done.] [daw: This confusing text has been removed.] [daw: done.] [daw: We added a note about this.] [daw: Done.] [daw: Added signature validation as a way.] Regards, Roman

stored or transported, as compared to the less efficient text-based form of the original vocabulary. <ins> Through use of CDDL-based integer labels, CoSWID allows for future expansion in subsequent revisions of this specification and through extensions (see model-extension).  New constructs can be associated with a new integer index.  A deprecated construct can be replaced by a new construct with a new integer index.  An implementation can use these integer indexes to identify the construct to parse.  The CoSWID Items registry, defined in iana-coswid-items, is used to ensure that new constructs are assigned a unique index value on a first-come, first-served basis.  This approach avoids the need to have an explicit CoSWID version. </ins> The root of the CDDL specification provided by this document is the rule "coswid" (as defined in tagged):


integrity measurements for files.  The ISO-19770-2:2015 XML schema uses XML DSIG to support cryptographic signatures. <del> Signing CoSWID tags follows the procedues defined in CBOR Object Signing and Encryption RFC8152.  A CoSWID tg MUST be wrapped in a </del>  COSE Single Signer Data Object (COSE_Sign1) that contains a single signature and MUST be signed by the tag creator.  The following CDDL specification defines a restrictive subset of COSE header parameters

integrity measurements for files.  The ISO-19770-2:2015 XML schema uses XML DSIG to support cryptographic signatures.  <ins> Signing CoSWID tags follows the procedures defined in CBOR Object Signing and Encryption RFC8152.  A CoSWID tag MUST be wrapped in a </ins> COSE Single Signer Data Object (COSE_Sign1) that contains a single signature and MUST be signed by the tag creator.  The following CDDL specification defines a restrictive subset of COSE header parameters


provide a signature on a signature allowing for a proof that a signature existed at a given time (i.e., a timestamp).  8. This specification allows for tagged and untagged CBOR data items

provide a signature on a signature allowing for a proof that a signature existed at a given time (i.e., a timestamp). <ins> A CoSWID SHOULD be signed, using the above mechanism, to protect the integrity of the CoSWID tag.  See the security considerations (in sec-sec) for more information on why a signed CoSWID is valuable in most cases. </ins> 8. This specification allows for tagged and untagged CBOR data items


A tag is considered "authoritative" if the CoSWID tag was created by the software provider.  An authoritative CoSWID tag contains <del> information about a software component provided by the maintainer of </del>  the software component, who is expected to be an expert in their own <del> software.  Thus, authoritative CoSWID tags can be trusted to represent authoritative information about the software component. </del>  A signed CoSWID tag (see coswid-cose) whose signature has been validated can be relied upon to be unchanged since it was signed.  By <del> contrast, the data contained in unsigned tags cannot be trusted to be unmodified. When an authoritative tag is signed, the software provider can be authenticated as the originator of the signature.  A trustworthy association between the signature and the originator of the signature can be established via trust anchors.  A certification path between a trust anchor and a certificate including a pub-key enabling the validation of a tag signature can realize the assessment of trustworthiness of an authoritative tag.  Having a signed authoritative CoSWID tag can be useful when the information in the tag needs to be trusted, such as when the tag is being used to convey reference integrity measurements for software components. </del>  CoSWID tags are intended to contain public information about software components and, as such, the contents of a CoSWID tag does not need

A tag is considered "authoritative" if the CoSWID tag was created by the software provider.  An authoritative CoSWID tag contains  <ins> information about a software component provided by the supplier of </ins> the software component, who is expected to be an expert in their own  <ins> software.  Thus, authoritative CoSWID tags can represent authoritative information about the software component.  The degree to which this information can be trusted depends on the tag's chain of custody and the ability to verify a signature provided by the supplier if present in the CoSWID tag.  The provisioning and validation of CoSWID tags are handled by local policy and is outside the scope of this document. </ins> A signed CoSWID tag (see coswid-cose) whose signature has been validated can be relied upon to be unchanged since it was signed.  By  <ins> contrast, the data contained in unsigned tags can be altered by any user or process with write-access to the tag.  To support signature validation, there is the need associate the right key with the software provider or party originating the signature.  This operation is application specific and needs to be addressed by the application or a user of the application; a specific approach for which is out- of-scope for this document. When an authoritative tag is signed, the originator of the signature can be verified.  A trustworthy association between the signature and the originator of the signature can be established via trust anchors. A certification path between a trust anchor and a certificate including a public key enabling the validation of a tag signature can realize the assessment of trustworthiness of an authoritative tag. Verifying that the software provider is the signer is a different matter.  This requires an association between the signature and the tag's entity item associated corresponding to the software provider. No mechanism is defined in this draft to make this association; therefore, this association will need to be handled by local policy. </ins> CoSWID tags are intended to contain public information about software components and, as such, the contents of a CoSWID tag does not need


do this, CoSWID tags can be created by any party and the CoSWID tags collected from an endpoint could contain a mixture of vendor and non- vendor created tags.  For this reason, a CoSWID tag might contain <del> potentially malicious content.  Input sanitization and loop detection are two ways that implementations can address this concern. </del>  10.

do this, CoSWID tags can be created by any party and the CoSWID tags collected from an endpoint could contain a mixture of vendor and non- vendor created tags.  For this reason, a CoSWID tag might contain  <ins> potentially malicious content.  Input sanitization, loop detection, and signature verification are ways that implementations can address this concern. </ins> 10.


Aligned excerpt examples in I-D text with full CDDL <del> Fixed titels where title was referring to group instead of map </del>  <del> Added missig date in SEMVER </del>  Fixed root cardinality for file and directory, etc.

Aligned excerpt examples in I-D text with full CDDL  <ins> Fixed titles where title was referring to group instead of map </ins>  <ins> Added missing date in SEMVER </ins> Fixed root cardinality for file and directory, etc.


This interaction is often limited to signaling between the record layer and the handshake layer. <del> ESP </del>  Mobility Events (ME): The record protocol can be signaled that it is being migrated to another transport or interface due to

Completes
We collapsed IKEv2 and ESP into IPsec. Should we remove ESP from feature lists, e.g., the list of protocols that support PSK import?
Agreed, we should make sure this is consistent. One of our features, Key Expiration, currently only mentions ESP though. Is this actually an IPsec feature now, do we remove the feature, or is there another solution?

This interaction is often limited to signaling between the record layer and the handshake layer.  <ins> IPsec </ins> Mobility Events (ME): The record protocol can be signaled that it is being migrated to another transport or interface due to


4. There exists a common set of features shared across the transport <del> protocols surveyed in this document.  The mandatory features should be provided by any transport security protocol, while the optional features are extensions that a subset of the protocols provide.  For clarity, we also distinguish between handshake and record features. </del>  4.1. <del> 4.1.1. </del>  <del> Forward-secure segment encryption and authentication: Transit data must be protected with an authenticated encryption algorithm. </del>  Private key interface or injection: Authentication based on public key signatures is commonplace for many transport security

…/security and security/transport dependencies.
NAME can you please take a look before Wednesday?
Yep, I will review Monday morning.
I think this is fine. We can do further tweaks in subsequent PRs.

4. There exists a common set of features shared across the transport  <ins> protocols surveyed in this document.  Mandatory features constitute a baseline of functionality that an application may assume for any TAPS implementation.  Optional features by contrast may vary from implementation to implementation, and so an application cannot simply assume they are available.  Applications learn of and use optional features by querying for their presence and support.  Optional features may not be implemented, or may be disabled if their presence impacts transport services or if a necessary transport service is unavailable. </ins> 4.1.  <ins> Segment encryption and authentication: Transit data must be protected with an authenticated encryption algorithm. </ins>  <ins> Forward-secure key establishment: Negotiated keying material must come from an authenticated, forward-secure key exchange protocol. </ins> Private key interface or injection: Authentication based on public key signatures is commonplace for many transport security


connection must be authenticated before any data is sent to said party. <del> Source validation: Source validation must be provided to mitigate server-targeted DoS attacks.  This can be done with puzzles or cookies. 4.1.2. Pre-shared key support: A record protocol must be able to use a pre-shared key established out-of-band to encrypt individual messages, packets, or datagrams. </del>  4.2. <del> 4.2.1. </del> Mutual authentication: Transport security protocols must allow each endpoint to authenticate the other if required by the application.  Application-layer feature negotiation: The type of application using a transport security protocol often requires features configured at the connection establishment layer, e.g., ALPN

connection must be authenticated before any data is sent to said party.  <ins> Pre-shared key support: A security protocol must be able to use a pre-shared key established out-of-band or from a prior session to encrypt individual messages, packets, or datagrams. </ins> 4.2.  Mutual authentication: Transport security protocols must allow each endpoint to authenticate the other if required by the application. <ins> Transport dependency: None. Application dependency: Mutual authentication required for application support. Connection mobility: Sessions should not be bound to a network connection (or 5-tuple).  This allows cryptographic key material and other state information to be reused in the event of a connection change.  Examples of this include a NAT rebinding that occurs without a client's knowledge. Transport dependency: Connections are unreliable or can change due to unpredictable network events, e.g., NAT re-bindings. Application dependency: None. Source validation: Source validation must be provided to mitigate server-targeted DoS attacks.  This can be done with puzzles or cookies. Transport dependency: Packets may arrive as datagrams instead of streams from unauthenticated sources. Application dependency: None. </ins> Application-layer feature negotiation: The type of application using a transport security protocol often requires features configured at the connection establishment layer, e.g., ALPN


mechanism to allow for such application-specific features and options to be configured or otherwise negotiated.  Configuration extensions: The protocol negotiation should be extensible with addition of new configuration options.  Session caching and management: Sessions should be cacheable to enable reuse and amortize the cost of performing session establishment handshakes. <del> 4.2.2. </del>  <del> Connection mobility: Sessions should not be bound to a network connection (or 5-tuple).  This allows cryptographic key material and other state information to be reused in the event of a connection change.  Examples of this include a NAT rebinding that occurs without a client's knowledge. </del>  5. This section describes the interface surface exposed by the security <del> protocols described above, with each interface.  Note that not all protocols support each interface. </del>  5.1.

mechanism to allow for such application-specific features and options to be configured or otherwise negotiated. <ins> Transport dependency: None. Application dependency: Specification of application-layer features or functionality. </ins> Configuration extensions: The protocol negotiation should be extensible with addition of new configuration options. <ins> Transport dependency: None. Application dependency: Specification of application-specific extensions. </ins> Session caching and management: Sessions should be cacheable to enable reuse and amortize the cost of performing session establishment handshakes.  <ins> Transport dependency: None. </ins>  <ins> Application dependency: None. </ins> 5. This section describes the interface surface exposed by the security  <ins> protocols described above.  Note that not all protocols support each interface.  We partition these interfaces into pre-connection (configuration), connection, and post-connection interfaces. </ins> 5.1.


key exchange, signatures, and ciphersuites. Protocols: TLS, DTLS, QUIC + TLS, MinimalT, tcpcrypt, IKEv2, SRTP <del> Session Cache The application provides the ability to save and retrieve session state (such as tickets, keying material, and server parameters) that may be used to resume the security session. </del>  Protocols: TLS, DTLS, QUIC + TLS, MinimalT Authentication Delegation

key exchange, signatures, and ciphersuites. Protocols: TLS, DTLS, QUIC + TLS, MinimalT, tcpcrypt, IKEv2, SRTP  <ins> Session Cache Management The application provides the ability to save and retrieve session state (such as tickets, keying material, and server parameters) that may be used to resume the security session. </ins> Protocols: TLS, DTLS, QUIC + TLS, MinimalT Authentication Delegation


provide authentication, using EAP for example. Protocols: IKEv2, SRTP <del> 5.2. </del>  <del> Handshake interfaces are the points of interaction between a handshake protocol and the application, record protocol, and transport once the handshake is active. </del>  <del> Send Handshake Messages The handshake protocol needs to be able to send messages over a transport to the remote peer to establish trust and to negotiate keys. Protocols: All (TLS, DTLS, QUIC + TLS, MinimalT, CurveCP, IKEv2, WireGuard, SRTP (DTLS)) </del>  <del> Receive Handshake Messages The handshake protocol needs to be able to receive messages from the remote peer over a transport to establish trust and to negotiate keys. Protocols: All (TLS, DTLS, QUIC + TLS, MinimalT, CurveCP, IKEv2, WireGuard, SRTP (DTLS)) </del>  Identity Validation During a handshake, the security protocol will conduct identity

provide authentication, using EAP for example. Protocols: IKEv2, SRTP  <ins> Pre-Shared Key Import Either the handshake protocol or the application directly can supply pre-shared keys for the record protocol use for encryption/ decryption and authentication.  If the application can supply keys directly, this is considered explicit import; if the handshake protocol traditionally provides the keys directly, it is considered direct import; if the keys can only be shared by the handshake, they are considered non-importable. </ins>  <ins> Explict import: QUIC, ESP Direct import: TLS, DTLS, MinimalT, tcpcrypt, WireGuard </ins>  <ins> Non-importable: CurveCP </ins>  <ins> 5.2. </ins> Identity Validation During a handshake, the security protocol will conduct identity


involves sending a cookie exchange to avoid DoS attacks. Protocols: QUIC + TLS, DTLS, WireGuard  Key Update The handshake protocol may be instructed to update its keying material, either by the application directly or by the record protocol sending a key expiration event. Protocols: TLS, DTLS, QUIC + TLS, MinimalT, tcpcrypt, IKEv2 <del> Pre-Shared Key Export The handshake protocol will generate one or more keys to be used for record encryption/decryption and authentication.  These may be explicitly exportable to the application, traditionally limited to direct export to the record protocol, or inherently non-exportable because the keys must be used directly in conjunction with the record protocol. </del>  Explict export: TLS (for QUIC), tcpcrypt, IKEv2, DTLS (for SRTP)

involves sending a cookie exchange to avoid DoS attacks. Protocols: QUIC + TLS, DTLS, WireGuard <ins> 5.3. Connection Termination The security protocol may be instructed to tear down its connection and session information.  This is needed by some protocols to prevent application data truncation attacks. Protocols: TLS, DTLS, QUIC + TLS, MinimalT, tcpcrypt, IKEv2 </ins> Key Update The handshake protocol may be instructed to update its keying material, either by the application directly or by the record protocol sending a key expiration event. Protocols: TLS, DTLS, QUIC + TLS, MinimalT, tcpcrypt, IKEv2  <ins> Pre-Shared Key Export The handshake protocol will generate one or more keys to be used for record encryption/decryption and authentication.  These may be explicitly exportable to the application, traditionally limited to direct export to the record protocol, or inherently non-exportable because the keys must be used directly in conjunction with the record protocol. </ins> Explict export: TLS (for QUIC), tcpcrypt, IKEv2, DTLS (for SRTP)


Non-exportable: CurveCP <del> 5.3. Record interfaces are the points of interaction between a record protocol and the application, handshake protocol, and transport once in use. Pre-Shared Key Import Either the handshake protocol or the application directly can supply pre-shared keys for the record protocol use for encryption/ decryption and authentication.  If the application can supply keys directly, this is considered explicit import; if the handshake protocol traditionally provides the keys directly, it is considered direct import; if the keys can only be shared by the handshake, they are considered non-importable. Explict import: QUIC, ESP Direct import: TLS, DTLS, MinimalT, tcpcrypt, WireGuard Non-importable: CurveCP Encrypt application data The application can send data to the record protocol to encrypt it into a format that can be sent on the underlying transport.  The encryption step may require that the application data is treated as a stream or as datagrams, and that the transport to send the encrypted records present a stream or datagram interface. Stream-to-Stream Protocols: TLS, tcpcrypt Datagram-to-Datagram Protocols: DTLS, ESP, SRTP, WireGuard Stream-to-Datagram Protocols: QUIC ((Editor's Note: This depends on the interface QUIC exposes to applications.)) Decrypt application data The application can receive data from its transport to be decrypted using record protocol.  The decryption step may require that the incoming transport data is presented as a stream or as datagrams, and that the resulting application data is a stream or datagrams. Stream-to-Stream Protocols: TLS, tcpcrypt Datagram-to-Datagram Protocols: DTLS, ESP, SRTP, WireGuard Datagram-to-Stream Protocols: QUIC ((Editor's Note: This depends on the interface QUIC exposes to applications.)) </del> Key Expiration The record protocol can signal that its keys are expiring due to reaching a time-based deadline, or a use-based deadline (number of

Non-exportable: CurveCP  Key Expiration The record protocol can signal that its keys are expiring due to reaching a time-based deadline, or a use-based deadline (number of


more on this, as well as https://mailarchive.ietf.org/arch/msg/tls/ TugB5ddJu3nYg7chcyeIyUqWSbA.]]  2.1.1. To be compatible with the specializations described in this section,

This PR looks good to me.
cTLS enumerates keys in the template, but does not explain how templates can be extended. Suggestion: Clients must reject the whole template if it contains any key they do not understand. The “optional” key holds a map of optional extensions that are safe to ignore.
Thanks for addressing your own issue with a PR. Creating an IANA registry for the keys used in the configuration data makes sense. I would, however, like to point out (and maybe we need to make this explicit) that the configuration information is defined for convenience but is not a mandatory-to-implement functionality for a stack.
Sure, some use cases can pre-arrange, or even hardcode, a specific configuration through a nonstandard channel. Some use cases (where the client and server are developed separately) obviously cannot.

more on this, as well as https://mailarchive.ietf.org/arch/msg/tls/ TugB5ddJu3nYg7chcyeIyUqWSbA.]] <ins> contains keys that are not required to be understood by the client.  Server operators MUST NOT place a key in this section unless the server is able to determine whether the key is in use based on the client data it receives.  A key MUST NOT appear in both the main template and the optional section. </ins> 2.1.1. To be compatible with the specializations described in this section,


6.  This document requests that a code point be allocated from the "TLS ContentType registry.  This value must be in the range 0-31 (inclusive).  The row to be added in the registry has the following

6. <ins> 6.1. </ins> This document requests that a code point be allocated from the "TLS ContentType registry.  This value must be in the range 0-31 (inclusive).  The row to be added in the registry has the following


[[OPEN ISSUE: Should we require standards action for all profile IDs that would fit in 2 octets.]] <ins> 6.2. This document requests that IANA open a new registry entitled "cTLS Template Keys", on the Transport Layer Security (TLS) Parameters page, with a "Specification Required" registration policy and the following initial contents: </ins>


https://mailarchive.ietf.org/arch/msg/tls/ TugB5ddJu3nYg7chcyeIyUqWSbA.  contains keys that are not required to be understood by the client.  Server operators MUST NOT place a key in this section unless the server is able to determine whether the key is in use

FYI, this PR now moves out of the ClientHello back into (now called ). This avoids confusing questions about how to demultiplex profiles that use different modes.
LGTM.
This would allow recipients to detect the end of a handshake message from the CTLSPlaintext header alone, allowing the recipient to reconstruct the entire handshake message before parsing it. Currently, a streaming parser is required in order to detect the end. Suggested implementation: Senders set contenttype = ctlshandshake_end for a message’s final fragment.
I can see why you want that, but it's not generally a TLS property, and I'm reluctant to change things.
AFAIK, TLS does not require a streaming ClientHello parser. The recipient can read (uint24) and then buffer the remainder before parsing. cTLS, as currently specified, does not have . This means that the recipient has to cross all the way down into the extension parsing code before it finds out that the ClientHello is still incomplete. Given the complex template-driven handshake parsing code, I think making a streaming parser required is ill-advised. Given the desire for compactness, I think a flag of some kind on the final handshake message record seems like a reasonable solution, replacing the uint24 length. It would also simplify Pseudorandom cTLS. However, if that's not appealing, you could simply reintroduce .
NAME proposed a solution on slide 5 : I'm fine with that, so long as it doesn't end up requiring recipients to do something heroic to reconstruct the ClientHello. Thus, "framing = none" should imply that messages cannot be fragmented at all (max size limited to 2^14-1). I'm not sure I see the utility of the explicit distinction between "length" and "full". Surely "length" is not usable with DTLS due to reordering, and "full" is redundant in TLS/TCP. Perhaps we only need a single bit to enable/disable framing, and length-vs-full can be implicit from the transport.
I could live with this. Objections?
Solved by
The current text doesn’t mention this, although it seems relatively clear how it’s expected to work (using the DTLS Handshake struct).

https://mailarchive.ietf.org/arch/msg/tls/ TugB5ddJu3nYg7chcyeIyUqWSbA. <ins> If true, handshake messages MUST be conveyed inside a "Handshake" (RFC8446, Section 4) struct on stream transports, or a "DTLSHandshake" (RFC9147, Section 5.2) struct on datagram transports, and MAY be broken into multiple records as in TLS and DTLS.  Otherwise, each handshake message is conveyed in a "CTLSHandshake" or "CTLSDatagramHandshake" struct (ctlshandshake), which MUST be the payload of a single record. </ins> contains keys that are not required to be understood by the client.  Server operators MUST NOT place a key in this section unless the server is able to determine whether the key is in use


value to distinguish cTLS plaintext records from encrypted records, TLS/DTLS records, and other protocols using the same 5-tuple.  Encrypted records use DTLS 1.3 RFC9147 record framing, comprising a configuration octet followed by optional connection ID, sequence number, and length fields.  The encryption process and additional

value to distinguish cTLS plaintext records from encrypted records, TLS/DTLS records, and other protocols using the same 5-tuple. <ins> The "profile_id" field MUST identify the profile that is in use.  A zero-length ID corresponds to the cTLS default protocol.  The server's reply does not include the "profile_id", because the server must be using the same profile indicated by the client. </ins> Encrypted records use DTLS 1.3 RFC9147 record framing, comprising a configuration octet followed by optional connection ID, sequence number, and length fields.  The encryption process and additional


2.3. <del> The cTLS handshake framing is same as the TLS 1.3 handshake framing, except for two changes: The length field is omitted. The HelloRetryRequest message is a true handshake message instead of a specialization of ServerHello. </del>  3. <del> In general, we retain the basic structure of each individual TLS handshake message.  However, the following handshake messages have been modified for space reduction and cleaned up to remove pre-TLS 1.3 baggage. </del>  3.1. The cTLS ClientHello is defined as follows. <del> The "profile_id" field MUST identify the profile that is in use.  A zero-length ID corresponds to the cTLS default protocol. </del> 3.2. We redefine ServerHello in the following way. 3.3. <del> The HelloRetryRequest has the following format. </del>  The HelloRetryRequest is the same as the ServerHello above but without the unnecessary sentinel Random value.

2.3.  <ins> When "template.handshakeFraming" is not "true", cTLS uses a custom handshake framing that saves space by relying on the record layer for message lengths.  (This saves 3 bytes per message compared to TLS, or 9 bytes compared to DTLS.)  This compact framing is defined by the "CTLSHandshake" and "CTLSDatagramHandshake" structs. Any handshake type registered in the IANA TLS HandshakeType Registry can be conveyed in a "CTLS[Datagram]Handshake", but not all messages are actually allowed on a given connection.  This definition shows the messages types supported in "CTLSHandshake" as of TLS 1.3 and DTLS 1.3, but any future message types are also permitted. Each "CTLSHandshake" or "CTLSDatagramHandshake" MUST be conveyed as a single "CTLSClientPlaintext.fragment", "CTLSServerPlaintext.fragment", or "CTLSCiphertext.encrypted_record", and is therefore limited to a maximum length of "2^16-1" or less. When operating over UDP, large "CTLSDatagramHandshake" messages will also require the use of IP fragmentation, which is sometimes undesirable.  Operators can avoid these concerns by setting "template.handshakeFraming = true". </ins> 3.  <ins> In general, we retain the basic structure of each individual TLS or DTLS handshake message.  However, the following handshake messages have been modified for space reduction and cleaned up to remove pre- TLS 1.3 baggage. </ins> 3.1. The cTLS ClientHello is defined as follows.  3.2. We redefine ServerHello in the following way. 3.3.  <ins> In cTLS, the HelloRetryRequest message is a true handshake message instead of a specialization of ServerHello.  The HelloRetryRequest has the following format. </ins> The HelloRetryRequest is the same as the ServerHello above but without the unnecessary sentinel Random value.


6.3.  This document requests that IANA open a new registry entitled "Well- known cTLS Profile IDs", on the Transport Layer Security (TLS) Parameters page, with the following columns:

6.3. <ins> This document requests that IANA change the name of entry 6 in the TLS HandshakeType Registry from "hello_retry_request_RESERVED" to "hello_retry_request", and set its Reference field to this document. 6.4. </ins> This document requests that IANA open a new registry entitled "Well- known cTLS Profile IDs", on the Transport Layer Security (TLS) Parameters page, with the following columns:


Omitting the fields and handshake messages required for preserving backwards-compatibility with earlier TLS versions. <del> More compact encodings, for example point compression. </del>  A template-based specialization mechanism that allows pre- populating information at both endpoints without the need for negotiation. <del> Alternative cryptographic techniques, such as semi-static Diffie- Hellman. OPEN ISSUE: Semi-static and point compression are never mentioned again. </del>  For the common (EC)DHE handshake with pre-established certificates, Stream cTLS achieves an overhead of 53 bytes over the minimum

We have decided to moved the compressed elliptic curve representations to an external draft since the issue is equally applicable to regular TLS/DTLS and does not need to be cTLS specific.
NAME It looks like you need to run .
It seems that we have consensus to move compressed representations into new IANA codepoints, rather than try to reuse the existing codepoints with a template-driven encoding. That would make the question of compressed representations orthogonal to cTLS, so this topic can be removed from the draft.
Fixed by

Omitting the fields and handshake messages required for preserving backwards-compatibility with earlier TLS versions.  <ins> More compact encodings. </ins> A template-based specialization mechanism that allows pre- populating information at both endpoints without the need for negotiation.  <ins> Alternative cryptographic techniques, such as nonce truncation. </ins> For the common (EC)DHE handshake with pre-established certificates, Stream cTLS achieves an overhead of 53 bytes over the minimum


"encrypted_server_name" extension.  If the client does not retry in either scenario, it MUST report an error to the calling application.  5.1.3. When the server cannot decrypt or does not process the

NAME NAME please have a look.
We also need to specify server-side HRR behavior, right? Specifically, the server MUST recheck the second ClientHello's ESNI extension before sending the server certificate, otherwise putting the key share into the AD field doesn't really mean anything. The attacker would be able to do a cut-and-paste thing. (We could also incorporate the nonce into key schedule, but that upsets the document's split mode use case.)
Yep! Thanks for bringing that up. I'll prepare text.
Thank you for the text. LGTM.

"encrypted_server_name" extension.  If the client does not retry in either scenario, it MUST report an error to the calling application. <ins> If the server sends a HelloRetryRequest in response to the ClientHello and the client can send a second updated ClientHello per the rules in RFC8446, the "encrypted_server_name" extension values which do not depend on the (possibly updated) ClientHello.KeyShareClientHello, i.e,, ClientEncryptedSNI.suite, ClientEncryptedSNI.key_share, and ClientEncryptedSNI.record_digest, MUST NOT change across ClientHello messages.  Moreover, ClientESNIInner.nonce and ClientESNIInner.realSNI MUST not change across ClientHello messages.  Informally, the values of all unencrypted extension information, as well as the inner extension plaintext, must be consistent between the first and second ClientHello messages. </ins> 5.1.3. When the server cannot decrypt or does not process the


existing registry for Alerts (defined in RFC8446), with the "DTLS-OK" column being set to "Y". <del> 8.3. IANA is requested to create an entry, ESNI(0xff9f), in the existing registry for Resource Record (RR) TYPEs (defined in RFC6895) with "Meaning" column value being set to "Encrypted SNI". </del>

Because this document now delegates the way the keys are advertised from the RRType ESNI to HTTPSSVC shouldn't the RRType Considerations be removed from this document.

existing registry for Alerts (defined in RFC8446), with the "DTLS-OK" column being set to "Y".  <ins> 9. When operating in Split Mode, backend servers will not have access to PaddedServerNameList.sni or ClientESNIInner.nonce without access to the ESNI keys or a way to decrypt ClientEncryptedSNI.encrypted_sni. One way to address this for a single connection, at the cost of having communication not be unmodified TLS 1.3, is as follows. Assume there is a shared (symmetric) key between the client-facing server and the backend server and use it to AEAD-encrypt Z and send the encrypted blob at the beginning of the connection before the ClientHello.  The backend server can then decrypt ESNI to recover the true SNI and nonce. 10. Alternative approaches to encrypted SNI may be implemented at the TLS or application layer.  In this section we describe several alternatives and discuss drawbacks in comparison to the design in this document. 10.1. 10.1.1. In this variant, TLS Client Hellos are tunneled within early data payloads belonging to outer TLS connections established with the client-facing server.  This requires clients to have established a previous session --- and obtained PSKs --- with the server.  The client-facing server decrypts early data payloads to uncover Client Hellos destined for the backend server, and forwards them onwards as necessary.  Afterwards, all records to and from backend servers are forwarded by the client-facing server - unmodified.  This avoids double encryption of TLS records. Problems with this approach are: (1) servers may not always be able to distinguish inner Client Hellos from legitimate application data, (2) nested 0-RTT data may not function correctly, (3) 0-RTT data may not be supported - especially under DoS - leading to availability concerns, and (4) clients must bootstrap tunnels (sessions), costing an additional round trip and potentially revealing the SNI during the initial connection.  In contrast, encrypted SNI protects the SNI in a distinct Client Hello extension and neither abuses early data nor requires a bootstrapping connection. 10.1.2. In this variant, client-facing and backend servers coordinate to produce "combined tickets" that are consumable by both.  Clients offer combined tickets to client-facing servers.  The latter parse them to determine the correct backend server to which the Client Hello should be forwarded.  This approach is problematic due to non- trivial coordination between client-facing and backend servers for ticket construction and consumption.  Moreover, it requires a bootstrapping step similar to that of the previous variant.  In contrast, encrypted SNI requires no such coordination. 10.2. 10.2.1. In this variant, clients request secondary certificates with CERTIFICATE_REQUEST HTTP/2 frames after TLS connection completion. In response, servers supply certificates via TLS exported authenticators I-D.ietf-tls-exported-authenticator in CERTIFICATE frames.  Clients use a generic SNI for the underlying client-facing server TLS connection.  Problems with this approach include: (1) one additional round trip before peer authentication, (2) non-trivial application-layer dependencies and interaction, and (3) obtaining the generic SNI to bootstrap the connection.  In contrast, encrypted SNI induces no additional round trip and operates below the application layer. 11. The design described here only provides encryption for the SNI, but not for other extensions, such as ALPN.  Another potential design would be to encrypt all of the extensions using the same basic structure as we use here for ESNI.  That design has the following advantages: It protects all the extensions from ordinary eavesdroppers If the encrypted block has its own KeyShare, it does not necessarily require the client to use a single KeyShare, because the client's share is bound to the SNI by the AEAD (analysis needed). It also has the following disadvantages: The client-facing server can still see the other extensions.  By contrast we could introduce another EncryptedExtensions block that was encrypted to the backend server and not the client-facing server. It requires a mechanism for the client-facing server to provide the extension-encryption key to the backend server (as in communicating-sni and thus cannot be used with an unmodified backend server. A conformant middlebox will strip every extension, which might result in a ClientHello which is just unacceptable to the server (more analysis needed). </ins>


encrypt the ClientHello.  See hpke-map for information on how a cipher suite maps to corresponding HPKE algorithm identifiers. <del> the largest name the server expects to support.  If the server supports arbitrary wildcard names, it SHOULD set this value to 256.  Clients SHOULD reject ESNIConfig as invalid if maximum_name_length is greater than 256. </del>  A list of extensions that the client can take into consideration when generating a Client Hello message.  The purpose of the field

I've tried to capture what I think is a reasonable way to handle padding now we've changed from ESNI->ECHO. If we could do something like this, that'd be better than what's in -06. Note that I'd be even happier if we entirely eliminated ECHOConfig.minimuminnerlength - I don't think it actually adds any value and it represents yet another way to get a configuration wrong.
Thanks for the fixes. On the general point, I think that if we keep the flexibility for the client to vary the inner/outer CH however it chooses, then we will also have to depend on clients to figure out how to pad well for whatever they do. If we constrain the inner/outer variance a lot, then we could do better. It also strikes me that the minimuminnerlength is sort of in tension with the idea of compression - if a server has to set the minimuminnerlength to 300ish to handle clients that don't compress, then clients that do compress either don't get the benefit or have to ignore the minimuminnerlength.
I don't think this PR works. The server does not have enough information to report a useful value, and the value the server reports is not useful to maintain good anonymity sets. The server does not know that the client supports some large extension or key share type (or lots of cipher suites, ALPN protocols, etc). are especially fun. It also doesn't know which extensions the client will compress from the outer ClientHello and which it will reencode. Conversely, the value the server sets isn't useful. If the client implementation has a smaller baseline compression and extensions, we waste bytes without much benefit. Worse, if the client implementation has a larger baseline compression and extensions, this PR regresses anonymity. The ClientHello will then exceed and we don't hide the lengths of the sensitive bits. Stepping back, we want to hide the distribution of ClientHelloInner lengths within some anonymity set. Most of the contributors to that length come from local client configuration: how many ciphers you support, what ALPN protocols, etc. The client is the one that knows, e.g., it sometimes asks servers for protocols A and B and sometimes for A and C. It largely has enough information to pad itself. The main exception is the server name. Realistically we need to trim anonymity sets down to colocated services, and the client doesn't know that distribution of names. Thus, we want servers to report the value in ECHOConfig. Maybe we'll need more such statistics later, which is what extensions are for. It's annoying this is a bit complicated, but we've signing up to encrypt far more things now. I should note this presumes an anonymity set of similarly-configured clients. I think, realistically, that's all we can say rigorous things about. It's nice to reduce visible artifacts of configuration, which is why we additionally round up to multiples of 16, but that's something we can burn into the protocol without ECHOConfig support.
Hiya, Sorry, not seeing that last. The PR just says (or was meant to say) to pad to some multiple of 16 in that case which I agree isn't much guidance, but does allow doing something that works. (As well as allowing things that don't work well;-) I agree that all this really needs to be driven by the client. Well, yes and no. I don't believe a server config is useful for that, (as I've argued before and still do;-) ISTM the max server name value will almost always be set to 254. May as well tell the client to pad as do that IMO. Not quite sure if I agree with that last para or not TBH! S.
Well, if we were satisfied just padding names to a multiple of 16, we wouldn't need any of this. We'd just say to pad to a multiple 16 and move on. :-) In the current name-focused spelling, the client is always able to apply a smarter padding decision based on the server's knowledge of the name distribution. With this PR, clients whose local configuration exceeds or is near lose this and hit the baseline multiple of 16 behavior. Clients whose local configuration is decently below do hide the name distribution, but using many more bytes than they would with the current text. We have some metrics in Chrome on the distribution of DNS names. It's nowhere near 254. But, regardless, if you don't believe a server config is even useful for the name and agree with me that other extensions ought to be client-driven, I'm confused, why this PR? This PR seems to go in the opposite direction. Hehe. Which part?
HIya, Yes. That's IMO the downside of having any server config. (To answer your question below, I prefer not having any server config at all but proposed this as I think it's better than draft-06.) Having also looked at some passive DNS stuff, I fully agree. But ISTM for many scenarios the entity that generates the ECHOConfig won't know the distribution of names in use (e.g. whoever configures OpenSSL won't, same with Apache etc.) so it's likely they'll have to go for whatever is the max (i.e. 254). Same is true for anyone with a wild-card server cert in play somewhere. See above. I'm trying for either a modest improvement over draft-06 or for us all to arrive at a real improvement by ditching the server config entirely:-) I like the last sentence. I think I dislike the 1st:-) Cheers, S.
It's not a downside of the draft-06 formulation, is it? The client learns something targeted to the name and can pad accordingly. Even with a wildcard server cert, the server should still know the distribution. For instance, isn't going to see anything terribly long most of the time. (Looks like the registration limit is 39 characters.) For reference, this is how long a 254-character hostname is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa In order to enjoy wide adoption, ECHO can't be too much of a waste of resources. I think it thus makes sense to target a different maximum here. I guess my view is that, because of this issue above, this is a regression over the draft-06 formulation, even though it looks more general.
Hiya, Draft-06 assumes that no other inner CH content has the property that server guidance will help. My claim is that that guidance is useless in practice, and therefore unnecessary. I think the server config'd length in the PR is a little less useless:-) Some servers will. Some will not. Many (most?) server ECHOConfig instances will make use of default settings. Those'll pick 254 because adding a new VirtualHost to an apache instance (or similar) won't be co-ordinated with making a new ECHOConfig in general. And even it it were, (but it won't!) we get a TTL's worth of mismatch. If we don't provide a way for clients to handle the case where the server config is too short, again servers will publish 254. I am more interested in random smaller web sites/hosters myself. I think ECHO should work for those as well as we can make it, (albeit with smaller anonymity sets), and this tie between web server config and ECHOConfig is just a bad plan for such. AFAIK, all current deployments do just that. To be fair, that's largely driven by CF's draft-02 deployment, but I think that backs up my argument that if there's a max, that'll almost always be chosen, which implies it's a useless field that leads to the inefficiency you note. Then it can't be the max:-) The 254 value matches the max for servername IIRC. Ok. We disagree. But what do you think the client should do? Draft-06 is IMO plainly incorrect in that it says to pad in a way that'd expose other lengths should those be sensitive. If your answer were pad the SNI to at least ECHOConfig.maximumname_length and then make the overall a multiple of 16, with as many added 16 octets blocks as the client chooses, then a) that's != draft-06 and b) is quite close to this PR and c) just failing if the actual SNI in the inner CH is longer than the config setting seems quite wrong to me and d) hardcodes the assumption that SNI is the only thing where the server may know better. Cheers, S.
If we come up with other places where server guidance is useful, that can be addressed with extensions. But, gotcha, I suppose that is where we disagree. I think server guidance on the overall ClientHello size is entirely useless, while server guidance on the name is may be useful. Agreed that it should also work for smaller things. I don't follow how this PR helps in that regard. It seems they still need to come up with a random value or a default, but now it's even less clear how to set it well. Er, yes, sorry I meant to say target a different public length. That is, 254 is so far from the maximum domain name in practice (As it should be! Hard length limits ought to be comfortably away from the actual requirement.), so padding up to it is wasteful. I think it would be better to pad up to a tighter value and, if we exceed it, accept that we only have the fallback multiple of 16 padding. (Or maybe a different strategy.) It does result in smaller anonymity sets in edge cases, but I think that a reasonable default tradeoff given other desires like broader deployment and not wasting too much of users' data. I'm thinking something along the lines of: For each field, determine how much it makes sense to pad given what kinds of things it sends. If it varies ALPN, maybe round up to the largest of those. Most of this can be determined without server help. For fields where server help is useful, like the name, apply that help. Right now it's simply a function. I'm also open to other strategies. Sum all that padding together. In order to generally reduce entropy across different kinds of clients, maybe apply some additional overall padding, like rounding up to a multiple of 16, which cuts down the state space by 16x and doesn't cost much. (Or maybe we should round up to the nearest ? That avoids higher resolution on longer values while bounding the fraction of bytes wasted by this step.) That said, it's worth keeping in mind that clients already vary quite a bit in the cleartext portions of the ClientHello. There's a bit of tension between wanting to look like the other clients and wanting to ship new security improvements. This is different from this PR because this PR asks the server to report a value including things it doesn't know anything about (how large the client-controlled parameters are). I don't quite follow (c). It seems this PR and the above proposal has roughly the same failure modes when something is too long. The difference is that 's failure mode is only tripped on particular long names (something the server knows the distribution of), while this PR's equivalent failure mode is based on factors outside the server control, yet the server is responsible for the value.
Clarification: this is for each field where the client doesn't reference the outer ClientHello. If the client wishes to do that, it means the client doesn't consider that field secret so there isn't anything to pad.
I like NAME suggested algorithm, as an ideal padding function requires input from both the client and server. (Ideally, servers would send padding recommendations for each extension that might vary specifically for them, such as the server name. They don't have insight into anything else, so clients need to make padding decisions based on local configuration.) NAME what do you think?
Could live with it, but still prefer no server config. I'm looking a bit at some numbers and will try make a concrete suggestion later today. If I don't get that done, it seems fair to accept NAME algo and move on. Cheers, S.
If we can get away with no server config, I'm also entirely happy with that. Fewer moving parts is always great. We certainly could do that by saying names are padded up to 254, but I think that's too wasteful. But if we're happy with some global set of buckets that makes everyone happy (be it multiples of 16, some funny exponential thing), great!
(trimming violently and responding slowly:-) So your steps 1-6 is a better scheme than draft-06. I still think step 2 would be better as something like: ECHOConfig contains maxnamelen as before but we RECOMMEND it be zero and a) if the name to be padded is longer than maxnamelen, then names will be padded as follows: P=32-(len(name)%32)+headsortails*32, or b) if the name to be padded is shorter than maxnamelen then we just do as the server asked and pad to that length. That (hopefully:-) means a default of "pad out to the next multiple of 32, then toss a coin and add another 32 if the coin landed as heads." If we landed somewhere there, I'd be happy to make this PR say that or to make a new one or whatever. According to some data I have the CDFs for names and for these padded lengths would be as follows: Len, CDF, Padded-CDF 32, 81.28, 40.64 64, 97.87, 89.57 96, 99.31, 98.59 128, 99.87, 99.59 That means that 81.28 of names are <32 octets long and 40.64% of name+namepadding will be 32 octets long. 97.87% of names are <64 octets and 89.57% of name+namepadding are 64 octets long. I think we should RECOMMEND setting maxnamelen to zero unless an ESNI key generator has a specific reason to set it to a non-zero value. ISTM the use-case for non-zero values is where the anonymity set has only a few very long names that with length differences of ECHO. I'm basically fine that we default to not serving that use-case wellmby default, as I don't believe it's real. (But I could be wrong;-) Cheers, S.
Could the sender always pad their packets to at least 1200 bytes or something, using an encrypted extension in the ClientHello? I don't understand the focus on server input to a padding function that would ideally fill out one packet.
NAME what's the value in adding zero or one 32B blocks after rounding? Why not just stick with what was done, say, in RFC8467? (We could make it read something like, "clients may add zero or one blocks." Either way, I'm more or less fine with the suggested change. Would you mind updating this PR to match?)
Per above, clients could use help from servers in choosing appropriate padding lengths. (Only servers know their name anonymity set.)
Hiya, Say if the anonymity set has lots of names <32 length (~81% of names in the data I have) but a small number between 32 and 64 (~16% in my data). Then this should disguise the use of the longer names at the expense of sending more octets. Would be v. happy to know if that made sense to others. Cheers, S.
A friendly amendment below (but one I think is important)... I think that last really needs to be "Only servers can know their name anonymity set. But many servers will not know that, either due to wildcard certs or because names/vhosts are added and removed all the time independent of whatever is in the DNS." Cheers, S.
It makes sense, I'm just not not sure it's worth the cost. That said, this will always be an imperfect solution, so I'm happy either way.
Yep. Me neither. It is cheaper than padding to 254 octets for everyone though;-) Partly, I'm not that sympathetic towards anyone who wants to hide a crazily-long server_name. OTOH, I guess there may be a few who can't easily change names so we probably ought try do something for 'em. Cheers, S.
Agree that only servers could know their name anonymity set. But what is the cost of always padding out the ClientHello so it approaches the MTU? Just trying to understand why the spec attempts to economize on the number of bytes in the ClientHello packet.
As far as I know, there's no reason other than folks might not want to always "waste" these bytes.
Padding the ClientHello up to an MTU isn't free. See the numbers here on what a 400-byte increase costs. URL Likewise, also from that post and a , post-quantum key shares will likely exceed a packet anyway. I think our padding scheme should be designed with that expectation in mind (e.g., the mechanism fails this because a PQ key share in the inner ClientHello will blow past the built-in server assumptions on client behavior). Canary builds of Chrome already have code for such a thing behind a flag. Edit: Added a link to the later experiment, which I'd forgotten was a separate post.
It's not quite clear what's going on in those results. For example, the mobile results are close to zero. Without seeing confidence intervals, and the distributions of the full packet sizes, I don't think this experiment settles this issue (although it could, with more detail). Also, is there a theory on /why/ 400 bytes might add latency? If we're going to design the padding mechanism with PQ key shares in mind, but not conventional ones, that should be in the document.
NAME would know the details of that experiment, but I don't think the idea that sending more bytes takes more time would be terribly surprising! :-P I don't think anyone's suggested designing without conventional key shares in mind. They are what's deployed today, after all. However, we shouldn't design only for a small unpadded ClientHello. PQ key shares will need larger ones. Session tickets also go in the ClientHello, and it's common for TLS servers to stick client certificates inside tickets, so you can already get large ones today already.
Let's assume the results for "SI" in the first link actually do show a significant delta. The question is whether per-packet costs dominate or per-byte costs do, and whether the experiment sometimes increased the number of packets (e.g. by sometimes bumping the ultimate ClientHello size above 1280). See Section 5.1 in URL for device performance metrics on bytes vs packets. Looking at the ClientHello traffic on my computer, I can see that Safari is sending ClientHello messages that are about 500-600 bytes. My copy of Chrome seems to be sending CurveCECPQ2 (16696?) shares, and its ClientHello messages are fragmented.
NAME will you be able to update this as above?
would the spec allow me to put an arbitrarily-sized extension in the encrypted part of the ClientHello? if so, I don't care about the padding schemes.
Yes, of course! The padding policies described here are guidance at best.
I've updated the PR to try reflect the discussion above. Please take a peek and see if it seems useful now.
This looks like the right idea. I'll review this again as well, but it's probably better to wait for NAME suggestions to be addressed.
Thanks for all the changes Chris. I think I've actioned all those as requested. If not, I tried, but failed:-)
NAME do you need any help moving this forward?
Doing other stuff today but feel free to take the text and then do more edits. Or I can look at it tomorrow. Either's fine by me. S.
Thanks for taking the time. None of my comments are strongly-held opinions (meaning they only need to be addressed at all if others agree that the issues are important).
Strong +1 to NAME -- thank you for the work here, NAME
NAME can you please resolve conflicts? NAME NAME can you please review?
Fair point. The argument I'd make for keeping this is that if an anonymity set has ~80% of names <32 octets, then if we do nothing, passive observation will probably reveal when the server name is in the longest ~20%. And I'd guess that only a few names in that set would be popular/common, so we could be giving away the game whenever an ECHO is 32 octets longer than the usual. The random padding could mitigate that passive attack but yes would be vulnerable to an active reset based counter. I'd also be fine with just living with the issue in which case we might want to note that using ECHO with uncommonly long names is a bad idea.
Let's just drop the random addition. Servers don't (can't) do a padding check anyway, so clients can always choose to make this longer if desired.
NAME can you update this PR and resolve the conflicts?
"Fair point. The argument I'd make for keeping this is that if an anonymity set has ~80% of names <32 octets, then if we do nothing, passive observation will probably reveal when the server name is in the longest ~20%. " Which is precisely why we want the server to provide the longest name, so the client can pad to it.
As discussed on today's call, let's do the following: Resolve merge conflicts. Drop random padding for the SNI. And add text which says that if the client's name is larger than maxnamelength, it rounds up to the nearest 32B or 64B boundary. NAME do you need, or would you like, any help with this?
I think that this approach is generally better, but it runs afoul of divergence in client configuration that could dominate the calculation. For instance, a client that sends two key shares will have very different padding requirements to one that sends only one. For that to work, we need to assume that implementation-/deployment-specific variation of the inner CH is largely eliminated as a result of the compression scheme we adopt. That also assumes that these variations in client behaviour are not privacy-sensitive. I think that we should be directly acknowledging those assumptions if that is indeed the case. If there is a significant variation in size due to client-specific measures, then we're in a bit of an awkward position. That might render any similarly simple scheme ineffective. For instance, a client that later supports a set of ALPN identifiers that could vary in length depending on context cannot use this signal directly. It has to apply its own logic about the padding of that extension. That a client is doing this won't be known to a server that deploys this today. In that case, the advice from the server (which knows most about the anonymity set across which it is hoping to spread the resulting CH), isn't going to be forced through an additional filter at the client. The results are unlikely to be good without a great deal of care.I am generally fine with this, with the exception of the random padding, which I think should be omitted. It's hard to analyze and the value is unclear. In particular, many clients will retry if they receive TCP errors, and so the attacker can learn information about the true minimum value by forging TCP RSTs and looking at the new CH.

encrypt the ClientHello.  See hpke-map for information on how a cipher suite maps to corresponding HPKE algorithm identifiers.  <ins> The largest name the server expects to support, if known.  If this value is not known it can be set to zero, in which case clients SHOULD use the inner ClientHello padding scheme described below. That could happen if wildcard names are in use, or if names can be added or removed from the anonymity set during the lifetime of a particular resource record value. </ins> A list of extensions that the client can take into consideration when generating a Client Hello message.  The purpose of the field


an "echo_nonce" extension <del> TLS padding Padding SHOULD be P = L - D bytes, where L = ECHOConfig.maximum_name_length, rounded up to the nearest multiple of 16 D = len(dns_name), where dns_name is the DNS name in the ClientHelloInner "server_name" extension </del>  When offering an encrypted ClientHello, the client MUST NOT offer to resume any non-ECHO PSKs.  It additionally MUST NOT offer to resume

an "echo_nonce" extension  <ins> TLS padding RFC7685 (see section padding) </ins> When offering an encrypted ClientHello, the client MUST NOT offer to resume any non-ECHO PSKs.  It additionally MUST NOT offer to resume


7.2.  As described in server-behavior, the server MAY either accept ECHO and use ClientHelloInner or reject it and use ClientHelloOuter. However, there is no indication in ServerHello of which one the server has done and the client must therefore use trial decryption in order to determine this. <del> 7.2.1. </del>  If the server used ClientHelloInner, the client proceeds with the connection as usual, authenticating the connection for the origin server. <del> 7.2.2. </del>  If the server used ClientHelloOuter, the client proceeds with the handshake, authenticating for ECHOConfig.public_name as described in

7.2. <ins> Future extensions could reveal sensitive information through their length.  Consequently, padding should be flexible and support arbitrary extension changes. For each field in the inner ClientHello, clients need to determine how much to pad given the semantics of that field.  For example, if a client can propose various ALPN values, it could add padding to round up to the longest of those. The target padding length of most ClientHello extensions can be determined without server help.  However, the "server_name" extension could benefit from server input (ECHOConfig.maximum_name_length). Clients SHOULD compute the padding for this extension as follows: If ECHOConfig.maximum_name_length is longer than the actual server_name then clients SHOULD add padding to make up that difference. Otherwise, if ECHOConfig.maximum_name_length is zero or less than the length of the actual server_name then round the server_name up to a multiple of 32 octets and randomly add another 32 octets 50% of the time and then include that amount of additional padding. The amount of padding applied to the ClientHello is then computed as the sum of all per-extension padding values, rounded up to the nearest multiple of 32.  (This additional rounding step aims to hide variance across different client implementations.) In addition to padding ClientHelloInner, clients and servers will also need to pad all other handshake messages that have sensitive- length fields.  For example, if a client proposes ALPN values in ClientHelloInner, the server-selected value will be returned in an EncryptedExtension, so that handshake message also needs to be padded using TLS record layer padding. 7.3. </ins> As described in server-behavior, the server MAY either accept ECHO and use ClientHelloInner or reject it and use ClientHelloOuter. However, there is no indication in ServerHello of which one the server has done and the client must therefore use trial decryption in order to determine this.  <ins> 7.3.1. </ins> If the server used ClientHelloInner, the client proceeds with the connection as usual, authenticating the connection for the origin server.  <ins> 7.3.2. </ins> If the server used ClientHelloOuter, the client proceeds with the handshake, authenticating for ECHOConfig.public_name as described in


"encrypted_server_name" extension.  If the client does not retry in either scenario, it MUST report an error to the calling application. <del> 7.2.2.1. </del>  When the server cannot decrypt or does not process the "encrypted_server_name" extension, it continues with the handshake

"encrypted_server_name" extension.  If the client does not retry in either scenario, it MUST report an error to the calling application.  <ins> 7.3.2.1. </ins> When the server cannot decrypt or does not process the "encrypted_server_name" extension, it continues with the handshake


implemented, for instance, by reporting a failed connection with a dedicated error code. <del> 7.2.3. </del>  If the server sends a HelloRetryRequest in response to the ClientHello, the client sends a second updated ClientHello per the

implemented, for instance, by reporting a failed connection with a dedicated error code.  <ins> 7.3.3. </ins> If the server sends a HelloRetryRequest in response to the ClientHello, the client sends a second updated ClientHello per the


and this is easy to probe for, can we just instead have an extension to indicate what has happened.]] <del> 7.3. </del>  If the client attempts to connect to a server and does not have an ECHOConfig structure available for the server, it SHOULD send a

and this is easy to probe for, can we just instead have an extension to indicate what has happened.]]  <ins> 7.4. </ins> If the client attempts to connect to a server and does not have an ECHOConfig structure available for the server, it SHOULD send a


11.1. <del> In comparison to I-D.kazuho-protected-sni, wherein DNS Resource Records are signed via a server private key, ECHO records have no authenticity or provenance information.  This means that any attacker which can inject DNS responses or poison DNS caches, which is a common scenario in client access networks, can supply clients with fake ECHO records (so that the client encrypts data to them) or strip the ECHO record from the response.  However, in the face of an attacker that controls DNS, no encryption scheme can work because the attacker can replace the IP address, thus blocking client connections, or substituting a unique IP address which is 1:1 with the DNS name that was looked up (modulo DNS wildcards).  Thus, allowing the ECHO records in the clear does not make the situation significantly worse. Clearly, DNSSEC (if the client validates and hard fails) is a defense against this form of attack, but DoH/DPRIVE are also defenses against DNS attacks by attackers on the local network, which is a common case where ClientHello and SNI encryption are desired.  Moreover, as noted in the introduction, SNI encryption is less useful without encryption of DNS queries in transit via DoH or DPRIVE mechanisms. 11.2. Supporting optional record digests and trial decryption opens oneself up to DoS attacks.  Specifically, an adversary may send malicious ClientHello messages, i.e., those which will not decrypt with any known ECHO key, in order to force decryption.  Servers that support this feature should, for example, implement some form of rate limiting mechanism to limit the damage caused by such attacks. 11.3. ECHO 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. 11.4. I-D.ietf-tls-sni-encryption lists several requirements for SNI encryption.  In this section, we re-iterate these requirements and assess the ECHO design against them. 11.4.1. Since servers process either ClientHelloInner or ClientHelloOuter, and ClientHelloInner contains an HPKE-derived nonce, it is not possible for an attacker to "cut and paste" the ECHO value in a different Client Hello and learn information from ClientHelloInner. This is because the attacker lacks access to the HPKE-derived nonce used to derive the handshake secrets. 11.4.2. This design depends upon DNS as a vehicle for semi-static public key distribution.  Server operators may partition their private keys however they see fit provided each server behind an IP address has the corresponding private key to decrypt a key.  Thus, when one ECHO key is provided, sharing is optimally bound by the number of hosts that share an IP address.  Server operators may further limit sharing by publishing different DNS records containing ECHOConfig values with different keys using a short TTL. 11.4.3. This design requires servers to decrypt ClientHello messages with ClientEncryptedCH extensions carrying valid digests.  Thus, it is possible for an attacker to force decryption operations on the server.  This attack is bound by the number of valid TCP connections an attacker can open. 11.4.4. As more clients enable ECHO support, e.g., as normal part of Web browser functionality, with keys supplied by shared hosting providers, the presence of ECHO extensions becomes less suspicious and part of common or predictable client behavior.  In other words, if all Web browsers start using ECHO, the presence of this value does not signal suspicious behavior to passive eavesdroppers. Additionally, this specification allows for clients to send GREASE ECHO extensions (see grease-extensions), which helps ensure the ecosystem handles the values correctly. 11.4.5. This design is not forward secret because the server's ECHO key is static.  However, the window of exposure is bound by the key lifetime.  It is RECOMMENDED that servers rotate keys frequently. 11.4.6. This design permits servers operating in Split Mode to forward connections directly to backend origin servers, thereby avoiding unnecessary MiTM attacks. 11.4.7. Assuming ECHO 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 cleartext-dns for more details regarding cleartext DNS. Authenticating the ECHOConfigs structure naturally authenticates the included public name.  This also authenticates any retry signals from the server because the client validates the server certificate against the public name before retrying. 11.4.8. 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. 11.5. 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 backend server also only has one identity.  This does, however, change the situation slightly in that the backend server might previously have checked SNI and now cannot (and an attacker can route a connection with an encrypted SNI to any backend server and the TLS connection will still complete).  However, the client is still responsible for verifying the server's identity in its certificate. [[TODO: Some more analysis needed in this case, as it is a little odd, and probably some precise rules about handling ECHO and no SNI uniformly?]] 12. 12.1. </del> IANA is requested to create an entry, encrypted_server_name(0xffce), in the existing registry for ExtensionType (defined in RFC8446), with "TLS 1.3" column values being set to "CH, EE", and "Recommended" column being set to "Yes". <del> 12.2. </del>  IANA is requested to create an entry, echo_required(121) in the existing registry for Alerts (defined in RFC8446), with the "DTLS-OK"

11.1.  IANA is requested to create an entry, encrypted_server_name(0xffce), in the existing registry for ExtensionType (defined in RFC8446), with "TLS 1.3" column values being set to "CH, EE", and "Recommended" column being set to "Yes".  <ins> 11.2. </ins> IANA is requested to create an entry, echo_required(121) in the existing registry for Alerts (defined in RFC8446), with the "DTLS-OK"


has been unable to develop a completely generic solution.  I-D.ietf- tls-sni-encryption provides a description of the problem space and some of the proposed techniques.  One of the more difficult problems <del> is "Do not stick out" (I-D.ietf-tls-sni-encryption; Section 3.4): if </del>  only sensitive/private services use SNI encryption, then SNI encryption is a signal that a client is going to such a service.  For this reason, much recent work has focused on concealing the fact that

This addresses . cc NAME NAME NAME NAME NAME
This looks fine, though I'll note that since an HTTPSSVC record is public and the outer ClientHello record is public, it's not unreasonable to pull values from there to put in the public fields since the observer already knows (or can get) them. Restricting them to come only from the ECHOConfig seems unnecessary. I think the key observation in this PR is that the outer ClientHello isn't really offering to establish a TLS connection -- it's a not-crazy-looking wrapper for the actual ClientHello inside the ECHO extension, and the vehicle for the recovery flow. The only things a server can legitimately do are respond to the inner ClientHello or do a recovery handshake. Thus, most of the things you might set on the outer ClientHello are irrelevant; they can be chosen to look innocuous, chosen at random, or copied from the inner ClientHello as the implementation chooses.
NAME does this seem reasonable to you?
Seems reasonable.

has been unable to develop a completely generic solution.  I-D.ietf- tls-sni-encryption provides a description of the problem space and some of the proposed techniques.  One of the more difficult problems  <ins> is "Do not stick out" (I-D.ietf-tls-sni-encryption, Section 3.4): if </ins> only sensitive/private services use SNI encryption, then SNI encryption is a signal that a client is going to such a service.  For this reason, much recent work has focused on concealing the fact that


"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, <del> as shown here.  All TLS notation comes from RFC8446; Section 3. </del>  3.

"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals,  <ins> as shown here.  All TLS notation comes from RFC8446, Section 3. </ins> 3.


maximum_name_length is greater than 256. A list of extensions that the client can take into consideration <del> when generating a Client Hello message.  The purpose of the field is to provide room for additional features in the future.  The format is defined in RFC8446; Section 4.2.  The same interpretation rules apply: extensions MAY appear in any order, but there MUST NOT be more than one extension of the same type in the extensions block.  An extension may be tagged as mandatory by using an extension type codepoint with the high order bit set to 1.  A client which receives a mandatory extension they do not understand must reject the ECHOConfig content. </del>  Clients MUST parse the extension list and check for unsupported mandatory extensions.  If an unsupported mandatory extension is

maximum_name_length is greater than 256. A list of extensions that the client can take into consideration  <ins> when generating a ClientHello message.  The purpose of the field is to provide room for additional functionality in the future. See config-extensions for guidance on what type of extensions are appropriate for this structure. The format is defined in RFC8446, Section 4.2.  The same interpretation rules apply: extensions MAY appear in any order, but there MUST NOT be more than one extension of the same type in the extensions block.  An extension can be tagged as mandatory by using an extension type codepoint with the high order bit set to 1.  A client which receives a mandatory extension they do not understand MUST reject the ECHOConfig content. </ins> Clients MUST parse the extension list and check for unsupported mandatory extensions.  If an unsupported mandatory extension is


9.2. A more serious problem is MITM proxies which do not support this <del> extension.  RFC8446; Section 9.3 requires that such proxies remove </del>  any extensions they do not understand.  The handshake will then present a certificate based on the public name, without echoing the "encrypted_client_hello" extension to the client.

9.2. A more serious problem is MITM proxies which do not support this  <ins> extension.  RFC8446, Section 9.3 requires that such proxies remove </ins> any extensions they do not understand.  The handshake will then present a certificate based on the public name, without echoing the "encrypted_client_hello" extension to the client.


IANA is requested to create an entry, echo_required(121) in the existing registry for Alerts (defined in RFC8446), with the "DTLS-OK" column being set to "Y". <ins> 12. Any future information or hints that influence the outer ClientHello SHOULD be specified as ECHOConfig extensions, or in an entirely new version of ECHOConfig.  This is primarily because the outer ClientHello exists only in support of ECHO.  Namely, it is both an envelope for the encrypted inner ClientHello and enabler for authenticated key mismatch signals (see server-behavior).  In contrast, the inner ClientHello is the true ClientHello used upon ECHO negotiation. </ins>


match a value provided in the corresponding "ECHConfig.cipher_suites" list. <del> A cryptographic hash of the "ECHConfig" structure from which the ECH key was obtained, i.e., from the first byte of "version" to the end of the structure.  This hash is computed using the hash function associated with "cipher_suite", i.e., the corresponding HPKE KDF algorithm hash. </del>  The HPKE encapsulated key, used by servers to decrypt the corresponding "encrypted_ch" field.

Per NAME suggestion, this replaces computations involving the "hash underlying the KDF" with evaluation of the KDF itself. This respects the API defined in the HPKE draft. This supersedes .
Hey NAME and NAME I rolled up your changes! Please have another look before merging.
Rebased and rolled up.
Thanks -- let's let this stew until Friday, at which point we can merge.
Rebased.
Field is computed as "digest of the complete ClientHelloInner" (including presumably, the "outer_extensions" extension). I don't understand the analytical value of this hash. Can anyone explain its reasoning?
The hash is intended to prevent the attacker from influencing the reconstructed CHInner by manipulating CHOuter. Consider the contrived example of an extension which is separately protected but only works for SNI-A and not SNI-B. E.g., it's constructed by doing E(K_sni, SNI). If that extension were included in CHOuter and then imported into CHInner via this mechanism, then an attacker could substitute it and use a reaction attack to determine whether the CH referred to A or B. However, with the hash (which may be not well-specified), this attack gets caught by the client-facing server and the handshake is rejected without leaking information.
My initial understanding of this mechanism was incorrect. What happens is that the hash is computed over the ClientHelloInner that is consumed by the backend server. This is intended to ensure that if ECH accepts, then the backend server consumes the CH intended by the client. (PR URL makes this more clear, I think.) I wonder if this mechanism is redundant. Agreement on the CH between the client and backend server is provided by the binding of the transcript hash to the handshake traffic secret, so any attempt to manipulate the ClientHelloInner by fiddling with the ClientHelloOuter should be detected. On the other hand, the binding of the outer extensions to ClientHelloInner ensures agreement on the CH prior to the backend server consuming it. This is a strictly stronger property, which may or may not be useful. I agree that the attack works, but the example seems really contrived :) I'd be interested if there are more natural extensions for which this extra layer of security would be useful.
From the interim meeting, the consensus seems to be that we should err on the conservative side.
Let's close this issue and leave the mechanism as is.
Hrm, before closing I think it might be worth noting, in the spec, the stronger security property this provides.
I think we should also consider binding the CHInner to a hash of the whole CHOuter (minus the ClientEncryptedCH extension). That would have the same size overhead, but would give us a stronger property: modifying anything in CHOuter (not just one of the copied extensions) invalidates the whole thing.
The point of hashing outer extensions is to provide integrity of the ClientHelloInner. What would be the point in hashing more of the ClientHelloOuter? (Not a rhetorical question :) It seems conceptually different, and I'm curious what the security benefit might be.)
If we authenticate the ClientHelloOuter, we'd be authenticating all the inputs that go into the ClientHelloInner, so I think that would also provide integrity. I expect Ben is suggesting this in the context of URL, where GREASE can additionally be made a little stronger if we did that. Getting that to interact well with any PSK binders in ClientHelloOuter is tricky though, unless we decide to ban resumption attempts in outer ClientHellos. (Probably best to keep the GREASE-related conversation in one place. Though I see I didn't help on that front because some discussion is also in . Ah, GitHub.)
Yep, I'm just echoing NAME observation. See also URL
Today, the only thing that gets copied into ClientHelloInner is extensions, so I don't see how it's an improvement in terms of our primary security goal. (Not sure about the "don't stick out" benefit.)
I don't understand how hashing all of CHOuter is going to work. In split mode, the server never sees any of CHOuter.
Yes, the hash would be checked when reconstructing the inner ClientHello (as here), and would not be present in the reconstructed ClientHello.
There's not much discussion here. Unless there's objection, shall we leave the mechanism as-is and close out this issue? cc/ NAME
Works for me.
From Section 6.1: This assumes that the KDF specifies some underlying hash function. From the HPKE spec, it seems like all that's required of the KDF is that it's an "extract-then-expand" KDF: URL In fact, the currently assigned code points are all for HKDF: URL But there's no requirement that the KDF always have some underlying hash function. As an alternative to HKDF, one can imagine a dedicated primitive that satisfies the extract-then-expand API but is not constructed from a hash function.
Impacted fields: ClientEncryptedCH.record_digest URL
We can probably replace with and be done with it.
Putting on my theorist hat, I'd say that the extract function is a "randomness extractor" and not a collision resistant hash function. We want the latter in this context. From a practical stand point, using the extract function is more hashing than we need. I'd suggest doing away with (see ) and figuring something else out for . Could we simply require HKDF be used with HPKE?
Sure, but in practice randomness extractors use a collision resistant hash or PRF (CBC) under the hood. I don't think we can require HKDF for HPKE. That seems too restrictive. We might just say that ECH requires HKDF-based HPKE ciphersuites, as HKDF is already paramount for TLS 1.3, and then just reference HKDF's hash function.
addresses this issue.
As I mentioned on the list, we can use the KDF in place of a hash.
I tend to agree. I'll create a new PR.
Have a look at , NAME
Resolved in . Closing.

match a value provided in the corresponding "ECHConfig.cipher_suites" list.  <ins> Equal to "Expand(Extract("", config), "ech_config_digest", Nh)", where "config" is the "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.) </ins> The HPKE encapsulated key, used by servers to decrypt the corresponding "encrypted_ch" field.


When sending ClientHello, the client first computes ClientHelloInner, including any PSK binders, and then MAY substitute extensions which it knows will be duplicated in ClientHelloOuter.  To do so, the <del> client computes a hash of the entire ClientHelloInner message with the same hash as for the KDF used to encrypt ClientHelloInner.  Then, the client removes and replaces extensions from ClientHelloInner with a single "outer_extensions" extension.  The list of "outer_extensions" include those which were removed from </del>  ClientHelloInner, in the order in which they were removed.  The hash contains the full ClientHelloInner hash computed above.

When sending ClientHello, the client first computes ClientHelloInner, including any PSK binders, and then MAY substitute extensions which it knows will be duplicated in ClientHelloOuter.  To do so, the  <ins> client computes a hash of the entire ClientHelloInner message as: where "inner" is the ClientHelloInner structure and "Extract", "Expand", and "Nh" are as defined by the KDF API in I-D.irtf-cfrg- hpke.  Then, the client removes and replaces extensions from ClientHelloInner with a single "outer_extensions" extension.  The list of "outer_extensions" include those which were removed from </ins> ClientHelloInner, in the order in which they were removed.  The hash contains the full ClientHelloInner hash computed above.


server in the same session. Set the "config_digest" field to a randomly-generated string of <del> hash_length bytes, where hash_length is the length of the hash function associated with the chosen HpkeCipherSuite. </del>  Set the "enc" field to a randomly-generated valid encapsulated public key output by the HPKE KEM.

server in the same session. Set the "config_digest" field to a randomly-generated string of  <ins> "Nh" bytes, where "Nh" is the output length of the "Extract" function of the KDF associated with the chosen cipher suite.  (The KDF API is specified in I-D.irtf-cfrg-hpke.) </ins> Set the "enc" field to a randomly-generated valid encapsulated public key output by the HPKE KEM.


ClientEncryptedCH.encrypted_ch.  This matching procedure should be done using one of the following two checks: <del> Compare ClientEncryptedCH.config_digest against cryptographic hashes of known ECHConfig and choose the one that matches. </del>  Use trial decryption of ClientEncryptedCH.encrypted_ch with known ECHConfig and choose the one that succeeds.

ClientEncryptedCH.encrypted_ch.  This matching procedure should be done using one of the following two checks:  <ins> Compare ClientEncryptedCH.config_digest against digests of known ECHConfig and choose the one that matches. </ins> Use trial decryption of ClientEncryptedCH.encrypted_ch with known ECHConfig and choose the one that succeeds.


When a client wants to establish a TLS session with the backend server, it constructs its ClientHello as usual (we will refer to this as the ClientHelloInner message) and then encrypts this message using <del> the ECH public key.  It then constructs a new ClientHello (ClientHelloOuter) with innocuous values for sensitive extensions, e.g., SNI, ALPN, etc., and with the encrypted ClientHelloInner in an </del>  "encrypted_client_hello" extension, which this document defines <del> (encrypted-client-hello).  Finally, it sends ClientHelloOuter to the server. </del>  Upon receiving the ClientHelloOuter, the client-facing server takes one of the following actions:

In places, the current draft doesn't make a clear distinction between rejection and decryption failure. In particular "cannot decrypt" can be interpreted either: "the client-facing server doesn't recognize the configuration specified by the client"; or "the client-facing server recognizes the configuration but decryption fails". This change resolves this ambiguity. Addresses issue .
Two sections suggest to ignore the extension on decryption failure, but one suggests to send an alert. What should happen? Ignoring the extension on unrecognized failures sounds reasonable in order to "not stick out". However, it is not entirely unambiguous what to do if a valid ECHConfig is found but decryption fails. says: says: says:
I think the first two statements apply when the config_digest doesn't correspond to a known ECHConfig (i.e., "I can't decrypt this"); the last is when the ECHConfig is known, but decryption fails ("I should be able to decrypt this, but the ciphertext is invalid"). The text could be a lot clearer here.
NAME Yes, your interpretation is correct. I think this is the result of a number of uncoordinated changes.
Closing as resolved.

When a client wants to establish a TLS session with the backend server, it constructs its ClientHello as usual (we will refer to this as the ClientHelloInner message) and then encrypts this message using  <ins> the public key of the ECH configuration.  It then constructs a new ClientHello (ClientHelloOuter) with innocuous values for sensitive extensions, e.g., SNI, ALPN, etc., and with an </ins> "encrypted_client_hello" extension, which this document defines  <ins> (encrypted-client-hello).  The extension's payload carries the encrypted ClientHelloInner and specifies the ECH configuration used for encryption.  Finally, it sends ClientHelloOuter to the server. </ins> Upon receiving the ClientHelloOuter, the client-facing server takes one of the following actions:


"encrypted_client_hello" extension and proceeds with the handshake as usual, per RFC8446, Section 4.1.2. <del> If it supports ECH but cannot decrypt it, then it ignores the extension and proceeds with the handshake as usual.  This is </del>  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 can decrypt it, then 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 ECH was accepted or rejected and proceeds with the handshake

"encrypted_client_hello" extension and proceeds with the handshake as usual, per RFC8446, Section 4.1.2.  <ins> If it supports ECH but does not recognize the configuration specified by the client, then it ignores the extension and terminates the handshake using the ClientHelloOuter.  This is </ins> 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 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". </ins> Upon receiving the server's response, the client determines whether ECH was accepted or rejected and proceeds with the handshake


7.3.2.1. <del> When the server cannot decrypt or does not process the </del>  "encrypted_client_hello" extension, it continues with the handshake using the plaintext "server_name" extension instead (see server- behavior).  Clients that offer ECH then authenticate the connection

7.3.2.1.  <ins> When the server rejects ECH or otherwise ignores </ins> "encrypted_client_hello" extension, it continues with the handshake using the plaintext "server_name" extension instead (see server- behavior).  Clients that offer ECH then authenticate the connection