Subject: [TLS] ESNI PRs #124 and #125: Improving ESNI Robustness and GREASE

From: "Christopher Wood" <[email-masked]>
Date: Wed, 13 Feb 2019 14:15:57 -0800

Hi folks,

PRs [1] and [2] need a little more review before we merge since 
they’re non-trivial changes. Please have a look and let the list know 
if you have objections with the contents therein. Otherwise, we will 
merge them by the end of the next week.

Thanks!
Chris (no hat)

[1] https://github.com/tlswg/draft-ietf-tls-esni/pull/124
[2] https://github.com/tlswg/draft-ietf-tls-esni/pull/125

---

From: Stephen Farrell <[email-masked]>
Date: Wed, 13 Feb 2019 23:00:04 +0000

Hiya,

> [1] https://github.com/tlswg/draft-ietf-tls-esni/pull/124

I just re-read that. I've a question: why tie the version
change to this PR and not the I-D rev? I'd prefer if we
make the change to 0xff02 when -03 is published. (I don't
care which PR does that, but wouldn't like to see every
PR bump that number.)

Aside from that I think it's ok (though I may find other
issues when implementing later) with two caveats that can
be handled now or later:

1. The DNS RR structure still needs fixing but that is likely
better handled separately. (By "fixing" I mean a new RR type
but also that it needs to be designed for DNS admins as well
and not only for TLS implementers which is the current case.
(I'm not saying what might or might not make it more dnsops
friendly, just that that needs to be checked/done sometime.)

2. I don't think the text below ought be included, it's not
the job of this WG to design MITM attacks. (Or maybe I've
misinterpreted it?)

"The public name, however, makes this protocol compatible with
deployments that use correctly-implemented MITM proxies. If the
client has cached an ESNIKey for the origin server, the MITM
proxy will process the cleartext SNI field and terminate a
connection to the public name instead. If the client is
configured to trust the proxy's certificate, it will accept
the connection as valid for the public name and retry with
ESNI disabled."

I also don't think I'd implement that fallback in my openssl
fork. Earlier text says to complete the h/s but to not make
that visible to the application layer and the above seems to
conflict with that. I could hold my nose were that in -03 as it
has no effect really, but I'll whine about it later for sure;-)

> [2] https://github.com/tlswg/draft-ietf-tls-esni/pull/125

I like this one. But the "SHOULD send" and "MUST pad to 260"
seem a bit OTT to me, though I could live with 'em for now.
So consider these nits, not objections:

- Rather than "SHOULD send", it may be better to say something
like "SHOULD frequently send" and leave it to clients to decide
how often to grease. Wouldn't that have the same effect?

- Maybe add that even TLS1.3 clients that don't really do ESNI
MAY grease ESNI? (A bit weird but hey why not?:-)

- Padding to 260 is IIRC the max that works. A CH with such
padding is ~600 bytes. Seems like a waste of bytes to me and
it could stick out depending on real ESNI padding_lengths.
Maybe consider something like "pad to a length that matches
recent traffic" and leave it to clients to figure out what
might stick out less. (I'm not sure every server will ask
for padding to 260 as CF do;-)

Cheers,
S.

---

From: David Benjamin <[email-masked]>
Date: Wed, 13 Feb 2019 17:55:52 -0600

Thanks for the comments! Responses inline.

> care which PR does that, but wouldn't like to see every

I bumped it because the PR was making a wire-incompatible change, but
batching them up to I-D revs makes sense too. No preferences here. (Spec
editors, do you care? I can remove that part of the change.)

> friendly, just that that needs to be checked/done sometime.)

I'm guessing this is to do with the various discussions around multi-CDN
and whatnot? That seems orthogonal to that PR. (I don't personally have
particularly strong opinions or experience there.)

> the connection as valid for the public name and retry with

That text isn't prescribing any particular behavior. It's just describing
the effect the rest of the text has on "trusted MITM proxies" and the like.
Note this is specifically about "MITM proxies" which control a root
certificate that the client is configured to trust. I will refrain from
commenting on whether this deployment model is at all wise, but it does
exist (antivirus, etc). The text itself is just an updated version of
existing bits here:
https://tools.ietf.org/html/draft-ietf-tls-esni-02#section-6.2

As for where this effect comes from, it's a consequence of the rollback and
partial deployment robustness mechanism in the PR:

