rfc9849v2.txt   rfc9849.txt 
Internet Engineering Task Force (IETF) E. Rescorla Internet Engineering Task Force (IETF) E. Rescorla
Request for Comments: 9849 Knight-Georgetown Institute Request for Comments: 9849 Knight-Georgetown Institute
Category: Standards Track K. Oku Category: Standards Track K. Oku
ISSN: 2070-1721 Fastly ISSN: 2070-1721 Fastly
N. Sullivan N. Sullivan
Cryptography Consulting LLC Cryptography Consulting LLC
C. A. Wood C. A. Wood
Cloudflare Cloudflare
November 2025 December 2025
TLS Encrypted Client Hello TLS Encrypted Client Hello
Abstract Abstract
This document describes a mechanism in Transport Layer Security (TLS) This document describes a mechanism in Transport Layer Security (TLS)
for encrypting a ClientHello message under a server public key. for encrypting a ClientHello message under a server public key.
Status of This Memo Status of This Memo
skipping to change at line 191 skipping to change at line 191
Client <-----> | private.example.org | Client <-----> | private.example.org |
| | | |
| public.example.com | | public.example.com |
| | | |
+---------------------+ +---------------------+
Server Server
(Client-Facing and Backend Combined) (Client-Facing and Backend Combined)
Figure 1: Shared Mode Topology Figure 1: Shared Mode Topology
In Shared Mode, the provider is the origin server for all the domains In shared mode, the provider is the origin server for all the domains
whose DNS records point to it. In this mode, the TLS connection is whose DNS records point to it. In this mode, the TLS connection is
terminated by the provider. terminated by the provider.
+--------------------+ +---------------------+ +--------------------+ +---------------------+
| | | | | | | |
| 2001:DB8::1111 | | 2001:DB8::EEEE | | 2001:DB8::1111 | | 2001:DB8::EEEE |
Client <----------------------------->| | Client <----------------------------->| |
| public.example.com | | private.example.org | | public.example.com | | private.example.org |
| | | | | | | |
+--------------------+ +---------------------+ +--------------------+ +---------------------+
skipping to change at line 216 skipping to change at line 216
In split mode, the provider is not the origin server for private In split mode, the provider is not the origin server for private
domains. Rather, the DNS records for private domains point to the domains. Rather, the DNS records for private domains point to the
provider, and the provider's server relays the connection back to the provider, and the provider's server relays the connection back to the
origin server, who terminates the TLS connection with the client. origin server, who terminates the TLS connection with the client.
Importantly, the service provider does not have access to the Importantly, the service provider does not have access to the
plaintext of the connection beyond the unencrypted portions of the plaintext of the connection beyond the unencrypted portions of the
handshake. handshake.
In the remainder of this document, we will refer to the ECH-service In the remainder of this document, we will refer to the ECH-service
provider as the "client-facing server" and to the TLS terminator as provider as the "client-facing server" and to the TLS terminator as
the "backend server". These are the same entity in Shared Mode, but the "backend server". These are the same entity in shared mode, but
in split mode, the client-facing and backend servers are physically in split mode, the client-facing and backend servers are physically
separated. separated.
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
skipping to change at line 523 skipping to change at line 523
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 [RFC8446]. In DTLS, it uses the ClientHello
structured defined in Section 5.3 of [RFC9147]. This does not structure defined in Section 5.3 of [RFC9147]. This does not include
include Handshake structure's four-byte header in TLS, nor twelve- Handshake structure's four-byte header in TLS, nor twelve-byte header
byte header in DTLS. The zeros field MUST be all zeroes of length in DTLS. The zeros field MUST be all zeroes 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:
skipping to change at line 677 skipping to change at line 677
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 D.4 of [RFC8446]) 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
the "server_name" extension. Clients that do not follow this the "server_name" extension. Clients that do not follow this
step, or place a different value in the "server_name" extension, step, or place a different value in the "server_name" extension,
risk breaking the retry mechanism described in Section 6.1.6 or risk breaking the retry mechanism described in Section 6.1.6 or
failing to interoperate with servers that require this step to be failing to interoperate with servers that require this step to be
done; see Section 7.1. done; see Section 7.1.
skipping to change at line 1131 skipping to change at line 1131
application-level warning message when these are observed. application-level warning message when these are observed.
* By giving the extraneous configurations an invalid public key and * By giving the extraneous configurations an invalid public key and
a public name not associated with the server so that the initial a public name not associated with the server so that the initial
ClientHelloOuter will not be decryptable and the server cannot ClientHelloOuter will not be decryptable and the server cannot
perform the recovery flow described in Section 6.1.6. perform the recovery flow described in Section 6.1.6.
7. Server Behavior 7. Server Behavior
As described in Section 3.1, servers can play two roles, either as As described in Section 3.1, servers can play two roles, either as
the client-facing server or as the back-end 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.
In split mode, a client-facing server which receives a ClientHello In split mode, a client-facing server which receives a ClientHello
skipping to change at line 1201 skipping to change at line 1201
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, context = SetupBaseR(ECHClientHello.enc, skR,
"tls ech" || 0x00 || ECHConfig) "tls ech" || 0x00 || ECHConfig)
EncodedClientHelloInner = context.Open(ClientHelloOuterAAD, EncodedClientHelloInner = context.Open(ClientHelloOuterAAD,
ECHClientHello.payload) 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 1278 skipping to change at line 1278
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 1709 skipping to change at line 1709
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 [RFC8446] 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
the same cookie construction for all backend servers. the same cookie construction for all backend servers.
Note that, if the cookie includes a key name, analogous to Section 4 Note that, if the cookie includes a key name, analogous to Section 4
of [RFC5077], this may leak information if different backend servers of [RFC5077], this may leak information if different backend servers
skipping to change at line 2113 skipping to change at line 2113
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 extension is TLS Recommended: A "Y" or "N" value indicating if the TLS Working Group
WG 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 with 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 [RFC8447], Section 17.
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 8447.
skipping to change at line 2281 skipping to change at line 2281
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 [RFCYYY1] 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, November 2025, RFC YYY1, DOI 10.17487/RFCYYY1, December 2025,
<https://www.rfc-editor.org/info/rfcYYY1>. <https://www.rfc-editor.org/info/rfcYYY1>.
[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/#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
 End of changes. 12 change blocks. 
15 lines changed or deleted 15 lines changed or added

This html diff was produced by rfcdiff 1.48.