Subject: [TLS] draft-ietf-tls-esni feedback

From: Rob Sayre <[email-masked]>
Date: Sun, 20 Oct 2019 14:40:40 -0700

Hi,

I was implementing https://tools.ietf.org/html/draft-ietf-tls-esni-02
(since I believe that version is what Firefox and Cloudflare currently
ship), and I had a difficult time parsing this part of the draft:

struct {
  ServerNameList sni;
  opaque zeros[ESNIKeys.padded_length - length(sni)];
} PaddedServerNameList;

struct {
  uint8 nonce[16];
  PaddedServerNameList realSNI;
} ClientESNIInner;

I hadn't seen the fixed-but-variable length construction that the "zeros"
field uses before (although I haven't written much TLS code). It does end
up being easy to implement, because "realSNI" is placed at the end of
ClientESNIInner. However, this detail was not obvious to me until I got
through all of the serialization code I was writing, and it would also seem
to limit the places PaddedServerNameList should appear in TLS structs.

Judging by the mailing list archives, the design of the field is
intentional. It's not clear to me why "zeros" wasn't specified as
variable-length with a prose restriction, though.

This part of the spec is also just generally difficult to follow, in my
opinion. I had no trouble following the ESNIKeys section. Perhaps the
problem is in the interaction of prose order, serialization order, and
procedural code order.

thanks,
Rob

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 21 Oct 2019 06:06:01 -0700

On Sun, Oct 20, 2019 at 2:41 PM Rob Sayre <[email-masked]> wrote:

> field uses before (although I haven't written much TLS code).
>

It is used in other places. See, for instance:
https://tools.ietf.org/rfcmarkup?doc=8446#section-5.2

> variable-length with a prose restriction, though.

Because then you have a spurious length field.

> problem is in the interaction of prose order, serialization order, and

Well, this structure is likely to change a fair bit, so probably not worth
trying to update the text right at this moment.

-Ekr

>
> thanks,
> Rob
> _______________________________________________
> TLS mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/tls
>

---

From: Rob Sayre <[email-masked]>
Date: Mon, 21 Oct 2019 07:32:11 -0700

> https://tools.ietf.org/rfcmarkup?doc=8446#section-5.2

Ah. I have only worked on some handshake messages, and it was new to me. In
the future, I think it might be worth calling out this kind of field as a
distinct type. Maybe "dependent vector"? The TLS 1.3 RFC does say "The size
of the vector may be specified at documentation time or left unspecified
until runtime", but I thought the latter part of that sentence was
referring to variable-length vectors.

> Because then you have a spurious length field.

I don't understand why it would be spurious. In this case, the
deserializing implementation needs to inspect every byte anyway.

> trying to update the text right at this moment.

Fair enough. I would also suggest making sure that this section does not
span a page boundary. That made things worse for me.

thanks,
Rob

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 21 Oct 2019 07:40:58 -0700

> deserializing implementation needs to inspect every byte anyway.

Because if you set padding to be the length of the maximum value, then a
length byte makes every message one longer.

>> Well, this structure is likely to change a fair bit, so probably not
>> worth trying to update the text right at this moment.
>>
>

At this early stage, we usually don't worry over-much about page breaks.

-Ekr

---

From: Rob Sayre <[email-masked]>
Date: Mon, 21 Oct 2019 07:55:49 -0700

> length byte makes every message one longer.

Sorry if I'm being dense here. Couldn't "zeros" have a length? Maybe you
just mean it would be superfluous. That could be true, but it is dependent
on the value of a field in a DNS record. If it had a length, I could have
used existing payload deserialization code.

Having gone through every message in this draft, I don't understand the
rationale behind the following section and the corresponding
PaddedServerNameList:

"
...
CipherSuite cipher_suites<2..2^16-2>;
uint16 padded_length;

...

padded_length : 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."

That's not to say the draft is wrong, but the rationale seems missing. The
rationale may exist in a mailing list message or github issue.

thanks,
Rob

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 21 Oct 2019 09:44:24 -0700

On Mon, Oct 21, 2019 at 7:56 AM Rob Sayre <[email-masked]> wrote:

> just mean it would be superfluous.
>

Yes, that is what I mean.

-Ekr

---

From: Rob Sayre <[email-masked]>
Date: Mon, 21 Oct 2019 10:54:58 -0700

> Yes, that is what I mean.

OK. To be clear, I understand why there is padding in the spec. I don't
understand three aspects:

1) Where did the number 260 come from? It also seems to conflict with the
"multiples of 16" advice in the previous sentence.
2) Why does the server set the padding amount? If clients were allowed to
vary it with different amounts of zeros, wouldn't that be more anonymous?
3) Why is the length of "zeros" implicit rather than explicit? Is it to
save a few bytes, or is there a deeper reason?

None of this stuff signals a flaw in the draft from an interoperability
perspective--I was able to follow it as a non-expert in TLS and get things
working. But I still have questions about why things are specified this way.

thanks,
Rob

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 21 Oct 2019 11:08:53 -0700

> "multiples of 16" advice in the previous sentence.

I believe it was large enough to fit the maximum plausible label size, but
I'd have to go look at the relevant issue.

> vary it with different amounts of zeros, wouldn't that be more anonymous?

