Draft: draft-ietf-tls-esni

Commentary: [ This was split out of as the possibly more controversial idea . It 's a simplification but does make configs larger . Also it sits on top of and . Ignore the first two comments to look at it in isolation . ] We have two layers of parameter negotiation . Multiple KeyShareEntry values in an ESNIConfig , and multiple ESNIConfig values in an ESNIConfigs . We only need one mechanism , so store only one KeyShareEntry in an ESNIConfig . This simplifies representing client and server configuration , which simplies implementation internals as well as interchange formats . Right now , on the server , configuration has two layers of lists , something like list(tuple(ESNIConfig , list(PrivateKey ) ) ) . Now the server maintains list(tuple(ESNIConfig , PrivateKey ) ) . Note also that draft - farrell - tls - pemesni-00 has this oddity around what to do if the ESNIKeys contains multiple keys . This is particularly a nuisance because a single standalone PRIVATE KEY / ESNIKEY pair is not usable because the server has committed to answering to all keys in the ESNIKeys . The server must consume multiple PEM files , match up the ESNIKeyses , and then assert that it has a complete set . The downside is that , in the likely case that the server only supports one version and one set of extensions , the non - key ESNI config bits ( notably the public name ; the rest is small ) are repeated for every named group . However , the public name should not be that large and servers should only need one or two groups ( see ) . 
 A server can publish multuple HTTPSSVC RRs . Each of those RRs can contain multiple ECHOConfigContent values ( i.e. multiple public keys and public_names ) . I do n't see a real need for two different ways to publish more than one public key for a given server . There is a minor efficiency benefit in terms of the number of octets published in the DNS , but there is a lot of additional complexity in terms of code , and if nobody really publishes multiple public keys in one RR value , then that code is likely where we 'll find CVEs . Reducing down to one public key per RR value also reduces the complexity when writing code to create / publish RRs . I think we have to support multiple RR values , because that 's how the DNS works , and so the one to drop is the multiple public keys in one ECHOConfigs . IOW , I 'd suggest one ECHOConfig has exactly one public key . 
 A single ECHOConfig already has only one public key from and the HPKE bits . I 'm guessing you meant  ? There are multiple ECHOConfig values in a single ECHOConfigs , which came from ( Gosh , that was a terrible name . My bad . Maybe we should rename it ? ) I think the rationale there still holds ? The problem is that an HTTPSSVC RR implies transport - level decisions , while not every ECHOConfig can be consumed by your TLS logic . Folding them together means transport connect needs to be aware of the exact ECHO capabilities . For instance , the origin could advertise : echo = ECHOv1 echo = ECHOv2 The logic picking HTTPSSVC routes no longer gets a free choice . It must be aware of the TLS layer 's capabilities ( down to mandatory extensions and HPKE code points ) . ECHOConfigs means the expectation is : echo={ECHOv1,ECHOv2 } echo={ECHOv2,ECHOv2 } Now you pick a route freely and pass the entire opaque ECHO blob to TLS to interpret . Of course , one could still advertise : echo={ECHOv1 } echo={ECHOv2 } But you 're no longer forced to explode it out like that , so we can say an ECHOv1 - only client that happens to pick route2 can act as if route1 did n't exist . I.e. we set an expectation that all your routes must be equally capable . ( Just as we have that expectation elsewhere . If route1 only speaks TLS 1.0 , you 're not getting TLS 's downgrade protection because the attacker can always redirect you to the less secure config . ) 
 Got ta admit I 'm not at all getting what you 're saying , sorry . As - is , clients need to write the code to handle multiple keys ( and all other variations possible ) at both levels , or if not , then we 're missing text in the spec saying what does n't need to be supported . I do n't see a real benefit in that complexity . 
 As per today 's call , we 're closing this due to the simplifications it brings for client implementations , in particular around collating all logic about ECHOConfig compatibility inside the TLS stack without the need for additional interfaces . 
 This LGTM -- thanks ,  !
Paragraph (version A):
The ESNIConfigs structure contains one or more ESNIConfig structures
in decreasing order of preference.  This allows a server to support
multiple versions of ESNI and multiple sets of ESNI extensions.
Paragraph (version B):
The ESNIConfigs structure contains one or more ESNIConfig structures
in decreasing order of preference.  This allows a server to support
multiple versions of ESNI and multiple sets of ESNI parameters.
Paragraph (version A):
The list of keys which can be used by the client to encrypt the
SNI.  Every key being listed MUST belong to a different group.
Paragraph (version B):
The key which can be used by the client to encrypt the SNI.
Clients MUST ignore any ESNIConfig structure with a key using a
NamedGroup they do not support or are unwilling to use.
Paragraph (version A):
Any of the listed keys in the ESNIConfig value may be used to encrypt
the SNI for the associated domain name.  The cipher suite list is
orthogonal to the list of keys, so each key may be used with any
cipher suite.  Clients MUST parse the extension list and check for
unsupported mandatory extensions.  If an unsupported mandatory
extension is present, clients MUST reject the ESNIConfig value.
Paragraph (version B):
Clients MUST parse the extension list and check for unsupported
mandatory extensions.  If an unsupported mandatory extension is
present, clients MUST reject the ESNIConfig value.
Paragraph (version A):
In order to send an encrypted SNI, the client MUST first select one
of the ESNIConfig values in the ESNIConfigs structure which it is
able to process (see esni-configuration).  It MUST then select one of
the KeyShareEntry values in the ESNIConfig and generate an (EC)DHE
share in the matching group.  This share will then be sent to the
server in the "encrypted_server_name" extension and used to derive
the SNI encryption key.  It does not affect the (EC)DHE shared secret
used in the TLS key schedule.  The client MUST also select an
appropriate cipher suite from the list of suites offered by the
server.  If the client is unable to select an appropriate group or
suite it SHOULD ignore that ESNIConfig value and MAY attempt to use
another value provided by the server.  The client MUST NOT send
encrypted SNI using groups or cipher suites not advertised by the
server.
Paragraph (version B):
In order to send an encrypted SNI, the client MUST first select one
of the ESNIConfig values in the ESNIConfigs structure which it is
able to process (see esni-configuration).  It then generates an
(EC)DHE share in the matching group.  This share will then be sent to
the server in the "encrypted_server_name" extension and used to
derive the SNI encryption key.  It does not affect the (EC)DHE shared
secret used in the TLS key schedule.  The client MUST also select an
appropriate cipher suite from the list of suites offered by the
server.  If the client is unable to select an appropriate group or
suite it SHOULD ignore that ESNIConfig value and MAY attempt to use
another value provided by the server.  The client MUST NOT send
encrypted SNI using groups or cipher suites not advertised by the
server.
Paragraph (version A):
If the ClientEncryptedSNI.key_share group does not match one in
the ESNIConfigContents.keys, it MUST abort the connection with an
"illegal_parameter" alert.
Paragraph (version B):
If the ClientEncryptedSNI.key_share group does not match
ESNIConfigContents.key, it MUST abort the connection with an
"illegal_parameter" alert.