| Internet-Draft | TLS Encrypted Client Hello | October 2022 |
| Rescorla, et al. | Expires 6 April 2023 | [Page] |
This document describes a mechanism in Transport Layer Security (TLS) forencrypting a ClientHello message under a server public key.¶
This note is to be removed before publishing as an RFC.¶
Source for this draft and an issue tracker can be found athttps://github.com/tlswg/draft-ietf-tls-esni.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is athttps://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 6 April 2023.¶
Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
DISCLAIMER: This draft is work-in-progress and has not yet seen significant (orreally any) security analysis. It should not be used as a basis for buildingproduction systems. This published version of the draft has been designatedan "implementation draft" for testing and interop purposes.¶
Although TLS 1.3[RFC8446] encrypts most of the handshake, including theserver certificate, there are several ways in which an on-path attacker canlearn private information about the connection. The plaintext Server NameIndication (SNI) extension in ClientHello messages, which leaks the targetdomain for a given connection, is perhaps the most sensitive, unencryptedinformation in TLS 1.3.¶
The target domain may also be visible through other channels, such as plaintextclient DNS queries or visible server IP addresses. However, DoH[RFC8484]and DPRIVE[RFC7858][RFC8094] provide mechanisms for clients to concealDNS lookups from network inspection, and many TLS servers host multiple domainson the same IP address. Private origins may also be deployed behind a commonprovider, such as a reverse proxy. In such environments, the SNI remains theprimary explicit signal used to determine the server's identity.¶
This document specifies a new TLS extension, called Encrypted Client Hello(ECH), that allows clients to encrypt their ClientHello to such a deployment.This protects the SNI and other potentially sensitive fields, such as the ALPNlist[RFC7301]. Co-located servers with consistent externally visible TLSconfigurations, including supported versions and cipher suites, form ananonymity set. Usage of this mechanism reveals that a client is connecting to aparticular service provider, but does not reveal which server from theanonymity set terminates the connection.¶
ECH is only supported with (D)TLS 1.3[RFC8446] and newer versions of theprotocol.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD","SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in thisdocument are to be interpreted as described in BCP 14[RFC2119][RFC8174]when, and only when, they appear in all capitals, as shown here. All TLSnotation comes from[RFC8446],Section 3.¶
This protocol is designed to operate in one of two topologies illustrated below,which we call "Shared Mode" and "Split Mode".¶
+---------------------+ | | | 2001:DB8::1111 | | |Client <-----> | private.example.org | | | | public.example.com | | | +---------------------+ Server (Client-Facing and Backend Combined)
In Shared Mode, the provider is the origin server for all the domains whose DNSrecords point to it. In this mode, the TLS connection is terminated by theprovider.¶
+--------------------+ +---------------------+ | | | | | 2001:DB8::1111 | | 2001:DB8::EEEE |Client <----------------------------->| | | public.example.com | | private.example.com | | | | | +--------------------+ +---------------------+ Client-Facing Server Backend Server
In Split Mode, the provider is not the origin server for private domains.Rather, the DNS records for private domains point to the provider, and theprovider's server relays the connection back to the origin server, whoterminates the TLS connection with the client. Importantly, the service providerdoes not have access to the plaintext of the connection beyond the unencryptedportions of the handshake.¶
In the remainder of this document, we will refer to the ECH-service provider asthe "client-facing server" and to the TLS terminator as the "backend server".These are the same entity in Shared Mode, but in Split Mode, the client-facingand backend servers are physically separated.¶
A client-facing server enables ECH by publishing an ECH configuration, whichis an encryption public key and associated metadata. The server must publishthis for all the domains it serves via Shared or Split Mode. This documentdefines the ECH configuration's format, but delegates DNS publication detailsto[HTTPS-RR]. Other delivery mechanisms are alsopossible. For example, the client may have the ECH configuration preconfigured.¶
When a client wants to establish a TLS session with some backend server, itconstructs a private ClientHello, referred to as the ClientHelloInner.The client then constructs a public ClientHello, referred to as theClientHelloOuter. The ClientHelloOuter contains innocuous values forsensitive extensions and an "encrypted_client_hello" extension(Section 5), which carries the encrypted ClientHelloInner.Finally, the client sends ClientHelloOuter to the server.¶
The server takes one of the following actions:¶
Upon receiving the server's response, the client determines whether or not ECHwas accepted (Section 6.1.4) and proceeds with the handshakeaccordingly. When ECH is rejected, the resulting connection is not usable bythe client for application data. Instead, ECH rejection allows the client toretry with up-to-date configuration (Section 6.1.6).¶
The primary goal of ECH is to ensure that connections to servers in the sameanonymity set are indistinguishable from one another. Moreover, it shouldachieve this goal without affecting any existing security properties of TLS 1.3.SeeSection 10.1 for more details about the ECH security and privacy goals.¶
ECH uses HPKE for public key encryption[I-D.irtf-cfrg-hpke].The ECH configuration is defined by the followingECHConfig structure.¶
opaque HpkePublicKey<1..2^16-1>; uint16 HpkeKemId; // Defined in I-D.irtf-cfrg-hpke uint16 HpkeKdfId; // Defined in I-D.irtf-cfrg-hpke uint16 HpkeAeadId; // Defined in I-D.irtf-cfrg-hpke struct { HpkeKdfId kdf_id; HpkeAeadId aead_id; } HpkeSymmetricCipherSuite; struct { uint8 config_id; HpkeKemId kem_id; HpkePublicKey public_key; HpkeSymmetricCipherSuite cipher_suites<4..2^16-4>; } HpkeKeyConfig; struct { HpkeKeyConfig key_config; uint8 maximum_name_length; opaque public_name<1..255>; Extension extensions<0..2^16-1>; } ECHConfigContents; struct { uint16 version; uint16 length; select (ECHConfig.version) { case 0xfe0d: ECHConfigContents contents; } } ECHConfig;¶The structure contains the following fields:¶
The version of ECH for which this configuration is used. Beginning withdraft-08, the version is the same as the code point for the"encrypted_client_hello" extension. Clients MUST ignore anyECHConfigstructure with a version they do not support.¶
The length, in bytes, of the next field. This length field allowsimplementations to skip over the elements in such a list where they cannotparse the specific version of ECHConfig.¶
An opaque byte string whose contents depend on the version. For thisspecification, the contents are anECHConfigContents structure.¶
TheECHConfigContents structure contains the following fields:¶
AHpkeKeyConfig structure carrying the configuration information associatedwith the HPKE public key. Note that this structure contains theconfig_idfield, which applies to the entire ECHConfigContents.¶
The longest name of a backend server, if known. If not known, this value canbe set to zero. It is used to compute padding (Section 6.1.3) and does notconstrain server name lengths. Names may exceed this length if, e.g.,the server uses wildcard names or added new names to the anonymity set.¶
The DNS name of the client-facing server, i.e., the entity trustedto update the ECH configuration. This is used to correct misconfigured clients,as described inSection 6.1.6.¶
Clients MUST ignore anyECHConfig structure whose public_name is notparsable as a dot-separated sequence of LDH labels, as defined in[RFC5890],Section 2.3.1 or which begins or end with an ASCII dot.¶
Clients SHOULD ignore theECHConfig if it contains an encoded IPv4 address.To determine if a public_name value is an IPv4 address, clients can invoke theIPv4 parser algorithm in[WHATWG-IPV4]. It returns a value when the input isan IPv4 address.¶
SeeSection 6.1.7 for how the client interprets and validates thepublic_name.¶
A list of extensions that the client must take into consideration whengenerating a ClientHello message. These are described below(Section 4.2).¶
[[OPEN ISSUE: determine if clients should enforce a 63-octet label limit forpublic_name]][[OPEN ISSUE: fix reference to WHATWG-IPV4]]¶
TheHpkeKeyConfig structure contains the following fields:¶
A one-byte identifier for the given HPKE key configuration. This is used byclients to indicate the key used for ClientHello encryption.Section 4.1describes how client-facing servers allocate this value.¶
The HPKE KEM identifier corresponding topublic_key. Clients MUST ignore anyECHConfig structure with a key using a KEM they do not support.¶
The HPKE public key used by the client to encrypt ClientHelloInner.¶
The list of HPKE KDF and AEAD identifier pairs clients can use for encryptingClientHelloInner. SeeSection 6.1 for how clients choose from this list.¶
The client-facing server advertises a sequence of ECH configurations to clients,serialized as follows.¶
ECHConfig ECHConfigList<1..2^16-1>;¶
TheECHConfigList structure contains one or moreECHConfig structures indecreasing order of preference. This allows a server to support multipleversions of ECH and multiple sets of ECH parameters.¶
A client-facing server has a set of known ECHConfig values, with correspondingprivate keys. This set SHOULD contain the currently published values, as well asprevious values that may still be in use, since clients may cache DNS recordsup to a TTL or longer.¶
Section 7.1 describes a trial decryption process for decrypting theClientHello. This can impact performance when the client-facing server maintainsmany known ECHConfig values. To avoid this, the client-facing server SHOULDallocate distinctconfig_id values for each ECHConfig in its known set. TheRECOMMENDED strategy is via rejection sampling, i.e., to randomly selectconfig_id repeatedly until it does not match any known ECHConfig.¶
It is not necessary forconfig_id values across different client-facingservers to be distinct. A backend server may be hosted behind two differentclient-facing servers with collidingconfig_id values without any performanceimpact. Values may also be reused if the previous ECHConfig is no longer in theknown set.¶
ECH configuration extensions are used to provide room for additionalfunctionality as needed. SeeSection 12 for guidance onwhich types of extensions are appropriate for this structure.¶
The format is as defined in[RFC8446],Section 4.2.The same interpretation rules apply: extensions MAY appear in any order, butthere MUST NOT be more than one extension of the same type in the extensionsblock. An extension can be tagged as mandatory by using an extension typecodepoint with the high order bit set to 1.¶
Clients MUST parse the extension list and check for unsupported mandatoryextensions. If an unsupported mandatory extension is present, clients MUSTignore theECHConfig.¶
To offer ECH, the client sends an "encrypted_client_hello" extension in theClientHelloOuter. When it does, it MUST also send the extension inClientHelloInner.¶
enum { encrypted_client_hello(0xfe0d), (65535) } ExtensionType;¶The payload of the extension has the following structure:¶
enum { outer(0), inner(1) } ECHClientHelloType; struct { ECHClientHelloType type; select (ECHClientHello.type) { case outer: HpkeSymmetricCipherSuite cipher_suite; uint8 config_id; opaque enc<0..2^16-1>; opaque payload<1..2^16-1>; case inner: Empty; }; } ECHClientHello;¶The outer extension uses theouter variant and the inner extension uses theinner variant. The inner extension has an empty payload. The outerextension has the following fields:¶
The ECHConfigContents.key_config.config_id for the chosen ECHConfig.¶
The cipher suite used to encrypt ClientHelloInner. This MUST match a valueprovided in the correspondingECHConfigContents.cipher_suites list.¶
The HPKE encapsulated key, used by servers to decrypt the correspondingpayload field. This field is empty in a ClientHelloOuter sent in response toHelloRetryRequest.¶
The serialized and encrypted ClientHelloInner structure, encrypted using HPKEas described inSection 6.1.¶
When a client offers theouter version of an "encrypted_client_hello"extension, the server MAY include an "encrypted_client_hello" extension in itsEncryptedExtensions message, as described inSection 7.1, with thefollowing payload:¶
struct { ECHConfigList retry_configs; } ECHEncryptedExtensions;¶The response is valid only when the server used the ClientHelloOuter. If theserver sent this extension in response to theinner variant, then the clientMUST abort with an "unsupported_extension" alert.¶
An ECHConfigList structure containing one or more ECHConfig structures, indecreasing order of preference, to be used by the client as described inSection 6.1.6. These are known as the server's "retry configurations".¶
Finally, when the client offers the "encrypted_client_hello", if the payload istheinner variant and the server responds with HelloRetryRequest, it MUSTinclude an "encrypted_client_hello" extension with the following payload:¶
struct { opaque confirmation[8]; } ECHHelloRetryRequest;¶The value of ECHHelloRetryRequest.confirmation is set tohrr_accept_confirmation as described inSection 7.2.1.¶
This document also defines the "ech_required" alert, which the client MUST sendwhen it offered an "encrypted_client_hello" extension that was not accepted bythe server. (SeeSection 11.2.)¶
Before encrypting, the client pads and optionally compresses ClientHelloInnerinto a EncodedClientHelloInner structure, defined below:¶
struct { ClientHello client_hello; uint8 zeros[length_of_padding]; } EncodedClientHelloInner;¶Theclient_hello field is computed by first making a copy of ClientHelloInnerand setting thelegacy_session_id field to the empty string. Note this fielduses the ClientHello structure, defined inSection 4.1.2 of [RFC8446] whichdoes not include the Handshake structure's four byte header. Thezeros fieldMUST be all zeroes.¶
Repeating large extensions, such as "key_share" with post-quantum algorithms,between ClientHelloInner and ClientHelloOuter can lead to excessive size. Toreduce the size impact, the client MAY substitute extensions which it knowswill be duplicated in ClientHelloOuter. It does so by removing and replacingextensions from EncodedClientHelloInner with a single "ech_outer_extensions"extension, defined as follows:¶
enum { ech_outer_extensions(0xfd00), (65535) } ExtensionType; ExtensionType OuterExtensions<2..254>;¶OuterExtensions contains the removed ExtensionType values. Each value referencesthe matching extension in ClientHelloOuter. The values MUST be orderedcontiguously in ClientHelloInner, and the "ech_outer_extensions" extension MUSTbe inserted in the corresponding position in EncodedClientHelloInner.Additionally, the extensions MUST appear in ClientHelloOuter in the samerelative order. However, there is no requirement that they be contiguous. Forexample, OuterExtensions may contain extensions A, B, C, while ClientHelloOutercontains extensions A, D, B, C, E, F.¶
The "ech_outer_extensions" extension can only be included inEncodedClientHelloInner, and MUST NOT appear in either ClientHelloOuter orClientHelloInner.¶
Finally, the client pads the message by setting thezeros field to a bytestring whose contents are all zeros and whose length is the amount of paddingto add.Section 6.1.3 describes a recommended padding scheme.¶
The client-facing server computes ClientHelloInner by reversing this process.First it parses EncodedClientHelloInner, interpreting all bytes afterclient_hello as padding. If any padding byte is non-zero, the server MUSTabort the connection with an "illegal_parameter" alert.¶
Next it makes a copy of theclient_hello field and copies thelegacy_session_id field from ClientHelloOuter. It then looks for an"ech_outer_extensions" extension. If found, it replaces the extension with thecorresponding sequence of extensions in the ClientHelloOuter. The server MUSTabort the connection with an "illegal_parameter" alert if any of the followingare true:¶
These requirements prevent an attacker from performing a packet amplificationattack, by crafting a ClientHelloOuter which decompresses to a much largerClientHelloInner. This is discussed further inSection 10.11.4.¶
Implementations SHOULD bound the time to compute a ClientHelloInnerproportionally to the ClientHelloOuter size. If the cost is disproportionatelylarge, a malicious client could exploit this in a denial of service attack.Appendix B describes a linear-time procedure that may be usedfor this purpose.¶
To prevent a network attacker from modifying the reconstructed ClientHelloInner(seeSection 10.11.3), ECH authenticates ClientHelloOuter bypassing ClientHelloOuterAAD as the associated data for HPKE sealing and openingoperations. The ClientHelloOuterAAD is a serialized ClientHello structure,defined inSection 4.1.2 of [RFC8446], which matches the ClientHelloOuterexcept thepayload field of the "encrypted_client_hello" is replaced with abyte string of the same length but whose contents are zeros. This value doesnot include the four-byte header from the Handshake structure.¶
The client follows the procedure inSection 6.1.1 to firstconstruct ClientHelloOuterAAD with a placeholderpayload field, then replacethe field with the encrypted value to compute ClientHelloOuter.¶
The server then receives ClientHelloOuter and computes ClientHelloOuterAAD bymaking a copy and replacing the portion corresponding to thepayload fieldwith zeros.¶
The payload and the placeholder strings have the same length, so it is notnecessary for either side to recompute length prefixes when applying the abovetransformations.¶
The decompression process inSection 5.1 forbids"encrypted_client_hello" in OuterExtensions. This ensures the unauthenticatedportion of ClientHelloOuter is not incorporated into ClientHelloInner.¶
Clients that implement the ECH extension behave in one of two ways: either theyoffer a real ECH extension, as described inSection 6.1; or they send a GREASEECH extension, as described inSection 6.2. Clients of the latter type do notnegotiate ECH. Instead, they generate a dummy ECH extension that is ignored bythe server. (SeeSection 10.9.4 for an explanation.) The client offers ECHif it is in possession of a compatible ECH configuration and sends GREASE ECHotherwise.¶
To offer ECH, the client first chooses a suitable ECHConfig from the server'sECHConfigList. To determine if a givenECHConfig is suitable, it checks thatit supports the KEM algorithm identified byECHConfig.contents.kem_id, atleast one KDF/AEAD algorithm identified byECHConfig.contents.cipher_suites,and the version of ECH indicated byECHConfig.contents.version. Once asuitable configuration is found, the client selects the cipher suite it willuse for encryption. It MUST NOT choose a cipher suite or version not advertisedby the configuration. If no compatible configuration is found, then the clientSHOULD proceed as described inSection 6.2.¶
Next, the client constructs the ClientHelloInner message just as it does astandard ClientHello, with the exception of the following rules:¶
inner asdescribed inSection 5. (This requirement is not applicablewhen the "encrypted_client_hello" extension is generated as described inSection 6.2.)¶The client then constructs EncodedClientHelloInner as described inSection 5.1. It also computes an HPKE encryption context andenc valueas:¶
pkR = DeserializePublicKey(ECHConfig.contents.public_key) enc, context = SetupBaseS(pkR, "tls ech" || 0x00 || ECHConfig)¶
Next, it constructs a partial ClientHelloOuterAAD as it does a standardClientHello, with the exception of the following rules:¶
ECHConfig.contents.public_name MUST be placed in the"server_name" extension.¶Note that these rules may change in the presence of an application profilespecifying otherwise.¶
The client might duplicate non-sensitive extensions in both messages. However,implementations need to take care to ensure that sensitive extensions are notoffered in the ClientHelloOuter. SeeSection 10.5 for additionalguidance.¶
Finally, the client encrypts the EncodedClientHelloInner with the above values,as described inSection 6.1.1, to construct a ClientHelloOuter. Itsends this to the server, and processes the response as described inSection 6.1.4.¶
Given an EncodedClientHelloInner, an HPKE encryption context andenc value,and a partial ClientHelloOuterAAD, the client constructs a ClientHelloOuter asfollows.¶
First, the client determines the length L of encrypting EncodedClientHelloInnerwith the selected HPKE AEAD. This is typically the sum of the plaintext lengthand the AEAD tag length. The client then completes the ClientHelloOuterAAD withan "encrypted_client_hello" extension. This extension value contains the outervariant of ECHClientHello with the following fields:¶
config_id, the identifier corresponding to the chosen ECHConfig structure;¶cipher_suite, the client's chosen cipher suite;¶enc, as given above; and¶payload, a placeholder byte string containing L zeros.¶If configuration identifiers (seeSection 10.4) are to be ignored,config_id SHOULD be set to a randomly generated byte in the firstClientHelloOuter and, in the event of HRR, MUST be left unchanged forthe second ClientHelloOuter.¶
The client serializes this structure to construct the ClientHelloOuterAAD.It then computes the final payload as:¶
final_payload = context.Seal(ClientHelloOuterAAD, EncodedClientHelloInner)¶
Finally, the client replacespayload withfinal_payload to obtainClientHelloOuter. The two values have the same length, so it is not necessaryto recompute length prefixes in the serialized structure.¶
Note this construction requires the "encrypted_client_hello" be computed afterall other extensions. This is possible because the ClientHelloOuter's"pre_shared_key" extension is either omitted, or uses a random binder(Section 6.1.2).¶
When offering ECH, the client is not permitted to advertise PSK identities inthe ClientHelloOuter. However, the client can send a "pre_shared_key" extensionin the ClientHelloInner. In this case, when resuming a session with the client,the backend server sends a "pre_shared_key" extension in its ServerHello. Thiswould appear to a network observer as if the the server were sending thisextension without solicitation, which would violate the extension rulesdescribed in[RFC8446]. Sending a GREASE "pre_shared_key" extension in theClientHelloOuter makes it appear to the network as if the extension werenegotiated properly.¶
The client generates the extension payload by constructing anOfferedPsksstructure (see[RFC8446],Section 4.2.11) as follows. For each PSK identityadvertised in the ClientHelloInner, the client generates a random PSK identitywith the same length. It also generates a random, 32-bit, unsigned integer touse as theobfuscated_ticket_age. Likewise, for each inner PSK binder, theclient generates a random string of the same length.¶
Per the rules ofSection 6.1, the server is not permitted to resume aconnection in the outer handshake. If ECH is rejected and the client-facingserver replies with a "pre_shared_key" extension in its ServerHello, then theclient MUST abort the handshake with an "illegal_parameter" alert.¶
This section describes a deterministic padding mechanism based on the followingobservation: individual extensions can reveal sensitive information throughtheir length. Thus, each extension in the inner ClientHello may requiredifferent amounts of padding. This padding may be fully determined by theclient's configuration or may require server input.¶
By way of example, clients typically support a small number of applicationprofiles. For instance, a browser might support HTTP with ALPN values["http/1.1", "h2"] and WebRTC media with ALPNs ["webrtc", "c-webrtc"]. ClientsSHOULD pad this extension by rounding up to the total size of the longest ALPNextension across all application profiles. The target padding length of mostClientHello extensions can be computed in this way.¶
In contrast, clients do not know the longest SNI value in the client-facingserver's anonymity set without server input. Clients SHOULD use the ECHConfig'smaximum_name_length field as follows, where L is themaximum_name_lengthvalue.¶
Finally, the client SHOULD pad the entire message as follows:¶
This rounds the length of EncodedClientHelloInner up to a multiple of 32 bytes,reducing the set of possible lengths across all clients.¶
In addition to padding ClientHelloInner, clients and servers will also need topad all other handshake messages that have sensitive-length fields. For example,if a client proposes ALPN values in ClientHelloInner, the server-selected valuewill be returned in an EncryptedExtension, so that handshake message also needsto be padded using TLS record layer padding.¶
As described inSection 7, the server may either accept ECH and useClientHelloInner or reject it and use ClientHelloOuter. This is determined bythe server's initial message.¶
If the message does not negotiate TLS 1.3 or higher, the server has rejectedECH. Otherwise, it is either a ServerHello or HelloRetryRequest.¶
If the message is a ServerHello, the client computesaccept_confirmation asdescribed inSection 7.2. If this value matches the last 8 bytes ofServerHello.random, the server has accepted ECH. Otherwise, it has rejectedECH.¶
If the message is a HelloRetryRequest, the client checks for the"encrypted_client_hello" extension. If none is found, the server has rejectedECH. Otherwise, if it has a length other than 8, the client aborts the handshakewith a "decode_error" alert. Otherwise, the client computeshrr_accept_confirmation as described inSection 7.2.1. If this valuematches the extension payload, the server has accepted ECH. Otherwise, it hasrejected ECH.¶
[[OPEN ISSUE: Depending on what we do for issue#450, it may be appropriate tochange the client behavior if the HRR extension is present but with the wrongvalue.]]¶
If the server accepts ECH, the client handshakes with ClientHelloInner asdescribed inSection 6.1.5. Otherwise, the client handshakes withClientHelloOuter as described inSection 6.1.6.¶
If the server accepts ECH, the client proceeds with the connection as in[RFC8446], with the following modifications:¶
The client behaves as if it had sent ClientHelloInner as the ClientHello. Thatis, it evaluates the handshake using the ClientHelloInner's preferences, and,when computing the transcript hash (Section 4.4.1 of [RFC8446]), it usesClientHelloInner as the first ClientHello.¶
If the server responds with a HelloRetryRequest, the client computes the updatedClientHello message as follows:¶
It encrypts EncodedClientHelloInner as described inSection 6.1.1, using the second partial ClientHelloOuterAAD, toobtain a second ClientHelloOuter. It reuses the original HPKE encryptioncontext computed inSection 6.1 and uses the empty string forenc.¶
The HPKE context maintains a sequence number, so this operation internallyuses a fresh nonce for each AEAD operation. Reusing the HPKE context avoidsan attack described inSection 10.11.2.¶
The client then sends the second ClientHelloOuter to the server. However, asabove, it uses the second ClientHelloInner for preferences, and both theClientHelloInner messages for the transcript hash. Additionally, it checks theresulting ServerHello for ECH acceptance as inSection 6.1.4.If the ServerHello does not also indicate ECH acceptance, the client MUSTterminate the connection with an "illegal_parameter" alert.¶
If the server rejects ECH, the client proceeds with the handshake,authenticating for ECHConfig.contents.public_name as described inSection 6.1.7. If authentication or the handshake fails, the client MUSTreturn a failure to the calling application. It MUST NOT use the retryconfigurations. It MUST NOT treat this as a secure signal todisable ECH.¶
If the server supplied an "encrypted_client_hello" extension in itsEncryptedExtensions message, the client MUST check that it is syntacticallyvalid and the client MUST abort the connection with a "decode_error" alertotherwise. If an earlier TLS version was negotiated, the client MUST NOT enablethe False Start optimization[RFC7918] for this handshake. If bothauthentication and the handshake complete successfully, the client MUST performthe processing described below then abort the connection with an "ech_required"alert before sending any application data to the server.¶
If the server provided "retry_configs" and if at least one of the valuescontains a version supported by the client, the client can regard the ECH keysas securely replaced by the server. It SHOULD retry the handshake with a newtransport connection, using the retry configurations supplied by theserver. The retry configurations may only be applied to the retryconnection. The client MUST NOT use retry configurations for connections beyondthe retry. This avoids introducing pinning concerns or a tracking vector,should a malicious server present client-specific retry configurations in orderto identify the client in a subsequent ECH handshake.¶
If none of the values provided in "retry_configs" contains a supported version,or an earlier TLS version was negotiated, the client can regard ECH as securelydisabled by the server, and it SHOULD retry the handshake with a new transportconnection and ECH disabled.¶
Clients SHOULD implement a limit on retries caused by receipt of "retry_configs"or servers which do not acknowledge the "encrypted_client_hello" extension. Ifthe client does not retry in either scenario, it MUST report an error to thecalling application.¶
When the server rejects ECH, it continues with the handshake using the plaintext"server_name" extension instead (seeSection 7). Clients that offerECH then authenticate the connection with the public name, as follows:¶
In verifying the client-facing server certificate, the client MUST interpretthe public name as a DNS-based reference identity. Clients that incorporate DNSnames and IP addresses into the same syntax (e.g.[RFC3986],Section 7.4 and[WHATWG-IPV4]) MUST reject names that would be interpreted as IPv4 addresses.Clients that enforce this by checking and rejecting encoded IPv4 addressesin ECHConfig.contents.public_name do not need to repeat the check at this layer.¶
Note that authenticating a connection for the public name does not authenticateit for the origin. The TLS implementation MUST NOT report such connections assuccessful to the application. It additionally MUST ignore all session ticketsand session IDs presented by the server. These connections are only used totrigger retries, as described inSection 6.1.6. This may be implemented, forinstance, by reporting a failed connection with a dedicated error code.¶
If the client attempts to connect to a server and does not have an ECHConfigstructure available for the server, it SHOULD send a GREASE[RFC8701]"encrypted_client_hello" extension in the first ClientHello as follows:¶
config_id field to a random byte.¶cipher_suite field to a supported HpkeSymmetricCipherSuite. Theselection SHOULD vary to exercise all supported configurations, but MAY beheld constant for successive connections to the same server in the samesession.¶enc field to a randomly-generated valid encapsulated public keyoutput by the HPKE KEM.¶payload field to a randomly-generated string of L+C bytes, where Cis the ciphertext expansion of the selected AEAD scheme and L is the size ofthe EncodedClientHelloInner the client would compute when offering ECH, paddedaccording toSection 6.1.3.¶If sending a second ClientHello in response to a HelloRetryRequest, theclient copies the entire "encrypted_client_hello" extension from the firstClientHello. The identical value will reveal to an observer that the value of"encrypted_client_hello" was fake, but this only occurs if there is aHelloRetryRequest.¶
If the server sends an "encrypted_client_hello" extension in eitherHelloRetryRequest or EncryptedExtensions, the client MUST check the extensionsyntactically and abort the connection with a "decode_error" alert if it isinvalid. It otherwise ignores the extension. It MUST NOT save the "retry_config"value in EncryptedExtensions.¶
Offering a GREASE extension is not considered offering an encrypted ClientHellofor purposes of requirements inSection 6.1. In particular, the clientMAY offer to resume sessions established without ECH.¶
Servers that support ECH play one of two roles, depending on the payload of the"encrypted_client_hello" extension in the initial ClientHello:¶
ECHClientHello.type isouter, then the server acts as a client-facingserver and proceeds as described inSection 7.1 to extract aClientHelloInner, if available.¶ECHClientHello.type isinner, then the server acts as a backend serverand proceeds as described inSection 7.2.¶ECHClientHello.type is not a validECHClientHelloType, thenthe server MUST abort with an "illegal_parameter" alert.¶If the "encrypted_client_hello" is not present, then the server completes thehandshake normally, as described in[RFC8446].¶
Upon receiving an "encrypted_client_hello" extension in an initialClientHello, the client-facing server determines if it will accept ECH, priorto negotiating any other TLS parameters. Note that successfully decrypting theextension will result in a new ClientHello to process, so even the client's TLSversion preferences may have changed.¶
First, the server collects a set of candidate ECHConfig values. This list isdetermined by one of the two following methods:¶
Some uses of ECH, such as local discovery mode, may randomize theECHClientHello.config_id since it can be used as a tracking vector. In suchcases, the second method should be used for matching the ECHClientHello to aknown ECHConfig. SeeSection 10.4. Unless specified by the applicationprofile or otherwise externally configured, implementations MUST use the firstmethod.¶
The server then iterates over the candidate ECHConfig values, attempting todecrypt the "encrypted_client_hello" extension:¶
The server verifies that the ECHConfig supports the cipher suite indicated bythe ECHClientHello.cipher_suite and that the version of ECH indicated by theclient matches the ECHConfig.version. If not, the server continues to the nextcandidate ECHConfig.¶
Next, the server decrypts ECHClientHello.payload, using the private key skRcorresponding to ECHConfig, as follows:¶
context = SetupBaseR(ECHClientHello.enc, skR, "tls ech" || 0x00 || ECHConfig) EncodedClientHelloInner = context.Open(ClientHelloOuterAAD, ECHClientHello.payload)¶
ClientHelloOuterAAD is computed from ClientHelloOuter as described inSection 5.2. Theinfo parameter to SetupBaseR is theconcatenation "tls ech", a zero byte, and the serialized ECHConfig. Ifdecryption fails, the server continues to the next candidate ECHConfig.Otherwise, the server reconstructs ClientHelloInner fromEncodedClientHelloInner, as described inSection 5.1. It then stopsiterating over the candidate ECHConfig values.¶
Upon determining the ClientHelloInner, the client-facing server checks that themessage includes a well-formed "encrypted_client_hello" extension of typeinner and that it does not offer TLS 1.2 or below. If either of these checksfails, the client-facing server MUST abort with an "illegal_parameter" alert.¶
If these checks succeed, the client-facing server then forwards theClientHelloInner to the appropriate backend server, which proceeds as inSection 7.2. If the backend server responds with a HelloRetryRequest, theclient-facing server forwards it, decrypts the client's second ClientHelloOuterusing the procedure inSection 7.1.1, and forwards the resultingsecond ClientHelloInner. The client-facing server forwards all other TLSmessages between the client and backend server unmodified.¶
Otherwise, if all candidate ECHConfig values fail to decrypt the extension, theclient-facing server MUST ignore the extension and proceed with the connectionusing ClientHelloOuter, with the following modifications:¶
Note that decryption failure could indicate a GREASE ECH extension (seeSection 6.2), so it is necessary for servers to proceed with the connectionand rely on the client to abort if ECH was required. In particular, theunrecognized value alone does not indicate a misconfigured ECH advertisement(Section 8.1). Instead, servers can measure occurrences of the"ech_required" alert to detect this case.¶
After sending or forwarding a HelloRetryRequest, the client-facing server doesnot repeat the steps inSection 7.1 with the secondClientHelloOuter. Instead, it continues with the ECHConfig selection from thefirst ClientHelloOuter as follows:¶
If the client-facing server accepted ECH, it checks the second ClientHelloOuteralso contains the "encrypted_client_hello" extension. If not, it MUST abort thehandshake with a "missing_extension" alert. Otherwise, it checks thatECHClientHello.cipher_suite and ECHClientHello.config_id are unchanged, and thatECHClientHello.enc is empty. If not, it MUST abort the handshake with an"illegal_parameter" alert.¶
Finally, it decrypts the new ECHClientHello.payload as a second message with theprevious HPKE context:¶
EncodedClientHelloInner = context.Open(ClientHelloOuterAAD, ECHClientHello.payload)¶
ClientHelloOuterAAD is computed as described inSection 5.2, butusing the second ClientHelloOuter. If decryption fails, the client-facingserver MUST abort the handshake with a "decrypt_error" alert. Otherwise, itreconstructs the second ClientHelloInner from the new EncodedClientHelloInneras described inSection 5.1, using the second ClientHelloOuter forany referenced extensions.¶
The client-facing server then forwards the resulting ClientHelloInner to thebackend server. It forwards all subsequent TLS messages between the client andbackend server unmodified.¶
If the client-facing server rejected ECH, or if the first ClientHello did notinclude an "encrypted_client_hello" extension, the client-facing serverproceeds with the connection as usual. The server does not decrypt thesecond ClientHello's ECHClientHello.payload value, if there is one.Moreover, if the server is configured with any ECHConfigs, it MUST include the"encrypted_client_hello" extension in its EncryptedExtensions with the"retry_configs" field set to one or more ECHConfig structures with up-to-datekeys, as described inSection 7.1.¶
Note that a client-facing server that forwards the first ClientHello cannotinclude its own "cookie" extension if the backend server sends aHelloRetryRequest. This means that the client-facing server either needs tomaintain state for such a connection or it needs to coordinate with the backendserver to include any information it requires to process the second ClientHello.¶
Upon receipt of an "encrypted_client_hello" extension of typeinner in aClientHello, if the backend server negotiates TLS 1.3 or higher, then it MUSTconfirm ECH acceptance to the client by computing its ServerHello as describedhere.¶
The backend server embeds in ServerHello.random a string derived from the innerhandshake. It begins by computing its ServerHello as usual, except the last 8bytes of ServerHello.random are set to zero. It then computes the transcripthash for ClientHelloInner up to and including the modified ServerHello, asdescribed in[RFC8446],Section 4.4.1. Let transcript_ech_conf denote theoutput. Finally, the backend server overwrites the last 8 bytes of theServerHello.random with the following string:¶
accept_confirmation = HKDF-Expand-Label( HKDF-Extract(0, ClientHelloInner.random), "ech accept confirmation", transcript_ech_conf, 8)¶
where HKDF-Expand-Label is defined in[RFC8446],Section 7.1, "0" indicates astring of Hash.length bytes set to zero, and Hash is the hash function used tocompute the transcript hash.¶
The backend server MUST NOT perform this operation if it negotiated TLS 1.2 orbelow. Note that doing so would overwrite the downgrade signal for TLS 1.3 (see[RFC8446],Section 4.1.3).¶
When the backend server sends HelloRetryRequest in response to the ClientHello,it similarly confirms ECH acceptance by adding a confirmation signal to itsHelloRetryRequest. But instead of embedding the signal in theHelloRetryRequest.random (the value of which is specified by[RFC8446]), itsends the signal in an extension.¶
The backend server begins by computing HelloRetryRequest as usual, except thatit also contains an "encrypted_client_hello" extension with a payload of 8 zerobytes. It then computes the transcript hash for the first ClientHelloInner,denoted ClientHelloInner1, up to and including the modified HelloRetryRequest.Let transcript_hrr_ech_conf denote the output. Finally, the backend serveroverwrites the payload of the "encrypted_client_hello" extension with thefollowing string:¶
hrr_accept_confirmation = HKDF-Expand-Label( HKDF-Extract(0, ClientHelloInner1.random), "hrr ech accept confirmation", transcript_hrr_ech_conf, 8)¶
In the subsequent ServerHello message, the backend server sends theaccept_confirmation value as described inSection 7.2.¶
Unlike most TLS extensions, placing the SNI value in an ECH extension is notinteroperable with existing servers, which expect the value in the existingplaintext extension. Thus server operators SHOULD ensure servers understand agiven set of ECH keys before advertising them. Additionally, servers SHOULDretain support for any previously-advertised keys for the duration of theirvalidity.¶
However, in more complex deployment scenarios, this may be difficult to fullyguarantee. Thus this protocol was designed to be robust in case ofinconsistencies between systems that advertise ECH keys and servers, at the costof extra round-trips due to a retry. Two specific scenarios are detailed below.¶
It is possible for ECH advertisements and servers to become inconsistent. Thismay occur, for instance, from DNS misconfiguration, caching issues, or anincomplete rollout in a multi-server deployment. This may also occur if a serverloses its ECH keys, or if a deployment of ECH must be rolled back on the server.¶
The retry mechanism repairs inconsistencies, provided the server isauthoritative for the public name. If server and advertised keys mismatch, theserver will reject ECH and respond with "retry_configs". If the server doesnot understandthe "encrypted_client_hello" extension at all, it will ignore it as required bySection 4.1.2 of [RFC8446]. Provided the server can present a certificatevalid for the public name, the client can safely retry with updated settings,as described inSection 6.1.6.¶
Unless ECH is disabled as a result of successfully establishing a connection tothe public name, the client MUST NOT fall back to using unencryptedClientHellos, as this allows a network attacker to disclose the contents of thisClientHello, including the SNI. It MAY attempt to use another server from theDNS results, if one is provided.¶
When connecting through a TLS-terminating proxy that does not support thisextension,[RFC8446],Section 9.3 requires the proxy still act as aconforming TLS client and server. The proxy must ignore unknown parameters, andgenerate its own ClientHello containing only parameters it understands. Thus,when presenting a certificate to the client or sending a ClientHello to theserver, the proxy will act as if connecting to the public name, without echoingthe "encrypted_client_hello" extension.¶
Depending on whether the client is configured to accept the proxy's certificateas authoritative for the public name, this may trigger the retry logic describedinSection 6.1.6 or result in a connection failure. A proxy which is notauthoritative for the public name cannot forge a signal to disable ECH.¶
In the absence of an application profile standard specifying otherwise,a compliant ECH application MUST implement the following HPKE cipher suite:¶
ECH considers two types of attackers: passive and active. Passive attackers canread packets from the network, but they cannot perform any sort of activebehavior such as probing servers or querying DNS. A middlebox that filters basedon plaintext packet contents is one example of a passive attacker. In contrast,active attackers can also write packets into the network for malicious purposes,such as interfering with existing connections, probing servers, and queryingDNS. In short, an active attacker corresponds to the conventional threat modelfor TLS 1.3[RFC8446].¶
Given these types of attackers, the primary goals of ECH are as follows.¶
These properties were formally proven in[ECH-Analysis].¶
With regards to handshake privacy, client-facing server configurationdetermines the size of the anonymity set. For example, if a client-facingserver uses distinct ECHConfig values for each host, then each anonymity sethas size k = 1. Client-facing servers SHOULD deploy ECH in such a way so as tomaximize the size of the anonymity set where possible. This means client-facingservers should use the same ECHConfig for as many hosts as possible. Anattacker can distinguish two hosts that have different ECHConfig values basedon the ECHClientHello.config_id value. This also means public information in aTLS handshake should be consistent across hosts. For example, if aclient-facing server services many backend origin hosts, only one of whichsupports some cipher suite, it may be possible to identify that host based onthe contents of unencrypted handshake messages.¶
Beyond these primary security and privacy goals, ECH also aims to hide, to someextent, the fact that it is being used at all. Specifically, the GREASE ECHextension described inSection 6.2 does not change the security properties ofthe TLS handshake at all. Its goal is to provide "cover" for the real ECHprotocol (Section 6.1), as a means of addressing the "do not stick out"requirements of[RFC8744]. SeeSection 10.9.4 for details.¶
In comparison to[I-D.kazuho-protected-sni], wherein DNS Resource Records aresigned via a server private key, ECH records have no authenticity or provenanceinformation. This means that any attacker which can inject DNS responses orpoison DNS caches, which is a common scenario in client access networks, cansupply clients with fake ECH records (so that the client encrypts data to them)or strip the ECH record from the response. However, in the face of an attackerthat controls DNS, no encryption scheme can work because the attacker canreplace the IP address, thus blocking client connections, or substitute aunique IP address which is 1:1 with the DNS name that was looked up (modulo DNSwildcards). Thus, allowing the ECH records in the clear does not make thesituation significantly worse.¶
Clearly, DNSSEC (if the client validates and hard fails) is a defense againstthis form of attack, but DoH/DPRIVE are also defenses against DNS attacks byattackers on the local network, which is a common case where ClientHello and SNIencryption are desired. Moreover, as noted in the introduction, SNI encryptionis less useful without encryption of DNS queries in transit via DoH or DPRIVEmechanisms.¶
A malicious client-facing server could distribute unique, per-client ECHConfigstructures as a way of tracking clients across subsequent connections. On-pathadversaries which know about these unique keys could also track clients in thisway by observing TLS connection attempts.¶
The cost of this type of attack scales linearly with the desired number oftarget clients. Moreover, DNS caching behavior makes targeting individual usersfor extended periods of time, e.g., using per-client ECHConfig structuresdelivered via HTTPS RRs with high TTLs, challenging. Clients can help mitigatethis problem by flushing any DNS or ECHConfig state upon changing networks.¶
Ignoring configuration identifiers may be useful in scenarios where clients andclient-facing servers do not want to reveal information about the client-facingserver in the "encrypted_client_hello" extension. In such settings, clients senda randomly generated config_id in the ECHClientHello. Servers in these settingsmust perform trial decryption since they cannot identify the client's chosen ECHkey using the config_id value. As a result, ignoring configurationidentifiers may exacerbate DoS attacks. Specifically, an adversary may sendmalicious ClientHello messages, i.e., those which will not decrypt with anyknown ECH key, in order to force wasteful decryption. Servers that support thisfeature should, for example, implement some form of rate limiting mechanism tolimit the potential damage caused by such attacks.¶
Unless specified by the application using (D)TLS or externally configured,implementations MUST NOT use this mode.¶
Any information that the client includes in the ClientHelloOuter is visible topassive observers. The client SHOULD NOT send values in the ClientHelloOuterwhich would reveal a sensitive ClientHelloInner property, such as the trueserver name. It MAY send values associated with the public name in theClientHelloOuter.¶
In particular, some extensions require the client send a server-name-specificvalue in the ClientHello. These values may reveal information about thetrue server name. For example, the "cached_info" ClientHello extension[RFC7924] can contain the hash of a previously observed server certificate.The client SHOULD NOT send values associated with the true server name in theClientHelloOuter. It MAY send such values in the ClientHelloInner.¶
A client may also use different preferences in different contexts. For example,it may send a different ALPN lists to different servers or in differentapplication contexts. A client that treats this context as sensitive SHOULD NOTsend context-specific values in ClientHelloOuter.¶
Values which are independent of the true server name, or other information theclient wishes to protect, MAY be included in ClientHelloOuter. If they matchthe corresponding ClientHelloInner, they MAY be compressed as described inSection 5.1. However, note the payload length reveals information aboutwhich extensions are compressed, so inner extensions which only sometimes matchthe corresponding outer extension SHOULD NOT be compressed.¶
Clients MAY include additional extensions in ClientHelloOuter to avoidsignaling unusual behavior to passive observers, provided the choice of valueand value itself are not sensitive. SeeSection 10.9.4.¶
ECH requires encrypted DNS to be an effective privacy protection mechanism.However, verifying the server's identity from the Certificate message,particularly when using the X509 CertificateType, may result in additionalnetwork traffic that may reveal the server identity. Examples of this trafficmay include requests for revocation information, such as OCSP or CRL traffic, orrequests for repository information, such as authorityInformationAccess. It mayalso include implementation-specific traffic for additional information sourcesas part of verification.¶
Implementations SHOULD avoid leaking information that may identify the server.Even when sent over an encrypted transport, such requests may result in indirectexposure of the server's identity, such as indicating a specific CA or servicebeing used. To mitigate this risk, servers SHOULD deliver such informationin-band when possible, such as through the use of OCSP stapling, and clientsSHOULD take steps to minimize or protect such requests during certificatevalidation.¶
Attacks that rely on non-ECH traffic to infer server identity in an ECHconnection are out of scope for this document. For example, a client thatconnects to a particular host prior to ECH deployment may later resume aconnection to that same host after ECH deployment. An adversary that observesthis can deduce that the ECH-enabled connection was made to a host that theclient previously connected to and which is within the same anonymity set.¶
Section 4.2.2 of [RFC8446] defines a cookie value that servers may send inHelloRetryRequest for clients to echo in the second ClientHello. While ECHencrypts the cookie in the second ClientHelloInner, the backend server'sHelloRetryRequest is unencrypted.This means differences in cookies betweenbackend servers, such as lengths or cleartext components, may leak informationabout the server identity.¶
Backend servers in an anonymity set SHOULD NOT reveal information in the cookiewhich identifies the server. This may be done by handling HelloRetryRequeststatefully, thus not sending cookies, or by using the same cookie constructionfor all backend servers.¶
Note that, if the cookie includes a key name, analogous to Section 4 of[RFC5077], this may leak information if different backend servers issuecookies with different key names at the time of the connection. In particular,if the deployment operates in Split Mode, the backend servers may not sharecookie encryption keys. Backend servers may mitigate this by either handlingkey rotation with trial decryption, or coordinating to match key names.¶
To signal acceptance, the backend server overwrites 8 bytes of itsServerHello.random with a value derived from the ClientHelloInner.random. (SeeSection 7.2 for details.) This behavior increases the likelihood of theServerHello.random colliding with the ServerHello.random of a previous session,potentially reducing the overall security of the protocol. However, theremaining 24 bytes provide enough entropy to ensure this is not a practicalavenue of attack.¶
On the other hand, the probability that two 8-byte strings are the same isnon-negligible. This poses a modest operational risk. Suppose the client-facingserver terminates the connection (i.e., ECH is rejected or bypassed): if thelast 8 bytes of its ServerHello.random coincide with the confirmation signal,then the client will incorrectly presume acceptance and proceed as if thebackend server terminated the connection. However, the probability of a falsepositive occurring for a given connection is only 1 in 2^64. This value issmaller than the probability of network connection failures in practice.¶
Note that the same bytes of the ServerHello.random are used to implementdowngrade protection for TLS 1.3 (see[RFC8446],Section 4.1.3). Thesemechanisms do not interfere because the backend server only signals ECHacceptance in TLS 1.3 or higher.¶
[RFC8744] lists several requirements for SNI encryption.In this section, we re-iterate these requirements and assess the ECH designagainst them.¶
Since servers process either ClientHelloInner or ClientHelloOuter, and becauseClientHelloInner.random is encrypted, it is not possible for an attacker to "cutand paste" the ECH value in a different Client Hello and learn information fromClientHelloInner.¶
This design depends upon DNS as a vehicle for semi-static public keydistribution. Server operators may partition their private keys however theysee fit provided each server behind an IP address has the corresponding privatekey to decrypt a key. Thus, when one ECH key is provided, sharing is optimallybound by the number of hosts that share an IP address. Server operators mayfurther limit sharing by publishing different DNS records containing ECHConfigvalues with different keys using a short TTL.¶
This design requires servers to decrypt ClientHello messages with ECHClientHelloextensions carrying valid digests. Thus, it is possible for an attacker to forcedecryption operations on the server. This attack is bound by the number of validTCP connections an attacker can open.¶
As a means of reducing the impact of network ossification,[RFC8744]recommends SNI-protection mechanisms be designed in such a way that networkoperators do not differentiate connections using the mechanism from connectionsnot using the mechanism. To that end, ECH is designed to resemble a standardTLS handshake as much as possible. The most obvious difference is the extensionitself: as long as middleboxes ignore it, as required by[RFC8446], the restof the handshake is designed to look very much as usual.¶
The GREASE ECH protocol described inSection 6.2 provides a low-risk way toevaluate the deployability of ECH. It is designed to mimic the real ECH protocol(Section 6.1) without changing the security properties of the handshake. Theunderlying theory is that if GREASE ECH is deployable without triggeringmiddlebox misbehavior, and real ECH looks enough like GREASE ECH, then ECHshould be deployable as well. Thus, our strategy for mitigating networkossification is to deploy GREASE ECH widely enough to disincentivizedifferential treatment of the real ECH protocol by the network.¶
Ensuring that networks do not differentiate between real ECH and GREASE ECH maynot be feasible for all implementations. While most middleboxes will not treatthem differently, some operators may wish to block real ECH usage but allowGREASE ECH. This specification aims to provide a baseline security level thatmost deployments can achieve easily, while providing implementations enoughflexibility to achieve stronger security where possible. Minimally, real ECH isdesigned to be indifferentiable from GREASE ECH for passive adversaries withfollowing capabilities:¶
This leaves a variety of practical differentiators out-of-scope. including,though not limited to, the following:¶
These can be addressed with more sophisticated implementations, but somemitigations require coordination between the client and server. Thesemitigations are out-of-scope for this specification.¶
This design is not forward secret because the server's ECH key is static.However, the window of exposure is bound by the key lifetime. It is RECOMMENDEDthat servers rotate keys frequently.¶
This design permits servers operating in Split Mode to forward connectionsdirectly to backend origin servers. The client authenticates the identity ofthe backend origin server, thereby avoiding unnecessary MiTM attacks.¶
Conversely, assuming ECH records retrieved from DNS are authenticated, e.g.,via DNSSEC or fetched from a trusted Recursive Resolver, spoofing aclient-facing server operating in Split Mode is not possible. SeeSection 10.2 for more details regarding plaintext DNS.¶
Authenticating the ECHConfig structure naturally authenticates the includedpublic name. This also authenticates any retry signals from the client-facingserver because the client validates the server certificate against the publicname before retrying.¶
This design has no impact on application layer protocol negotiation. It mayaffect connection routing, server certificate selection, and client certificateverification. Thus, it is compatible with multiple application and transportprotocols. By encrypting the entire ClientHello, this design additionallysupports encrypting the ALPN extension.¶
Variations in the length of the ClientHelloInner ciphertext could leakinformation about the corresponding plaintext.Section 6.1.3 describes aRECOMMENDED padding mechanism for clients aimed at reducing potentialinformation leakage.¶
This section describes the rationale for ECH properties and mechanics asdefenses against active attacks. In all the attacks below, the attacker ison-path between the target client and server. The goal of the attacker is tolearn private information about the inner ClientHello, such as the true SNIvalue.¶
This attack uses the client's reaction to an incorrect certificate as an oracle.The attacker intercepts a legitimate ClientHello and replies with a ServerHello,Certificate, CertificateVerify, and Finished messages, wherein the Certificatemessage contains a "test" certificate for the domain name it wishes to query. Ifthe client decrypted the Certificate and failed verification (or leakedinformation about its verification process by a timing side channel), theattacker learns that its test certificate name was incorrect. As an example,suppose the client's SNI value in its inner ClientHello is "example.com," andthe attacker replied with a Certificate for "test.com". If the client produces averification failure alert because of the mismatch faster than it would due tothe Certificate signature validation, information about the name leaks. Notethat the attacker can also withhold the CertificateVerify message. In thatscenario, a client which first verifies the Certificate would then respondsimilarly and leak the same information.¶
Client Attacker Server ClientHello + key_share + ech ------> (intercept) -----> X (drop) ServerHello + key_share {EncryptedExtensions} {CertificateRequest*} {Certificate*} {CertificateVerify*} <------ Alert ------>ClientHelloInner.random prevents this attack. In particular, since the attackerdoes not have access to this value, it cannot produce the right transcript andhandshake keys needed for encrypting the Certificate message. Thus, the clientwill fail to decrypt the Certificate and abort the connection.¶
This attack aims to exploit server HRR state management to recover informationabout a legitimate ClientHello using its own attacker-controlled ClientHello.To begin, the attacker intercepts and forwards a legitimate ClientHello with an"encrypted_client_hello" (ech) extension to the server, which triggers alegitimate HelloRetryRequest in return. Rather than forward the retry to theclient, the attacker attempts to generate its own ClientHello in response basedon the contents of the first ClientHello and HelloRetryRequest exchange with theresult that the server encrypts the Certificate to the attacker. If the serverused the SNI from the first ClientHello and the key share from the second(attacker-controlled) ClientHello, the Certificate produced would leak theclient's chosen SNI to the attacker.¶
Client Attacker Server ClientHello + key_share + ech ------> (forward) -------> HelloRetryRequest + key_share (intercept) <------- ClientHello + key_share' + ech' -------> ServerHello + key_share {EncryptedExtensions} {CertificateRequest*} {Certificate*} {CertificateVerify*} {Finished} <------- (process server flight)This attack is mitigated by using the same HPKE context for both ClientHellomessages. The attacker does not possess the context's keys, so it cannotgenerate a valid encryption of the second inner ClientHello.¶
If the attacker could manipulate the second ClientHello, it might be possiblefor the server to act as an oracle if it required parameters from the firstClientHello to match that of the second ClientHello. For example, imagine theclient's original SNI value in the inner ClientHello is "example.com", and theattacker's hijacked SNI value in its inner ClientHello is "test.com". A serverwhich checks these for equality and changes behavior based on the result can beused as an oracle to learn the client's SNI.¶
This attack aims to leak information about secret parts of the encryptedClientHello by adding attacker-controlled parameters and observing the server'sresponse. In particular, the compression mechanism described inSection 5.1 references parts of a potentially attacker-controlledClientHelloOuter to construct ClientHelloInner, or a buggy server mayincorrectly apply parameters from ClientHelloOuter to the handshake.¶
To begin, the attacker first interacts with a server to obtain a resumptionticket for a given test domain, such as "example.com". Later, upon receipt of aClientHelloOuter, it modifies it such that the server will process theresumption ticket with ClientHelloInner. If the server only accepts resumptionPSKs that match the server name, it will fail the PSK binder check with analert when ClientHelloInner is for "example.com" but silently ignore the PSKand continue when ClientHelloInner is for any other name. This introduces anoracle for testing encrypted SNI values.¶
Client Attacker Server handshake and ticket for "example.com" <--------> ClientHello + key_share + ech + ech_outer_extensions(pre_shared_key) + pre_shared_key --------> (intercept) ClientHello + key_share + ech + ech_outer_extensions(pre_shared_key) + pre_shared_key' --------> Alert -or- ServerHello ... Finished <--------
This attack may be generalized to any parameter which the server varies byserver name, such as ALPN preferences.¶
ECH mitigates this attack by only negotiating TLS parameters fromClientHelloInner and authenticating all inputs to the ClientHelloInner(EncodedClientHelloInner and ClientHelloOuter) with the HPKE AEAD. SeeSection 5.2. An earlier iteration of this specification onlyencrypted and authenticated the "server_name" extension, which left the overallClientHello vulnerable to an analogue of this attack.¶
Client-facing servers must decompress EncodedClientHelloInners. A maliciousattacker may craft a packet which takes excessive resources to decompressor may be much larger than the incoming packet:¶
ECH mitigates this attack by requiring that OuterExtensions be referenced inorder, that duplicate references be rejected, and by recommending thatclient-facing servers use a linear scan to perform decompression. Theserequirements are detailed inSection 5.1.¶
IANA is requested to create the following entries in the existing registry forExtensionType (defined in[RFC8446]):¶
IANA is requested to create an entry, ech_required(121) in the existing registryfor Alerts (defined in[RFC8446]), with the "DTLS-OK" column set to"Y".¶
Any future information or hints that influence ClientHelloOuter SHOULD bespecified as ECHConfig extensions. This is primarily because the outerClientHello exists only in support of ECH. Namely, it is both an envelope forthe encrypted inner ClientHello and enabler for authenticated key mismatchsignals (seeSection 7). In contrast, the inner ClientHello is thetrue ClientHello used upon ECH negotiation.¶
Alternative approaches to encrypted SNI may be implemented at the TLS orapplication layer. In this section we describe several alternatives and discussdrawbacks in comparison to the design in this document.¶
In this variant, TLS Client Hellos are tunneled within early data payloadsbelonging to outer TLS connections established with the client-facing server.This requires clients to have established a previous session --- and obtainedPSKs --- with the server. The client-facing server decrypts early data payloadsto uncover Client Hellos destined for the backend server, and forwards themonwards as necessary. Afterwards, all records to and from backend servers areforwarded by the client-facing server -- unmodified. This avoids doubleencryption of TLS records.¶
Problems with this approach are: (1) servers may not always be able todistinguish inner Client Hellos from legitimate application data, (2) nested0-RTT data may not function correctly, (3) 0-RTT data may not be supported --especially under DoS -- leading to availability concerns, and (4) clients mustbootstrap tunnels (sessions), costing an additional round trip and potentiallyrevealing the SNI during the initial connection. In contrast, encrypted SNIprotects the SNI in a distinct Client Hello extension and neither abuses earlydata nor requires a bootstrapping connection.¶
In this variant, client-facing and backend servers coordinate to produce"combined tickets" that are consumable by both. Clients offer combined ticketsto client-facing servers. The latter parse them to determine the correct backendserver to which the Client Hello should be forwarded. This approach isproblematic due to non-trivial coordination between client-facing and backendservers for ticket construction and consumption. Moreover, it requires abootstrapping step similar to that of the previous variant. In contrast,encrypted SNI requires no such coordination.¶
In this variant, clients request secondary certificates with CERTIFICATE_REQUESTHTTP/2 frames after TLS connection completion. In response, servers supplycertificates via TLS exported authenticators[I-D.ietf-tls-exported-authenticator] in CERTIFICATE frames. Clients use ageneric SNI for the underlying client-facing server TLS connection. Problemswith this approach include: (1) one additional round trip before peerauthentication, (2) non-trivial application-layer dependencies and interaction,and (3) obtaining the generic SNI to bootstrap the connection. In contrast,encrypted SNI induces no additional round trip and operates below theapplication layer.¶
The following procedure processes the "ech_outer_extensions" extension (seeSection 5.1) in linear time, ensuring that each referenced extensionin the ClientHelloOuter is included at most once:¶
For each extension type, E, in OuterExtensions:¶
This document draws extensively from ideas in[I-D.kazuho-protected-sni], butis a much more limited mechanism because it depends on the DNS for theprotection of the ECH key. Richard Barnes, Christian Huitema, Patrick McManus,Matthew Prince, Nick Sullivan, Martin Thomson, and David Benjamin also providedimportant ideas and contributions.¶
RFC Editor's Note: Please remove this section prior to publication of afinal version of this document.¶
Issue and pull request numbers are listed with a leading octothorp.¶
draft-ietf-tls-esni-15
| Document | Document type | This is an older version of an Internet-Draft whose latest revision state is "Active". Expired & archived | |
|---|---|---|---|
| Select version | |||
| Compare versions | |||
| Authors | Eric Rescorla,Kazuho Oku,Nick Sullivan,Christopher A. Wood | ||
| Replaces | draft-rescorla-tls-esni | ||
| RFC stream | |||
| Other formats | |||
| Additional resources | Mailing list discussion |