No. You want padding to be set to be the longest size that you would send
to any origin in the anonymity group, and the server knows this. Many
client padding strategies leak information over time and it's hard to know
how to construct one that doesn't unless you know the max. For instance,
consider what happens if the anonymity group consists of "a.example" and "
thisisaverylongname.example.com" and the client always pads to the next 16.

> save a few bytes, or is there a deeper reason?

It saves bytes on the wire. It's also the way we've done other zero padding.

> working. But I still have questions about why things are specified this way.

Generally speaking, these issues were aired on the list or in Github
issues, so the best way to answer them is to go look at the history

-Ekr

---

From: Rob Sayre <[email-masked]>
Date: Mon, 21 Oct 2019 11:25:52 -0700

On Mon, Oct 21, 2019 at 11:09 AM Eric Rescorla <[email-masked]> wrote:

>>>> Sorry if I'm being dense here. Couldn't "zeros" have a length? Maybe
>>>> you just mean it would be superfluous.
>>>>
>>>

I have not tested this, but I wondered about IDNA-encoded domain names as I
read. Is their encoded form always under 255? So, it might be
worthwhile for the draft to explain where 260 came from.

> thisisaverylongname.example.com" and the client always pads to the next

I thought the "padded_length" field might be more useful as a minimum. I
agree with you about narrowly-padded messages.

> issues, so the best way to answer them is to go look at the history

I don't agree with this. These questions all concern MUST or SHOULD
requirements in the draft. There should be rationales for the requirements
that aren't obvious. Especially the "SHOULD" ones.

thanks,
Rob

---

From: Stephen Farrell <[email-masked]>
Date: Mon, 21 Oct 2019 19:41:39 +0100

Hiya,

On 21/10/2019 19:08, Eric Rescorla wrote:
> to any origin in the anonymity group, and the server knows this.

In the past, I've argued that this is not necessarily true
and hence the current padding scheme is not a good plan.

Two main reasons:

- a server may not have visibility of all names that can
be in certificate SANs

- even if a server does have such visibility at time t, a
CA re-issuing certs can change the situation during the
lifetime of one ESNIKeys value

I believe it is not unknown for servers to have a DB
of TLS server certs/private keys that is queried based
on the SNI (which could've arrived as ESNI). I don't
know how common that is.

My guess is that all of the above will lead to everyone
always using 260 for this value, making it pointless
and somewhat wasteful.

I would argue for an algorithmic method of padding and
to not require servers to include any value in ESNIKeys at
all. I proposed one such algorithm on the list before.

Cheers,
S.

PS: I think 260 is the right max, didn't look it up just
now but I did some time ago and it seemed correct.

---

From: Christian Huitema <[email-masked]>
Date: Mon, 21 Oct 2019 11:42:56 -0700

On 10/21/2019 11:08 AM, Eric Rescorla wrote:

>
>     3) Why is the length of "zeros" implicit rather than explicit? Is
>     it to save a few bytes, or is there a deeper reason?
>
>

There also off-by-one or off-by-two issues that arise when the natural
length is equal to or very close to the padding target. Suppose that you
need zero padding to achieve the limit. Then if you have to stick in one
byte of length, you go over the limit. You might get around that by
making the padding field optional, but then the syntax would allow to
not have any padding and that opens a can of worms.. Or suppose that you
need exactly one byte of padding, but the length field is two bytes --
you can't just add one byte, you end up always off by one.

-- Christian Huitema

---

From: Rob Sayre <[email-masked]>
Date: Mon, 21 Oct 2019 12:01:13 -0700

> always using 260 for this value, making it pointless

Whether it's wasteful depends on how big typical ClientHello (without early
data) messages are. If they'll easily fit in one packet, 260 doesn't matter.

This seems like something TLS WG should track, tbh.

thanks,
Rob

---

From: Stephen Farrell <[email-masked]>
Date: Mon, 21 Oct 2019 20:10:14 +0100

Hiya,

> data) messages are. If they'll easily fit in one packet, 260 doesn't matter.

I don't think we ought be so confident of that. TLS is
so broadly used that there may be other circumstances
now or in future where this would be a problem that'd
cause ESNI to not be used. It seems prudent to use fewer
bytes when that's possible (so long as we don't expose
the actual SNI length).

Removing the padding_length field also removes a way
in which server configurations can be broken (if some
server admin sets a too-low value), which is also a
more prudent design than we currently have.

S.

---

From: Rob Sayre <[email-masked]>
Date: Mon, 21 Oct 2019 12:14:40 -0700

> bytes when that's possible (so long as we don't expose

