rfc9849v4.txt   rfc9849.txt 
skipping to change at line 76 skipping to change at line 76
6.1.4. Determining ECH Acceptance 6.1.4. Determining ECH Acceptance
6.1.5. Handshaking with ClientHelloInner 6.1.5. Handshaking with ClientHelloInner
6.1.6. Handshaking with ClientHelloOuter 6.1.6. Handshaking with ClientHelloOuter
6.1.7. Authenticating for the Public Name 6.1.7. Authenticating for the Public Name
6.1.8. Impact of Retry on Future Connections 6.1.8. Impact of Retry on Future Connections
6.2. GREASE ECH 6.2. GREASE ECH
6.2.1. Client Greasing 6.2.1. Client Greasing
6.2.2. Server Greasing 6.2.2. Server Greasing
7. Server Behavior 7. Server Behavior
7.1. Client-Facing Server 7.1. Client-Facing Server
7.1.1. Sending HelloRetryRequest 7.1.1. Processing ClientHello after HelloRetryRequest
7.2. Backend Server 7.2. Backend Server
7.2.1. Sending HelloRetryRequest 7.2.1. Sending HelloRetryRequest
8. Deployment Considerations 8. Deployment Considerations
8.1. Compatibility Issues 8.1. Compatibility Issues
8.1.1. Misconfiguration and Deployment Concerns 8.1.1. Misconfiguration and Deployment Concerns
8.1.2. Middleboxes 8.1.2. Middleboxes
8.2. Deployment Impact 8.2. Deployment Impact
9. Compliance Requirements 9. Compliance Requirements
10. Security Considerations 10. Security Considerations
10.1. Security and Privacy Goals 10.1. Security and Privacy Goals
skipping to change at line 433 skipping to change at line 433
enabler for authenticated key mismatch signals (see Section 7). In enabler for authenticated key mismatch signals (see Section 7). In
contrast, the inner ClientHello is the true ClientHello used upon ECH contrast, the inner ClientHello is the true ClientHello used upon ECH
negotiation. negotiation.
5. The "encrypted_client_hello" Extension 5. The "encrypted_client_hello" Extension
To offer ECH, the client sends an "encrypted_client_hello" extension To offer ECH, the client sends an "encrypted_client_hello" extension
in the ClientHelloOuter. When it does, it MUST also send the in the ClientHelloOuter. When it does, it MUST also send the
extension in ClientHelloInner. extension in ClientHelloInner.
~~ enum { encrypted_client_hello(0xfe0d), (65535) } ExtensionType; ~~ enum {
encrypted_client_hello(0xfe0d), (65535)
} ExtensionType;
The payload of the extension has the following structure: The payload of the extension has the following structure:
enum { outer(0), inner(1) } ECHClientHelloType; enum { outer(0), inner(1) } ECHClientHelloType;
struct { struct {
ECHClientHelloType type; ECHClientHelloType type;
select (ECHClientHello.type) { select (ECHClientHello.type) {
case outer: case outer:
HpkeSymmetricCipherSuite cipher_suite; HpkeSymmetricCipherSuite cipher_suite;
skipping to change at line 463 skipping to change at line 465
uses the inner variant. The inner extension has an empty payload, uses the inner variant. The inner extension has an empty payload,
which is included because TLS servers are not allowed to provide which is included because TLS servers are not allowed to provide
extensions in ServerHello which were not included in ClientHello. extensions in ServerHello which were not included in ClientHello.
The outer extension has the following fields: The outer extension has the following fields:
config_id: The ECHConfigContents.key_config.config_id for the chosen config_id: The ECHConfigContents.key_config.config_id for the chosen
ECHConfig. ECHConfig.
cipher_suite: The cipher suite used to encrypt ClientHelloInner. cipher_suite: The cipher suite used to encrypt ClientHelloInner.
This MUST match a value provided in the corresponding This MUST match a value provided in the corresponding
ECHConfigContents.cipher_suites list. ECHConfigContents.key_config.cipher_suites list.
enc: The HPKE encapsulated key used by servers to decrypt the enc: The HPKE encapsulated key used by servers to decrypt the
corresponding payload field. This field is empty in a corresponding payload field. This field is empty in a
ClientHelloOuter sent in response to HelloRetryRequest. ClientHelloOuter sent in response to HelloRetryRequest.
payload: The serialized and encrypted EncodedClientHelloInner payload: The serialized and encrypted EncodedClientHelloInner
structure, encrypted using HPKE as described in Section 6.1. structure, encrypted using HPKE as described in Section 6.1.
When a client offers the outer version of an "encrypted_client_hello" When a client offers the outer version of an "encrypted_client_hello"
extension, the server MAY include an "encrypted_client_hello" extension, the server MAY include an "encrypted_client_hello"
extension in its EncryptedExtensions message, as described in extension in its EncryptedExtensions message, as described in
Section 7.1, with the following payload: Section 7.1, with the following payload:
~~ struct { ECHConfigList retry_configs; } ECHEncryptedExtensions; ~~ struct {
ECHConfigList retry_configs;
} ECHEncryptedExtensions;
The response is valid only when the server used the ClientHelloOuter. The response is valid only when the server used the ClientHelloOuter.
If the server sent this extension in response to the inner variant, If the server sent this extension in response to the inner variant,
then the client MUST abort with an "unsupported_extension" alert. then the client MUST abort with an "unsupported_extension" alert.
retry_configs: An ECHConfigList structure containing one or more retry_configs: An ECHConfigList structure containing one or more
ECHConfig structures, in decreasing order of preference, to be ECHConfig structures, in decreasing order of preference, to be
used by the client as described in Section 6.1.6. These are known used by the client as described in Section 6.1.6. These are known
as the server's "retry configurations". as the server's "retry configurations".
Finally, when the client offers the "encrypted_client_hello", if the Finally, when the client offers the "encrypted_client_hello", if the
payload is the inner variant and the server responds with payload is the inner variant and the server responds with
HelloRetryRequest, it MUST include an "encrypted_client_hello" HelloRetryRequest, it MUST include an "encrypted_client_hello"
extension with the following payload: extension with the following payload:
~~ struct { opaque confirmation[8]; } ECHHelloRetryRequest; ~~ struct {
opaque confirmation[8];
} ECHHelloRetryRequest;
The value of ECHHelloRetryRequest.confirmation is set to The value of ECHHelloRetryRequest.confirmation is set to
hrr_accept_confirmation as described in Section 7.2.1. hrr_accept_confirmation as described in Section 7.2.1.
This document also defines the "ech_required" alert, which the client This document also defines the "ech_required" alert, which the client
MUST send when it offered an "encrypted_client_hello" extension that MUST send when it offered an "encrypted_client_hello" extension that
was not accepted by the server. (See Section 11.2.) was not accepted by the server. (See Section 11.2.)
5.1. Encoding the ClientHelloInner 5.1. Encoding the ClientHelloInner
Before encrypting, the client pads and optionally compresses Before encrypting, the client pads and optionally compresses
ClientHelloInner into an EncodedClientHelloInner structure, defined ClientHelloInner into an EncodedClientHelloInner structure, defined
below: below:
~~ struct { ClientHello client_hello; uint8 zeros[length_of_padding]; struct {
} EncodedClientHelloInner; ~~ ClientHello client_hello;
uint8 zeros[length_of_padding];
} EncodedClientHelloInner;
The client_hello field is computed by first making a copy of The client_hello field is computed by first making a copy of
ClientHelloInner and setting the legacy_session_id field to the empty ClientHelloInner and setting the legacy_session_id field to the empty
string. In TLS, this field uses the ClientHello structure defined in string. In TLS, this field uses the ClientHello structure defined in
Section 4.1.2 of [RFC8446]. In DTLS, it uses the ClientHello Section 4.1.2 of [RFC8446]. In DTLS, it uses the ClientHello
structure defined in Section 5.3 of [RFC9147]. This does not include structure defined in Section 5.3 of [RFC9147]. This does not include
Handshake structure's four-byte header in TLS, nor twelve-byte header the Handshake structure's four-byte header in TLS, nor the twelve-
in DTLS. The zeros field MUST be all zeroes of length byte header in DTLS. The zeros field MUST be all zeros of length
length_of_padding (see Section 6.1.3). length_of_padding (see Section 6.1.3).
Repeating large extensions, such as "key_share" with post-quantum Repeating large extensions, such as "key_share" with post-quantum
algorithms, between ClientHelloInner and ClientHelloOuter can lead to algorithms, between ClientHelloInner and ClientHelloOuter can lead to
excessive size. To reduce the size impact, the client MAY substitute excessive size. To reduce the size impact, the client MAY substitute
extensions which it knows will be duplicated in ClientHelloOuter. It extensions which it knows will be duplicated in ClientHelloOuter. It
does so by removing and replacing extensions from does so by removing and replacing extensions from
EncodedClientHelloInner with a single "ech_outer_extensions" EncodedClientHelloInner with a single "ech_outer_extensions"
extension, defined as follows: extension, defined as follows:
~~ enum { ech_outer_extensions(0xfd00), (65535) } ExtensionType; enum {
ech_outer_extensions(0xfd00), (65535)
} ExtensionType;
ExtensionType OuterExtensions<2..254>; ~~ ExtensionType OuterExtensions<2..254>;
OuterExtensions contains the removed ExtensionType values. Each OuterExtensions contains a list of the removed ExtensionType values.
value references the matching extension in ClientHelloOuter. The Each value references the matching extension in ClientHelloOuter.
values MUST be ordered contiguously in ClientHelloInner, and the The values MUST be ordered contiguously in ClientHelloInner, and the
"ech_outer_extensions" extension MUST be inserted in the "ech_outer_extensions" extension MUST be inserted in the
corresponding position in EncodedClientHelloInner. Additionally, the corresponding position in EncodedClientHelloInner. Additionally, the
extensions MUST appear in ClientHelloOuter in the same relative extensions MUST appear in ClientHelloOuter in the same relative
order. However, there is no requirement that they be contiguous. order. However, there is no requirement that they be contiguous.
For example, OuterExtensions may contain extensions A, B, and C, For example, OuterExtensions may contain extensions A, B, and C,
while ClientHelloOuter contains extensions A, D, B, C, E, and F. while ClientHelloOuter contains extensions A, D, B, C, E, and F.
The "ech_outer_extensions" extension can only be included in The "ech_outer_extensions" extension can only be included in
EncodedClientHelloInner and MUST NOT appear in either EncodedClientHelloInner and MUST NOT appear in either
ClientHelloOuter or ClientHelloInner. ClientHelloOuter or ClientHelloInner.
skipping to change at line 578 skipping to change at line 588
* "encrypted_client_hello" is referenced in OuterExtensions. * "encrypted_client_hello" is referenced in OuterExtensions.
* The extensions in ClientHelloOuter corresponding to those in * The extensions in ClientHelloOuter corresponding to those in
OuterExtensions do not occur in the same order. OuterExtensions do not occur in the same order.
These requirements prevent an attacker from performing a packet These requirements prevent an attacker from performing a packet
amplification attack by crafting a ClientHelloOuter which amplification attack by crafting a ClientHelloOuter which
decompresses to a much larger ClientHelloInner. This is discussed decompresses to a much larger ClientHelloInner. This is discussed
further in Section 10.12.4. further in Section 10.12.4.
Implementations SHOULD construct the ClientHelloInner in linear time. Receiving implementations SHOULD construct the ClientHelloInner in
Quadratic time implementations (such as may happen via naive copying) linear time. Quadratic time implementations (such as may happen via
create a denial-of-service risk. Appendix A describes a linear-time naive copying) create a denial-of-service risk. Appendix A describes
procedure that may be used for this purpose. a linear-time procedure that may be used for this purpose.
5.2. Authenticating the ClientHelloOuter 5.2. Authenticating the ClientHelloOuter
To prevent a network attacker from modifying the ClientHelloOuter To prevent a network attacker from modifying the ClientHelloOuter
while keeping the same encrypted ClientHelloInner (see while keeping the same encrypted ClientHelloInner (see
Section 10.12.3), ECH authenticates ClientHelloOuter by passing Section 10.12.3), ECH authenticates ClientHelloOuter by passing
ClientHelloOuterAAD as the associated data for HPKE sealing and ClientHelloOuterAAD as the associated data for HPKE sealing and
opening operations. The ClientHelloOuterAAD is a serialized opening operations. The ClientHelloOuterAAD is a serialized
ClientHello structure, defined in Section 4.1.2 of [RFC8446] for TLS ClientHello structure, defined in Section 4.1.2 of [RFC8446] for TLS
and Section 5.3 of [RFC9147] for DTLS, which matches the and Section 5.3 of [RFC9147] for DTLS, which matches the
ClientHelloOuter except that the payload field of the ClientHelloOuter except that the payload field of the
"encrypted_client_hello" is replaced with a byte string of the same "encrypted_client_hello" is replaced with a byte string of the same
length but whose contents are zeros. This value does not include length but whose contents are zeros. This value does not include the
Handshake structure's four-byte header in TLS nor twelve-byte header Handshake structure's four-byte header in TLS nor the twelve-byte
in DTLS. header in DTLS.
6. Client Behavior 6. Client Behavior
Clients that implement the ECH extension behave in one of two ways: Clients that implement the ECH extension behave in one of two ways:
either they offer a real ECH extension, as described in Section 6.1, either they offer a real ECH extension, as described in Section 6.1,
or they send a Generate Random Extensions And Sustain Extensibility or they send a Generate Random Extensions And Sustain Extensibility
(GREASE) [RFC8701] ECH extension, as described in Section 6.2. (GREASE) [RFC8701] ECH extension, as described in Section 6.2. The
Clients of the latter type do not negotiate ECH. Instead, they client offers ECH if it is in possession of a compatible ECH
configuration and sends GREASE ECH (see Section 6.2) otherwise.
Clients of the latter type do not negotiate ECH; instead, they
generate a dummy ECH extension that is ignored by the server. (See generate a dummy ECH extension that is ignored by the server. (See
Section 10.10.4 for an explanation.) The client offers ECH if it is Section 10.10.4 for an explanation.) It is also possible for clients
in possession of a compatible ECH configuration and sends GREASE ECH to always send GREASE ECH without implementing the remainder of this
(see Section 6.2) otherwise. specification.
6.1. Offering ECH 6.1. Offering ECH
To offer ECH, the client first chooses a suitable ECHConfig from the To offer ECH, the client first chooses a suitable ECHConfig from the
server's ECHConfigList. To determine if a given ECHConfig is server's ECHConfigList. To determine if a given ECHConfig is
suitable, it checks that it supports the KEM algorithm identified by suitable, it checks that it supports the KEM algorithm identified by
ECHConfig.contents.kem_id, at least one KDF/AEAD algorithm identified ECHConfig.contents.key_config.kem_id, at least one KDF/AEAD algorithm
by ECHConfig.contents.cipher_suites, and the version of ECH indicated identified by ECHConfig.contents.key_config.cipher_suites, and the
by ECHConfig.version. Once a suitable configuration is found, the version of ECH indicated by ECHConfig.version. Once a suitable
client selects the cipher suite it will use for encryption. It MUST configuration is found, the client selects the cipher suite it will
NOT choose a cipher suite or version not advertised by the use for encryption. It MUST NOT choose a cipher suite or version not
configuration. If no compatible configuration is found, then the advertised by the configuration. If no compatible configuration is
client SHOULD proceed as described in Section 6.2. found, then the client SHOULD proceed as described in Section 6.2.
Next, the client constructs the ClientHelloInner message just as it Next, the client constructs the ClientHelloInner message just as it
does a standard ClientHello, with the exception of the following does a standard ClientHello, with the exception of the following
rules: rules:
1. It MUST NOT offer to negotiate TLS 1.2 or below. This is 1. It MUST NOT offer to negotiate TLS 1.2 or below. This is
necessary to ensure the backend server does not negotiate a TLS necessary to ensure the backend server does not negotiate a TLS
version that is incompatible with ECH. version that is incompatible with ECH.
2. It MUST NOT offer to resume any session for TLS 1.2 and below. 2. It MUST NOT offer to resume any session for TLS 1.2 and below.
skipping to change at line 645 skipping to change at line 657
4. It MUST include the "encrypted_client_hello" extension of type 4. It MUST include the "encrypted_client_hello" extension of type
inner as described in Section 5. (This requirement is not inner as described in Section 5. (This requirement is not
applicable when the "encrypted_client_hello" extension is applicable when the "encrypted_client_hello" extension is
generated as described in Section 6.2.) generated as described in Section 6.2.)
The client then constructs EncodedClientHelloInner as described in The client then constructs EncodedClientHelloInner as described in
Section 5.1. It also computes an HPKE encryption context and enc Section 5.1. It also computes an HPKE encryption context and enc
value as: value as:
~~ pkR = DeserializePublicKey(ECHConfig.contents.public_key) enc, pkR = DeserializePublicKey(ECHConfig.contents.key_config.public_key)
context = SetupBaseS(pkR, "tls ech" || 0x00 || ECHConfig) ~~ enc, context = SetupBaseS(pkR,
"tls ech" || 0x00 || ECHConfig)
Next, it constructs a partial ClientHelloOuterAAD as it does a Next, it constructs a partial ClientHelloOuterAAD as it does a
standard ClientHello, with the exception of the following rules: standard ClientHello, with the exception of the following rules:
1. It MUST offer to negotiate TLS 1.3 or above. 1. It MUST offer to negotiate TLS 1.3 or above.
2. If it compressed any extensions in EncodedClientHelloInner, it 2. If it compressed any extensions in EncodedClientHelloInner, it
MUST copy the corresponding extensions from ClientHelloInner. MUST copy the corresponding extensions from ClientHelloInner.
The copied extensions additionally MUST be in the same relative The copied extensions additionally MUST be in the same relative
order as in ClientHelloInner. order as in ClientHelloInner.
skipping to change at line 733 skipping to change at line 746
* payload, a placeholder byte string containing L zeros. * payload, a placeholder byte string containing L zeros.
If configuration identifiers (see Section 10.4) are to be ignored, If configuration identifiers (see Section 10.4) are to be ignored,
config_id SHOULD be set to a randomly generated byte in the first config_id SHOULD be set to a randomly generated byte in the first
ClientHelloOuter and, in the event of a HelloRetryRequest (HRR), MUST ClientHelloOuter and, in the event of a HelloRetryRequest (HRR), MUST
be left unchanged for the second ClientHelloOuter. be left unchanged for the second ClientHelloOuter.
The client serializes this structure to construct the The client serializes this structure to construct the
ClientHelloOuterAAD. It then computes the final payload as: ClientHelloOuterAAD. It then computes the final payload as:
~~ final_payload = context.Seal(ClientHelloOuterAAD, final_payload = context.Seal(ClientHelloOuterAAD,
EncodedClientHelloInner) ~~ EncodedClientHelloInner)
Including ClientHelloOuterAAD as the HPKE AAD binds the Including ClientHelloOuterAAD as the HPKE AAD binds the
ClientHelloOuter to the ClientHelloInner, thus preventing attackers ClientHelloOuter to the ClientHelloInner, thus preventing attackers
from modifying ClientHelloOuter while keeping the same from modifying ClientHelloOuter while keeping the same
ClientHelloInner, as described in Section 10.12.3. ClientHelloInner, as described in Section 10.12.3.
Finally, the client replaces payload with final_payload to obtain Finally, the client replaces payload with final_payload to obtain
ClientHelloOuter. The two values have the same length, so it is not ClientHelloOuter. The two values have the same length, so it is not
necessary to recompute length prefixes in the serialized structure. necessary to recompute length prefixes in the serialized structure.
skipping to change at line 836 skipping to change at line 849
EncryptedExtension, so that handshake message also needs to be padded EncryptedExtension, so that handshake message also needs to be padded
using TLS record layer padding. using TLS record layer padding.
6.1.4. Determining ECH Acceptance 6.1.4. Determining ECH Acceptance
As described in Section 7, the server may either accept ECH and use As described in Section 7, the server may either accept ECH and use
ClientHelloInner or reject it and use ClientHelloOuter. This is ClientHelloInner or reject it and use ClientHelloOuter. This is
determined by the server's initial message. determined by the server's initial message.
If the message does not negotiate TLS 1.3 or higher, the server has If the message does not negotiate TLS 1.3 or higher, the server has
rejected ECH. Otherwise, it is either a ServerHello or rejected ECH. Otherwise, the message will be either a ServerHello or
HelloRetryRequest. a HelloRetryRequest.
If the message is a ServerHello, the client computes If the message is a ServerHello, the client computes
accept_confirmation as described in Section 7.2. If this value accept_confirmation as described in Section 7.2. If this value
matches the last 8 bytes of ServerHello.random, the server has matches the last 8 bytes of ServerHello.random, the server has
accepted ECH. Otherwise, it has rejected ECH. accepted ECH. Otherwise, it has rejected ECH.
If the message is a HelloRetryRequest, the client checks for the If the message is a HelloRetryRequest, the client checks for the
"encrypted_client_hello" extension. If none is found, the server has "encrypted_client_hello" extension. If none is found, the server has
rejected ECH. Otherwise, if it has a length other than 8, the client rejected ECH. Otherwise, if the extension has a length other than 8,
aborts the handshake with a "decode_error" alert. Otherwise, the the client MUST abort the handshake with a "decode_error" alert.
client computes hrr_accept_confirmation as described in Otherwise, the client computes hrr_accept_confirmation as described
Section 7.2.1. If this value matches the extension payload, the in Section 7.2.1. If this value matches the extension payload, the
server has accepted ECH. Otherwise, it has rejected ECH. server has accepted ECH. Otherwise, it has rejected ECH.
If the server accepts ECH, the client handshakes with If the server accepts ECH, the client handshakes with
ClientHelloInner as described in Section 6.1.5. Otherwise, the ClientHelloInner as described in Section 6.1.5. Otherwise, the
client handshakes with ClientHelloOuter as described in client handshakes with ClientHelloOuter as described in
Section 6.1.6. Section 6.1.6.
6.1.5. Handshaking with ClientHelloInner 6.1.5. Handshaking with ClientHelloInner
If the server accepts ECH, the client proceeds with the connection as If the server accepts ECH, the client proceeds with the connection as
skipping to change at line 929 skipping to change at line 942
processing described below and then abort the connection with an processing described below and then abort the connection with an
"ech_required" alert before sending any application data to the "ech_required" alert before sending any application data to the
server. server.
If the server provided "retry_configs" and if at least one of the If the server provided "retry_configs" and if at least one of the
values contains a version supported by the client, the client can values contains a version supported by the client, the client can
regard the ECH configuration as securely replaced by the server. It regard the ECH configuration as securely replaced by the server. It
SHOULD retry the handshake with a new transport connection using the SHOULD retry the handshake with a new transport connection using the
retry configurations supplied by the server. retry configurations supplied by the server.
Clients can implement a new transport connection in a way that best Because the new ECH configuration replaces the old ECH configuration,
suits their deployment. For example, clients can reuse the same clients can implement a new transport connection in any way that is
server IP address when establishing the new transport connection or consistent with the previous ECH configuration. For example, clients
they can choose to use a different IP address if provided with can reuse the same server IP address when establishing the new
options from DNS. ECH does not mandate any specific implementation transport connection or they can choose to use a different IP address
choices when establishing this new connection. if DNS provided other IP addresses for the previous configuration.
However, it is not safe to use IP addresses discovered with a new DNS
query, as those may correspond to a different ECH server
configuration, for instance associated with a different ECH server
with a different public_name.
The retry configurations are meant to be used for retried The retry configurations are meant to be used for retried
connections. Further use of retry configurations could yield a connections. Further use of retry configurations could yield a
tracking vector. In settings where the client will otherwise already tracking vector. In settings where the client will otherwise already
let the server track the client, e.g., because the client will send let the server track the client, e.g., because the client will send
cookies to the server in parallel connections, using the retry cookies to the server in parallel connections, using the retry
configurations for these parallel connections does not introduce a configurations for these parallel connections does not introduce a
new tracking vector. new tracking vector.
If none of the values provided in "retry_configs" contains a If none of the values provided in "retry_configs" contains a
skipping to change at line 996 skipping to change at line 1013
Note that authenticating a connection for the public name does not Note that authenticating a connection for the public name does not
authenticate it for the origin. The TLS implementation MUST NOT authenticate it for the origin. The TLS implementation MUST NOT
report such connections as successful to the application. It report such connections as successful to the application. It
additionally MUST ignore all session tickets and session IDs additionally MUST ignore all session tickets and session IDs
presented by the server. These connections are only used to trigger presented by the server. These connections are only used to trigger
retries, as described in Section 6.1.6. This may be implemented, for retries, as described in Section 6.1.6. This may be implemented, for
instance, by reporting a failed connection with a dedicated error instance, by reporting a failed connection with a dedicated error
code. code.
Prior to attempting a connection, a client SHOULD validate the Prior to attempting a connection, a client SHOULD validate the
ECHConfig. Clients SHOULD ignore any ECHConfig structure with a ECHConfig.contents.public_name. Clients SHOULD ignore any ECHConfig
public_name that is not a valid host name in preferred name syntax structure with a public_name that is not a valid host name in
(see Section 2 of [DNS-TERMS]). That is, to be valid, the preferred name syntax (see Section 2 of [DNS-TERMS]). That is, to be
public_name needs to be a dot-separated sequence of LDH labels, as valid, the public_name needs to be a dot-separated sequence of LDH
defined in Section 2.3.1 of [RFC5890], where: labels, as defined in Section 2.3.1 of [RFC5890], where:
* the sequence does not begin or end with an ASCII dot, and * the sequence does not begin or end with an ASCII dot, and
* all labels are at most 63 octets. * all labels are at most 63 octets.
Clients additionally SHOULD ignore the structure if the final LDH Clients additionally SHOULD ignore the structure if the final LDH
label either consists of all ASCII digits (i.e., '0' through '9') or label either consists of all ASCII digits (i.e., '0' through '9') or
is "0x" or "0X" followed by some, possibly empty, sequence of ASCII is "0x" or "0X" followed by some, possibly empty, sequence of ASCII
hexadecimal digits (i.e., '0' through '9', 'a' through 'f', and 'A' hexadecimal digits (i.e., '0' through '9', 'a' through 'f', and 'A'
through 'F'). This avoids public_name values that may be interpreted through 'F'). This avoids public_name values that may be interpreted
skipping to change at line 1060 skipping to change at line 1077
6.2.1. Client Greasing 6.2.1. Client Greasing
If the client attempts to connect to a server and does not have an If the client attempts to connect to a server and does not have an
ECHConfig structure available for the server, it SHOULD send a GREASE ECHConfig structure available for the server, it SHOULD send a GREASE
[RFC8701] "encrypted_client_hello" extension in the first ClientHello [RFC8701] "encrypted_client_hello" extension in the first ClientHello
as follows: as follows:
* Set the config_id field to a random byte. * Set the config_id field to a random byte.
* Set the cipher_suite field to a supported * Set the cipher_suite field to a supported
HpkeSymmetricCipherSuite. The selection SHOULD vary to exercise HpkeSymmetricCipherSuite. The selection SHOULD vary, so that all
all supported configurations, but MAY be held constant for plausible configurations are exercised, but MAY be held constant
successive connections to the same server in the same session. for successive connections to the same server in the same session.
Note: A "plausible" configuration is one that an observer might
expect to see. A client that fully supports ECH will have a set
of supported HPKE cipher suites to select from. A client that
only supports GREASE ECH has no such list, so it should select
from a set of values that are in common usage.
* Set the enc field to a randomly generated valid encapsulated * Set the enc field to a randomly generated valid encapsulated
public key output by the HPKE KEM. public key output by the HPKE KEM.
* Set the payload field to a randomly generated string of L+C bytes, * Set the payload field to a randomly generated string of L+C bytes,
where C is the ciphertext expansion of the selected AEAD scheme where C is the ciphertext expansion of the selected AEAD scheme
and L is the size of the EncodedClientHelloInner the client would and L is the size of the EncodedClientHelloInner the client would
compute when offering ECH, padded according to Section 6.1.3. compute when offering ECH, padded according to Section 6.1.3.
If sending a second ClientHello in response to a HelloRetryRequest, If sending a second ClientHello in response to a HelloRetryRequest,
skipping to change at line 1130 skipping to change at line 1152
the client-facing server or as the backend server. Depending on the the client-facing server or as the backend server. Depending on the
server role, the ECHClientHello will be different: server role, the ECHClientHello will be different:
* A client-facing server expects an ECHClientHello.type of outer, * A client-facing server expects an ECHClientHello.type of outer,
and proceeds as described in Section 7.1 to extract a and proceeds as described in Section 7.1 to extract a
ClientHelloInner, if available. ClientHelloInner, if available.
* A backend server expects an ECHClientHello.type of inner, and * A backend server expects an ECHClientHello.type of inner, and
proceeds as described in Section 7.2. proceeds as described in Section 7.2.
If ECHClientHello.type is not a valid ECHClientHelloType, then the
server MUST abort with an "illegal_parameter" alert.
In split mode, a client-facing server which receives a ClientHello In split mode, a client-facing server which receives a ClientHello
with ECHClientHello.type of inner MUST abort with an with ECHClientHello.type of inner MUST abort with an
"illegal_parameter" alert. Similarly, in split mode, a backend "illegal_parameter" alert. Similarly, in split mode, a backend
server which receives a ClientHello with ECHClientHello.type of outer server which receives a ClientHello with ECHClientHello.type of outer
MUST abort with an "illegal_parameter" alert. MUST abort with an "illegal_parameter" alert.
In shared mode, a server plays both roles, first decrypting the In shared mode, a server plays both roles, first decrypting the
ClientHelloOuter and then using the contents of the ClientHelloInner. ClientHelloOuter and then using the contents of the ClientHelloInner.
A shared mode server which receives a ClientHello with A shared mode server which receives a ClientHello with
ECHClientHello.type of inner MUST abort with an "illegal_parameter" ECHClientHello.type of inner MUST abort with an "illegal_parameter"
alert, because such a ClientHello should never be received directly alert, because such a ClientHello should never be received directly
from the network. from the network.
If ECHClientHello.type is not a valid ECHClientHelloType, then the
server MUST abort with an "illegal_parameter" alert.
If the "encrypted_client_hello" is not present, then the server If the "encrypted_client_hello" is not present, then the server
completes the handshake normally, as described in [RFC8446]. completes the handshake normally, as described in [RFC8446].
7.1. Client-Facing Server 7.1. Client-Facing Server
Upon receiving an "encrypted_client_hello" extension in an initial Upon receiving an "encrypted_client_hello" extension in an initial
ClientHello, the client-facing server determines if it will accept ClientHello, the client-facing server determines if it will accept
ECH prior to negotiating any other TLS parameters. Note that ECH prior to negotiating any other TLS parameters. Note that
successfully decrypting the extension will result in a new successfully decrypting the extension will result in a new
ClientHello to process, so even the client's TLS version preferences ClientHello to process, so even the client's TLS version preferences
skipping to change at line 1187 skipping to change at line 1209
follows. follows.
The server verifies that the ECHConfig supports the cipher suite The server verifies that the ECHConfig supports the cipher suite
indicated by the ECHClientHello.cipher_suite and that the version of indicated by the ECHClientHello.cipher_suite and that the version of
ECH indicated by the client matches the ECHConfig.version. If not, ECH indicated by the client matches the ECHConfig.version. If not,
the server continues to the next candidate ECHConfig. the server continues to the next candidate ECHConfig.
Next, the server decrypts ECHClientHello.payload, using the private Next, the server decrypts ECHClientHello.payload, using the private
key skR corresponding to ECHConfig, as follows: key skR corresponding to ECHConfig, as follows:
~~ context = SetupBaseR(ECHClientHello.enc, skR, "tls ech" || 0x00 || context = SetupBaseR(ECHClientHello.enc, skR,
ECHConfig) EncodedClientHelloInner = "tls ech" || 0x00 || ECHConfig)
context.Open(ClientHelloOuterAAD, ECHClientHello.payload) ~~ EncodedClientHelloInner = context.Open(ClientHelloOuterAAD,
ECHClientHello.payload)
ClientHelloOuterAAD is computed from ClientHelloOuter as described in ClientHelloOuterAAD is computed from ClientHelloOuter as described in
Section 5.2. The info parameter to SetupBaseR is the concatenation Section 5.2. The info parameter to SetupBaseR is the concatenation
"tls ech", a zero byte, and the serialized ECHConfig. If decryption "tls ech", a zero byte, and the serialized ECHConfig. If decryption
fails, the server continues to the next candidate ECHConfig. fails, the server continues to the next candidate ECHConfig.
Otherwise, the server reconstructs ClientHelloInner from Otherwise, the server reconstructs ClientHelloInner from
EncodedClientHelloInner, as described in Section 5.1. It then stops EncodedClientHelloInner, as described in Section 5.1. It then stops
iterating over the candidate ECHConfig values. iterating over the candidate ECHConfig values.
Once the server has chosen the correct ECHConfig, it MAY verify that Once the server has chosen the correct ECHConfig, it MAY verify that
skipping to change at line 1247 skipping to change at line 1270
support multiple versions at once. support multiple versions at once.
Note that decryption failure could indicate a GREASE ECH extension Note that decryption failure could indicate a GREASE ECH extension
(see Section 6.2), so it is necessary for servers to proceed with the (see Section 6.2), so it is necessary for servers to proceed with the
connection and rely on the client to abort if ECH was required. In connection and rely on the client to abort if ECH was required. In
particular, the unrecognized value alone does not indicate a particular, the unrecognized value alone does not indicate a
misconfigured ECH advertisement (Section 8.1.1). Instead, servers misconfigured ECH advertisement (Section 8.1.1). Instead, servers
can measure occurrences of the "ech_required" alert to detect this can measure occurrences of the "ech_required" alert to detect this
case. case.
7.1.1. Sending HelloRetryRequest 7.1.1. Processing ClientHello after HelloRetryRequest
After sending or forwarding a HelloRetryRequest, the client-facing After sending or forwarding a HelloRetryRequest, the client-facing
server does not repeat the steps in Section 7.1 with the second server does not repeat the steps in Section 7.1 with the second
ClientHelloOuter. Instead, it continues with the ECHConfig selection ClientHelloOuter. Instead, it continues with the ECHConfig selection
from the first ClientHelloOuter as follows: from the first ClientHelloOuter as follows:
If the client-facing server accepted ECH, it checks that the second If the client-facing server accepted ECH, it checks that the second
ClientHelloOuter also contains the "encrypted_client_hello" ClientHelloOuter also contains the "encrypted_client_hello"
extension. If not, it MUST abort the handshake with a extension. If not, it MUST abort the handshake with a
"missing_extension" alert. Otherwise, it checks that "missing_extension" alert. Otherwise, it checks that
ECHClientHello.cipher_suite and ECHClientHello.config_id are ECHClientHello.cipher_suite and ECHClientHello.config_id are
unchanged, and that ECHClientHello.enc is empty. If not, it MUST unchanged, and that ECHClientHello.enc is empty. If not, it MUST
abort the handshake with an "illegal_parameter" alert. abort the handshake with an "illegal_parameter" alert.
Finally, it decrypts the new ECHClientHello.payload as a second Finally, it decrypts the new ECHClientHello.payload as a second
message with the previous HPKE context: message with the previous HPKE context:
~~ EncodedClientHelloInner = context.Open(ClientHelloOuterAAD, EncodedClientHelloInner = context.Open(ClientHelloOuterAAD,
ECHClientHello.payload) ~~ ECHClientHello.payload)
ClientHelloOuterAAD is computed as described in Section 5.2, but ClientHelloOuterAAD is computed as described in Section 5.2, but
using the second ClientHelloOuter. If decryption fails, the client- using the second ClientHelloOuter. If decryption fails, the client-
facing server MUST abort the handshake with a "decrypt_error" alert. facing server MUST abort the handshake with a "decrypt_error" alert.
Otherwise, it reconstructs the second ClientHelloInner from the new Otherwise, it reconstructs the second ClientHelloInner from the new
EncodedClientHelloInner as described in Section 5.1, using the second EncodedClientHelloInner as described in Section 5.1, using the second
ClientHelloOuter for any referenced extensions. ClientHelloOuter for any referenced extensions.
The client-facing server then forwards the resulting ClientHelloInner The client-facing server then forwards the resulting ClientHelloInner
to the backend server. It forwards all subsequent TLS messages to the backend server. It forwards all subsequent TLS messages
skipping to change at line 1312 skipping to change at line 1335
The backend server embeds in ServerHello.random a string derived from The backend server embeds in ServerHello.random a string derived from
the inner handshake. It begins by computing its ServerHello as the inner handshake. It begins by computing its ServerHello as
usual, except the last 8 bytes of ServerHello.random are set to zero. usual, except the last 8 bytes of ServerHello.random are set to zero.
It then computes the transcript hash for ClientHelloInner up to and It then computes the transcript hash for ClientHelloInner up to and
including the modified ServerHello, as described in [RFC8446], including the modified ServerHello, as described in [RFC8446],
Section 4.4.1. Let transcript_ech_conf denote the output. Finally, Section 4.4.1. Let transcript_ech_conf denote the output. Finally,
the backend server overwrites the last 8 bytes of the the backend server overwrites the last 8 bytes of the
ServerHello.random with the following string: ServerHello.random with the following string:
~~ accept_confirmation = HKDF-Expand-Label( HKDF-Extract(0, accept_confirmation = HKDF-Expand-Label(
ClientHelloInner.random), "ech accept confirmation", HKDF-Extract(0, ClientHelloInner.random),
transcript_ech_conf, 8) ~~ "ech accept confirmation",
transcript_ech_conf,
8)
where HKDF-Expand-Label is defined in [RFC8446], Section 7.1, "0" where HKDF-Expand-Label is defined in [RFC8446], Section 7.1, "0"
indicates a string of Hash.length bytes set to zero, and Hash is the indicates a string of Hash.length bytes set to zero, and Hash is the
hash function used to compute the transcript hash. In DTLS, the hash function used to compute the transcript hash. In DTLS, the
modified version of HKDF-Expand-Label defined in [RFC9147], modified version of HKDF-Expand-Label defined in [RFC9147],
Section 5.9 is used instead. Section 5.9 is used instead.
The backend server MUST NOT perform this operation if it negotiated The backend server MUST NOT perform this operation if it negotiated
TLS 1.2 or below. Note that doing so would overwrite the downgrade TLS 1.2 or below. Note that doing so would overwrite the downgrade
signal for TLS 1.3 (see [RFC8446], Section 4.1.3). signal for TLS 1.3 (see [RFC8446], Section 4.1.3).
skipping to change at line 1344 skipping to change at line 1369
The backend server begins by computing HelloRetryRequest as usual, The backend server begins by computing HelloRetryRequest as usual,
except that it also contains an "encrypted_client_hello" extension except that it also contains an "encrypted_client_hello" extension
with a payload of 8 zero bytes. It then computes the transcript hash with a payload of 8 zero bytes. It then computes the transcript hash
for the first ClientHelloInner, denoted ClientHelloInner1, up to and for the first ClientHelloInner, denoted ClientHelloInner1, up to and
including the modified HelloRetryRequest. Let including the modified HelloRetryRequest. Let
transcript_hrr_ech_conf denote the output. Finally, the backend transcript_hrr_ech_conf denote the output. Finally, the backend
server overwrites the payload of the "encrypted_client_hello" server overwrites the payload of the "encrypted_client_hello"
extension with the following string: extension with the following string:
~~ hrr_accept_confirmation = HKDF-Expand-Label( HKDF-Extract(0, hrr_accept_confirmation = HKDF-Expand-Label(
ClientHelloInner1.random), "hrr ech accept confirmation", HKDF-Extract(0, ClientHelloInner1.random),
transcript_hrr_ech_conf, 8) ~~ "hrr ech accept confirmation",
transcript_hrr_ech_conf,
8)
In the subsequent ServerHello message, the backend server sends the In the subsequent ServerHello message, the backend server sends the
accept_confirmation value as described in Section 7.2. accept_confirmation value as described in Section 7.2.
8. Deployment Considerations 8. Deployment Considerations
The design of ECH as specified in this document necessarily requires The design of ECH as specified in this document necessarily requires
changes to client, client-facing server, and backend server. changes to client, client-facing server, and backend server.
Coordination between client-facing and backend server requires care, Coordination between client-facing and backend server requires care,
as deployment mistakes can lead to compatibility issues. These are as deployment mistakes can lead to compatibility issues. These are
discussed in Section 8.1. discussed in Section 8.1.
Beyond coordination difficulties, ECH deployments may also induce Beyond coordination difficulties, ECH deployments may also create
challenges for use cases of information that ECH protects. In challenges for uses of information that ECH protects. In particular,
particular, use cases which depend on this unencrypted information use cases which depend on this unencrypted information may no longer
may no longer work as desired. This is elaborated upon in work as desired. This is elaborated upon in Section 8.2.
Section 8.2.
8.1. Compatibility Issues 8.1. Compatibility Issues
Unlike most TLS extensions, placing the SNI value in an ECH extension Unlike most TLS extensions, placing the SNI value in an ECH extension
is not interoperable with existing servers, which expect the value in is not interoperable with existing servers, which expect the value in
the existing plaintext extension. Thus, server operators SHOULD the existing plaintext extension. Thus, server operators SHOULD
ensure servers understand a given set of ECH keys before advertising ensure servers understand a given set of ECH keys before advertising
them. Additionally, servers SHOULD retain support for any previously them. Additionally, servers SHOULD retain support for any previously
advertised keys for the duration of their validity. advertised keys for the duration of their validity.
skipping to change at line 1610 skipping to change at line 1636
perform trial decryption since they cannot identify the client's perform trial decryption since they cannot identify the client's
chosen ECH key using the config_id value. As a result, ignoring chosen ECH key using the config_id value. As a result, ignoring
configuration identifiers may exacerbate DoS attacks. Specifically, configuration identifiers may exacerbate DoS attacks. Specifically,
an adversary may send malicious ClientHello messages, i.e., those an adversary may send malicious ClientHello messages, i.e., those
which will not decrypt with any known ECH key, in order to force which will not decrypt with any known ECH key, in order to force
wasteful decryption. Servers that support this feature should, for wasteful decryption. Servers that support this feature should, for
example, implement some form of rate limiting mechanism to limit the example, implement some form of rate limiting mechanism to limit the
potential damage caused by such attacks. potential damage caused by such attacks.
Unless specified by the application using (D)TLS or externally Unless specified by the application using (D)TLS or externally
configured, implementations MUST NOT use this mode. configured, client implementations MUST NOT use this mode.
10.5. Outer ClientHello 10.5. Outer ClientHello
Any information that the client includes in the ClientHelloOuter is Any information that the client includes in the ClientHelloOuter is
visible to passive observers. The client SHOULD NOT send values in visible to passive observers. The client SHOULD NOT send values in
the ClientHelloOuter which would reveal a sensitive ClientHelloInner the ClientHelloOuter which would reveal a sensitive ClientHelloInner
property, such as the true server name. It MAY send values property, such as the true server name. It MAY send values
associated with the public name in the ClientHelloOuter. associated with the public name in the ClientHelloOuter.
In particular, some extensions require the client send a server-name- In particular, some extensions require the client send a server-name-
skipping to change at line 1903 skipping to change at line 1929
the attacker learns that its test certificate name was incorrect. As the attacker learns that its test certificate name was incorrect. As
an example, suppose the client's SNI value in its inner ClientHello an example, suppose the client's SNI value in its inner ClientHello
is "example.com," and the attacker replied with a Certificate for is "example.com," and the attacker replied with a Certificate for
"test.com". If the client produces a verification failure alert "test.com". If the client produces a verification failure alert
because of the mismatch faster than it would due to the Certificate because of the mismatch faster than it would due to the Certificate
signature validation, information about the name leaks. Note that signature validation, information about the name leaks. Note that
the attacker can also withhold the CertificateVerify message. In the attacker can also withhold the CertificateVerify message. In
that scenario, a client which first verifies the Certificate would that scenario, a client which first verifies the Certificate would
then respond similarly and leak the same information. then respond similarly and leak the same information.
~~ Client Attacker Server ClientHello + key_share + ech ------> Client Attacker Server
(intercept) -----> X (drop) ClientHello
+ key_share
+ ech ------> (intercept) -----> X (drop)
ServerHello ServerHello
+ key_share + key_share
{EncryptedExtensions} {EncryptedExtensions}
{CertificateRequest*} {CertificateRequest*}
{Certificate*} {Certificate*}
{CertificateVerify*} {CertificateVerify*}
<------ Alert <------
------> ~~ Alert
------>
Figure 3: Client Reaction Attack Figure 3: Client Reaction Attack
ClientHelloInner.random prevents this attack. In particular, since ClientHelloInner.random prevents this attack: because the attacker
the attacker does not have access to this value, it cannot produce does not have access to this value, it cannot produce the right
the right transcript and handshake keys needed for encrypting the transcript and handshake keys needed for encrypting the Certificate
Certificate message. Thus, the client will fail to decrypt the message. Thus, the client will fail to decrypt the Certificate and
Certificate and abort the connection. abort the connection.
10.12.2. HelloRetryRequest Hijack Mitigation 10.12.2. HelloRetryRequest Hijack Mitigation
This attack aims to exploit server HRR state management to recover This attack aims to exploit server HRR state management to recover
information about a legitimate ClientHello using its own attacker- information about a legitimate ClientHello using its own attacker-
controlled ClientHello. To begin, the attacker intercepts and controlled ClientHello. To begin, the attacker intercepts and
forwards a legitimate ClientHello with an "encrypted_client_hello" forwards a legitimate ClientHello with an "encrypted_client_hello"
(ech) extension to the server, which triggers a legitimate (ech) extension to the server, which triggers a legitimate
HelloRetryRequest in return. Rather than forward the retry to the HelloRetryRequest in return. Rather than forward the retry to the
client, the attacker attempts to generate its own ClientHello in client, the attacker attempts to generate its own ClientHello in
response based on the contents of the first ClientHello and response based on the contents of the first ClientHello and
HelloRetryRequest exchange with the result that the server encrypts HelloRetryRequest exchange with the result that the server encrypts
the Certificate to the attacker. If the server used the SNI from the the Certificate to the attacker. If the server used the SNI from the
first ClientHello and the key share from the second (attacker- first ClientHello and the key share from the second (attacker-
controlled) ClientHello, the Certificate produced would leak the controlled) ClientHello, the Certificate produced would leak the
client's chosen SNI to the attacker. client's chosen SNI to the attacker.
~~ Client Attacker Server ClientHello + key_share + ech ------> Client Attacker Server
(forward) -------> HelloRetryRequest + key_share (intercept) <------- ClientHello
+ key_share
+ ech ------> (forward) ------->
HelloRetryRequest
+ key_share
(intercept) <-------
ClientHello ClientHello
+ key_share' + key_share'
+ ech' -------> + ech' ------->
ServerHello ServerHello
+ key_share + key_share
{EncryptedExtensions} {EncryptedExtensions}
{CertificateRequest*} {CertificateRequest*}
{Certificate*} {Certificate*}
{CertificateVerify*} {CertificateVerify*}
{Finished} {Finished}
<------- <-------
(process server flight) ~~ (process server flight)
Figure 4: HelloRetryRequest Hijack Attack Figure 4: HelloRetryRequest Hijack Attack
This attack is mitigated by using the same HPKE context for both This attack is mitigated by using the same HPKE context for both
ClientHello messages. The attacker does not possess the context's ClientHello messages. The attacker does not possess the context's
keys, so it cannot generate a valid encryption of the second inner keys, so it cannot generate a valid encryption of the second inner
ClientHello. ClientHello.
If the attacker could manipulate the second ClientHello, it might be If the attacker could manipulate the second ClientHello, it might be
possible for the server to act as an oracle if it required parameters possible for the server to act as an oracle if it required parameters
skipping to change at line 1991 skipping to change at line 2025
To begin, the attacker first interacts with a server to obtain a To begin, the attacker first interacts with a server to obtain a
resumption ticket for a given test domain, such as "example.com". resumption ticket for a given test domain, such as "example.com".
Later, upon receipt of a ClientHelloOuter, it modifies it such that Later, upon receipt of a ClientHelloOuter, it modifies it such that
the server will process the resumption ticket with ClientHelloInner. the server will process the resumption ticket with ClientHelloInner.
If the server only accepts resumption PSKs that match the server If the server only accepts resumption PSKs that match the server
name, it will fail the PSK binder check with an alert when name, it will fail the PSK binder check with an alert when
ClientHelloInner is for "example.com" but silently ignore the PSK and ClientHelloInner is for "example.com" but silently ignore the PSK and
continue when ClientHelloInner is for any other name. This continue when ClientHelloInner is for any other name. This
introduces an oracle for testing encrypted SNI values. introduces an oracle for testing encrypted SNI values.
~~ Client Attacker Server Client Attacker Server
handshake and ticket handshake and ticket
for "example.com" for "example.com"
<--------> <-------->
ClientHello ClientHello
+ key_share + key_share
+ ech + ech
+ ech_outer_extensions(pre_shared_key) + ech_outer_extensions(pre_shared_key)
+ pre_shared_key + pre_shared_key
--------> -------->
(intercept) (intercept)
ClientHello ClientHello
+ key_share + key_share
+ ech + ech
+ ech_outer_extensions(pre_shared_key) + ech_outer_extensions(pre_shared_key)
+ pre_shared_key' + pre_shared_key'
--------> -------->
Alert Alert
-or- -or-
ServerHello ServerHello
... ...
Finished Finished
<-------- ~~ <--------
Figure 5: Message Flow for Malleable ClientHello Figure 5: Message Flow for Malleable ClientHello
This attack may be generalized to any parameter which the server This attack may be generalized to any parameter which the server
varies by server name, such as ALPN preferences. varies by server name, such as ALPN preferences.
ECH mitigates this attack by only negotiating TLS parameters from ECH mitigates this attack by only negotiating TLS parameters from
ClientHelloInner and authenticating all inputs to the ClientHelloInner and authenticating all inputs to the
ClientHelloInner (EncodedClientHelloInner and ClientHelloOuter) with ClientHelloInner (EncodedClientHelloInner and ClientHelloOuter) with
the HPKE AEAD. See Section 5.2. The decompression process in the HPKE AEAD. See Section 5.2. The decompression process in
 End of changes. 39 change blocks. 
130 lines changed or deleted 164 lines changed or added

This html diff was produced by rfcdiff 1.48.