> 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, verifying the certificate against
> ESNIKeys.public_name as described in {{verify-public-name}}. The client
MUST
> NOT enable the False Start optimization {{RFC7918}}. If the handshake
completes
> successfully, the client MUST abort the connection with an
"esni_required" alert.
> It then SHOULD retry the handshake with a new transport connection and
ESNI
> disabled."

Or, in other words, IF the server is able to speak authoritatively for the
public name (relatively to the client's trust anchors) but appears to not
understand ESNI at all, that is a signal to the client that ESNI got turned
off or hasn't fully been turned on yet. ESNI involves client state and,
without this, it's risky for a server operator to deploy ESNI. Deployments
are complex systems, and complex systems react to change unpredictably. For
most changes, if some show-stopping problem is found, it is safe to
rollback the change. For instance, clients naturally tolerate servers
turning TLS 1.3 on and off, a fact I'm sure every early adopter of TLS 1.3
has used many times. ESNI, a priori, breaks this property. The intent of
this text is to restore it, without totally breaking it (the stop signal is
authenticated under the public name, the same standard this PR sets for
replacing the key).

It turns out that a user moving in and out of one of these "trusted MITMs"
looks the same as a rollback, so we get robustness to that scenario too.
The current draft attempted to handle this case too, but did so with extra
machinery. From the link above:

>   A Web client client can securely detect case (2) because it will
>   result in a connection which has an invalid identity (most likely)
>   but which is signed by a certificate which does not chain to a
>   publicly known trust anchor.  The client can detect this case and
>   disable ESNI while in that network configuration

Here, there is no name check, so any publicly known root that the client
trusts can be used to trigger that fallback, even if it's just, say, an
intranet server and not a MITM proxy. The PR fixes this by checking the
public name. It only counts as a signal if the server can speak for the
service's public name, not any arbitrary name.

> has no effect really, but I'll whine about it later for sure;-)

I'm guessing you're referring to this?

> Note that verifying a connection for the public name does not verify it
for the
> origin. The TLS implementation MUST NOT surface such connections as
successful to
> the application.

That just says you can't report it as successful. Whether you report it to
the application at all depends on your API shape. For a low-level TLS
library that doesn't create transport connections, I'm envisioning it
report failure with a special error code, which higher-level logic can
interpret as a retry. (This is how we handle 0-RTT rejects in BoringSSL.
0-RTT rejects affect connection usage, such as if you thought you were
speaking HTTP/2, but the server rejected and then negotiated HTTP/1.1. It's
ultimately a very funny retry.) For higher-level code that knows how to
make transport connections, one option then is for the retry to be handled
more transparently.

> So consider these nits, not objections:

(260 is just a SHOULD rather than a MUST. More below.)

> how often to grease. Wouldn't that have the same effect?

Is there any reason not to just do it in every ClientHello?

Indeed! The PR currently says:

> If the client attempts to connect to a server and does not have an
ESNIKeys
> structure available for the server,

Knowing what ESNI is but not really doing it I think counts as "does not
have an ESNIKeys structure available". Do you think it should be called out
more explicitly?

260 comes from elsewhere which says:

> The length to pad the ServerNameList value to prior to encryption.
> This value SHOULD be set to the largest ServerNameList the server
> expects to support rounded up the nearest multiple of 16. If the
> server supports wildcard names, it SHOULD set this value to 260.

I figured that assuming, by default, that the server supports wildcard
names seemed reasonable so the text mirrored the other SHOULD. Though maybe
that's a bit much? I don't have strong feelings here. What do you think the
text should say? Perhaps it should pick a random multiple-of-16 length
between 64 and 260? Or maybe we should decrease the wildcard value... a
260-byte SNI name is kind of excessive, honestly.

David

---

From: Stephen Farrell <[email-masked]>
Date: Thu, 14 Feb 2019 00:24:09 +0000

Hiya,

Various bits'n'pieces below...

> particularly strong opinions or experience there.)

Not just that. ESNIKeys is a fairly complex structure that
has a number sets/sequences of values. There are various
possible deployment models. The current structure assumes
that it's ok to encode all that stuff up in one TLS style
blob and then put that in the DNS. That might not make sense
for some deployments in particular where the DNS operator
is not closely tied to the TLS server admin or where there's
1 DNS operator and N TLS server admins (for the same origin).
And then there's the use of the TXT RR. But I agree this
is orthogonal - I was mostly saying that in agreeing with
this PR I continue to think the DNS RR stuff needs other
work.

> That text isn't prescribing any particular behavior. 

Then delete it:-)

> It's just describing