I have seen MTUs under 1500 many times, but nothing under 1200. Is there
data on this? (I honestly haven't seen any)

> more prudent design than we currently have.

I think padding_length makes sense as a minimum. As a maximum, it could
actually be an attack as well.

thanks,
Rob

---

From: Stephen Farrell <[email-masked]>
Date: Mon, 21 Oct 2019 20:23:47 +0100

> data on this? (I honestly haven't seen any)

My assumption is that maybe 90% of names are <60 octets.
That means padding_length of 260 is wasting roughly
200 octets, almost all the time (hi there GREASE!).

If that's 20% of what remains available in an MTU then
it's still wasted as it'll no longer be available for
whatever other things people wanna send with or add
to a CH.

Prediction: if we stick with the current design, in
a few years, if ESNI gets widely deployed, we'll have
to revisit that aspect and come up with some more
efficient way to solve the problem, and that'll mean
ignoring the value 260 in then-deployed ESNIKeys;-(

S.

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 21 Oct 2019 12:29:25 -0700

> - a server may not have visibility of all names that can

The question is not the server, but the operator.

> always using 260 for this value, making it pointless

I don't agree that 260 is pointless, though perhaps wasteful.

> all. I proposed one such algorithm on the list before.

Yes, but I do not believe that it obtained the consensus of the WG.
Obviously, if the chairs call consensus on this point, we will change the
draft.

-Ekr

---

From: Stephen Farrell <[email-masked]>
Date: Mon, 21 Oct 2019 20:48:00 +0100

Hiya,

> The question is not the server, but the operator.

Sure, but the point holds though. If ESNIKeys are changed every
N seconds, and any new certificate is loaded during that time,
then the server operator can't tell the lengths that the CAs
might produce in future. So with the current design 260-always is
the only thing a server-operator (or really an ESNIKeys generator
who may be a slightly different entity) can rely on in general.

> Yes, but I do not believe that it obtained the consensus of the WG.

Not yet, that's true. OTOH, the 260 value wasn't decided on
the list either that I recall. However, I'm not objecting to
the current design for process reasons at all, I'm only critical
of it technically:-)

> Obviously, if the chairs call consensus on this point, we will change the

Sure. We'll see where it lands. I remain hopeful a better
design will be the result.

S.

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 21 Oct 2019 13:02:27 -0700

> who may be a slightly different entity) can rely on in general.

I don't believe that this claim is correct in general. Remember that these
records are stored in the DNS under the name that becomes the SNI, so,
absent wildcards, ths eet of names is in fact known, regardless of what
happens to be in the certificate.

> the list either that I recall.

IIRC it was there at the time of adoption.

-Ekr

However, I'm not objecting to

---

From: Rob Sayre <[email-masked]>
Date: Mon, 21 Oct 2019 13:07:18 -0700

On Mon, Oct 21, 2019 at 1:03 PM Eric Rescorla <[email-masked]> wrote:

> On Mon, Oct 21, 2019 at 12:48 PM Stephen Farrell <
> [email-masked]> wrote:
>
>>
>>

Yes, it's there in https://tools.ietf.org/html/draft-rescorla-tls-esni-00.

I think we should do better than "pretty sure it's right", though.

thanks,
Rob

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 21 Oct 2019 13:08:38 -0700

> I think we should do better than "pretty sure it's right", though.

I don't believe that's what I said.

-Ekr

---

From: Rob Sayre <[email-masked]>
Date: Mon, 21 Oct 2019 13:12:55 -0700

> I don't believe that's what I said.

It is not. You said to look up the reasons for the requirements in the
draft in the mailing list archives and GH issues.

Stephen wrote:

"PS: I think 260 is the right max, didn't look it up just
now but I did some time ago and it seemed correct."

thanks,
Rob

---

From: Stephen Farrell <[email-masked]>
Date: Mon, 21 Oct 2019 21:46:10 +0100

Hiya,

> happens to be in the certificate.

Depends which "in general" is more general I guess.

Wildcards do exist in the DNS, though TBH I'm not really
familiar with how they're implemented in authoritatives.

But even ignoring those, deployment models where the
ESNIKeys are generated by the TLS server operator, but
DNS records are published by a different entity (say the
owner of the name or registrar) ought not be precluded
I think. Supporting such a model I think more or less
requires setting padding_length to 260 or else risking
a failure nobody will notice (if browsers fall back to
cleartext SNI) or know how to diagnose if they do.

And even in the case of a monolithic service that does it
all for every name, I think it'd still likely pick 260
in order to avoid having to exercise/write the code to
detect and react to a need to increase the padding_length.
("Holy crap - you mean I need to re-publish everyone's
ESNIKeys just because this bozo has a really long name?
Who made that up?")

I really can't see what'd motivate anyone to publish
ESNIKeys with a padding_length < 260 tbh (well, other
than not having thought it through;-). Anything <260
just seems to be asking for later problems.

S.

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 21 Oct 2019 13:55:40 -0700

> detect and react to a need to increase the padding_length.

Fortunately, we have a number of such operators on this list. Alessandro?
McManus? Nygren, What say you?

-Ekr

---

From: Patrick McManus <[email-masked]>
Date: Mon, 21 Oct 2019 19:58:41 -0400

wildcards are real in both dns and http services.. (also the dns entries
might be invisible to the http provider thanks to cname indirections..
though obviously service names are not.)

---

From: Rob Sayre <[email-masked]>
Date: Mon, 21 Oct 2019 17:09:52 -0700

> though obviously service names are not.)

That all seems right. I was wondering where the 260 number came from.

It seems like relying on fixed numbers has burned in the past. Is 260 one
of those "I was asked to put this in" numbers?

It seems like that's probably not the case here, but I think the rationale
should be written down in the draft.

thanks,
Rob

---

From: Ben Schwartz <[email-masked]>
Date: Mon, 21 Oct 2019 23:27:30 -0400

> 200 octets, almost all the time (hi there GREASE!).

Note that the current text in the editors' draft says that when
applying GREASE, "The padded_length value SHOULD be 260 or a multiple
of 16 less than 260.".  We don't need GREASE to send 260 all the time,
and the draft doesn't recommend it.

Personally, I expect that 260 will be rare for real deployments,
because most systems serve a fixed, known set of domains, and those
that serve a large, dynamic set probably already impose a tighter
length limit.

One intriguing alternative would be to define some ESNI ciphersuites
that encrypt a strong hash of the name.  Then a server with a large
but finite name database can choose one of these ciphersuites,
pre-compute hashes for names when entering them into the DB, and
quickly invert incoming hashes with a DB lookup.  I wouldn't want to
make this the only option because it can't support true wildcard
servers, but I think it would cover most potential users while
limiting the length to 32 octets or similar.

---

From: Stephen Farrell <[email-masked]>
Date: Tue, 22 Oct 2019 09:21:08 +0100

Hiya,

> and the draft doesn't recommend it.

ISTM that GREASE needs to follow the kinds of lengths
used in practice to be most useful, so if 260 does get
widely used, then I guess that's what'd be most useful
to GREASE.

> that serve a large, dynamic set probably already impose a tighter

I don't know of any hoster or service with such a name
length limit. Do you have any example where a DNS name
that can be published and used as a TLS SNI would be
declined by a service provider?

> limiting the length to 32 octets or similar.

Yeah, that'd be nice but as you say doesn't work well
for wildcard certs, which I think is a showstopper. I
do think there are other algorithmic options we could
go with though, that would work.

Cheers,
S.

---

From: Ben Schwartz <[email-masked]>
Date: Tue, 22 Oct 2019 10:56:05 -0400

> widely used, then I guess that's what'd be most useful

Agreed.  (Although the details of this are potentially tricky, like
whether the random length can be sticky without accidentally labeling
the user.)

> declined by a service provider?

Sure.  For example, tumblr limits usernames to 32 characters:
https://unwrapping.tumblr.com/post/58535402323/tips-tumblr-username

These usernames also form the subdomain part of the *.tumblr.com
wildcard, so the longest allowed name is [32 chars].tumblr.com.

I expect that most wildcard TLS hosts impose similar limits.

> for wildcard certs, which I think is a showstopper.

I don't think it's quite that bad.  For example, this approach would
work fine for tumblr in principle.  Any hash corresponding to a name
that exists can be inverted from their database.  Any hash
corresponding to a name that doesn't exist will return the default
cert, which still covers *.tumblr.com.

The case where this doesn't work is when multiple wildcard domains
share an IP but not a certificate.  That seems most likely in a CDN
context, where multiple wildcard customers could be sharing an IP and
providing their own certificates.  If the CDN's operational
architecture allows pushing all wildcard customers into a single
certificate, the limiting factor becomes the number of names allowed
in one certificate.

> I

I suppose a server could indicate that the first N labels be included
verbatim, and the remainder should be hashed.  Or maybe it should only
be hashed if it's longer than the hash size ... there are all sorts of
options here.

---

From: Stephen Farrell <[email-masked]>
Date: Tue, 22 Oct 2019 16:06:39 +0100

> I expect that most wildcard TLS hosts impose similar limits.

Fair enough. Sub-domains (or whatever may be the right
term) can have such limits. However, IIUC most services
ilke hosters or CDNs will just allow anything that's a
valid DNS name so I argue that our design target ought
be to handle that well. (The current spec does handle
it, but not, IMO, well;-)

Cheers,
S.

---

From: Rob Sayre <[email-masked]>
Date: Tue, 22 Oct 2019 09:21:51 -0700

> it, but not, IMO, well;-)

