Draft: draft-ietf-tls-esni

Commentary: Partially addresses . Whether the client offers ECH or sends GREASE ECH depends on whether it can find a suitable ECH config . Whether the server acts like the client - facing server or the backend server depends on whether it has custody of a set of ECH configs . This change clarifies these decision making processes . As a bonus , this change also cleans up the section titles and levels a bit . 
 { { encrypted - client - hello } } now stipulates that the ECH payload may be empty . 
 can you please have another look ? 
 It is unclear how a general TLS server is supposed to react to an ECH extension . It 's sometimes empty and sometimes a ClientECH . An empty extension is not a valid ClientECH extension , so a server expending ClientECH should produce a ( and vice versa ) . The spec does talk about client - facing and backend servers as separate kinds of servers , but I thought the theory behind   was that backend servers were meant to be mostly standard TLS servers . That would suggest that backend - server - specific logic should be common to all TLS server implementations that know about ECH . In that case , perhaps we should say that : The client ECH extension is either empty or a ClientECH structure . If you see empty , this is an inner ClientHello . Do the thing and otherwise handshake normally . If you see non - empty and have ECHConfigs , parse as a ClientECH and decodeerror on parse failure as usual . Do the client - facing server thing . Or is the idea that client - facing and backend servers are completely separate beasts and everyone always knows which they are ? In that case , what happens if a client - facing server sees an empty ECH extension ? What happens if a backend server sees a ClientECH - carrying ECH extension . Failure to parse an extension is normally fatal , but the two categories of server believe different parses are valid . In particular , this requires a backend server never * see a general - purpose client connection , since it 'd get confused by ( possibly GREASE ) ClientECH extensions . 
 I think this is the intention , yeah . This is how I understand the spec : TLS server is a backend server . If a TLS server knows a set of ECHConfigs , then it is also a client - facing server . empty ECH extension signals that the server should play the role of the backend server . ( Hence , the client - facing server would skip ECH processing and proceed as if it were a backend server . ) non - empty ECH extension signals that the server should play the role of the client - facing server . ( The server ignores the extension if it is not a client - facing server . ) 
 Yeah , sounds like you and I are on the same page there . But I 'm not sure the spec text actually supports that interpretation . Let 's fix that . 
 Agreed . Who wants to take the PR ? 
 I 'd be happy to take it , since  did a lot of the heavy lifting last week . Unless you want to take a crack at it ,  ? 
 I 'm working on a PR . 
 PR ready . Note that it also clarifies how the client 's role ( real or GREASE ) is determined . 
 Another thought : we could also avoid this odd " maybe empty , maybe not " behavior by just using a different codepoint for the " please give me an ECH acceptance signal " extension . As things stand , the { { server - hrr } } text is also kinda off : That text does n't account for CH1 containing a ClientECH " encryptedclienthello " extension and CH2 containing an empty " encryptedclient_hello " extension . If the two modes are different codepoints , we do n't have to keep expending words to talk about the two flavors . 
 The downside of two codepoints is it 's now possible to construct a ClientHello with both extensions at once and we need to decide whether , on ECH reject , the client - facing server is expected to do the computation , error , or ignore it . I do n't care strongly there . Any of option seems fine . Doing the computation has a nice orthogonality to it . We 'd just be saying : There 's this swizzleserverrandom extension . If you see it in the ClientHello you process , go do the thing . Whatever . Independently , there 's an encryptedclienthello extension . If you see it , try to decrypt it and use it . Backend servers behind client - facing servers MUST support swizzleserverrandom and the client MUST stick swizzleserverrandom in ClientHelloInner . These two rules together avoid the trial decryption mess . 
 I 'd support this change . Is there a downside to relaxing the client requirement to " MAY stick swizzleserverrandom in CHI " ? That would allow client implementations to bear the burden of trial decryption , if they want . ( I do n't think it make a difference on the server side . ) IIRC a similar idea came in the long - long ago of and people did n't seem to like it . I could be wrong though . 
 What would be the point of allowing that ? Having two ways to do something adds complexity to the protocol and ecosystem . ( E.g. a client that does trial decrypt instead will fail to ensure backend servers implement their requirements . ) We should add options in the protocol as a last resort when we really need it , not because we can . ( Elsewhere , TLS 1.2 session tickets specified two different ways to check something . We ended up with random downstream protocol picking the wrong one and a security vulnerability in OpenSSL . ) 
 Agreed , just wanted to confirm . 
 can we merge before we consider changing the codepoint of the inner ECH extension ? 
 Oh sorry , missed that was waiting on me . Looking . 
 I landed . We can spin up a PR with separate codepoints now , if desired . ( I also like the idea ! ) 
 is going to take a stab at this ! 
 I agree that this seems like the right direction . Have n't reviewed the PR . 
 Fixed in . Closing .
