Draft: draft-ietf-tls-esni

Commentary: minor suggested change 
 Hiya , For me , for a protocol element , " optional " means " not included " whereas here we 're talking about " optionally ignoring the proposed value . " ( Yeah , I probably read too much ASN.1 once , or even twice:- ) " Random " might not be right , but " optional " could maybe briefly confuse an implementer . Sure . ( Not that I know how to do that easily , but feel free to just do it , or wait for me to figure it out tomorrow;- ) Cheers , S. 
 I agree . 
 It 's not possible to omit the config ID ( it 's a byte ) . It 's only possible to not use it . Optional seems like a fine word to capture that . We could also say that it 's unused or ignored ? For example : Or something , with similar updates to the text and section titles . Would that work ? 
 Interesting , ( but unimportant:- ) my take on those facts is the opposite . For me : " ignored " is ok , " unused " is as odd as " optional . " Cheers , S. 
 updated the proposal above to use " ignored " . Does that work ? 
 Sure . Thanks , S 
 Great ! Could you please update this PR to match ? 
 I think I 've made those changes now .
Paragraph (version A):
DISCLAIMER: This draft is work-in-progress and has not yet seen
significant (or really any) security analysis.  It should not be used
as a basis for building production systems.
Paragraph (version B):
DISCLAIMER: This draft is work-in-progress and has not yet seen
significant (or really any) security analysis.  It should not be used
as a basis for building production systems.  This published version
of the draft has been designated an "implementation draft" for
testing and interop purposes.
Paragraph (version A):
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 the provider's server relays the connection back to the
origin server, who terminates the TLS connection with the client.
Importantly, service provider does not have access to the plaintext
of the connection.
Paragraph (version B):
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 the provider's server relays the connection back to the
origin server, who terminates the TLS connection with the client.
Importantly, the service provider does not have access to the
plaintext of the connection beyond the unencrypted portions of the
handshake.
Paragraph (version B):
ECH uses HPKE for public key encryption I-D.irtf-cfrg-hpke.  The ECH
configuration is defined by the following "ECHConfig" structure.
Paragraph (version B):
The length, in bytes, of the next field.  This length field allows
implementations to skip over the elements in such a list where
they cannot parse the specific version of ECHConfig.
Paragraph (version B):
A "HpkeKeyConfig" structure carrying the configuration information
associated with the HPKE public key.  Note that this structure
contains the "config_id" field, which applies to the entire
ECHConfigContents.
Paragraph (version B):
A one-byte identifier for the given HPKE key configuration.  This
is used by clients to indicate the key used for ClientHello
encryption. config-ids describes how client-facing servers
allocate this value.
Paragraph (version A):
The list of HPKE KDF and AEAD identifier pairs clients can use for
encrypting ClientHelloInner.
Paragraph (version B):
The list of HPKE KDF and AEAD identifier pairs clients can use for
encrypting ClientHelloInner.  See real-ech for how clients choose
from this list.
Paragraph (version B):
A client-facing server has a set of known ECHConfig values, with
corresponding private keys.  This set SHOULD contain the currently
published values, as well as previous values that may still be in
use, since clients may cache DNS records up to a TTL or longer.
Paragraph (version B):
client-facing-server describes a trial decryption process for
decrypting the ClientHello.  This can impact performance when the
client-facing server maintains many known ECHConfig values.  To avoid
this, the client-facing server SHOULD allocate distinct "config_id"
values for each ECHConfig in its known set.  The RECOMMENDED strategy
is via rejection sampling, i.e., to randomly select "config_id"
repeatedly until it does not match any known ECHConfig.
Paragraph (version B):
It is not necessary for "config_id" values across different client-
facing servers to be distinct.  A backend server may be hosted behind
two different client-facing servers with colliding "config_id" values
without any performance impact.  Values may also be reused if the
previous ECHConfig is no longer in the known set.
Paragraph (version B):
The format is as defined in RFC8446, Section 4.2.  The same
interpretation rules apply: extensions MAY appear in any order, but
there MUST NOT be more than one extension of the same type in the
extensions block.  An extension can be tagged as mandatory by using
an extension type codepoint with the high order bit set to 1.
Paragraph (version B):
An ECHConfigList structure containing one or more ECHConfig
structures, in decreasing order of preference, to be used by the
client as described in rejected-ech.  These are known as the
server's "retry configurations".
Paragraph (version B):
OuterExtensions contains the removed ExtensionType values.  Each
value references the matching extension in ClientHelloOuter.  The
values MUST be ordered contiguously in ClientHelloInner, and the
"ech_outer_extensions" extension MUST be inserted in the
corresponding position in EncodedClientHelloInner.  Additionally, the
extensions MUST appear in ClientHelloOuter in the same relative
order.  However, there is no requirement that they be contiguous.
For example, OuterExtensions may contain extensions A, B, C, while
ClientHelloOuter contains extensions A, D, B, C, E, F.
Paragraph (version B):
The "ech_outer_extensions" extension can only be included in
EncodedClientHelloInner, and MUST NOT appear in either
ClientHelloOuter or ClientHelloInner.
Paragraph (version A):
Implementations SHOULD bound the time to compute a ClientHelloInner
proportionally to the ClientHelloOuter size.  If the cost are
disproportionately large, a malicious client could exploit this in a
denial of service attack.  linear-outer-extensions describes a
linear-time procedure that may be used for this purpose.
Paragraph (version B):
Implementations SHOULD bound the time to compute a ClientHelloInner
proportionally to the ClientHelloOuter size.  If the cost is
disproportionately large, a malicious client could exploit this in a
denial of service attack.  linear-outer-extensions describes a
linear-time procedure that may be used for this purpose.
Paragraph (version A):
If optional configuration identifiers (see optional-configs) are
used, "config_id" SHOULD be set to a randomly generated byte in the
first ClientHelloOuter and MUST be left unchanged for the second
ClientHelloOuter.
Paragraph (version B):
If configuration identifiers (see ignored-configs) are to be ignored,
"config_id" SHOULD be set to a randomly generated byte in the first
ClientHelloOuter and, in the event of HRR, MUST be left unchanged for
the second ClientHelloOuter.
Paragraph (version A):
By way of example, clients typically support a small number of
application profiles.  For instance, a browser might support HTTP
with ALPN values ["http/1.1, "h2"] and WebRTC media with ALPNs
["webrtc", "c-webrtc"].  Clients SHOULD pad this extension by
rounding up to the total size of the longest ALPN extension across
all application profiles.  The target padding length of most
ClientHello extensions can be computed in this way.
Paragraph (version B):
By way of example, clients typically support a small number of
application profiles.  For instance, a browser might support HTTP
with ALPN values ["http/1.1", "h2"] and WebRTC media with ALPNs
["webrtc", "c-webrtc"].  Clients SHOULD pad this extension by
rounding up to the total size of the longest ALPN extension across
all application profiles.  The target padding length of most
ClientHello extensions can be computed in this way.
Paragraph (version A):
If the message is a HelloRetryRequest, the client checks for the
"encrypted_client_hello" extension.  If none is found, the server has
rejected ECH.  Otherwise, if it has a length other than 8, the client
aborts the handshake with a "decode_error" alert.  Otherwise, the
client computes "hrr_accept_confirmation" as described in backend-
server-hrr.  If this value matches the extension payload, the server
has accept ECH.  Otherwise, it has rejected ECH.
Paragraph (version B):
If the message is a HelloRetryRequest, the client checks for the
"encrypted_client_hello" extension.  If none is found, the server has
rejected ECH.  Otherwise, if it has a length other than 8, the client
aborts the handshake with a "decode_error" alert.  Otherwise, the
client computes "hrr_accept_confirmation" as described in backend-
server-hrr.  If this value matches the extension payload, the server
has accepted ECH.  Otherwise, it has rejected ECH.
Paragraph (version B):
Some uses of ECH, such as local discovery mode, may randomize the
ECHClientHello.config_id since it can be used as a tracking vector.
In such cases, the second method should be used for matching the
ECHClientHello to a known ECHConfig.  See ignored-configs.  Unless
specified by the application profile or otherwise externally
configured, implementations MUST use the first method.
Paragraph (version B):
If sending a HelloRetryRequest, the server MAY include an
"encrypted_client_hello" extension with a payload of 8 random
bytes; see dont-stick-out for details.
Paragraph (version B):
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-date keys.  Servers MAY supply multiple
ECHConfig values of different versions.  This allows a server to
support multiple versions at once.
Paragraph (version B):
If the client-facing server rejected ECH, or if the first ClientHello
did not include an "encrypted_client_hello" extension, the client-
facing server proceeds with the connection as usual.  The server does
not decrypt the second 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-date keys, as described in
client-facing-server.
Paragraph (version B):
The retry mechanism repairs inconsistencies, provided the server is
authoritative for the public name.  If server and advertised keys
mismatch, the server will reject ECH and respond with
"retry_configs".  If the server does not understand the
"encrypted_client_hello" extension at all, it will ignore it as
required by Section 4.1.2 of RFC8446.  Provided the server can
present a certificate valid for the public name, the client can
safely retry with updated settings, as described in rejected-ech.
Paragraph (version A):
Client-facing server configuration determines the size of the
anonymity set.  For example, if a client-facing server uses distinct
ECHConfig values for each host, then each anonymity set has size k =
maximize the size of the anonymity set where possible.  This means
client-facing servers should use the same ECHConfig for as many hosts
as possible.  An attacker can distinguish two hosts that have
different ECHConfig values based on the ECHClientHello.config_id
value.  This also means public information in a TLS handshake is also
consistent across hosts.  For example, if a client-facing server
services many backend origin hosts, only one of which supports some
cipher suite, it may be possible to identify that host based on the
contents of unencrypted handshake messages.
Paragraph (version B):
Client-facing server configuration determines the size of the
anonymity set.  For example, if a client-facing server uses distinct
ECHConfig values for each host, then each anonymity set has size k =
maximize the size of the anonymity set where possible.  This means
client-facing servers should use the same ECHConfig for as many hosts
as possible.  An attacker can distinguish two hosts that have
different ECHConfig values based on the ECHClientHello.config_id
value.  This also means public information in a TLS handshake should
be consistent across hosts.  For example, if a client-facing server
services many backend origin hosts, only one of which supports some
cipher suite, it may be possible to identify that host based on the
contents of unencrypted handshake messages.
Paragraph (version A):
In comparison to I-D.kazuho-protected-sni, wherein DNS Resource
Records are signed via a server private key, ECH records have no
authenticity or provenance information.  This means that any attacker
which can inject DNS responses or poison DNS caches, which is a
common scenario in client access networks, can supply clients with
fake ECH records (so that the client encrypts data to them) or strip
the ECH record from the response.  However, in the face of an
attacker that controls DNS, no encryption scheme can work because the
attacker can replace the IP address, thus blocking client
connections, or substituting a unique IP address which is 1:1 with
the DNS name that was looked up (modulo DNS wildcards).  Thus,
allowing the ECH records in the clear does not make the situation
significantly worse.
Paragraph (version B):
In comparison to I-D.kazuho-protected-sni, wherein DNS Resource
Records are signed via a server private key, ECH records have no
authenticity or provenance information.  This means that any attacker
which can inject DNS responses or poison DNS caches, which is a
common scenario in client access networks, can supply clients with
fake ECH records (so that the client encrypts data to them) or strip
the ECH record from the response.  However, in the face of an
attacker that controls DNS, no encryption scheme can work because the
attacker can replace the IP address, thus blocking client
connections, or substitute a unique IP address which is 1:1 with the
DNS name that was looked up (modulo DNS wildcards).  Thus, allowing
the ECH records in the clear does not make the situation
significantly worse.
Paragraph (version A):
Optional configuration identifiers may be useful in scenarios where
clients and client-facing servers do not want to reveal information
about the client-facing server in the "encrypted_client_hello"
extension.  In such settings, clients send a randomly generated
config_id in the ECHClientHello.  Servers in these settings must
perform trial decryption since they cannot identify the client's
chosen ECH key using the config_id value.  As a result, support for
optional configuration identifiers may exacerbate DoS attacks.
Specifically, an adversary may send malicious ClientHello messages,
i.e., those which will not decrypt with any known ECH key, in order
to force wasteful decryption.  Servers that support this feature
should, for example, implement some form of rate limiting mechanism
to limit the damage caused by such attacks.
Paragraph (version A):
Unless specified by the application using (D)TLS or externally
configured on both sides, implementations MUST NOT use this mode.
Paragraph (version B):
Ignoring configuration identifiers may be useful in scenarios where
clients and client-facing servers do not want to reveal information
about the client-facing server in the "encrypted_client_hello"
extension.  In such settings, clients send a randomly generated
config_id in the ECHClientHello.  Servers in these settings must
perform trial decryption since they cannot identify the client's
chosen ECH key using the config_id value.  As a result, ignoring
configuration identifiers may exacerbate DoS attacks.  Specifically,
an adversary may send malicious ClientHello messages, i.e., those
which will not decrypt with any known ECH key, in order to force
wasteful decryption.  Servers that support this feature should, for
example, implement some form of rate limiting mechanism to limit the
potential damage caused by such attacks.
Paragraph (version B):
Unless specified by the application using (D)TLS or externally
configured, implementations MUST NOT use this mode.
Paragraph (version A):
Ensuring that networks do not differentiate between real ECH and
GREASE ECH may not be feasible for all implementations.  While most
middleboxes will not treat them differently, some operators may wish
to block real ECH usage but allow GREASE ECH.  This specification
aims to provide a baseline security level that most deployments can
achieve easily, while providing implementations enough flexibility to
achieve stronger security where possible.  Minimally, real ECH is
designed to be indifferentiable from GREASE ECH for passive
adversaries with following capabilities: 1.  The attacker does not
know the ECHConfigList used by the server.  1.  The attacker keeps
per-connection state only.  In particular, it does not track
endpoints across connections.  1.  ECH and GREASE ECH are designed so
that the following features do not vary: the code points of
extensions negotiated in the clear; the length of messages; and the
values of plaintext alert messages.
Paragraph (version A):
This leaves a variety of practical differentiators out-of-scope.
including, though not limited to, the following: 1. the value of the
configuration identifier; 1. the value of the outer SNI; 1. use of
the "pre_shared_key" extension in the ClientHelloOuter, which is
permitted in GREASE ECH but not real ECH; [[TODO: Remove this
differentiator if issue #384 is resolved by a spec change.]] 1. the
TLS version negotiated, which may depend on ECH acceptance; 1. client
authentication, which may depend on ECH acceptance; and 1.  HRR
issuance, which may depend on ECH acceptance.
Paragraph (version B):
The attacker does not know the ECHConfigList used by the server.
Paragraph (version B):
The attacker keeps per-connection state only.  In particular, it
does not track endpoints across connections.
Paragraph (version B):
ECH and GREASE ECH are designed so that the following features do
not vary: the code points of extensions negotiated in the clear;
the length of messages; and the values of plaintext alert
messages.
Paragraph (version B):
HRR issuance, which may depend on ECH acceptance.
Paragraph (version A):
This attack aims to exploit server HRR state management to recover
information about 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 a legitimate
HelloRetryRequest in return.  Rather than forward the retry to the
client, the attacker, attempts to generate its own ClientHello in
response based on the contents of the first ClientHello and
HelloRetryRequest exchange with the result that the server encrypts
the Certificate to the attacker.  If the server used the SNI from the
first ClientHello and the key share from the second (attacker-
controlled) ClientHello, the Certificate produced would leak the
client's chosen SNI to the attacker.
Paragraph (version B):
This attack aims to exploit server HRR state management to recover
information about 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 a legitimate
HelloRetryRequest in return.  Rather than forward the retry to the
client, the attacker attempts to generate its own ClientHello in
response based on the contents of the first ClientHello and
HelloRetryRequest exchange with the result that the server encrypts
the Certificate to the attacker.  If the server used the SNI from the
first ClientHello and the key share from the second (attacker-
controlled) ClientHello, the Certificate produced would leak the
client's chosen SNI to the attacker.