On reflection, I’m not really comfortable with the code I’ve written on the
client side. It does work, but I don’t think the DNS record should dictate
the padding so precisely. I’d like my client to send 260 (or whatever the
right number is) whenever possible. As specified, short TTLs and varying
padding could be a problem.

thanks,
Rob

---

From: "Salz, Rich" <[email-masked]>
Date: Tue, 22 Oct 2019 16:44:34 +0000

>I don’t think the DNS record should dictate the padding so precisely. I’d like my client to send 260 (or whatever the right number is) whenever possible. As specified, short TTLs and varying padding could be a problem.

I think varying padding to some fixed multiple is a good trade-off.  Apparently the next published draft will say that.

---

From: Stephen Farrell <[email-masked]>
Date: Tue, 22 Oct 2019 18:49:23 +0100

On 22/10/2019 17:44, Salz, Rich wrote:
> I think varying padding to some fixed multiple is a good trade-off.

Me too. I'd go for multiples of 32 octets, with a SHOULD
to add an extra block or two randomly, but anything of
that kind should work.

> Apparently the next published draft will say that.
Hmm.

That *really* ought be communicated to the list by the draft
authors, and before -05 is submitted.

Cheers,
S.

---

From: Eric Rescorla <[email-masked]>
Date: Tue, 22 Oct 2019 11:10:28 -0700

> authors, and before -05 is submitted.

Uh,why? Authors generally have a fair amount of latitude at this stage of
the process, with the understanding that the draft can be reverted.

And I say that as someone who isn't quite sure what the draft in Github
currently says :)

-Ekr

---

From: Stephen Farrell <[email-masked]>
Date: Tue, 22 Oct 2019 19:15:17 +0100

On 22/10/2019 19:10, Eric Rescorla wrote:
> Uh,why? 

Openness, transparency, enabling the WG to make decisions on
the list. I'd have thought all that was pretty obvious TBH.

It also seems a minimal level of politeness given there's an
active discussion on the list.

S.

---

From: Stephen Farrell <[email-masked]>
Date: Tue, 22 Oct 2019 19:15:17 +0100

