rfc9849v6.txt   rfc9849.txt 
skipping to change at line 122 skipping to change at line 122
11.3. ECH Configuration Extension Registry 11.3. ECH Configuration Extension Registry
12. References 12. References
12.1. Normative References 12.1. Normative References
12.2. Informative References 12.2. Informative References
Appendix A. Linear-Time Outer Extension Processing Appendix A. Linear-Time Outer Extension Processing
Acknowledgements Acknowledgements
Authors' Addresses Authors' Addresses
1. Introduction 1. Introduction
Although TLS 1.3 [RFC8446] encrypts most of the handshake, including Although TLS 1.3 [RFC9846] encrypts most of the handshake, including
the server certificate, there are several ways in which an on-path the server certificate, there are several ways in which an on-path
attacker can learn private information about the connection. The attacker can learn private information about the connection. The
plaintext Server Name Indication (SNI) extension in ClientHello plaintext Server Name Indication (SNI) extension in ClientHello
messages, which leaks the target domain for a given connection, is messages, which leaks the target domain for a given connection, is
perhaps the most sensitive information left unencrypted in TLS 1.3. perhaps the most sensitive information left unencrypted in TLS 1.3.
This document specifies a new TLS extension called Encrypted Client This document specifies a new TLS extension called Encrypted Client
Hello (ECH) that allows clients to encrypt their ClientHello to the Hello (ECH) that allows clients to encrypt their ClientHello to the
TLS server. This protects the SNI and other potentially sensitive TLS server. This protects the SNI and other potentially sensitive
fields, such as the Application-Layer Protocol Negotiation (ALPN) fields, such as the Application-Layer Protocol Negotiation (ALPN)
skipping to change at line 157 skipping to change at line 157
channels, such as plaintext client DNS queries or visible server IP channels, such as plaintext client DNS queries or visible server IP
addresses. However, encrypted DNS mechanisms such as DNS over HTTPS addresses. However, encrypted DNS mechanisms such as DNS over HTTPS
[RFC8484], DNS over TLS/DTLS [RFC7858] [RFC8094], and DNS over QUIC [RFC8484], DNS over TLS/DTLS [RFC7858] [RFC8094], and DNS over QUIC
[RFC9250] provide mechanisms for clients to conceal DNS lookups from [RFC9250] provide mechanisms for clients to conceal DNS lookups from
network inspection, and many TLS servers host multiple domains on the network inspection, and many TLS servers host multiple domains on the
same IP address. Private origins may also be deployed behind a same IP address. Private origins may also be deployed behind a
common provider, such as a reverse proxy. In such environments, the common provider, such as a reverse proxy. In such environments, the
SNI remains the primary explicit signal available to observers to SNI remains the primary explicit signal available to observers to
determine the server's identity. determine the server's identity.
ECH is supported in TLS 1.3 [RFC8446], DTLS 1.3 [RFC9147], and newer ECH is supported in TLS 1.3 [RFC9846], DTLS 1.3 [RFC9147], and newer
versions of the TLS and DTLS protocols. versions of the TLS and DTLS protocols.
2. Conventions and Definitions 2. Conventions and Definitions
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in BCP "OPTIONAL" in this document are to be interpreted as described in BCP
14 [RFC2119] [RFC8174] when, and only when, they appear in all 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here. All TLS notation comes from [RFC8446], capitals, as shown here. All TLS notation comes from [RFC9846],
Section 3. Section 3.
3. Overview 3. Overview
This protocol is designed to operate in one of two topologies This protocol is designed to operate in one of two topologies
illustrated below, which we call "Shared Mode" and "Split Mode". illustrated below, which we call "Shared Mode" and "Split Mode".
These modes are described in the following section. These modes are described in the following section.
3.1. Topologies 3.1. Topologies
skipping to change at line 230 skipping to change at line 230
See Section 10 for more discussion about the ECH threat model and how See Section 10 for more discussion about the ECH threat model and how
it relates to the client, client-facing server, and backend server. it relates to the client, client-facing server, and backend server.
3.2. Encrypted ClientHello (ECH) 3.2. Encrypted ClientHello (ECH)
A client-facing server enables ECH by publishing an ECH A client-facing server enables ECH by publishing an ECH
configuration, which is an encryption public key and associated configuration, which is an encryption public key and associated
metadata. Domains which wish to use ECH must publish this metadata. Domains which wish to use ECH must publish this
configuration, using the key associated with the client-facing configuration, using the key associated with the client-facing
server. This document defines the ECH configuration's format, but server. This document defines the ECH configuration's format, but
delegates DNS publication details to [RFC9460]. See [RFCYYY1] for delegates DNS publication details to [RFC9460]. See [RFC9848] for
specifics about how ECH configurations are advertised in SVCB and specifics about how ECH configurations are advertised in SVCB and
HTTPS records. Other delivery mechanisms are also possible. For HTTPS records. Other delivery mechanisms are also possible. For
example, the client may have the ECH configuration preconfigured. example, the client may have the ECH configuration preconfigured.
When a client wants to establish a TLS session with some backend When a client wants to establish a TLS session with some backend
server, it constructs a private ClientHello, referred to as the server, it constructs a private ClientHello, referred to as the
ClientHelloInner. The client then constructs a public ClientHello, ClientHelloInner. The client then constructs a public ClientHello,
referred to as the ClientHelloOuter. The ClientHelloOuter contains referred to as the ClientHelloOuter. The ClientHelloOuter contains
innocuous values for sensitive extensions and an innocuous values for sensitive extensions and an
"encrypted_client_hello" extension (Section 5), which carries the "encrypted_client_hello" extension (Section 5), which carries the
skipping to change at line 406 skipping to change at line 406
It is not necessary for config_id values across different client- It is not necessary for config_id values across different client-
facing servers to be distinct. A backend server may be hosted behind facing servers to be distinct. A backend server may be hosted behind
two different client-facing servers with colliding config_id values two different client-facing servers with colliding config_id values
without any performance impact. Values may also be reused if the without any performance impact. Values may also be reused if the
previous ECHConfig is no longer in the known set. previous ECHConfig is no longer in the known set.
4.2. Configuration Extensions 4.2. Configuration Extensions
ECH configuration extensions are used to provide room for additional ECH configuration extensions are used to provide room for additional
functionality as needed. The format is as defined in Section 4 and functionality as needed. The format is as defined in Section 4 and
mirrors Section 4.2 of [RFC8446]. However, ECH configuration mirrors Section 4.2 of [RFC9846]. However, ECH configuration
extension types are maintained by IANA as described in Section 11.3. extension types are maintained by IANA as described in Section 11.3.
ECH configuration extensions follow the same interpretation rules as ECH configuration extensions follow the same interpretation rules as
TLS extensions: extensions MAY appear in any order, but there MUST TLS extensions: extensions MAY appear in any order, but there MUST
NOT be more than one extension of the same type in the extensions NOT be more than one extension of the same type in the extensions
block. Unlike TLS extensions, an extension can be tagged as block. Unlike TLS extensions, an extension can be tagged as
mandatory by using an extension type codepoint with the high order mandatory by using an extension type codepoint with the high order
bit set to 1. bit set to 1.
Clients MUST parse the extension list and check for unsupported Clients MUST parse the extension list and check for unsupported
mandatory extensions. If an unsupported mandatory extension is mandatory extensions. If an unsupported mandatory extension is
skipping to change at line 522 skipping to change at line 522
below: below:
struct { struct {
ClientHello client_hello; ClientHello client_hello;
uint8 zeros[length_of_padding]; uint8 zeros[length_of_padding];
} EncodedClientHelloInner; } 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 [RFC9846]. 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
the Handshake structure's four-byte header in TLS, nor the twelve- the Handshake structure's four-byte header in TLS, nor the twelve-
byte header in DTLS. The zeros field MUST be all zeros 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
skipping to change at line 600 skipping to change at line 600
naive copying) create a denial-of-service risk. Appendix A describes naive copying) create a denial-of-service risk. Appendix A describes
a linear-time 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 [RFC9846] 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 the length but whose contents are zeros. This value does not include the
Handshake structure's four-byte header in TLS nor the twelve-byte Handshake structure's four-byte header in TLS nor the twelve-byte
header 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:
skipping to change at line 673 skipping to change at line 673
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.
3. It MUST copy the legacy_session_id field from ClientHelloInner. 3. It MUST copy the legacy_session_id field from ClientHelloInner.
This allows the server to echo the correct session ID for TLS This allows the server to echo the correct session ID for TLS
1.3's compatibility mode (see Appendix D.4 of [RFC8446]) when ECH 1.3's compatibility mode (see Appendix E.4 of [RFC9846]) when ECH
is negotiated. Note that compatibility mode is not used in DTLS is negotiated. Note that compatibility mode is not used in DTLS
1.3, but following this rule will produce the correct results for 1.3, but following this rule will produce the correct results for
both TLS 1.3 and DTLS 1.3. both TLS 1.3 and DTLS 1.3.
4. It MAY copy any other field from the ClientHelloInner except 4. It MAY copy any other field from the ClientHelloInner except
ClientHelloInner.random. Instead, it MUST generate a fresh ClientHelloInner.random. Instead, it MUST generate a fresh
ClientHelloOuter.random using a secure random number generator. ClientHelloOuter.random using a secure random number generator.
(See Section 10.12.1.) (See Section 10.12.1.)
5. It SHOULD place the value of ECHConfig.contents.public_name in 5. It SHOULD place the value of ECHConfig.contents.public_name in
skipping to change at line 704 skipping to change at line 704
extension to advertise a PSK to the client-facing server. (See extension to advertise a PSK to the client-facing server. (See
Section 10.12.3.) When the client includes a GREASE Section 10.12.3.) When the client includes a GREASE
"pre_shared_key" extension, it MUST also copy the "pre_shared_key" extension, it MUST also copy the
"psk_key_exchange_modes" from the ClientHelloInner into the "psk_key_exchange_modes" from the ClientHelloInner into the
ClientHelloOuter. ClientHelloOuter.
7. When the client offers the "early_data" extension in 7. When the client offers the "early_data" extension in
ClientHelloInner, it MUST also include the "early_data" extension ClientHelloInner, it MUST also include the "early_data" extension
in ClientHelloOuter. This allows servers that reject ECH and use in ClientHelloOuter. This allows servers that reject ECH and use
ClientHelloOuter to safely ignore any early data sent by the ClientHelloOuter to safely ignore any early data sent by the
client per [RFC8446], Section 4.2.10. client per [RFC9846], Section 4.2.10.
The client might duplicate non-sensitive extensions in both messages. The client might duplicate non-sensitive extensions in both messages.
However, implementations need to take care to ensure that sensitive However, implementations need to take care to ensure that sensitive
extensions are not offered in the ClientHelloOuter. See Section 10.5 extensions are not offered in the ClientHelloOuter. See Section 10.5
for additional guidance. for additional guidance.
Finally, the client encrypts the EncodedClientHelloInner with the Finally, the client encrypts the EncodedClientHelloInner with the
above values, as described in Section 6.1.1, to construct a above values, as described in Section 6.1.1, to construct a
ClientHelloOuter. It sends this to the server and processes the ClientHelloOuter. It sends this to the server and processes the
response as described in Section 6.1.4. response as described in Section 6.1.4.
skipping to change at line 772 skipping to change at line 772
6.1.2. GREASE PSK 6.1.2. GREASE PSK
When offering ECH, the client is not permitted to advertise PSK When offering ECH, the client is not permitted to advertise PSK
identities in the ClientHelloOuter. However, the client can send a identities in the ClientHelloOuter. However, the client can send a
"pre_shared_key" extension in the ClientHelloInner. In this case, "pre_shared_key" extension in the ClientHelloInner. In this case,
when resuming a session with the client, the backend server sends a when resuming a session with the client, the backend server sends a
"pre_shared_key" extension in its ServerHello. This would appear to "pre_shared_key" extension in its ServerHello. This would appear to
a network observer as if the server were sending this extension a network observer as if the server were sending this extension
without solicitation, which would violate the extension rules without solicitation, which would violate the extension rules
described in [RFC8446]. When offering a PSK in ClientHelloInner, described in [RFC9846]. When offering a PSK in ClientHelloInner,
clients SHOULD send a GREASE "pre_shared_key" extension in the clients SHOULD send a GREASE "pre_shared_key" extension in the
ClientHelloOuter to make it appear to the network as if the extension ClientHelloOuter to make it appear to the network as if the extension
were negotiated properly. were negotiated properly.
The client generates the extension payload by constructing an The client generates the extension payload by constructing an
OfferedPsks structure (see [RFC8446], Section 4.2.11) as follows. OfferedPsks structure (see [RFC9846], Section 4.2.11) as follows.
For each PSK identity advertised in the ClientHelloInner, the client For each PSK identity advertised in the ClientHelloInner, the client
generates a random PSK identity with the same length. It also generates a random PSK identity with the same length. It also
generates a random, 32-bit, unsigned integer to use as the generates a random, 32-bit, unsigned integer to use as the
obfuscated_ticket_age. Likewise, for each inner PSK binder, the obfuscated_ticket_age. Likewise, for each inner PSK binder, the
client generates a random string of the same length. client generates a random string of the same length.
Per the rules of Section 6.1, the server is not permitted to resume a Per the rules of Section 6.1, the server is not permitted to resume a
connection in the outer handshake. If ECH is rejected and the connection in the outer handshake. If ECH is rejected and the
client-facing server replies with a "pre_shared_key" extension in its client-facing server replies with a "pre_shared_key" extension in its
ServerHello, then the client MUST abort the handshake with an ServerHello, then the client MUST abort the handshake with an
skipping to change at line 873 skipping to change at line 873
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
in [RFC8446], with the following modifications: in [RFC9846], with the following modifications:
The client behaves as if it had sent ClientHelloInner as the The client behaves as if it had sent ClientHelloInner as the
ClientHello. That is, it evaluates the handshake using the ClientHello. That is, it evaluates the handshake using the
ClientHelloInner's preferences, and, when computing the transcript ClientHelloInner's preferences, and, when computing the transcript
hash (Section 4.4.1 of [RFC8446]), it uses ClientHelloInner as the hash (Section 4.4.1 of [RFC9846]), it uses ClientHelloInner as the
first ClientHello. first ClientHello.
If the server responds with a HelloRetryRequest, the client computes If the server responds with a HelloRetryRequest, the client computes
the updated ClientHello message as follows: the updated ClientHello message as follows:
1. It computes a second ClientHelloInner based on the first 1. It computes a second ClientHelloInner based on the first
ClientHelloInner, as in Section 4.1.4 of [RFC8446]. The ClientHelloInner, as in Section 4.1.4 of [RFC9846]. The
ClientHelloInner's "encrypted_client_hello" extension is left ClientHelloInner's "encrypted_client_hello" extension is left
unmodified. unmodified.
2. It constructs EncodedClientHelloInner as described in 2. It constructs EncodedClientHelloInner as described in
Section 5.1. Section 5.1.
3. It constructs a second partial ClientHelloOuterAAD message. This 3. It constructs a second partial ClientHelloOuterAAD message. This
message MUST be syntactically valid. The extensions MAY be message MUST be syntactically valid. The extensions MAY be
copied from the original ClientHelloOuter unmodified or omitted. copied from the original ClientHelloOuter unmodified or omitted.
If not sensitive, the client MAY copy updated extensions from the If not sensitive, the client MAY copy updated extensions from the
skipping to change at line 1046 skipping to change at line 1046
enforcing the single retry limit from Section 6.1.6. The reason for enforcing the single retry limit from Section 6.1.6. The reason for
this requirement is that if the server sends a "retry_config" and this requirement is that if the server sends a "retry_config" and
then immediately rejects the resulting connection, it is most likely then immediately rejects the resulting connection, it is most likely
misconfigured. However, if the server sends a "retry_config" and misconfigured. However, if the server sends a "retry_config" and
then the client tries to use that to connect some time later, it is then the client tries to use that to connect some time later, it is
possible that the server has changed its configuration again and is possible that the server has changed its configuration again and is
now trying to recover. now trying to recover.
Any persisted information MUST be associated with the ECHConfig Any persisted information MUST be associated with the ECHConfig
source used to bootstrap the connection, such as a DNS SVCB source used to bootstrap the connection, such as a DNS SVCB
ServiceMode record [RFCYYY1]. Clients MUST limit any sharing of ServiceMode record [RFC9848]. Clients MUST limit any sharing of
persisted ECH-related state to connections that use the same persisted ECH-related state to connections that use the same
ECHConfig source. Otherwise, it might become possible for the client ECHConfig source. Otherwise, it might become possible for the client
to have the wrong public name for the server, making recovery to have the wrong public name for the server, making recovery
impossible. impossible.
ECHConfigs learned from ECH rejection can be used as a tracking ECHConfigs learned from ECH rejection can be used as a tracking
vector. Clients SHOULD impose the same lifetime and scope vector. Clients SHOULD impose the same lifetime and scope
restrictions that they apply to other server-based tracking vectors restrictions that they apply to other server-based tracking vectors
such as PSKs. such as PSKs.
skipping to change at line 1169 skipping to change at line 1169
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 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 [RFC9846].
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
may have changed. may have changed.
skipping to change at line 1330 skipping to change at line 1330
Upon receipt of an "encrypted_client_hello" extension of type inner Upon receipt of an "encrypted_client_hello" extension of type inner
in a ClientHello, if the backend server negotiates TLS 1.3 or higher, in a ClientHello, if the backend server negotiates TLS 1.3 or higher,
then it MUST confirm ECH acceptance to the client by computing its then it MUST confirm ECH acceptance to the client by computing its
ServerHello as described here. ServerHello as described here.
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 [RFC9846],
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( accept_confirmation = HKDF-Expand-Label(
HKDF-Extract(0, ClientHelloInner.random), HKDF-Extract(0, ClientHelloInner.random),
"ech accept confirmation", "ech accept confirmation",
transcript_ech_conf, transcript_ech_conf,
8) 8)
where HKDF-Expand-Label is defined in [RFC8446], Section 7.1, "0" where HKDF-Expand-Label is defined in [RFC9846], 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 [RFC9846], Section 4.1.3).
7.2.1. Sending HelloRetryRequest 7.2.1. Sending HelloRetryRequest
When the backend server sends HelloRetryRequest in response to the When the backend server sends HelloRetryRequest in response to the
ClientHello, it similarly confirms ECH acceptance by adding a ClientHello, it similarly confirms ECH acceptance by adding a
confirmation signal to its HelloRetryRequest. But instead of confirmation signal to its HelloRetryRequest. But instead of
embedding the signal in the HelloRetryRequest.random (the value of embedding the signal in the HelloRetryRequest.random (the value of
which is specified by [RFC8446]), it sends the signal in an which is specified by [RFC9846]), it sends the signal in an
extension. extension.
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:
skipping to change at line 1420 skipping to change at line 1420
misconfiguration, caching issues, or an incomplete rollout in a misconfiguration, caching issues, or an incomplete rollout in a
multi-server deployment. This may also occur if a server loses its multi-server deployment. This may also occur if a server loses its
ECH keys, or if a deployment of ECH must be rolled back on the ECH keys, or if a deployment of ECH must be rolled back on the
server. server.
The retry mechanism repairs inconsistencies, provided the TLS server The retry mechanism repairs inconsistencies, provided the TLS server
has a certificate for the public name. If server and advertised keys has a certificate for the public name. If server and advertised keys
mismatch, the server will reject ECH and respond with mismatch, the server will reject ECH and respond with
"retry_configs". If the server does not understand the "retry_configs". If the server does not understand the
"encrypted_client_hello" extension at all, it will ignore it as "encrypted_client_hello" extension at all, it will ignore it as
required by Section 4.1.2 of [RFC8446]. Provided the server can required by Section 4.1.2 of [RFC9846]. Provided the server can
present a certificate valid for the public name, the client can present a certificate valid for the public name, the client can
safely retry with updated settings, as described in Section 6.1.6. safely retry with updated settings, as described in Section 6.1.6.
Unless ECH is disabled as a result of successfully establishing a Unless ECH is disabled as a result of successfully establishing a
connection to the public name, the client MUST NOT fall back to using connection to the public name, the client MUST NOT fall back to using
unencrypted ClientHellos, as this allows a network attacker to unencrypted ClientHellos, as this allows a network attacker to
disclose the contents of this ClientHello, including the SNI. It MAY disclose the contents of this ClientHello, including the SNI. It MAY
attempt to use another server from the DNS results, if one is attempt to use another server from the DNS results, if one is
provided. provided.
In order to ensure that the retry mechanism works successfully, In order to ensure that the retry mechanism works successfully,
servers SHOULD ensure that every endpoint which might receive a TLS servers SHOULD ensure that every endpoint which might receive a TLS
connection is provisioned with an appropriate certificate for the connection is provisioned with an appropriate certificate for the
public name. This is especially important during periods of server public name. This is especially important during periods of server
reconfiguration when different endpoints might have different reconfiguration when different endpoints might have different
configurations. configurations.
8.1.2. Middleboxes 8.1.2. Middleboxes
The requirements in [RFC8446], Section 9.3 which require proxies to The requirements in [RFC9846], Section 9.3 which require proxies to
act as conforming TLS client and server provide interoperability with act as conforming TLS client and server provide interoperability with
TLS-terminating proxies even in cases where the server supports ECH TLS-terminating proxies even in cases where the server supports ECH
but the proxy does not, as detailed below. but the proxy does not, as detailed below.
The proxy must ignore unknown parameters and generate its own The proxy must ignore unknown parameters and generate its own
ClientHello containing only parameters it understands. Thus, when ClientHello containing only parameters it understands. Thus, when
presenting a certificate to the client or sending a ClientHello to presenting a certificate to the client or sending a ClientHello to
the server, the proxy will act as if connecting to the the server, the proxy will act as if connecting to the
ClientHelloOuter server_name, which SHOULD match the public name (see ClientHelloOuter server_name, which SHOULD match the public name (see
Section 6.1) without echoing the "encrypted_client_hello" extension. Section 6.1) without echoing the "encrypted_client_hello" extension.
skipping to change at line 1506 skipping to change at line 1506
10.1. Security and Privacy Goals 10.1. Security and Privacy Goals
ECH considers two types of attackers: passive and active. Passive ECH considers two types of attackers: passive and active. Passive
attackers can read packets from the network, but they cannot perform attackers can read packets from the network, but they cannot perform
any sort of active behavior such as probing servers or querying DNS. any sort of active behavior such as probing servers or querying DNS.
A middlebox that filters based on plaintext packet contents is one A middlebox that filters based on plaintext packet contents is one
example of a passive attacker. In contrast, active attackers can example of a passive attacker. In contrast, active attackers can
also write packets into the network for malicious purposes, such as also write packets into the network for malicious purposes, such as
interfering with existing connections, probing servers, and querying interfering with existing connections, probing servers, and querying
DNS. In short, an active attacker corresponds to the conventional DNS. In short, an active attacker corresponds to the conventional
threat model [RFC3552] for TLS 1.3 [RFC8446]. threat model [RFC3552] for TLS 1.3 [RFC9846].
Passive and active attackers can exist anywhere in the network, Passive and active attackers can exist anywhere in the network,
including between the client and client-facing server, as well as including between the client and client-facing server, as well as
between the client-facing and backend servers when running ECH in between the client-facing and backend servers when running ECH in
split mode. However, for split mode in particular, ECH makes two split mode. However, for split mode in particular, ECH makes two
additional assumptions: additional assumptions:
1. The channel between each client-facing and each backend server is 1. The channel between each client-facing and each backend server is
authenticated such that the backend server only accepts messages authenticated such that the backend server only accepts messages
from trusted client-facing servers. The exact mechanism for from trusted client-facing servers. The exact mechanism for
skipping to change at line 1576 skipping to change at line 1576
Specifically, the GREASE ECH extension described in Section 6.2 does Specifically, the GREASE ECH extension described in Section 6.2 does
not change the security properties of the TLS handshake at all. Its not change the security properties of the TLS handshake at all. Its
goal is to provide "cover" for the real ECH protocol (Section 6.1), goal is to provide "cover" for the real ECH protocol (Section 6.1),
as a means of addressing the "do not stick out" requirements of as a means of addressing the "do not stick out" requirements of
[RFC8744]. See Section 10.10.4 for details. [RFC8744]. See Section 10.10.4 for details.
10.2. Unauthenticated and Plaintext DNS 10.2. Unauthenticated and Plaintext DNS
ECH supports delivery of configurations through the DNS using SVCB or ECH supports delivery of configurations through the DNS using SVCB or
HTTPS records without requiring any verifiable authenticity or HTTPS records without requiring any verifiable authenticity or
provenance information [RFCYYY1]. This means that any attacker which provenance information [RFC9848]. This means that any attacker which
can inject DNS responses or poison DNS caches, which is a common can inject DNS responses or poison DNS caches, which is a common
scenario in client access networks, can supply clients with fake ECH scenario in client access networks, can supply clients with fake ECH
configurations (so that the client encrypts data to them) or strip configurations (so that the client encrypts data to them) or strip
the ECH configurations from the response. However, in the face of an the ECH configurations from the response. However, in the face of an
attacker that controls DNS, no encryption scheme can work because the attacker that controls DNS, no encryption scheme can work because the
attacker can replace the IP address, thus blocking client attacker can replace the IP address, thus blocking client
connections, or substitute a unique IP address for each DNS name that connections, or substitute a unique IP address for each DNS name that
was looked up. Thus, using DNS records without additional was looked up. Thus, using DNS records without additional
authentication does not make the situation significantly worse. authentication does not make the situation significantly worse.
skipping to change at line 1715 skipping to change at line 1715
Attacks that rely on non-ECH traffic to infer server identity in an Attacks that rely on non-ECH traffic to infer server identity in an
ECH connection are out of scope for this document. For example, a ECH connection are out of scope for this document. For example, a
client that connects to a particular host prior to ECH deployment may client that connects to a particular host prior to ECH deployment may
later resume a connection to that same host after ECH deployment. An later resume a connection to that same host after ECH deployment. An
adversary that observes this can deduce that the ECH-enabled adversary that observes this can deduce that the ECH-enabled
connection was made to a host that the client previously connected to connection was made to a host that the client previously connected to
and which is within the same anonymity set. and which is within the same anonymity set.
10.8. Cookies 10.8. Cookies
Section 4.2.2 of [RFC8446] defines a cookie value that servers may Section 4.2.2 of [RFC9846] defines a cookie value that servers may
send in HelloRetryRequest for clients to echo in the second send in HelloRetryRequest for clients to echo in the second
ClientHello. While ECH encrypts the cookie in the second ClientHello. While ECH encrypts the cookie in the second
ClientHelloInner, the backend server's HelloRetryRequest is ClientHelloInner, the backend server's HelloRetryRequest is
unencrypted. This means differences in cookies between backend unencrypted. This means differences in cookies between backend
servers, such as lengths or cleartext components, may leak servers, such as lengths or cleartext components, may leak
information about the server identity. information about the server identity.
Backend servers in an anonymity set SHOULD NOT reveal information in Backend servers in an anonymity set SHOULD NOT reveal information in
the cookie which identifies the server. This may be done by handling the cookie which identifies the server. This may be done by handling
HelloRetryRequest statefully, thus not sending cookies, or by using HelloRetryRequest statefully, thus not sending cookies, or by using
skipping to change at line 1759 skipping to change at line 1759
Suppose the client-facing server terminates the connection (i.e., ECH Suppose the client-facing server terminates the connection (i.e., ECH
is rejected or bypassed): if the last 8 bytes of its is rejected or bypassed): if the last 8 bytes of its
ServerHello.random coincide with the confirmation signal, then the ServerHello.random coincide with the confirmation signal, then the
client will incorrectly presume acceptance and proceed as if the client will incorrectly presume acceptance and proceed as if the
backend server terminated the connection. However, the probability backend server terminated the connection. However, the probability
of a false positive occurring for a given connection is only 1 in of a false positive occurring for a given connection is only 1 in
2^64. This value is smaller than the probability of network 2^64. This value is smaller than the probability of network
connection failures in practice. connection failures in practice.
Note that the same bytes of the ServerHello.random are used to Note that the same bytes of the ServerHello.random are used to
implement downgrade protection for TLS 1.3 (see [RFC8446], implement downgrade protection for TLS 1.3 (see [RFC9846],
Section 4.1.3). These mechanisms do not interfere because the Section 4.1.3). These mechanisms do not interfere because the
backend server only signals ECH acceptance in TLS 1.3 or higher. backend server only signals ECH acceptance in TLS 1.3 or higher.
10.10. Comparison Against Criteria 10.10. Comparison Against Criteria
[RFC8744] lists several requirements for SNI encryption. In this [RFC8744] lists several requirements for SNI encryption. In this
section, we reiterate these requirements and assess the ECH design section, we reiterate these requirements and assess the ECH design
against them. against them.
10.10.1. Mitigate Cut-and-Paste Attacks 10.10.1. Mitigate Cut-and-Paste Attacks
skipping to change at line 1803 skipping to change at line 1803
connections an attacker can open. connections an attacker can open.
10.10.4. Do Not Stick Out 10.10.4. Do Not Stick Out
As a means of reducing the impact of network ossification, [RFC8744] As a means of reducing the impact of network ossification, [RFC8744]
recommends SNI-protection mechanisms be designed in such a way that recommends SNI-protection mechanisms be designed in such a way that
network operators do not differentiate connections using the network operators do not differentiate connections using the
mechanism from connections not using the mechanism. To that end, ECH mechanism from connections not using the mechanism. To that end, ECH
is designed to resemble a standard TLS handshake as much as possible. is designed to resemble a standard TLS handshake as much as possible.
The most obvious difference is the extension itself: as long as The most obvious difference is the extension itself: as long as
middleboxes ignore it, as required by [RFC8446], the rest of the middleboxes ignore it, as required by [RFC9846], the rest of the
handshake is designed to look very much as usual. handshake is designed to look very much as usual.
The GREASE ECH protocol described in Section 6.2 provides a low-risk The GREASE ECH protocol described in Section 6.2 provides a low-risk
way to evaluate the deployability of ECH. It is designed to mimic way to evaluate the deployability of ECH. It is designed to mimic
the real ECH protocol (Section 6.1) without changing the security the real ECH protocol (Section 6.1) without changing the security
properties of the handshake. The underlying theory is that if GREASE properties of the handshake. The underlying theory is that if GREASE
ECH is deployable without triggering middlebox misbehavior, and real ECH is deployable without triggering middlebox misbehavior, and real
ECH looks enough like GREASE ECH, then ECH should be deployable as ECH looks enough like GREASE ECH, then ECH should be deployable as
well. Thus, the strategy for mitigating network ossification is to well. Thus, the strategy for mitigating network ossification is to
deploy GREASE ECH widely enough to disincentivize differential deploy GREASE ECH widely enough to disincentivize differential
skipping to change at line 2097 skipping to change at line 2097
ECH mitigates this attack by requiring that OuterExtensions be ECH mitigates this attack by requiring that OuterExtensions be
referenced in order, that duplicate references be rejected, and by referenced in order, that duplicate references be rejected, and by
recommending that client-facing servers use a linear scan to perform recommending that client-facing servers use a linear scan to perform
decompression. These requirements are detailed in Section 5.1. decompression. These requirements are detailed in Section 5.1.
11. IANA Considerations 11. IANA Considerations
11.1. Update of the TLS ExtensionType Registry 11.1. Update of the TLS ExtensionType Registry
IANA has created the following entries in the existing "TLS IANA has created the following entries in the existing "TLS
ExtensionType Values" registry (defined in [RFC8446]): ExtensionType Values" registry (defined in [RFC9846]):
1. encrypted_client_hello (0xfe0d), with "TLS 1.3" column values set 1. encrypted_client_hello (0xfe0d), with "TLS 1.3" column values set
to "CH, HRR, EE", "DTLS-Only" column set to "N", and to "CH, HRR, EE", "DTLS-Only" column set to "N", and
"Recommended" column set to "Y". "Recommended" column set to "Y".
2. ech_outer_extensions (0xfd00), with the "TLS 1.3" column values 2. ech_outer_extensions (0xfd00), with the "TLS 1.3" column values
set to "CH", "DTLS-Only" column set to "N", "Recommended" column set to "CH", "DTLS-Only" column set to "N", "Recommended" column
set to "Y", and the "Comment" column set to "Only appears in set to "Y", and the "Comment" column set to "Only appears in
inner CH." inner CH."
11.2. Update of the TLS Alert Registry 11.2. Update of the TLS Alert Registry
IANA has created an entry, ech_required (121) in the existing "TLS IANA has created an entry, ech_required (121) in the existing "TLS
Alerts" registry (defined in [RFC8446]), with the "DTLS-OK" column Alerts" registry (defined in [RFC9846]), with the "DTLS-OK" column
set to "Y". set to "Y".
11.3. ECH Configuration Extension Registry 11.3. ECH Configuration Extension Registry
IANA has created a new "TLS ECHConfig Extension" registry in a new IANA has created a new "TLS ECHConfig Extension" registry in a new
"TLS Encrypted Client Hello (ECH) Configuration Extensions" registry "TLS Encrypted Client Hello (ECH) Configuration Extensions" registry
group. New registrations will list the following attributes: group. New registrations will list the following attributes:
Value: The two-byte identifier for the ECHConfigExtension, i.e., the Value: The two-byte identifier for the ECHConfigExtension, i.e., the
ECHConfigExtensionType ECHConfigExtensionType
Extension Name: Name of the ECHConfigExtension Extension Name: Name of the ECHConfigExtension
Recommended: A "Y" or "N" value indicating if the TLS Working Group Recommended: A "Y" or "N" value indicating if the TLS Working Group
recommends that the extension be supported. This column is recommends that the extension be supported. This column is
assigned a value of "N" unless explicitly requested. Adding a assigned a value of "N" unless explicitly requested. Adding a
value of "Y" requires Standards Action [RFC8126]. value of "Y" requires Standards Action [RFC8126].
Reference: The specification where the ECHConfigExtension is defined Reference: The specification where the ECHConfigExtension is defined
Notes: Any notes associated with the entry Notes: Any notes associated with the entry
New entries in the "TLS ECHConfig Extension" registry are subject to New entries in the "TLS ECHConfig Extension" registry are subject to
the Specification Required registration policy ([RFC8126], the Specification Required registration policy ([RFC8126],
Section 4.6), with the policies described in [RFC8447], Section 17. Section 4.6), with the policies described in [RFC9847], Section 16.
IANA has added the following note to the "TLS ECHConfig Extension" IANA has added the following note to the "TLS ECHConfig Extension"
registry: registry:
Note: The role of the designated expert is described in RFC 8447. Note: The role of the designated expert is described in RFC 9847.
The designated expert [RFC8126] ensures that the specification is The designated expert [RFC8126] ensures that the specification is
publicly available. It is sufficient to have an Internet-Draft (that publicly available. It is sufficient to have an Internet-Draft (that
is posted and never published as an RFC) or a document from another is posted and never published as an RFC) or a document from another
standards body, industry consortium, university site, etc. The standards body, industry consortium, university site, etc. The
expert may provide more in-depth reviews, but their approval should expert may provide more in-depth reviews, but their approval should
not be taken as an endorsement of the extension. not be taken as an endorsement of the extension.
This document defines several Reserved values for ECH configuration This document defines several Reserved values for ECH configuration
extensions to be used for "greasing" as described in Section 6.2.2. extensions to be used for "greasing" as described in Section 6.2.2.
skipping to change at line 2191 skipping to change at line 2191
[RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for
Writing an IANA Considerations Section in RFCs", BCP 26, Writing an IANA Considerations Section in RFCs", BCP 26,
RFC 8126, DOI 10.17487/RFC8126, June 2017, RFC 8126, DOI 10.17487/RFC8126, June 2017,
<https://www.rfc-editor.org/info/rfc8126>. <https://www.rfc-editor.org/info/rfc8126>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>. May 2017, <https://www.rfc-editor.org/info/rfc8174>.
[RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol
Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
<https://www.rfc-editor.org/info/rfc8446>.
[RFC8447] Salowey, J. and S. Turner, "IANA Registry Updates for TLS
and DTLS", RFC 8447, DOI 10.17487/RFC8447, August 2018,
<https://www.rfc-editor.org/info/rfc8447>.
[RFC9147] Rescorla, E., Tschofenig, H., and N. Modadugu, "The [RFC9147] Rescorla, E., Tschofenig, H., and N. Modadugu, "The
Datagram Transport Layer Security (DTLS) Protocol Version Datagram Transport Layer Security (DTLS) Protocol Version
1.3", RFC 9147, DOI 10.17487/RFC9147, April 2022, 1.3", RFC 9147, DOI 10.17487/RFC9147, April 2022,
<https://www.rfc-editor.org/info/rfc9147>. <https://www.rfc-editor.org/info/rfc9147>.
[RFC9460] Schwartz, B., Bishop, M., and E. Nygren, "Service Binding [RFC9460] Schwartz, B., Bishop, M., and E. Nygren, "Service Binding
and Parameter Specification via the DNS (SVCB and HTTPS and Parameter Specification via the DNS (SVCB and HTTPS
Resource Records)", RFC 9460, DOI 10.17487/RFC9460, Resource Records)", RFC 9460, DOI 10.17487/RFC9460,
November 2023, <https://www.rfc-editor.org/info/rfc9460>. November 2023, <https://www.rfc-editor.org/info/rfc9460>.
[RFC9525] Saint-Andre, P. and R. Salz, "Service Identity in TLS", [RFC9525] Saint-Andre, P. and R. Salz, "Service Identity in TLS",
RFC 9525, DOI 10.17487/RFC9525, November 2023, RFC 9525, DOI 10.17487/RFC9525, November 2023,
<https://www.rfc-editor.org/info/rfc9525>. <https://www.rfc-editor.org/info/rfc9525>.
[RFC9846] Rescorla, E., "The Transport Layer Security (TLS) Protocol
Version 1.3", RFC 9846, DOI 10.17487/RFC9846, February
2026, <https://www.rfc-editor.org/info/rfc9846>.
[RFC9847] Salowey, J. and S. Turner, "IANA Registry Updates for TLS
and DTLS", RFC 9847, DOI 10.17487/RFC9847, December 2025,
<https://www.rfc-editor.org/info/rfc9847>.
12.2. Informative References 12.2. Informative References
[DNS-TERMS] [DNS-TERMS]
Hoffman, P. and K. Fujiwara, "DNS Terminology", BCP 219, Hoffman, P. and K. Fujiwara, "DNS Terminology", BCP 219,
RFC 9499, DOI 10.17487/RFC9499, March 2024, RFC 9499, DOI 10.17487/RFC9499, March 2024,
<https://www.rfc-editor.org/info/rfc9499>. <https://www.rfc-editor.org/info/rfc9499>.
[ECH-Analysis] [ECH-Analysis]
Bhargavan, K., Cheval, V., and C. Wood, "A Symbolic Bhargavan, K., Cheval, V., and C. Wood, "A Symbolic
Analysis of Privacy for TLS 1.3 with Encrypted Client Analysis of Privacy for TLS 1.3 with Encrypted Client
skipping to change at line 2289 skipping to change at line 2289
[RFC8744] Huitema, C., "Issues and Requirements for Server Name [RFC8744] Huitema, C., "Issues and Requirements for Server Name
Identification (SNI) Encryption in TLS", RFC 8744, Identification (SNI) Encryption in TLS", RFC 8744,
DOI 10.17487/RFC8744, July 2020, DOI 10.17487/RFC8744, July 2020,
<https://www.rfc-editor.org/info/rfc8744>. <https://www.rfc-editor.org/info/rfc8744>.
[RFC9250] Huitema, C., Dickinson, S., and A. Mankin, "DNS over [RFC9250] Huitema, C., Dickinson, S., and A. Mankin, "DNS over
Dedicated QUIC Connections", RFC 9250, Dedicated QUIC Connections", RFC 9250,
DOI 10.17487/RFC9250, May 2022, DOI 10.17487/RFC9250, May 2022,
<https://www.rfc-editor.org/info/rfc9250>. <https://www.rfc-editor.org/info/rfc9250>.
[RFCYYY1] Schwartz, B., Bishop, M., and E. Nygren, "Bootstrapping [RFC9848] Schwartz, B., Bishop, M., and E. Nygren, "Bootstrapping
TLS Encrypted ClientHello with DNS Service Bindings", TLS Encrypted ClientHello with DNS Service Bindings",
RFC YYY1, DOI 10.17487/RFCYYY1, December 2025, RFC 9848, DOI 10.17487/RFC9848, February 2026,
<https://www.rfc-editor.org/info/rfcYYY1>. <https://www.rfc-editor.org/info/rfc9848>.
[WHATWG-IPV4] [WHATWG-IPV4]
WHATWG, "URL - IPv4 Parser", WHATWG Living Standard, May WHATWG, "URL - IPv4 Parser", WHATWG Living Standard, May
2021, <https://url.spec.whatwg.org/#concept-ipv4-parser>. 2021, <https://url.spec.whatwg.org/>. Commit snapshot:
<https://url.spec.whatwg.org/commit- snapshots/1b8b8c55eb4
bed9f139c9a439fb1c1bf5566b619/#concept- ipv4-parser>.
Appendix A. Linear-Time Outer Extension Processing Appendix A. Linear-Time Outer Extension Processing
The following procedure processes the "ech_outer_extensions" The following procedure processes the "ech_outer_extensions"
extension (see Section 5.1) in linear time, ensuring that each extension (see Section 5.1) in linear time, ensuring that each
referenced extension in the ClientHelloOuter is included at most referenced extension in the ClientHelloOuter is included at most
once: once:
1. Let I be initialized to zero and N be set to the number of 1. Let I be initialized to zero and N be set to the number of
extensions in ClientHelloOuter. extensions in ClientHelloOuter.
 End of changes. 36 change blocks. 
43 lines changed or deleted 45 lines changed or added

This html diff was produced by rfcdiff 1.48.