Draft: draft-ietf-tls-esni

Commentary: Along the way , I 've made two additional tweaks : Renamed outerextension to outerextensions , now that it contains multiple extensions . One of the diagrams even already referred to " outerextensions " because I did n't realize it was called " outerextension" . Clarified in compression process and ClientHelloInner construction rules that the to - be - compressed extensions must be consecutive . Hopefully that helps with . 
 FYI . I 'm hoping this will help clarify why the ordering thing is n't actually a big deal . 
 I 've updated the PR to include text to disambiguate the serialization . It 's ambiguous whether the encoding includes the 4 - byte ( 12 - byte in DTLS ) header from the Handshake structure or is just the body , from the ClientHello structure . I 've picked the smaller one . This also saves having to answer , in DTLS , what happens when the inner sequence number is wrong . 
 There are two ClientHelloInners , the actual one used in the handshake , and the encoded one with outerextensions substituted in . Both are described as ClientHelloInner , but this makes it slightly ambiguous which goes into , say , the handshake transcript . ( It 's late now , so I 'll leave this as an issue without a PR . If we do n't end up resolving this separately , I 'll probably fix this as part of . If we decide to implicitly copy over legacysession_id , the encryption payload becomes less and less defensibly an actual ClientHelloInner . ) 
 In my own implementation , I 've been referring to the plaintext payload as CompressedClientHelloInner . Which is terrible , but unambiguous . 
 Works for me . I was thinking EncodedClientHelloInner because it 's shorter and still works even if you choose not to compress anything . ( A no - op encoding is still an encoding . ) 
 +1 to EncodedClientHelloInner , given that compression is optional . if you have time , could you whip up a PR ?
Paragraph (version A):
Some TLS 1.3 extensions can be quite large and having them both in
ClientHelloInner and ClientHelloOuter will lead to a very large
overall size.  One particularly pathological example is "key_share"
with post-quantum algorithms.  In order to reduce the impact of
duplicated extensions, the client may use the "outer_extension"
extension.
Paragraph (version A):
OuterExtensions MUST only be used in ClientHelloInner.  It consists
of one or more ExtensionType values, each of which reference an
extension in ClientHelloOuter, and a digest of the complete
ClientHelloInner.
Paragraph (version A):
where "inner" is the ClientHelloInner structure and "Extract",
"Expand", and "Nh" are as defined by the KDF API in I-D.irtf-cfrg-
hpke.  Then, the client removes and replaces extensions from
ClientHelloInner with a single "outer_extension" extension.  The list
of outer extensions, OuterExtensions.outer_extensions, includes those
which were removed from ClientHelloInner, in the order in which they
were removed.
Paragraph (version A):
This process is reversed by client-facing server.  Specifically, the
server replaces the "outer_extension" with the corresponding sequence
of extensions in the ClientHelloOuter.  If any referenced extensions
are missing, the server MUST abort the connection with an
"illegal_parameter" alert.  The server then computes the digest of
the reconstructed ClientHelloInner.  If the digest does not equal
OuterExtensions.inner_digest, then the server MUST abort the
connection with a "decrypt_error" alert.
Paragraph (version B):
Some TLS 1.3 extensions can be quite large and having them both in
ClientHelloInner and ClientHelloOuter will lead to a very large
overall size.  One particularly pathological example is "key_share"
with post-quantum algorithms.  In order to reduce the impact of
duplicated extensions, the client may use the "outer_extensions"
extension.
Paragraph (version B):
OuterExtensions consists of one or more ExtensionType values, each of
which reference an extension in ClientHelloOuter, and a digest of the
complete ClientHelloInner.
Paragraph (version B):
where "inner" is the ClientHelloInner structure and "Extract",
"Expand", and "Nh" are as defined by the KDF API in I-D.irtf-cfrg-
hpke.  Then, the client removes and replaces extensions from
EncodedClientHelloInner with a single "outer_extensions" extension.
Removed extensions MUST be ordered consecutively in ClientHelloInner.
The list of outer extensions, OuterExtensions.outer_extensions,
includes those which were removed from EncodedClientHelloInner, in
the order in which they were removed.
Paragraph (version B):
Finally, EncodedClientHelloInner is serialized as a ClientHello
structure, defined in Section 4.1.2 of RFC8446.  Note this does not
include the four-byte header included in the Handshake structure.
Paragraph (version B):
The client-facing server computes ClientHelloInner by reversing this
process.  It scans EncodedClientHelloInner for an "outer_extensions"
extension.  If there is none, the ClientHelloInner is the
EncodedClientHelloInner.  Otherwise, it replaces the extension with
the corresponding sequence of extensions in the ClientHelloOuter.  If
any referenced extensions are missing, the server MUST abort the
connection with an "illegal_parameter" alert.  The server then
computes the digest of the reconstructed ClientHelloInner.  If the
digest does not equal OuterExtensions.inner_digest, then the server
MUST abort the connection with a "decrypt_error" alert.
Paragraph (version B):
The "outer_extensions" extension is only used for compressing the
ClientHelloInner.  It MUST NOT be sent in either ClientHelloOuter or
ClientHelloInner.
Paragraph (version B):
If it intends to compress any extensions (see outer-extensions),
it MUST order those extensions consecutively.
Paragraph (version B):
If it compressed any extensions in EncodedClientHelloInner, it
MUST copy the corresponding extensions from ClientHelloInner.
Paragraph (version B):
Note that the HPKE functions Deserialize and SetupBaseS are those
which match "ECHConfig.kem_id" and the AEAD/KDF used with "context"
are those which match the client's chosen preference from
"ECHConfig.cipher_suites".
Paragraph (version A):
If decryption fails, the server MUST abort the connection with a
"decrypt_error" alert.  Otherwise, the server scans ClientHelloInner
for an "outer_extension" extension and substitutes its value with the
values in ClientHelloOuter and validates the ClientHelloInner digest,
as described in outer-extensions.
Paragraph (version B):
If decryption fails, the server MUST abort the connection with a
"decrypt_error" alert.  Otherwise, the server reconstructs
ClientHelloInner from EncodedClientHelloInner, as described in outer-
extensions.
Paragraph (version A):
outer_extension(0xff04), with the "TLS 1.3" column values being
set to "CH", and "Recommended" column being set to "Yes".
Paragraph (version B):
outer_extensions(0xff04), with the "TLS 1.3" column values being
set to "", and "Recommended" column being set to "Yes".