S.

---

From: Eric Rescorla <[email-masked]>
Date: Tue, 22 Oct 2019 11:24:14 -0700

On Tue, Oct 22, 2019 at 11:15 AM Stephen Farrell <[email-masked]>
wrote:

> the list.

The WG has the chance to make decisions on the list *in response to*
proposals in the draft. At this stage of the draft development, I don't
think it's problematic for authors to put proposals in a draft with the
understanding that they are proposals. Eventually, we'll need to enter a
"no changes without consensus" phase, but I don't think it's at all obvious
that that's true yet.

-Ekr

---

From: "Salz, Rich" <[email-masked]>
Date: Tue, 22 Oct 2019 18:26:49 +0000

Sure, it’s allowed to work this way.

Not sure, since there is very active discussion going on in the WG email right now, that it is the best way.

Not everything is always done the best way.  But maybe we can all try harder?

                /r$

---

From: Rob Sayre <[email-masked]>
Date: Tue, 22 Oct 2019 11:28:55 -0700

On Tue, Oct 22, 2019 at 11:24 AM Eric Rescorla <[email-masked]> wrote:

>
>
> On Tue, Oct 22, 2019 at 11:15 AM Stephen Farrell <
> understanding that they are proposals. Eventually...
>

This seems fine to me, fwiw. It was a little weird to hear about the
decision in this way, but that kind of thing is always happening behind the
scenes. :)

It seems to me that the client is in the best position to set the padding,
so I’m not sure why there is anything in the DNS record.

thanks,
Rob

---

From: Eric Rescorla <[email-masked]>
Date: Tue, 22 Oct 2019 11:41:29 -0700

> Not everything is always done the best way.  But maybe we can all try

Well, I don't think it *is* being done quite that way. The last commit to
the draft was August 9, so I would expect the author team to take the
discussion here into account.

-Ekr

---

From: Ben Schwartz <[email-masked]>
Date: Tue, 22 Oct 2019 14:44:50 -0400

On Tue, Oct 22, 2019 at 2:29 PM Rob Sayre <[email-masked]> wrote:
>> On Tue, Oct 22, 2019 at 11:15 AM Stephen Farrell <[email-masked]> wrote:
>>>
>>>
>>>
>> The WG has the chance to make decisions on the list *in response to* proposals in the draft. At this stage of the draft development, I don't think it's problematic for authors to put proposals in a draft with the understanding that they are proposals.. Eventually...
>
>
> This seems fine to me, fwiw. It was a little weird to hear about the decision in this way, but that kind of thing is always happening behind the scenes. :)
>
> It seems to me that the client is in the best position to set the padding, so I’m not sure why there is anything in the DNS record.

Strongly disagree.  If one IP address hosts two domains, short.example
and longlonglonglonglonglonglonglong.example, a client of
short.example has no SNI privacy unless they pad up to the length of
the longer name.  The client can't know to do this unless the DNS
record says so.

---

From: Rob Sayre <[email-masked]>
Date: Tue, 22 Oct 2019 11:52:53 -0700

On Tue, Oct 22, 2019 at 11:45 AM Ben Schwartz <[email-masked]> wrote:

> understanding that they are proposals.. Eventually...
> >
> >
> > It seems to me that the client is in the best position to set the
> padding, so I’m not sure why there is anything in the DNS record.
>

Well, I am not sure we are disagreeing so strongly. I want to pad
everything up to 260 since the ClientHello will still fit in one packet. I
think it would be ok to send a minimum length in the DNS record.

thanks,
Rob

---

From: Christian Huitema <[email-masked]>
Date: Tue, 22 Oct 2019 11:55:02 -0700

> to add an extra block or two randomly, but anything of

Stephen, do you have some statistical analysis to back your "should
work" assertion?