Paragraph (version A):
If it supports ECH but cannot decrypt the extension, then it
terminates the handshake using the ClientHelloOuter.  This is
referred to as "ECH rejection".  When ECH is rejected, the server
sends an acceptable ECH configuration in its EncryptedExtensions
message.
Paragraph (version A):
If it supports ECH and decrypts the extension, it forwards the
ClientHelloInner to the backend, who terminates the connection.
This is referred to as "ECH acceptance".
Paragraph (version B):
If it is a client-facing server for the ECH protocol, but cannot
decrypt the extension, then it terminates the handshake using the
ClientHelloOuter.  This is referred to as "ECH rejection".  When
ECH is rejected, the client-facing server sends an acceptable ECH
configuration in its EncryptedExtensions message.
Paragraph (version B):
If it supports ECH and decrypts the extension, it forwards the
ClientHelloInner to the backend server, who terminates the
connection.  This is referred to as "ECH acceptance".
Paragraph (version A):
ECH uses draft-05 of HPKE for public key encryption I-D.irtf-cfrg-
hpke.  The ECH configuration is defined by the following "ECHConfigs"
structure.
Paragraph (version B):
ECH uses draft-05 of HPKE for public key encryption I-D.irtf-cfrg-
hpke.  The ECH configuration is defined by the following "ECHConfig"
structure.
Paragraph (version B):
The client-facing server advertises a sequence ECH configurations to
clients, serialized as follows.
Paragraph (version A):
The serialized and encrypted ClientHelloInner structure, encrypted
using HPKE as described in send-ech.
Paragraph (version B):
The serialized and encrypted ClientHelloInner structure, encrypted
using HPKE as described in real-ech.
Paragraph (version B):
Clients that implement the ECH extension behave in one of two ways:
either they offer a real ECH extension, as described in real-ech; or
they send a GREASE ECH extension, as described in grease-ech.
Clients of the latter type do not negotiate ECH.  Instead, they
generate a dummy ECH extension that is ignored by the server.  (See
dont-stick-out for an explanation.)  The client offers ECH if it is
in possession of a compatible ECH configuration and sends GREASE ECH
otherwise.
Paragraph (version A):
To offer ECH, the client first chooses a suitable ECH configuration.
To determine if a given "ECHConfig" is suitable, it checks that it
supports the KEM algorithm identified by "ECHConfig.kem_id", at least
one KDF/AEAD algorithm identified by "ECHConfig.cipher_suites", and
the version of ECH indicated by "ECHConfig.version".  Once a suitable
configuration is found, the client selects the cipher suite it will
use for encryption.  It MUST NOT choose a cipher suite or version not
advertised by the configuration.
Paragraph (version B):
To offer ECH, the client first chooses a suitable ECH configuration.
To determine if a given "ECHConfig" is suitable, it checks that it
supports the KEM algorithm identified by "ECHConfig.kem_id", at least
one KDF/AEAD algorithm identified by "ECHConfig.cipher_suites", and
the version of ECH indicated by "ECHConfig.version".  Once a suitable
configuration is found, the client selects the cipher suite it will
use for encryption.  It MUST NOT choose a cipher suite or version not
advertised by the configuration.  If no compatible configuration is
found, then the client SHOULD proceed as described in grease-ech.
Paragraph (version A):
As described in server-behavior, the server MAY either accept ECH and
use ClientHelloInner or reject it and use ClientHelloOuter.  In
handling the server's response, the client's first step is to
determine which value was used.  The client presumes acceptance if
the last 8 bytes of ServerHello.random are equal to
"accept_confirmation" as defined in backend-server-behavior.
Otherwise, it presumes rejection.
Paragraph (version A):
If the server used ClientHelloInner, the client proceeds with the
connection as usual, authenticating the connection for the origin
server.
Paragraph (version B):
As described in server-behavior, the server MAY either accept ECH and
use ClientHelloInner or reject it and use ClientHelloOuter.  In
handling the server's response, the client's first step is to
determine which value was used.  The client presumes acceptance if
the last 8 bytes of ServerHello.random are equal to
"accept_confirmation" as defined in backend-server.  Otherwise, it
presumes rejection.
Paragraph (version B):
If the server used ClientHelloInner, the client proceeds with the
connection as usual, authenticating the connection for the true
server name.
Paragraph (version A):
Upon receiving an "encrypted_client_hello" extension, the client-
facing server determines if it will accept ECH, prior to negotiating
any other TLS parameters.  Note that successfully decrypting the
extension will result in a new ClientHello to process, so even the
client's TLS version preferences may have changed.
Paragraph (version B):
Servers that that implement the ECH extension play one of two roles,
depending on the form of the ECH extension in the ClientHello.  If
the extension value is non-empty, the server acts as a client-facing
server and proceeds as described in client-facing-server to extract a
ClientHelloInner if available.  If the extension value is empty, the
server acts as a backend server and proceeds as described in backend-
server.
Paragraph (version B):
Upon receiving a non-empty "encrypted_client_hello" extension, the
client-facing server determines if it will accept ECH, prior to
negotiating any other TLS parameters.  Note that successfully
decrypting the extension will result in a new ClientHello to process,
so even the client's TLS version preferences may have changed.
Paragraph (version A):
Upon determining the ClientHelloInner, the client-facing server then
forwards the ClientHelloInner to the appropriate backend server,
which proceeds as in backend-server-behavior.  If the backend server
responds with a HelloRetryRequest, the client-facing server forwards
it, decrypts the client's second ClientHelloOuter using the modified
procedure in server-hrr, and forwards the resulting second
ClientHelloInner.  The client-facing server forwards all other TLS
messages between the client and backend server unmodified.
Paragraph (version B):
Upon determining the ClientHelloInner, the client-facing server then
forwards the ClientHelloInner to the appropriate backend server,
which proceeds as in backend-server.  If the backend server responds
with a HelloRetryRequest, the client-facing server forwards it,
decrypts the client's second ClientHelloOuter using the modified
procedure in server-hrr, and forwards the resulting second
ClientHelloInner.  The client-facing server forwards all other TLS
messages between the client and backend server unmodified.
Paragraph (version A):
Note that decryption failure could indicate a GREASE ECH extension
(see grease-extensions), so it is necessary for servers to proceed
with the connection and rely on the client to abort if ECH was
required.  In particular, the unrecognized value alone does not
indicate a misconfigured ECH advertisement (misconfiguration).
Instead, servers can measure occurrences of the "ech_required" alert
to detect this case.
Paragraph (version B):
Note that decryption failure could indicate a GREASE ECH extension
(see grease-ech), so it is necessary for servers to proceed with the
connection and rely on the client to abort if ECH was required.  In
particular, the unrecognized value alone does not indicate a
misconfigured ECH advertisement (misconfiguration).  Instead, servers
can measure occurrences of the "ech_required" alert to detect this
case.
Paragraph (version A):
Passive attackers with a known ECH configuration can distinguish
between a connection that negotiates ECH with that configuration
and one which does not, because the latter used a GREASE
"encrypted_client_hello" extension (as specified in grease-
extensions) or a different ECH configuration.
Paragraph (version B):
Passive attackers with a known ECH configuration can distinguish
between a connection that negotiates ECH with that configuration
and one which does not, because the latter used a GREASE
"encrypted_client_hello" extension (as specified in grease-ech) or
a different ECH configuration.
Paragraph (version A):
See do-not-stick-out for more discussion about the "do not stick out"
criteria from RFC8744.
Paragraph (version B):
See dont-stick-out for more discussion about the "do not stick out"
criteria from RFC8744.
Paragraph (version A):
Clients MAY include additional extensions in ClientHelloOuter to
avoid signaling unusual behavior to passive observers, provided the
choice of value and value itself are not sensitive.  See do-not-
stick-out.
Paragraph (version B):
Clients MAY include additional extensions in ClientHelloOuter to
avoid signaling unusual behavior to passive observers, provided the
choice of value and value itself are not sensitive.  See dont-stick-
out.
Paragraph (version A):
To signal acceptance, the backend server overwrites 8 bytes of its
ServerHello.random with a value derived from the
ClientHelloInner.random.  (See backend-server-behavior for details.)
This behavior increases the likelihood of the ServerHello.random
colliding with the ServerHello.random of a previous session,
potentially reducing the overall security of the protocol.  However,
the remaining 24 bytes provide enough entropy to ensure this is not a
practical avenue of attack.
Paragraph (version B):
To signal acceptance, the backend server overwrites 8 bytes of its
ServerHello.random with a value derived from the
ClientHelloInner.random.  (See backend-server for details.)  This
behavior increases the likelihood of the ServerHello.random colliding
with the ServerHello.random of a previous session, potentially
reducing the overall security of the protocol.  However, the
remaining 24 bytes provide enough entropy to ensure this is not a
practical avenue of attack.
Paragraph (version A):
The only explicit signal indicating possible use of ECH is the
ClientHello "encrypted_client_hello" extension.  Server handshake
messages do not contain any signal indicating use or negotiation of
ECH.  Clients MAY GREASE the "encrypted_client_hello" extension, as
described in grease-extensions, which helps ensure the ecosystem
handles ECH correctly.  Moreover, as more clients enable ECH support,
e.g., as normal part of Web browser functionality, with keys supplied
by shared hosting providers, the presence of ECH extensions becomes
less unusual and part of typical client behavior.  In other words, if
all Web browsers start using ECH, the presence of this value will not
signal unusual behavior to passive eavesdroppers.
Paragraph (version B):
The only explicit signal indicating possible use of ECH is the
ClientHello "encrypted_client_hello" extension.  Server handshake
messages do not contain any signal indicating use or negotiation of
ECH.  Clients MAY GREASE the "encrypted_client_hello" extension, as
described in grease-ech, which helps ensure the ecosystem handles ECH
correctly.  Moreover, as more clients enable ECH support, e.g., as
normal part of Web browser functionality, with keys supplied by
shared hosting providers, the presence of ECH extensions becomes less
unusual and part of typical client behavior.  In other words, if all
Web browsers start using ECH, the presence of this value will not
signal unusual behavior to passive eavesdroppers.