Draft: draft-ietf-tls-esni

Commentary: This may also be useful for . do let me know if this PR overloads the term " GREASE " in a way that you find to be inaccurate or not in the GREASE spirit :) I 'm perfectly happy to call it something else . 
 I do n't know the answer to this question , but , from the TLS 1.3 RFC : I noticed this while testing with a pre - baked ClientHello that had both extensions . The ECH draft clearly required that the extension be removed , but I wondered about . 
 Given , , and , I 'd say quite the opposite . 
 Ah , I see text has been saying it must appear in the ClientHelloOuter . Thanks for the references . I was working from draft-10 . 
 Here 's a fun case . Suppose the client talks to a 0 - RTT - capable , ECH - capable server . It 'll send earlydata + presharedkey in ClientHelloInner , wrap that in some ClientHelloOuter , and follow it up with early data records . Now the server rejects ECH and handshakes with the ClientHelloOuter . But the client has already sent early data , so the server needs to know to skip past it . I believe this means we need to require the client mirror ClientHelloInner.earlydata in ClientHelloOuter , even though it 's not actually offering to resume anything . Sending earlydata without presharedkey is slightly weird ( if tolerated at all ) , so we might even want to recommend a fake outer presharedkey . We almost _ do n't care about this : the client may as well stop the handshake at server Finished and skip the client Finished flight anyway , for purposes of the recovery flow . However : What 's not what the draft currently says If the server rejects ECH , handshakes with ClientHelloOuter , and sends HelloRetryRequest , we do care about the client 's second flight getting through . That second case is extra fun because the client - facing server must look for the second ClientHello too . 
 Was n't this already the outcome from ? ( That is , if the inner CH has a PSK , then the outer one ought have a dummy PSK , too . ) As for mirroring earlydata , why can the server not just ignore the application data ( as if it received earlydata and decided to ignore it ) ? Taking a quick look back at RFC8446 , the server behavior where clients send application data without earlydata is not defined , so are you concerned about that , or something else ? 
 Well , I think we only got as far as MAY in , but yeah I think this is another reason . Regarding ignoring application data , our server implementation only skips early data if there was an early_data extension that we rejected . I believe that matches RFC8446 since it does n't say to skip application data in general , just that case . And , yeah , that 's the concern . 
 Since this is behavior for the client - facing server , which supports ECH , ca n't we specify the desired behavior in this spec ? That is , we might say that a client - facing server which rejects ECH MUST ignore any early data sent by the server , or something . Would that work ? 
 We could , but then it 'd break the nice property that a plain RFC8446 server will handshake ClientHelloOuter without any fuss . This property is great for rollback safety . ( Otherwise any ECH server deployment needs to be two - stage , and introduces a lower bound that you can not rollback beyond . ) And elsewhere we 've tried to avoid contradicting RFC8446 . Yet another option would be to tell the client to retry on certain kinds of errors if it offered 0 - RTT in ClientHelloInner , but that 's a bit more fuss since retries are often outside the TLS stack . ( Besides , the fact that you offer 0 - RTT in ClientHelloInner is all but public anyway . While we do n't have a cleartext 0 - RTT marker [ ] , it 's pretty obvious from timing that some post - ClientHello record came before ServerHello . ) [ ] In TCP ... I want to say QUIC does , but I could be misremembering . 
 True ! This is fun . :-) 
 I 'm not sure why ignoring stuff is fuss . What 's the alternative ? To terminate the handshake if the server receives early data ? Would n't that be more fuss ? If RFC8446 does n't specify what to do in this situation , I 'm not sure why specifying it is in contradiction to RFC8446 ( as opposed to expanding on it ) . 
 I think RFC8446 does say what to do in this situation . Section 5.2 says at the bottom : The default for the record layer is that decryption errors are fatal ( as it should be ) . Early data skipping is an exception to this described in section 4.2.10 , and the exception only applies when the server declines an earlydata extension . Oh no , the goal is to ignore stuff . That 's what makes the recovery flow work . The issue is that , in RFC8446 , servers only ignore the early data if there was an earlydata extension in ClientHello which they declined . Otherwise , it 's just a fatal decryption error . In order to meet that condition , ClientHelloOuter needs the early_data extension whenever ClientHelloInner does . 
 ACK -- thanks for closing the loop ! 
 As discussed in , there are two real - ECH / grease - ECH differentiators related to the PSK extension we may wish to address . ECH disallows the PSK extension in ClientHelloOuter , whereas grease ECH permits PSK in ClientHello . ECH allows PSK in ClientHelloInner . In case of acceptance , the backend server may respond with PSK in ServerHello . The response would appear to be unsolicited . something that would not happen in a grease - ECH or vanilla handshake . The question we will ask ourselves here is if / how to mitigate these differentiators . We might simply say that clients MAY ( or SHOULD ? ) send a dummy PSK in the ClientHello(Outer ) . This ought to provide sufficient cover . 
 I do n't mind a MAY on sending a dummy PSK in case ( 2 ) , though I do n't think it 's a good idea for case ( 1 ) . The case that really matters here is when the outer and inner ClientHello both lack PSKs : Suppose the buggy network is sensitive to ( 1 ) and only allows ECH extensions when the outer ClientHello has a PSK because it knows those ca n't be ECH . That network has effectively broken all connections because the only way for the client to get a PSK is to have connected to the server without a PSK at some point . Suppose instead the buggy network is sensitive to ( 2 ) and breaks if the inner ClientHello has a PSK but the outer does not . The connect will fail , but between single - use tickets and bounded client session caches , the client will quickly exhaust its tickets and get out of case ( 2 ) . This is a performance issue , but the connections still work . ( Though , yeah , adding the option to send a dummy one might help there . shrug ) 
 I 'm not following the following point . Could you elaborate ? In any case , the case to mitigate ( 2 ) seems more compelling than the case to mitigate ( 1 ) , since ( 2 ) would look like non - compliance to an ECH - ignorant network . Would be curious to see what others think . 
 So I think the benefit of GREASE - like strategies is that broader breakages now are more noticeable than focused breakage later . More noticeable breakage is more likely to be fixed , and less likely to make it to the ecosystem in the first place . This applies to ECH GREASE by saying we want all ClientHellos to look like ECH was deployed , so the network is less likely to develop intolerances . Differences between GREASE ECH and actual ECH thus matter because the network be intolerant to something that we failed to simulate . ( 1 ) says that , in actual ECH , all outer ClientHellos have no PSK . In GREASE ECH , some outer ClientHellos have a PSK while some do not . If we were to translate that to actual intolerance , it would mean the network rejects outer ClientHellos without a PSK . But that would break everything , ECH or non - ECH , anyway because clients do n't send PSKs the first time [ ] they connect to a server . Clients only have PSKs to send the second time , and you ca n't connect a second time if you did n't connect a first time . Thus , even though ( 1 ) is a difference , it does n't seem that difference prevents us from noticing intolerance . Agreed that mitigating ( 2 ) is more compelling than mitigating ( 1 ) . [ ] First time overall , first time after a restart ( if sessions are n't persisted ) , or first time after a long break ( sessions expired ) . 
 I agree that ( 2 ) is more important . And I 'm fine with a " MAY / SHOULD send an outer dummy PSK if you are using ECH and have an inner PSK . " if we were to append on a dummy PSK , what do you think would be a suitable length ? ( Bikeshedding over that should be fun . ) As an aside , I wanted to drill in on this point : This seems true , if we 're assuming the the intolerance is " break the connection , " which I think is the right interpretation . But it occurs to me that there 's a slightly weaker form of misbehavior that s 's possible with ( 1 ): a network may learn information about when a given client uses ECH . This seems out of scope , but maybe something to keep in mind ? 
 Re length , I dunno leave it to the client to choose ? " Probably not very long . " Making that in scope sounds exceedingly difficult . For instance , for a given server , you might know that tickets issued today start with ( maybe the ID of today 's key ) , but synthesized dummy tickets wo n't match that . 
 Yep , no argument there . 
 Discussed in 110 : Will submit a PR that says " clients MAY send a dummy PSK if the inner CH uses a PSK . "
Paragraph (version B):
When the client offers the "pre_shared_key" extension in
ClientHelloInner, it SHOULD also include a GREASE "pre_shared_key"
extension in ClientHelloOuter, generated in the manner described
in grease-psk.  The client MUST NOT use this extension to
advertise a PSK to the client-facing server.  (See flow-
clienthello-malleability.)  When the client includes a GREASE
"pre_shared_key" extension, it MUST also copy the
"psk_key_exchange_modes" from the ClientHelloInner into the
ClientHelloOuter.
Paragraph (version B):
When offering ECH, the client is not permitted to advertise PSK
identities in the ClientHelloOuter.  However, the client can send a
"pre_shared_key" extension in the ClientHelloInner.  In this case,
when resuming a session with the client, the backend server sends a
"pre_shared_key" extension in its ServerHello.  This would appear to
a network observer as if the the server were sending this extension
without solicitation, which would violate the extension rules
described in RFC8446.  Sending a GREASE "pre_shared_key" extension in
the ClientHelloOuter makes it appear to the network as if the
extension were negotiated properly.
Paragraph (version B):
The client generates the extension payload by constructing an
"OfferedPsks" structure (see RFC8446, Section 4.2.11) as follows.
For each PSK identity advertised in the ClientHelloInner, the client
generates a random PSK identity with the same length.  It also
generates a random, 32-bit, unsigned integer to use as the
"obfuscated_ticket_age".  Likewise, for each inner PSK binder, the
client generates random string of the same length.
Paragraph (version B):
If the server replies with a "pre_shared_key" extension in its
SeverHello, then the client MUST abort the handshake with an
"illegal_parameter" alert.