Draft: draft-ietf-tls-esni

Commentary: ESNIConfig has a version number in front for extensibility , but it is unclear what the version invariants are . Presumably we would like versions to change the contents of an ESNIConfig ( indeed different drafts have done so ) , but it is not obvious this is possible and it is impossible to skip over an ESNIConfig with a version you do not understand . Fix this by moving the body of an ESNIConfig into an ESNIConfigContents and adding a length prefix in front . 
 As of draft - ietf - tls - esni-04 , when the server rejects ESNI with esniretryrequest , it includes one or more ESNIKeys for retry : The client behavior described in section 5.1.2 is to pick one of the ESNIKeys values from this vector : Encoding of contains the total size of the vector field but not the size of the individual ESNIKeys elements . This makes it difficult ( impossible ? ) to parse a vector with unknown future versions , so this part is not really extensible . 
 Thanks for the comment ! should resolve this . It 's a little goofy - looking but ah well . 
 Thank you for confirming the issue . Not the nicest but will be effective . It 's the only real blocking point I see when implementing draft  .
Paragraph (version B):
An opaque byte string whose contents depend on the version of the
structure.  For this specification, the contents are an
ESNIConfigContents structure.
Paragraph (version A):
Zero padding whose length makes the serialized
PaddedServerNameList struct have a length equal to
ESNIConfig.padded_length.
Paragraph (version A):
This value consists of the serialized ServerNameList from the
"server_name" extension, padded with enough zeroes to make the total
structure ESNIConfig.padded_length bytes long.  The purpose of the
padding is to prevent attackers from using the length of the
"encrypted_server_name" extension to determine the true SNI.  If the
serialized ServerNameList is longer than ESNIConfig.padded_length,
the client MUST NOT use the "encrypted_server_name" extension.
Paragraph (version B):
Zero padding whose length makes the serialized
PaddedServerNameList struct have a length equal to
ESNIConfigContents.padded_length.
Paragraph (version B):
This value consists of the serialized ServerNameList from the
"server_name" extension, padded with enough zeroes to make the total
structure ESNIConfigContents.padded_length bytes long.  The purpose
of the padding is to prevent attackers from using the length of the
"encrypted_server_name" extension to determine the true SNI.  If the
serialized ServerNameList is longer than
ESNIConfigContents.padded_length, the client MUST NOT use the
"encrypted_server_name" extension.
Paragraph (version A):
The client MUST place the value of ESNIConfig.public_name in the
"server_name" extension.  (This is required for technical conformance
with RFC7540; Section 9.2.)  The client MUST NOT send a "cached_info"
extension RFC7924 with a CachedObject entry whose
CachedInformationType is "cert", since this indication would divulge
the true server name.
Paragraph (version B):
The client MUST place the value of ESNIConfigContents.public_name in
the "server_name" extension.  (This is required for technical
conformance with RFC7540; Section 9.2.)  The client MUST NOT send a
"cached_info" extension RFC7924 with a CachedObject entry whose
CachedInformationType is "cert", since this indication would divulge
the true server name.
Paragraph (version A):
If the value is "esni_retry_request", the client proceeds with the
handshake, authenticating for ESNIConfig.public_name as described
in auth-public-name.  If authentication or the handshake fails,
the client MUST return a failure to the calling application.  It
MUST NOT use the retry keys.
Paragraph (version B):
If the value is "esni_retry_request", the client proceeds with the
handshake, authenticating for ESNIConfigContents.public_name as
described in auth-public-name.  If authentication or the handshake
fails, the client MUST return a failure to the calling
application.  It MUST NOT use the retry keys.
Paragraph (version A):
If the server negotiates an earlier version of TLS, or if it does not
provide an "encrypted_server_name" extension in EncryptedExtensions,
the client proceeds with the handshake, authenticating for
ESNIConfig.public_name as described in auth-public-name.  If an
earlier version was negotiated, the client MUST NOT enable the False
Start optimization RFC7918 for this handshake.  If authentication or
the handshake fails, the client MUST return a failure to the calling
application.  It MUST NOT treat this as a secure signal to disable
ESNI.
Paragraph (version B):
If the server negotiates an earlier version of TLS, or if it does not
provide an "encrypted_server_name" extension in EncryptedExtensions,
the client proceeds with the handshake, authenticating for
ESNIConfigContents.public_name as described in auth-public-name.  If
an earlier version was negotiated, the client MUST NOT enable the
False Start optimization RFC7918 for this handshake.  If
authentication or the handshake fails, the client MUST return a
failure to the calling application.  It MUST NOT treat this as a
secure signal to disable ESNI.
Paragraph (version A):
The client MUST verify that the certificate is valid for
ESNIConfig.public_name.  If invalid, it MUST abort the connection
with the appropriate alert.
Paragraph (version B):
The client MUST verify that the certificate is valid for
ESNIConfigContents.public_name.  If invalid, it MUST abort the
connection with the appropriate alert.
Paragraph (version A):
If the ClientEncryptedSNI.key_share group does not match one in
the ESNIConfig.keys, it MUST abort the connection with an
"illegal_parameter" alert.
Paragraph (version B):
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 A):
If the decrypted value's length is different from the advertised
ESNIConfig.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
ESNIConfigContents.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.