I say that because DKG performed that analysis for the padding of DNS
messages
(https://dns.cmrg.net/ndss2017-dprive-empirical-DNS-traffic-size.pdf).
The results were non trivial. In particular, the analysis showed that
random padding was not a good way to achieve privacy. If there is only
little randomness, the attacker that observes multiple transactions
transactions can see through the randomness. If there is a lot of
randomness, then the padding policy causes a lot of overhead, which made
that policy less efficient than padding to fixed size blocks. That study
was the basis for the recommended encrypted DNS padding strategy in RFC
8467. 

I do not claim that statistics on the DNS directly inform ESNI padding
strategies, but I would say that in the absence of better analysis we
should heed DKG's recommendations for now -- and the recommendation of
padding to 260 does that. I would of course be happy to change my
opinion once we have an ESNI specific study.

-- Christian Huitema

---

From: Stephen Farrell <[email-masked]>
Date: Tue, 22 Oct 2019 20:02:01 +0100

Hiya,

On 22/10/2019 19:55, Christian Huitema wrote:
>  In particular, the analysis showed that
> random padding was not a good way to achieve privacy. 

Sure. But I'm not suggesting the kind of random padding
that was under discussion then.

My suggestion was to pad to a multiple of 32 octets and
with a random addition of 0,1,2... or more 32 octet blocks
of zeros. Yes, some work would be needed to pick the right
block size (32 might be a little small maybe) and to pick
a (non-uniform) distribution from which to randomly select
how many additional blocks to send.

But like I said, I'm sure there're lots of different
algorithms that could work for this, and whichever we
picked would need some checking vs. reality of course.

Cheers,
S.

---

From: Rob Sayre <[email-masked]>
Date: Tue, 22 Oct 2019 14:00:08 -0700

I thought this discussion was important enough to surface with a new topic.

I can see why the server might need to set a minimum in the DNS record, but
I find it likely irrelevant, since I intend to effectively max out the
padding allowed within a packet.

thanks,
Rob

---

From: Stephen Farrell <[email-masked]>
Date: Wed, 23 Oct 2019 02:30:05 +0100

Unstylishly quoting myself...

> to add an extra block or two randomly, but anything of

Stylishly however, it seems I'm in the happy position to
also admit I was wrong there (thanks to Christian Huitema
for spelling this out to me offlist).

In most cases, when using ESNI, DNS queries will need to
be made for the A/AAAA and ESNIKeys (or HTTPSSSSSSSSSVC:-)
and hopefully those DNS queries will also be padded.

RFC8467 [1] defines a bunch of ways of doing that, and has
one recommended way.

While it is likely too early to say that the recommendation
in RFC8467 is really a best practice, I think it is the
case that padding of the DNS query and of the SNI within
the ESNI extension to the CH ought be "commensurate" in
the sense that observing both ought not provide more
information to someone who only observes one of those.

So, at minimum, that'd mean s/32/128/ in my quoted text
above, and likely more. (Plus, of course, doing the kind
of due-diligence that lead to [1].)

Bottom line is that I think I'd modify my starting out
position for what to suggest for draft-05 to be to copy
(and modify as needed) what's recommended in [1] for
padding the query.

Cheers,
S.

[1] https://tools.ietf.org/html/rfc8467

---

From: Rob Sayre <[email-masked]>
Date: Tue, 22 Oct 2019 19:05:55 -0700

> of due-diligence that lead to [1].)

Or, maybe, start at 256. :)

Low numbers might encounter all sorts of well-known cryptographic problems,
and varying the padding of the domain name with any granularity would tend
to narrow the search space for an attacker.

I'm not an expert in these matters, though.

thanks,
Rob

---

From: "Salz, Rich" <[email-masked]>
Date: Wed, 23 Oct 2019 02:29:14 +0000

*   Low numbers might encounter all sorts of well-known cryptographic problems, and varying the padding of the domain name with any granularity would tend to narrow the search space for an attacker.

What well-known cryptographic problems?  Varying the padding can also *add* security because foo.secret.example.com could show up with two different sizes.

---

From: Rob Sayre <[email-masked]>
Date: Tue, 22 Oct 2019 19:54:25 -0700

On Tue, Oct 22, 2019 at 7:29 PM Salz, Rich <[email-masked]> wrote:

>
>
>    - Low numbers might encounter all sorts of well-known cryptographic
>    problems, and varying the padding of the domain name with any granularity
>    would tend to narrow the search space for an attacker.
>
>
>
> What well-known cryptographic problems?  Varying the padding can also *
> *add** security because foo.secret.example.com could show up with two
> different sizes.
>

Hi Rich,

To be clear, I am in favor of varying padding. I want the "zeros" field to
have a prefix and I want my client to do whatever it wants with that
buffer, within the boundaries of an unsigned 16 bit integer.

I was concerned about a couple of different issues. The first is that the
search space for the plain text is actually quite restricted. For example, "
foo.example.com" might only vary by three characters vs other "example.com"
domains. So, 16-character padding boundaries might be an issue.

The other is that I worried that an attacker could use brute force to
replicate traffic, and thus determine what was requested. I couldn't come
up with a way to do this easily, but I did worry that a small search space
in the SNI text would make it easier.

And, as I wrote, I am not an expert in these matters. From what I do know,
I think padding the buffer to the maximum likely size seems like a good
idea.

thanks,
Rob

---

From: Watson Ladd <[email-masked]>
Date: Tue, 22 Oct 2019 22:39:24 -0700

On Tue, Oct 22, 2019 at 7:54 PM Rob Sayre <[email-masked]> wrote:
>> Low numbers might encounter all sorts of well-known cryptographic problems, and varying the padding of the domain name with any granularity would tend to narrow the search space for an attacker.
>>
>>
>>
> To be clear, I am in favor of varying padding. I want the "zeros" field to have a prefix and I want my client to do whatever it wants with that buffer, within the boundaries of an unsigned 16 bit integer.
>
> I was concerned about a couple of different issues. The first is that the search space for the plain text is actually quite restricted. For example, "foo.example.com" might only vary by three characters vs other "example.com" domains. So, 16-character padding boundaries might be an issue.
>
> The other is that I worried that an attacker could use brute force to replicate traffic, and thus determine what was requested. I couldn't come up with a way to do this easily, but I did worry that a small search space in the SNI text would make it easier.
>
> And, as I wrote, I am not an expert in these matters. From what I do know, I think padding the buffer to the maximum likely size seems like a good idea.

Padding to the max every time leaks no information. It also doesn't
have some of the operational issues. There are possible setups on
Cloudflare where Cloudflare will not know what domains are being
proxied ahead of time (wildcard DNS+wildcard cert,
https://support.cloudflare.com/hc/en-us/articles/360017421192-Cloudflare-DNS-FAQ#CloudflareDNSFAQ-DoesCloudflaresupportwildcardDNSentries
available to enterprise customer)

