Draft: draft-ietf-tls-esni

Commentary: Since the client 's ESNI key share does n't change across CHs in response to a HRR , the same AEAD IV would be used to encrypt / decrypt two different messages . This is an attempt to fix that , while also specifying the server - side HRR behavior . ( Basically , check that the ESNI contents have not changed . ) 
 Nice catch , Would it make more sense to instead use the KeyShare as a salt in the HKDF ? 
 Or you could include the handshake transcript up to , but not including , the ClientHello . That is the empty string before  < but something else after . 
 That is a little iffy with cookie - only HelloRetryRequests . Those do n't change the ClientHello key shares list , so the client would derive the same key + nonce pair . The client would also use the same plaintext so it 's fine , but it seems an unnecessarily fragility . 
 Agreed . I think I prefer the " new DH " version . 
 Thank you for the changes ! LGTM .
Paragraph (version A):
where ESNIContents is as specified below and Hash is the hash
function associated with the HKDF instantiation.  The salt argument
for HKDF-Extract is a string consisting of Hash.length bytes set to
zeros.
Paragraph (version A):
If the server sends a HelloRetryRequest in response to the
ClientHello and the client can send a second updated ClientHello per
the rules in RFC8446, the "encrypted_server_name" extension values
which do not depend on the (possibly updated) KeyShareClientHello,
i.e,, ClientEncryptedSNI.suite, ClientEncryptedSNI.key_share, and
ClientEncryptedSNI.record_digest, MUST NOT change across ClientHello
messages.  Moreover, ClientESNIInner.nonce and
ClientESNIInner.realSNI MUST not change across ClientHello messages.
Informally, the values of all unencrypted extension information, as
well as the inner extension plaintext, must be consistent between the
first and second ClientHello messages.
Paragraph (version B):
If the server sends a HelloRetryRequest in response to the
ClientHello and the client can send a second updated ClientHello per
the rules in RFC8446, the "encrypted_server_name" extension values
which do not depend on the (possibly updated) KeyShareClientHello,
i.e,, ClientEncryptedSNI.suite, ClientEncryptedSNI.key_share, and
ClientEncryptedSNI.record_digest, MUST NOT change across ClientHello
messages.  Moreover, ClientESNIInner MUST not change across
ClientHello messages.  Informally, the values of all unencrypted
extension information, as well as the inner extension plaintext, must
be consistent between the first and second ClientHello messages.
Paragraph (version A):
If the decrypted value's length is different from the advertised
ESNIKeys.padded_length or the padding consists of any value other
than 0, then the server MUST abort the connection with an
illegal_parameter alert.  Otherwise, the server uses the
PaddedServerNameList.sni value as if it were the "server_name"
extension.  Any actual "server_name" extension is ignored, which also
means the server MUST NOT send the "server_name" extension to the
client.
Paragraph (version B):
If the decrypted value's length is different from the advertised
ESNIKeys.padded_length or the padding consists of any value other
than 0, then the server MUST abort the connection with an
"illegal_parameter" alert.  Otherwise, the server uses the
PaddedServerNameList.sni value as if it were the "server_name"
extension.  Any actual "server_name" extension is ignored, which also
means the server MUST NOT send the "server_name" extension to the
client.
Paragraph (version B):
If the ClientHello is the result of a HelloRetryRequest, servers MUST
abort the connection with an "illegal_parameter" alert if any of the
ClientEncryptedSNI.suite, ClientEncryptedSNI.key_share,
ClientEncryptedSNI.record_digest, or decrypted ClientESNIInner values
from the second ClientHello do not match that of the first
ClientHello.