Disagree. "Just describing" does not match the use of a meaningless
marketing term like "trusted blah proxy" sorry. Better to avoid all
that fuss really, no?

> https://tools.ietf.org/html/draft-ietf-tls-esni-02#section-6.2

I don't recall that having a concept of it being possible to
"correctly" implement breaking the TLS protocol? (As is inherent
in being an MITM.)

> authenticated under the public name, the same standard this PR sets for

It may be ok to live with such fallback whilst ESNI is being
introduced but I think ongoing support for it would be unwise.
And such a fallback requires no discussion of MITM attacks.
(Other than as an attack.)

> It turns out that a user moving in and out of one of these "trusted MITMs"

I object to that term again, sorry:-) It's marketing meaninglessness.

> That just says you can't report it as successful. 

"MUST NOT surface" seems like bad phrasing then.

> Whether you report it to
> interpret as a retry. 

That would be ok. Saying that requires no discussion of MITM attacks.
(My openssl code would actually make that visible to the application
if the application called a status API, but the TLS h/s would have
failed from the application POV even if the h/s looks like it worked
on the wire.)

> (This is how we handle 0-RTT rejects in BoringSSL.

I'd guess that some implementers may be put off by the
wasted bandwidth. Others won't care but if it's the case
that sending a bogus ESNI x% of the time gets as good a
result as sending all the time (which is how I interpret
what the SHOULD calls for) then it seems better to encourage
x% and not 100%.

>> structure available for the server,

"The client" in almost all IETF specs means a thing that
really implements the spec. So in this case, yeah, I think
it might be good to say that a TLS client implementer who
only has time to grease and not do the real thing is still
doing good overall by just doing that. (That said, I've no
idea if there'd ever be such an implementer, though when
we did DKIM there were many mail receivers who parsed but
didn't actually check signatures - maybe mail implementers
are more slapdash though:-)

>> server supports wildcard names, it SHOULD set this value to 260.

Yeah, and I disagree with that too:-)

> 260-byte SNI name is kind of excessive, honestly.

Regardless of the above disagreement about 260, if a client has
been sending a bunch of CH's including real ESNI that are about
400 bytes because some server's ESNIKeys says to pad to 160, and
that client then sends 600 bytes CH's to everyone else, I think
it'd be crystal clear which is grease and which not.

Cheers,
S.

---

From: Mike Bishop <[email-masked]>
Date: Thu, 14 Feb 2019 00:59:45 +0000