What's not clear is what the other proposals leak. Some of them like
randomized padding end up leaking much more the might be expected.

At the same time Client Hello sizes aren't constrained to be tiny, but
the next problem of 1280 bytes is not that far off either. So we
should be judicious in spending those bytes.

--
"Man is born free, but everywhere he is in chains".
--Rousseau.

---

From: Bill Frantz <[email-masked]>
Date: Wed, 23 Oct 2019 10:34:57 -0400

A perhaps radical suggestion:

Make the server name field fixed length e.g. 256 bytes. Longer 
server names are not supported and clients MUST NOT send them. 
(Both client and server can't use them because they won't fit in 
the fixed length field.)

Putting a limitation like this one into a protocol certainly can 
create problems, but we can look to the file system name 
situation for some insight. In the dark ages, file names were 
limited to a small number of characters -- 4, 5, or 6. I 
remember when the file system I used increased the limit to 8 
characters, seeming like infinity for a few days. Finally some 
file systems raised the limit to 256 characters and I stopped 
hearing complaints that the length limit was a problem.

With the suggestion, DNS lookups are padded to allow all 255 
byte names to be represented in what is, in effect, a fixed 
length lookup string.

Now people with more information about the problem can describe 
the problems this suggestion would cause.

Cheers - Bill

-----------------------------------------------------------------------
Bill Frantz        | gets() remains as a monument | Periwinkle
(408)356-8506      | to C's continuing support of | 16345 
Englewood Ave
www.pwpconsult.com | buffer overruns.             | Los Gatos, 
CA 95032

---

From: Watson Ladd <[email-masked]>
Date: Wed, 23 Oct 2019 07:52:33 -0700

> (Both client and server can't use them because they won't fit in

The limit of server name in DNS is 260 bytes, so that limit already
exists. No reason to shorten it elsewhere!
-- 
"Man is born free, but everywhere he is in chains".
--Rousseau.

---

From: Ilari Liusvaara <[email-masked]>
Date: Wed, 23 Oct 2019 18:40:59 +0300

> exists. No reason to shorten it elsewhere!

Got a reference for the 260 byte limit?

According to RFC 1035, the maximum DNS hostname length is 253 bytes:

"To simplify implementations, the total length of a domain name (i.e.,
label octets and label length octets) is restricted to 255 octets or
less."

This is for wire-form encoding, which has 2 bytes of overhead (initial
and terminal lengths), so maximum 253 bytes for the hostname.

However RFC2181 says:

"A full domain name is limited to 255 octets (including the separators).
The zero length full name is defined as representing the root of the DNS
tree, and is typically written and displayed as '.'."

Which could be interpretted as that the final length is not part of the
255 byte limit, and thus DNS name being maximum of 256 octets,
corresponding to maximum hostname length of 254 bytes. However, dig
utility refuses to send such queries (can send 253 bytes just fine), so
I presume that the 255 octet limit is intended to include the terminal
length -> maximum hostname length is 253 octets.

I can not find any justification for higher limit from any RFC updating
1035 or 2181. And I would expect any such limit to have been
significantly above 253 bytes.

-Ilari

---

From: Ben Schwartz <[email-masked]>
Date: Wed, 23 Oct 2019 12:13:39 -0400

On the topic of radical suggestions, here's another one:
https://github.com/tlswg/draft-ietf-tls-esni/pull/186

In brief, this replaces the variable-length name with a fixed-length
hash, plus some accommodations to allow *.example.com,
*.*.example.com, etc.

My hope is that this design would work in the architecture described
by Watson, while saving ~220 bytes in each ClientHello.

One interesting feature of this design is that it doesn't require each
wildcard domain to publish any unique DNS record.  Instead, all
third-level wildcard customers can share a configuration, all
fourth-level wildcard customers can share a configuration, etc.  This
distinction is not visible in the TLS handshake, so the anonymity set
is not reduced.

---

From: Ilari Liusvaara <[email-masked]>
Date: Wed, 23 Oct 2019 20:11:13 +0300

> distinction is not visible in the TLS handshake, so the anonymity set

AFAIK, PKIX in practice only allows single full-label wildcard in
terminal position (the only place * can appear is as first character,
followed by label separator).

And the scheme in #186 does not seem to distinguish between
"example.org" (the base name) and "*.example.org" (a wildcard).
There also seems to be issue that seemingly nothing constrains the case
of hashed encoding. And you do not want to deal with arbitrary casings,
as the number of those quickly blows up.

Perhaps a simpler way would be to have a flag that causes the first
label to be overwritten with '*'. That would be set on nodes covered
by a wildcard certificate. Alphabet would be hashed lowercased. Then
the server could just hash every lowercased name from every known
certificate and use the hashes as lookup table keys without worrying
about encoding. And in the structure, the label_limit, num_labels and
length field for name_digest seem to be superfluous.

This would give that the encrypted_sni is 64 octets with AES-128 or
Chacha20, and 80 octets with AES-256.

On optimizing stuff, the length fields for record_digest and
encrypted_sni in client structure are also superfluous, because the
length of record_digest is impiled by suite (and unknown suites are
unprocessable anyway) and encrypted_sni runs to end of explicit-length
record. The length of key share probably can not be removed, as some
algorithms may have variable-length ciphertexts.

Using the above figures, this would mean that the part after the
share would be 96 octets for AES-128 and Chacha20 and 128 octets for
AES-256.

-Ilari

---

