Draft: draft-ietf-tls-esni

Commentary: Thanks ! 
 We previously decided not to bind the outer ClientHello to the ECH decryption , because doing so is rather a hassle . We 'd need something similar to the TLS 1.3 PSK binder mess , with the complexity of ordering relative to the PSK binders themselves . Additionally , while the binding helps with some of the do n't stick out properties , there were other attacks on distinguishability anyway . So , instead , we mitigated the inner ClientHello malleability with OuterExtensions.innerdigest and left the outer ClientHello unbound . However , we 've since decided not to allow PSKs in the outer ClientHello . Perhaps we should revisit this . Suppose the AD parameter to the ECH decryption were the entire outer ClientHello , minus the ECH extension . I believe this means we no longer need OuterExtensions.innerdigest . That would give an immediate 33 - byte savings . It would then unlock a further 32 byte savings by amending to say : Client always encodes an empty legacysessionid in ECH plaintext . Client - facing server copies outer legacysessionid to inner ClientHello as part of decompression . ( The reason we ca n't do this easily right now is that , if the inner ClientHello lacks outerextension , nothing 's authenticating legacysessionid . Since the field in TLS 1.3 is all but ignored , it 's " obvious " that the malleability does n't matter , but it 's nicer to not need to think about such things . ) From looking at Chrome 's ClientHellos and working through what we 'd send ( drop 1.2 - only extensions , compress most ) , it looks like the inner ClientHello will be maybe 130 - 140 bytes , plus a padded servername . The 65 bytes above would almost halve the overhead . In some sense what 's going on here is our 16 - byte tag on the AEAD in the ECH ciphertext is going to waste . We did n't authenticate everything that goes into reconstructing the inner ClientHello ( outerextensions ) , so instead we authenticate another hash ( OuterExtensions.innerdigest ) and check that afterwards . ( To that end , if we do this , we probably need to say the server MUST reject encryptedclienthello showing up in outer_extensions , that way all inputs to decompression are authenticated . Equivalently , decompression is done relative to the ECH - extension - less AD input rather than the original outer ClientHello . ) 
 I like this idea . How do you think the AD ought to be structured ? The ClientHelloOuter , but with an an empty " encryptedclienthello " extension ? 
 Yeah , that 's seems the simplest to me . Filling it with zeros , as pointed out to me , requires predicting the length of the encrypted inner ClientHello . This is n't strictly impossible ( ADs do n't change ciphertext length ) , but it seems needlessly fussy and ECH is already requiring we be able re - encode ClientHellos , lengths and all . Note this assumes there are no computed PSK binders in the outer ClientHello because otherwise there 's a circular dependency . ( If we wanted to allow that , the AD would need to zero / trim the binders or so . ) 
 Another benefit is it stops the attacker from probing information about compressed extensions . Currently an attacker can learn which extensions are compressed in the inner ClientHello by removing them from the outer ClientHello and seeing if the server still responds . This is n't a huge deal , as compressed extensions are assumed public , but this way we remove that vector and leave only the fuzzier signal from the ciphertext length . 
 On second thought , a lot of implementations will need to do that prediction anyway . The workaround for the old F5 bug means we 'll need to know the eventual size for the padding extension . ( On the other hand , you can probably assume anyone doing ECH is not running those things . On the other hand , turning off the workaround would stick out . ) Ah well . We did it for PSK already . ( I wonder if we can do drop that workaround now that TLS 1.0 and 1.1 are gone ... ) 
 What 's the " old F5 bug " ? What 's the value in authenticating the length of the " encryptedclienthello " extension ? This is authenticated by the handshake already , no ? 
 It 's why we have a padding extension . There is n't . It 's just a question of what 's easier to deal with . Filling it with zeros means that , when computing the AD on the receiving side , you do n't need to fully reconstruct a modified outer ClientHello with updated length prefixes . We avoided this when computing the PSK binder in RFC8446 . It 's a mild hassle but not a huge deal . More importantly , we 've thoroughly given up on that elsewhere in the spec . The F5 padding business also means computing this AD will likely take some length prediction anyway , but so it goes . 
 I agree , it 's not a big hassle . 
 Rather than make the extension empty , can we just omit the and fields ? ( The and should arguably be included , a la ) . 
 That works , though it 's even more fussy for the client to construct , since it needs to half - encode the ECH extension before fully encoding it . is already bound into HPKE itself . is less clear , but I thought our model already said all this did n't matter ? Is n't the binding here just to replace and provide malleability ? If there 's something more going on , I 'd like us to have some principled answer here , so we can answer questions like ... what about the handshake transcript , which may not be empty on  ? If we do that , what 's going on with echhrr_key ? 
 The principle I was following is : include as much as possible in the AD . Yeah , it 's more of a pain , and we 've gotten away with no binding whatsoever up to now , so maybe we do n't need it . I 'm happy to start with an empty ECH extension and then consider the other parts later , if that 'll help . 
 I do n't feel very strongly either way . 
 Let 's just do the simpler thing now , then ! :-) 
 If the client uses TLS 1.3 's , there are a couple subtle points : Even though the middlebox will never see the inner ClientHello , we still need a non - empty legacysessionid , because some servers use that value to condition the other bits . More importantly , the inner legacysessionid needs to match the outer legacysessionid ! Otherwise the server will echo back the wrong one and trip up all the buggy middleboxes again . Alternatively , we could say the server uses the outer ClientHello to negotiate middlebox compatibility mode . That would reduce bytes on the wire , but it 'd upset all the split mode arrangements . 
 Good catch . I 'd be fine with this matching constraint . Could you please propose text ?
Mailing list commentary: It is a little bit more calculation than that and related to some historic reasons , aka SSLv2 . For SSL records , the SSLv3 and TLS ClientHello headers are as follows : If this is interpreted as an SSLv2 header , it will be considered as a 3 byte header : The value for Client Hello message type is  which is 1 . When there is an SSLv3 / TLS client - hello of length 256 - 511 bytes , this is ambiguous as " message type " is 1 or it is the " length high bits " to be 1 . Out implementation before the patch was to prefer SSLv2 and thus the issue . As I am explaining this in detail , I would say that another work around on this would be making a client hello that exceeds 512 in length .
Paragraph (version B):
If implementing TLS 1.3's compatibility mode (see Appendix D.4 of
RFC8446), it MUST copy the legacy_session_id field from
ClientHelloOuter.  This allows the server to echo the correct
session ID when ECH is negotiated.