Perhaps a better way to phrase it is that a server which successfully authenticates as the public_name but does not support ESNI has securely disabled ESNI for that origin, subject to the same rules as if it had supplied a new ESNI key (i.e. use for now, but don't persist).  Leave as an implementation detail heuristics to extrapolate that the current network will securely disable ESNI for all origins.

-----Original Message-----
From: TLS <[email-masked]> On Behalf Of Stephen Farrell
Sent: Wednesday, February 13, 2019 4:24 PM
To: David Benjamin <[email-masked]>
Cc: TLS WG <[email-masked]>
Subject: Re: [TLS] ESNI PRs #124 and #125: Improving ESNI Robustness and GREASE

Hiya,

On 13/02/2019 23:55, David Benjamin wrote:
>> I just re-read that. I've a question: why tie the version change to 
>> this PR and not the I-D rev? I'd prefer if we make the change to 
>> 0xff02 when -03 is published. (I don't care which PR does that, but 
>> wouldn't like to see every PR bump that number.)
>>
> 
> batching them up to I-D revs makes sense too. No preferences here. 
> (Spec editors, do you care? I can remove that part of the change.)
> 
> 
>> Aside from that I think it's ok (though I may find other issues when 
>> implementing later) with two caveats that can be handled now or 
>> later:
>>
>> 1. The DNS RR structure still needs fixing but that is likely better 
>> handled separately. (By "fixing" I mean a new RR type but also that 
>> it needs to be designed for DNS admins as well and not only for TLS 
>> implementers which is the current case.
>> (I'm not saying what might or might not make it more dnsops friendly, 
>> just that that needs to be checked/done sometime.)
>>
> 
> I'm guessing this is to do with the various discussions around 
> multi-CDN and whatnot? That seems orthogonal to that PR. (I don't 
> personally have particularly strong opinions or experience there.)

Not just that. ESNIKeys is a fairly complex structure that has a number sets/sequences of values. There are various possible deployment models. The current structure assumes that it's ok to encode all that stuff up in one TLS style blob and then put that in the DNS. That might not make sense for some deployments in particular where the DNS operator is not closely tied to the TLS server admin or where there's
1 DNS operator and N TLS server admins (for the same origin).
And then there's the use of the TXT RR. But I agree this is orthogonal - I was mostly saying that in agreeing with this PR I continue to think the DNS RR stuff needs other work.

> 
> 
>> 2. I don't think the text below ought be included, it's not the job 
>> of this WG to design MITM attacks. (Or maybe I've misinterpreted it?)
>>
>> client has cached an ESNIKey for the origin server, the MITM proxy 
>> will process the cleartext SNI field and terminate a connection to 
>> the public name instead. If the client is configured to trust the 
>> proxy's certificate, it will accept the connection as valid for the 
>> public name and retry with ESNI disabled."
>>
> 

Then delete it:-)

> the effect the rest of the text has on "trusted MITM proxies" and the like.

Disagree. "Just describing" does not match the use of a meaningless marketing term like "trusted blah proxy" sorry. Better to avoid all that fuss really, no?

> certificate that the client is configured to trust. I will refrain 
> from commenting on whether this deployment model is at all wise, but 
> it does exist (antivirus, etc). The text itself is just an updated 
> version of existing bits here:

I don't recall that having a concept of it being possible to "correctly" implement breaking the TLS protocol? (As is inherent in being an MITM.)

> 
> As for where this effect comes from, it's a consequence of the 
> rollback and partial deployment robustness mechanism in the PR:
> 
>> provide an "encrypted_server_name" extension in EncryptedExtensions, 
>> the client proceeds with the handshake, verifying the certificate 
>> against ESNIKeys.public_name as described in {{verify-public-name}}. 
>> The client
> MUST
> Or, in other words, IF the server is able to speak authoritatively for 
> the public name (relatively to the client's trust anchors) but appears 
> to not understand ESNI at all, that is a signal to the client that 
> ESNI got turned off or hasn't fully been turned on yet. ESNI involves 
> client state and, without this, it's risky for a server operator to 
> deploy ESNI. Deployments are complex systems, and complex systems 
> react to change unpredictably. For most changes, if some show-stopping 
> problem is found, it is safe to rollback the change. For instance, 
> clients naturally tolerate servers turning TLS 1.3 on and off, a fact 
> I'm sure every early adopter of TLS 1.3 has used many times. ESNI, a 
> priori, breaks this property. The intent of this text is to restore 
> it, without totally breaking it (the stop signal is authenticated 
> under the public name, the same standard this PR sets for replacing the key).

It may be ok to live with such fallback whilst ESNI is being introduced but I think ongoing support for it would be unwise.
And such a fallback requires no discussion of MITM attacks.
(Other than as an attack.)

> The current draft attempted to handle this case too, but did so with 
> extra machinery. From the link above:
> 
> Here, there is no name check, so any publicly known root that the 
> client trusts can be used to trigger that fallback, even if it's just, 
> say, an intranet server and not a MITM proxy. The PR fixes this by 
> checking the public name. It only counts as a signal if the server can 
> speak for the service's public name, not any arbitrary name.
> 
>> fork. Earlier text says to complete the h/s but to not make that 
>> visible to the application layer and the above seems to conflict with 
>> that. I could hold my nose were that in -03 as it has no effect 
>> really, but I'll whine about it later for sure;-)
>>
> 

That would be ok. Saying that requires no discussion of MITM attacks.
(My openssl code would actually make that visible to the application if the application called a status API, but the TLS h/s would have failed from the application POV even if the h/s looks like it worked on the wire.)

> speaking HTTP/2, but the server rejected and then negotiated HTTP/1.1. 
> It's ultimately a very funny retry.) For higher-level code that knows 
> how to make transport connections, one option then is for the retry to 
> be handled more transparently.
> 
> 
>> - Rather than "SHOULD send", it may be better to say something like 
>> "SHOULD frequently send" and leave it to clients to decide how often 
>> to grease. Wouldn't that have the same effect?
>>
> 

I'd guess that some implementers may be put off by the wasted bandwidth. Others won't care but if it's the case that sending a bogus ESNI x% of the time gets as good a result as sending all the time (which is how I interpret what the SHOULD calls for) then it seems better to encourage x% and not 100%.

> 
> 
>> - Maybe add that even TLS1.3 clients that don't really do ESNI MAY 
>> grease ESNI? (A bit weird but hey why not?:-)
>>
> 

"The client" in almost all IETF specs means a thing that really implements the spec. So in this case, yeah, I think it might be good to say that a TLS client implementer who only has time to grease and not do the real thing is still doing good overall by just doing that. (That said, I've no idea if there'd ever be such an implementer, though when we did DKIM there were many mail receivers who parsed but didn't actually check signatures - maybe mail implementers are more slapdash though:-)

> 
> Knowing what ESNI is but not really doing it I think counts as "does 
> not have an ESNIKeys structure available". Do you think it should be 
> called out more explicitly?
> 
> 
>> - Padding to 260 is IIRC the max that works. A CH with such padding 
>> is ~600 bytes. Seems like a waste of bytes to me and it could stick 
>> out depending on real ESNI padding_lengths.
>> Maybe consider something like "pad to a length that matches recent 
>> traffic" and leave it to clients to figure out what might stick out 
>> less. (I'm not sure every server will ask for padding to 260 as CF 
>> do;-)
>>
> 

> names seemed reasonable so the text mirrored the other SHOULD. Though 
> maybe that's a bit much? I don't have strong feelings here. What do 
> you think the text should say? Perhaps it should pick a random 
> multiple-of-16 length between 64 and 260? Or maybe we should decrease 
> the wildcard value... a 260-byte SNI name is kind of excessive, honestly.

Regardless of the above disagreement about 260, if a client has been sending a bunch of CH's including real ESNI that are about
400 bytes because some server's ESNIKeys says to pad to 160, and that client then sends 600 bytes CH's to everyone else, I think it'd be crystal clear which is grease and which not.

Cheers,
S.

---

From: David Benjamin <[email-masked]>
Date: Wed, 13 Feb 2019 19:05:16 -0600

To be clear, the intent of the PR is definitely not to extrapolate any
signals about the current network. That way lies attacks. It's only ever
that one origin. If it turns out that all origins securely disable ESNI,
then that's what happens, but they each have to do so individually.

(A bit late here, so I'll go through the rest of Stephen's response
tomorrow. Wanted to clarify this detail quickly.)

On Wed, Feb 13, 2019 at 6:59 PM Mike Bishop <[email-masked]> wrote:

> Perhaps a better way to phrase it is that a server which successfully
> authenticates as the public_name but does not support ESNI has securely
> disabled ESNI for that origin, subject to the same rules as if it had
> supplied a new ESNI key (i.e. use for now, but don't persist).  Leave as an
> implementation detail heuristics to extrapolate that the current network
> will securely disable ESNI for all origins.
>
> Not just that. ESNIKeys is a fairly complex structure that has a number
> sets/sequences of values. There are various possible deployment models. The
> current structure assumes that it's ok to encode all that stuff up in one
> TLS style blob and then put that in the DNS. That might not make sense for
> some deployments in particular where the DNS operator is not closely tied
> to the TLS server admin or where there's
> And then there's the use of the TXT RR. But I agree this is orthogonal - I
> was mostly saying that in agreeing with this PR I continue to think the DNS
> RR stuff needs other work.
>
> >
> >
> marketing term like "trusted blah proxy" sorry. Better to avoid all that
> fuss really, no?
>
> I don't recall that having a concept of it being possible to "correctly"
> implement breaking the TLS protocol? (As is inherent in being an MITM.)
>
> >
> It may be ok to live with such fallback whilst ESNI is being introduced
> but I think ongoing support for it would be unwise.
> (My openssl code would actually make that visible to the application if
> the application called a status API, but the TLS h/s would have failed from
> the application POV even if the h/s looks like it worked on the wire.)
>
> I'd guess that some implementers may be put off by the wasted bandwidth.
> Others won't care but if it's the case that sending a bogus ESNI x% of the
> time gets as good a result as sending all the time (which is how I
> interpret what the SHOULD calls for) then it seems better to encourage x%
> and not 100%.
>
> >
> >
> "The client" in almost all IETF specs means a thing that really implements
> the spec. So in this case, yeah, I think it might be good to say that a TLS
> client implementer who only has time to grease and not do the real thing is
> still doing good overall by just doing that. (That said, I've no idea if
> there'd ever be such an implementer, though when we did DKIM there were
> many mail receivers who parsed but didn't actually check signatures - maybe
> mail implementers are more slapdash though:-)
>
> >
> Regardless of the above disagreement about 260, if a client has been
> sending a bunch of CH's including real ESNI that are about
> 400 bytes because some server's ESNIKeys says to pad to 160, and that
> client then sends 600 bytes CH's to everyone else, I think it'd be crystal
> clear which is grease and which not.
>
> Cheers,
> S.
>
> >
> > David
> >
>

---

From: Roelof DuToit <[email-masked]>
Date: Wed, 13 Feb 2019 20:36:44 -0500

Questions for PR [1]:

* Regarding this text:

The client MUST NOT use the server-provided retry keys until the handshake completes successfully. On success, it MUST NOT overwrite the DNS-provided keys with the retry keys. It MUST use the retry keys at most once and continue offering DNS-provided keys for subsequent connections. This avoids introducing a tracking vector, should a malicious server present client-specific retry keys.

.. specifically this part: ".. use the retry keys at most once".  

Q1: Are you saying the client should persistently remember which public_name values triggered retry keys?  For how long?

Q2: What happens if fronting server A sent retry keys, and the subsequent transport connection ends up on server B, which also sends retry keys?

--Roelof

---- On Wed, 13 Feb 2019 17:15:57 -0500 Christopher Wood <[email-masked]> wrote ----

Hi folks,

Thanks!

Chris (no hat)

_______________________________________________

TLS mailing list

mailto:[email-masked]

https://www.ietf.org/mailman/listinfo/tls

---

From: David Benjamin <[email-masked]>
Date: Thu, 14 Feb 2019 12:00:16 -0600

On Wed, Feb 13, 2019 at 7:37 PM Roelof DuToit <[email-masked]> wrote:

> Questions for PR [1]:
>
> * Regarding this text:
> The client MUST NOT use the server-provided retry keys until the handshake
> completes successfully. On success, it MUST NOT overwrite the DNS-provided
> keys with the retry keys. It MUST use the retry keys at most once and
> continue offering DNS-provided keys for subsequent connections. This avoids
> introducing a tracking vector, should a malicious server present
> client-specific retry keys.
>
> Q1: Are you saying the client should persistently remember which
> public_name values triggered retry keys?  For how long?
>

No, exactly the opposite. You use the retry key for just the retry and then
forget about it.
https://mailarchive.ietf.org/arch/msg/tls/xBEHe1_CcYEYinZQHxWGq8vjA0Q

Q2: What happens if fronting server A sent retry keys, and the subsequent
> transport connection ends up on server B, which also sends retry keys?
>

You keep retrying. And hen you hit the text which says:

> Clients SHOULD implement a limit on retries caused by
"esni_retry_request" or
> servers which do not acknowledge the "encrypted_server_name" extension.

This is an error-correcting mechanism to avoid deployment risks. If your
TLS deployment is so out of sync with itself that:

- It deployed ESNI keys in the DNS that your servers do not understand.
- Even on a retry to presumably the same IP address, you hit a different
server node.
- Your load balancer keeps bouncing between different server nodes
connections right after each other.
- Each of your server nodes believes in a totally disjoint set of ESNI keys.

Then I think giving up and failing the connection is not the end of the
world.

>
> --Roelof
>
>
> ---- On Wed, 13 Feb 2019 17:15:57 -0500 *Christopher Wood
> <[email-masked] <[email-masked]>>* wrote ----
>
> Hi folks,
>
> [1] https://github..com/tlswg/draft-ietf-tls-esni/pull/124
> <https://github.com/tlswg/draft-ietf-tls-esni/pull/124>
>
> [email-masked]
> [email-masked]

---

From: David Benjamin <[email-masked]>
Date: Thu, 14 Feb 2019 13:21:05 -0600

> the

I have been using air quotes for a reason... :-P My personal view on these
things is very far from positive.

The intent was simply to update the existing text talking about this same
scenario ("A more serious problem is MITM proxies [...] The client can
detect this case and disable ESNI while in that network configuration"). In
so far as it made sense for the original document to talk about this, among
the many complex compatibility considerations in ESNI, I think it continues
to makes sense for the PR to do so.

That said, you have a good point about the word "correct". I was using that
just to invert the existing sentence which begins "A non-conformant MITM
proxy [...]", but you are right that the phrasing in the PR has different
implications. I need to go through the comments on GitHub and update the
PR. In doing so, I will also take another stab at wordsmithing this.
Hopefully I can come up with something less objectionable.

> "MUST NOT surface" seems like bad phrasing then.

I'm blanking on better wording. I wanted to keep the wording independent of
whether your TLS stack knows how to open transport connections or not,
which changes things a bunch, which constrained things a bit. Any thoughts?

> what the SHOULD calls for) then it seems better to encourage

When Chrome sends GREASE extensions today, we do it unconditionally on all
ClientHellos.

I think x% doesn't give a great result. Then implementation bugs get
papered over with some probability on retry. The world is full of
transparent retries, so this is a poor enforcement of protocol invariants.
But, in terms of interop, nothing goes wrong if you choose not to send it
sometimes (maybe you're doing a field trial, I dunno). Hence SHOULD, not
MUST.

> maybe

This is precisely why client and server recommendations should align. It
sounds like you believe that the server recommendation of 260 is too much.
I would support a change to that (together with a matching client change).
What do you think it should say instead?

I don't think "pad to a length that matches recent traffic" works well
because that adds a bit of correlation between multiple services. It's a
minor correlation, but such things still aren't great for privacy and
doesn't seem worth adding here. I certainly would not want to implement
such a thing. I'm fine with recommending a fixed value, or picking randomly
within a range. Beyond that, I think the problem should be solved at both
recommendations together.

David

---

From: "Salz, Rich" <[email-masked]>
Date: Thu, 14 Feb 2019 19:26:56 +0000

*   I'm blanking on better wording. I wanted to keep the wording independent of whether your TLS stack knows how to open transport connections or not, which changes things a bunch, which constrained things a bit. Any thoughts?

Represent instead of surface?

---

From: Stephen Farrell <[email-masked]>
Date: Thu, 14 Feb 2019 19:37:31 +0000

Hiya,

> Represent instead of surface?

I'd be fine if the PR wasn't fully wordsmithed, e.g. I've often
written drafts that have text like "[[this needs more right,
"surface" isn't quite right]]" - there will, after all, be a -04
and so on when we can fix that.

Cheers,
S.

---

From: Roelof DuToit <[email-masked]>
Date: Thu, 14 Feb 2019 14:46:21 -0500

---- On Thu, 14 Feb 2019 13:00:16 -0500 David Benjamin <[email-masked]> wrote ----

On Wed, Feb 13, 2019 at 7:37 PM Roelof DuToit <mailto:[email-masked]> wrote:

Questions for PR [1]:

* Regarding this text:

No, exactly the opposite. You use the retry key for just the retry and then forget about it.

I understood that part.   Let my clarify my question with an example:

A1. Client uses DNS-provided keys, and server returns retry keys

A2. Client uses retry keys, and everything works..

A3. Client restarts

A4. Client uses DNS-provided keys, and server returns the same retry keys as in A1

A5. Client violates spec by using those retry keys for a second time?

And what about this example:

B1. Client uses DNS-provided keys, and server returns retry keys

B2. Client uses retry keys, and everything works..

B3. Client uses DNS-provided keys, and server returns retry keys
B4. Client violates spec by using those retry keys for a second time?

You keep retrying. And hen you hit the text which says:

> Clients SHOULD implement a limit on retries caused by "esni_retry_request" or

> servers which do not acknowledge the "encrypted_server_name" extension.

This is an error-correcting mechanism to avoid deployment risks. If your TLS deployment is so out of sync with itself that:

- Even on a retry to presumably the same IP address, you hit a different server node.

- Your load balancer keeps bouncing between different server nodes connections right after each other.

Then I think giving up and failing the connection is not the end of the world.

--Roelof

---- On Wed, 13 Feb 2019 17:15:57 -0500 Christopher Wood <mailto:[email-masked]> wrote ----

Hi folks,

Thanks!

Chris (no hat)

TLS mailing list

mailto:[email-masked]

 TLS mailing list

 mailto:[email-masked]

---

From: Stephen Farrell <[email-masked]>
Date: Thu, 14 Feb 2019 20:08:40 +0000

Hiya,

> things is very far from positive.

That's what I thought. You're right there anyway:-)

> Hopefully I can come up with something less objectionable.

Fair enough.

> sometimes (maybe you're doing a field trial, I dunno). Hence SHOULD, not

Also fair. I guess we can see what's folks do in other cases.

>> it'd be crystal clear which is grease and which not.

As a possible side-note, isn't this greasing a little different
from others - this is also really chaff that functions to discourage
blocking all ESNI (as well as the usual greasing) by causing real
uses of ESNI to "not stand out" as per the section in Christian's
draft. I think that comes into play here.

> sounds like you believe that the server recommendation of 260 is too much.

That, but moreso that I don't think a per-server padding_length is
really a good design choice. If it's there, different services will
choose different values. That means greasers need to pick a value,
and either that forces all services to pick whatever the best
greaser chooses (or real use of ESNI with that service stands out),
or else it forces greasers to use whatever is the most commonly
used padding_length (current whatever CF deploy I guess, which is
260), and that again means the non grease uses out stand out.
Either way we all end up at 260 or risk getting blocked.

> What do you think it should say instead?

Drop paddling_length entirely and replace it with some MUST level
thing that everyone does. E.g. for real uses of ESNI could be
"padding MUST be to a multiple of 64 octets and SHOULD be minimal"
perhaps with "greasers MUST send some percentage <X% padded to 128
or bigger" and then I think only very few would stand out if we get
X even roughly correct (and we could measure to find a good X).

(I think there are other things we can/should be thinking about
from the "don't stand out" POV, but they, and the suggestion above,
probably go beyond this PR. It's just this PR also highlights the
issue.)

> recommendations together.

Fair point. I was trying to suggest something that'd work within
the scope of this PR. Let me try argue for it a little bit more:
If paddling_length remains as-is, then ISTM that a particular
client will recently have been seen emitting mostly grease-padding
lengths, but also a few different lengths as determined by real
services. In order to stop use of those services sticking out, I
think the greaser needs to emit some CHs matching the lengths of
those real services too. So I'd suggest maybe keeping a set of
(padding_length, probability) tuples and randomly picking from
that when greasing, with that table updated based on traffic
seen/sent. Bit complex yes, but I think that's the consequence
of per service padding_length in ESNIKeys. Sound any better?

Cheers,
S.

---

From: David Benjamin <[email-masked]>
Date: Thu, 14 Feb 2019 14:13:11 -0600

On Thu, Feb 14, 2019 at 1:46 PM Roelof DuToit <[email-masked]> wrote:

>
>
>
> ---- On Thu, 14 Feb 2019 13:00:16 -0500 *David Benjamin
> <[email-masked] <[email-masked]>>* wrote ----
>
>> The client MUST NOT use the server-provided retry keys until the
>> handshake completes successfully. On success, it MUST NOT overwrite the
>> DNS-provided keys with the retry keys. It MUST use the retry keys at most
>> once and continue offering DNS-provided keys for subsequent connections.
>> This avoids introducing a tracking vector, should a malicious server
>> present client-specific retry keys.
>>

Oh, I see. Yeah, that's just a mistake in the text. A5 and B4 aren't meant
to be violations, since the client saw the retry keys again. I'll wordsmith
that too in the next iteration.

---

From: Roelof DuToit <[email-masked]>
Date: Thu, 14 Feb 2019 15:25:08 -0500

---- On Thu, 14 Feb 2019 15:13:11 -0500 David Benjamin <[email-masked]> wrote ----

On Thu, Feb 14, 2019 at 1:46 PM Roelof DuToit <mailto:[email-masked]> wrote:

---- On Thu, 14 Feb 2019 13:00:16 -0500 David Benjamin <mailto:[email-masked]> wrote ----

Questions for PR [1]:

* Regarding this text:

A3. Client restarts

Oh, I see. Yeah, that's just a mistake in the text. A5 and B4 aren't meant to be violations, since the client saw the retry keys again. I'll wordsmith that too in the next iteration.

Could a MITM (the kind that can finish the handshake) set esni_retry_request every time it sees an unknown record_digest in the ESNI extension, and essentially use the retry mechanism to subvert the intent of ESNI?

 

--Roelof

Hi folks,

Thanks!

Chris (no hat)

TLS mailing list

mailto:[email-masked]

TLS mailing list

mailto:[email-masked]

---

From: David Benjamin <[email-masked]>
Date: Thu, 14 Feb 2019 14:40:25 -0600

On Thu, Feb 14, 2019 at 2:25 PM Roelof DuToit <[email-masked]> wrote:

> ---- On Thu, 14 Feb 2019 15:13:11 -0500 *David Benjamin
> Could a MITM (the kind that can finish the handshake) set
> esni_retry_request every time it sees an unknown record_digest in the ESNI
> extension, and essentially use the retry mechanism to subvert the intent of
> ESNI?
>

It would need to be able to authenticate as the public name for the client
to pay any attention to this. The public name is the name of the entity
trusted to update the ESNI keys. (Presumably the name of the hosting
provider or so.)

The point is to give a secure retry signal, in hopes of getting both
deployability and security.

David