From: Ilari Liusvaara <[email-masked]>
Date: Wed, 23 Oct 2019 20:37:24 +0300

> should be judicious in spending those bytes.

I do not think 1280 bytes is a big issue.

- If using QUIC, one expects fragmentation above 1200 bytes. I am not
  sure if fragmentation is presently allowed, but I am sure it is not
  pleasant to implement in robust way.
- For classical TLS over TCP, in practice one can push something like
  1400 octets or so in a single packet over virtually all paths.
- Present handshake sizes are AFAIK bit north of 256 bytes (still
  mostly padded to 512 to avoid old TLS server bugs). So sticking even
  350 bytes (256 for name plus 80 bytes crypto overhead plus few odd
  other bytes) extra would not blow any soft limits.
- With post-quantum, you are going to bust single packet limits no
  matter what, since:
  - SIKE is slow, so server operators probably prefer lattices as
    those are like two orders of magnitude faster than SIKE (or SIDH).
  - Lattices are roughly 800 bytes at minimum at reasonable security
    levels.
  - You are going to need two keys, because all the post-quantum
    ways of sharing one key are both even slower and more exciting
    (not in a good way) than anything in NISTPQC.

-Ilari

---

From: Ben Schwartz <[email-masked]>
Date: Wed, 23 Oct 2019 16:52:57 -0400

> "example.org" (the base name) and "*.example.org" (a wildcard).

It does, with num_labels in the ClientESNIInner.

> by a wildcard certificate.

This is a reasonable simplification.  It would also work nicely
without the hashing, for servers that only have reasonably-sized names
but can't make promises about wildcards.  However, it does still
suffer from the configuration brittleness described by David Benjamin
in #186.

> Alphabet would be hashed lowercased. Then

---

From: Rob Sayre <[email-masked]>
Date: Wed, 23 Oct 2019 14:10:23 -0700

> significantly above 253 bytes.

I found the rationale here:

https://github.com/tlswg/draft-ietf-tls-esni/pull/54

I think this explanation should be in the draft, too.

thanks,
Rob

---

From: Stephen Farrell <[email-masked]>
Date: Wed, 23 Oct 2019 22:12:17 +0100

> https://github.com/tlswg/draft-ietf-tls-esni/pull/186

How about a variant like this (which is maybe close to your
most recent email, not quite sure):

Names < N octets: pad those to N.

Names >= N octets: hash those and pad to N.

With N ~=64 I think that'd be ok, assuming we do some checking
that N covers a sufficient percentage of names in real use.

I think the WG could easily make the case that if some web
site really does need/want to hide in the crowd, they just
better not try do that with a gigantic DNS name.

Cheers,
S.

---

From: "Christopher Wood" <[email-masked]>
Date: Wed, 23 Oct 2019 14:45:52 -0700

> that N covers a sufficient percentage of names in real use.

For this and other proposals, it seems there's different assumptions being made. I'd prefer to not make any change absent further analysis with clear guidance pointing towards a safe policy. Absent that, the safest approach (260B) seems prudent.

> better not try do that with a gigantic DNS name.

Why would such a site use ESNI at all?

Best,
Chris

---

From: Stephen Farrell <[email-masked]>
Date: Wed, 23 Oct 2019 22:57:37 +0100

Hiya,

On 23/10/2019 22:45, Christopher Wood wrote:
>> How about a variant like this (which is maybe close to your most
>> recent email, not quite sure):
>> 
>> With N ~=64 I think that'd be ok, assuming we do some checking that
>> N covers a sufficient percentage of names in real use.
> 
> For this and other proposals, it seems there's different assumptions
> being made. I'd prefer to not make any change absent further analysis
> with clear guidance pointing towards a safe policy. Absent that, the
> safest approach (260B) seems prudent.

Fixed at 260 octets is better that what we have and safest, yes.
I think we could do better though, but agree that proposals for
that need analysis.

>> I think the WG could easily make the case that if some web site
>> really does need/want to hide in the crowd, they just better not
>> try do that with a gigantic DNS name.
> 

My hope is browsers and sites might all just use ESNI eventually.
But I think we are ok to consider that over-sized names may face
some implementation obstacles. I suspect, but don't know, that
hash based approaches are liable to break server-internal APIs
in various ways. But that might be ok, if the numbers are small
enough.

Cheers,
S.

PS: Despite raising the above variant, I still think "behave
the same as DNS query padding as far as possible" is still the
right approach to try next. Given DNS query padding works, that
is I think, as safe as a fixed use of 260 octets.

> 
> Best, Chris
> 
> _______________________________________________ TLS mailing list 
> [email-masked] https://www.ietf.org/mailman/listinfo/tls
>

---

From: Ilari Liusvaara <[email-masked]>
Date: Fri, 25 Oct 2019 18:54:06 +0300

> suffer from the configuration brittleness described by David Benjamin

I think all mechanisms that transmit only a single hash need to know
if some node is covered by exact name or a wildcard.

And wildcard expansion is at worst 63 bytes, due to DNS limitations,
so transmitting full first label and 32 octet hash of rest would take
96 octets (if one can assume host character set, that could be fit into
80 octets with some encoding).

Then if one had two hashes, one could fit those to 64 bytes (or 48 if
one truncated the hashes to 192 bits, as scope of uniqueness is just a
single server). This would not depend on knowing if node is wildcard or
not.

-Ilari