Question:
FYI, this PR now moves out of the ClientHello back into (now called ). This avoids confusing questions about how to demultiplex profiles that use different modes.
LGTM.
This would allow recipients to detect the end of a handshake message from the CTLSPlaintext header alone, allowing the recipient to reconstruct the entire handshake message before parsing it. Currently, a streaming parser is required in order to detect the end. Suggested implementation: Senders set contenttype = ctlshandshake_end for a message’s final fragment.
I can see why you want that, but it's not generally a TLS property, and I'm reluctant to change things.
AFAIK, TLS does not require a streaming ClientHello parser. The recipient can read (uint24) and then buffer the remainder before parsing. cTLS, as currently specified, does not have . This means that the recipient has to cross all the way down into the extension parsing code before it finds out that the ClientHello is still incomplete. Given the complex template-driven handshake parsing code, I think making a streaming parser required is ill-advised. Given the desire for compactness, I think a flag of some kind on the final handshake message record seems like a reasonable solution, replacing the uint24 length. It would also simplify Pseudorandom cTLS. However, if that's not appealing, you could simply reintroduce .
NAME proposed a solution on slide 5 : I'm fine with that, so long as it doesn't end up requiring recipients to do something heroic to reconstruct the ClientHello. Thus, "framing = none" should imply that messages cannot be fragmented at all (max size limited to 2^14-1). I'm not sure I see the utility of the explicit distinction between "length" and "full". Surely "length" is not usable with DTLS due to reordering, and "full" is redundant in TLS/TCP. Perhaps we only need a single bit to enable/disable framing, and length-vs-full can be implicit from the transport.
I could live with this. Objections?
Solved by
The current text doesn’t mention this, although it seems relatively clear how it’s expected to work (using the DTLS Handshake struct).

value to distinguish cTLS plaintext records from encrypted records, TLS/DTLS records, and other protocols using the same 5-tuple. <ins> The "profile_id" field MUST identify the profile that is in use.  A zero-length ID corresponds to the cTLS default protocol.  The server's reply does not include the "profile_id", because the server must be using the same profile indicated by the client. </ins> Encrypted records use DTLS 1.3 RFC9147 record framing, comprising a configuration octet followed by optional connection ID, sequence number, and length fields.  The encryption process and additional


Question:
FYI, this PR now moves out of the ClientHello back into (now called ). This avoids confusing questions about how to demultiplex profiles that use different modes.
LGTM.
This would allow recipients to detect the end of a handshake message from the CTLSPlaintext header alone, allowing the recipient to reconstruct the entire handshake message before parsing it. Currently, a streaming parser is required in order to detect the end. Suggested implementation: Senders set contenttype = ctlshandshake_end for a message’s final fragment.
I can see why you want that, but it's not generally a TLS property, and I'm reluctant to change things.
AFAIK, TLS does not require a streaming ClientHello parser. The recipient can read (uint24) and then buffer the remainder before parsing. cTLS, as currently specified, does not have . This means that the recipient has to cross all the way down into the extension parsing code before it finds out that the ClientHello is still incomplete. Given the complex template-driven handshake parsing code, I think making a streaming parser required is ill-advised. Given the desire for compactness, I think a flag of some kind on the final handshake message record seems like a reasonable solution, replacing the uint24 length. It would also simplify Pseudorandom cTLS. However, if that's not appealing, you could simply reintroduce .
NAME proposed a solution on slide 5 : I'm fine with that, so long as it doesn't end up requiring recipients to do something heroic to reconstruct the ClientHello. Thus, "framing = none" should imply that messages cannot be fragmented at all (max size limited to 2^14-1). I'm not sure I see the utility of the explicit distinction between "length" and "full". Surely "length" is not usable with DTLS due to reordering, and "full" is redundant in TLS/TCP. Perhaps we only need a single bit to enable/disable framing, and length-vs-full can be implicit from the transport.
I could live with this. Objections?
Solved by
The current text doesn’t mention this, although it seems relatively clear how it’s expected to work (using the DTLS Handshake struct).

2.3. <del> The cTLS handshake framing is same as the TLS 1.3 handshake framing, except for two changes: The length field is omitted. The HelloRetryRequest message is a true handshake message instead of a specialization of ServerHello. </del> <ins> When "template.handshakeFraming" is not "true", cTLS uses a custom handshake framing that saves space by relying on the record layer for message lengths.  (This saves 3 bytes per message compared to TLS, or 9 bytes compared to DTLS.)  This compact framing is defined by the "CTLSHandshake" and "CTLSDatagramHandshake" structs. Any handshake type registered in the IANA TLS HandshakeType Registry can be conveyed in a "CTLS[Datagram]Handshake", but not all messages are actually allowed on a given connection.  This definition shows the messages types supported in "CTLSHandshake" as of TLS 1.3 and DTLS 1.3, but any future message types are also permitted. Each "CTLSHandshake" or "CTLSDatagramHandshake" MUST be conveyed as a single "CTLSClientPlaintext.fragment", "CTLSServerPlaintext.fragment", or "CTLSCiphertext.encrypted_record", and is therefore limited to a maximum length of "2^16-1" or less. When operating over UDP, large "CTLSDatagramHandshake" messages will also require the use of IP fragmentation, which is sometimes undesirable.  Operators can avoid these concerns by setting "template.handshakeFraming = true". </ins> 3. <del> In general, we retain the basic structure of each individual TLS handshake message.  However, the following handshake messages have been modified for space reduction and cleaned up to remove pre-TLS 1.3 baggage. </del> <ins> In general, we retain the basic structure of each individual TLS or DTLS handshake message.  However, the following handshake messages have been modified for space reduction and cleaned up to remove pre- TLS 1.3 baggage. </ins> 3.1. The cTLS ClientHello is defined as follows. <del> The "profile_id" field MUST identify the profile that is in use.  A zero-length ID corresponds to the cTLS default protocol. </del> 3.2. We redefine ServerHello in the following way. 3.3. <del> The HelloRetryRequest has the following format. </del> <ins> In cTLS, the HelloRetryRequest message is a true handshake message instead of a specialization of ServerHello.  The HelloRetryRequest has the following format. </ins> The HelloRetryRequest is the same as the ServerHello above but without the unnecessary sentinel Random value.


Question:
FYI, this PR now moves out of the ClientHello back into (now called ). This avoids confusing questions about how to demultiplex profiles that use different modes.
LGTM.
This would allow recipients to detect the end of a handshake message from the CTLSPlaintext header alone, allowing the recipient to reconstruct the entire handshake message before parsing it. Currently, a streaming parser is required in order to detect the end. Suggested implementation: Senders set contenttype = ctlshandshake_end for a message’s final fragment.
I can see why you want that, but it's not generally a TLS property, and I'm reluctant to change things.
AFAIK, TLS does not require a streaming ClientHello parser. The recipient can read (uint24) and then buffer the remainder before parsing. cTLS, as currently specified, does not have . This means that the recipient has to cross all the way down into the extension parsing code before it finds out that the ClientHello is still incomplete. Given the complex template-driven handshake parsing code, I think making a streaming parser required is ill-advised. Given the desire for compactness, I think a flag of some kind on the final handshake message record seems like a reasonable solution, replacing the uint24 length. It would also simplify Pseudorandom cTLS. However, if that's not appealing, you could simply reintroduce .
NAME proposed a solution on slide 5 : I'm fine with that, so long as it doesn't end up requiring recipients to do something heroic to reconstruct the ClientHello. Thus, "framing = none" should imply that messages cannot be fragmented at all (max size limited to 2^14-1). I'm not sure I see the utility of the explicit distinction between "length" and "full". Surely "length" is not usable with DTLS due to reordering, and "full" is redundant in TLS/TCP. Perhaps we only need a single bit to enable/disable framing, and length-vs-full can be implicit from the transport.
I could live with this. Objections?
Solved by
The current text doesn’t mention this, although it seems relatively clear how it’s expected to work (using the DTLS Handshake struct).

6.3. <ins> This document requests that IANA change the name of entry 6 in the TLS HandshakeType Registry from "hello_retry_request_RESERVED" to "hello_retry_request", and set its Reference field to this document. 6.4. </ins> This document requests that IANA open a new registry entitled "Well- known cTLS Profile IDs", on the Transport Layer Security (TLS) Parameters page, with the following columns:


Question:
We have decided to moved the compressed elliptic curve representations to an external draft since the issue is equally applicable to regular TLS/DTLS and does not need to be cTLS specific.
NAME It looks like you need to run .
It seems that we have consensus to move compressed representations into new IANA codepoints, rather than try to reuse the existing codepoints with a template-driven encoding. That would make the question of compressed representations orthogonal to cTLS, so this topic can be removed from the draft.
Fixed by

Omitting the fields and handshake messages required for preserving backwards-compatibility with earlier TLS versions. <del> More compact encodings, for example point compression. </del> <ins> More compact encodings. </ins> A template-based specialization mechanism that allows pre- populating information at both endpoints without the need for negotiation. <del> Alternative cryptographic techniques, such as semi-static Diffie- Hellman. OPEN ISSUE: Semi-static and point compression are never mentioned again. </del> <ins> Alternative cryptographic techniques, such as nonce truncation. </ins> For the common (EC)DHE handshake with pre-established certificates, Stream cTLS achieves an overhead of 53 bytes over the minimum


Question:
NAME NAME please have a look.
We also need to specify server-side HRR behavior, right? Specifically, the server MUST recheck the second ClientHello's ESNI extension before sending the server certificate, otherwise putting the key share into the AD field doesn't really mean anything. The attacker would be able to do a cut-and-paste thing. (We could also incorporate the nonce into key schedule, but that upsets the document's split mode use case.)
Yep! Thanks for bringing that up. I'll prepare text.
Thank you for the text. LGTM.

"encrypted_server_name" extension.  If the client does not retry in either scenario, it MUST report an error to the calling application. <ins> If the server sends a HelloRetryRequest in response to the ClientHello and the client can send a second updated ClientHello per the rules in RFC8446, the "encrypted_server_name" extension values which do not depend on the (possibly updated) ClientHello.KeyShareClientHello, i.e,, ClientEncryptedSNI.suite, ClientEncryptedSNI.key_share, and ClientEncryptedSNI.record_digest, MUST NOT change across ClientHello messages.  Moreover, ClientESNIInner.nonce and ClientESNIInner.realSNI MUST not change across ClientHello messages.  Informally, the values of all unencrypted extension information, as well as the inner extension plaintext, must be consistent between the first and second ClientHello messages. </ins> 5.1.3. When the server cannot decrypt or does not process the


Question: Because this document now delegates the way the keys are advertised from the RRType ESNI to HTTPSSVC shouldn't the RRType Considerations be removed from this document.

existing registry for Alerts (defined in RFC8446), with the "DTLS-OK" column being set to "Y". <del> 8.3. IANA is requested to create an entry, ESNI(0xff9f), in the existing registry for Resource Record (RR) TYPEs (defined in RFC6895) with "Meaning" column value being set to "Encrypted SNI". </del> <ins> 9. When operating in Split Mode, backend servers will not have access to PaddedServerNameList.sni or ClientESNIInner.nonce without access to the ESNI keys or a way to decrypt ClientEncryptedSNI.encrypted_sni. One way to address this for a single connection, at the cost of having communication not be unmodified TLS 1.3, is as follows. Assume there is a shared (symmetric) key between the client-facing server and the backend server and use it to AEAD-encrypt Z and send the encrypted blob at the beginning of the connection before the ClientHello.  The backend server can then decrypt ESNI to recover the true SNI and nonce. 10. Alternative approaches to encrypted SNI may be implemented at the TLS or application layer.  In this section we describe several alternatives and discuss drawbacks in comparison to the design in this document. 10.1. 10.1.1. In this variant, TLS Client Hellos are tunneled within early data payloads belonging to outer TLS connections established with the client-facing server.  This requires clients to have established a previous session --- and obtained PSKs --- with the server.  The client-facing server decrypts early data payloads to uncover Client Hellos destined for the backend server, and forwards them onwards as necessary.  Afterwards, all records to and from backend servers are forwarded by the client-facing server - unmodified.  This avoids double encryption of TLS records. Problems with this approach are: (1) servers may not always be able to distinguish inner Client Hellos from legitimate application data, (2) nested 0-RTT data may not function correctly, (3) 0-RTT data may not be supported - especially under DoS - leading to availability concerns, and (4) clients must bootstrap tunnels (sessions), costing an additional round trip and potentially revealing the SNI during the initial connection.  In contrast, encrypted SNI protects the SNI in a distinct Client Hello extension and neither abuses early data nor requires a bootstrapping connection. 10.1.2. In this variant, client-facing and backend servers coordinate to produce "combined tickets" that are consumable by both.  Clients offer combined tickets to client-facing servers.  The latter parse them to determine the correct backend server to which the Client Hello should be forwarded.  This approach is problematic due to non- trivial coordination between client-facing and backend servers for ticket construction and consumption.  Moreover, it requires a bootstrapping step similar to that of the previous variant.  In contrast, encrypted SNI requires no such coordination. 10.2. 10.2.1. In this variant, clients request secondary certificates with CERTIFICATE_REQUEST HTTP/2 frames after TLS connection completion. In response, servers supply certificates via TLS exported authenticators I-D.ietf-tls-exported-authenticator in CERTIFICATE frames.  Clients use a generic SNI for the underlying client-facing server TLS connection.  Problems with this approach include: (1) one additional round trip before peer authentication, (2) non-trivial application-layer dependencies and interaction, and (3) obtaining the generic SNI to bootstrap the connection.  In contrast, encrypted SNI induces no additional round trip and operates below the application layer. 11. The design described here only provides encryption for the SNI, but not for other extensions, such as ALPN.  Another potential design would be to encrypt all of the extensions using the same basic structure as we use here for ESNI.  That design has the following advantages: It protects all the extensions from ordinary eavesdroppers If the encrypted block has its own KeyShare, it does not necessarily require the client to use a single KeyShare, because the client's share is bound to the SNI by the AEAD (analysis needed). It also has the following disadvantages: The client-facing server can still see the other extensions.  By contrast we could introduce another EncryptedExtensions block that was encrypted to the backend server and not the client-facing server. It requires a mechanism for the client-facing server to provide the extension-encryption key to the backend server (as in communicating-sni and thus cannot be used with an unmodified backend server. A conformant middlebox will strip every extension, which might result in a ClientHello which is just unacceptable to the server (more analysis needed). </ins>


Question:
I've tried to capture what I think is a reasonable way to handle padding now we've changed from ESNI->ECHO. If we could do something like this, that'd be better than what's in -06. Note that I'd be even happier if we entirely eliminated ECHOConfig.minimuminnerlength - I don't think it actually adds any value and it represents yet another way to get a configuration wrong.
Thanks for the fixes. On the general point, I think that if we keep the flexibility for the client to vary the inner/outer CH however it chooses, then we will also have to depend on clients to figure out how to pad well for whatever they do. If we constrain the inner/outer variance a lot, then we could do better. It also strikes me that the minimuminnerlength is sort of in tension with the idea of compression - if a server has to set the minimuminnerlength to 300ish to handle clients that don't compress, then clients that do compress either don't get the benefit or have to ignore the minimuminnerlength.
I don't think this PR works. The server does not have enough information to report a useful value, and the value the server reports is not useful to maintain good anonymity sets. The server does not know that the client supports some large extension or key share type (or lots of cipher suites, ALPN protocols, etc). are especially fun. It also doesn't know which extensions the client will compress from the outer ClientHello and which it will reencode. Conversely, the value the server sets isn't useful. If the client implementation has a smaller baseline compression and extensions, we waste bytes without much benefit. Worse, if the client implementation has a larger baseline compression and extensions, this PR regresses anonymity. The ClientHello will then exceed and we don't hide the lengths of the sensitive bits. Stepping back, we want to hide the distribution of ClientHelloInner lengths within some anonymity set. Most of the contributors to that length come from local client configuration: how many ciphers you support, what ALPN protocols, etc. The client is the one that knows, e.g., it sometimes asks servers for protocols A and B and sometimes for A and C. It largely has enough information to pad itself. The main exception is the server name. Realistically we need to trim anonymity sets down to colocated services, and the client doesn't know that distribution of names. Thus, we want servers to report the value in ECHOConfig. Maybe we'll need more such statistics later, which is what extensions are for. It's annoying this is a bit complicated, but we've signing up to encrypt far more things now. I should note this presumes an anonymity set of similarly-configured clients. I think, realistically, that's all we can say rigorous things about. It's nice to reduce visible artifacts of configuration, which is why we additionally round up to multiples of 16, but that's something we can burn into the protocol without ECHOConfig support.
Hiya, Sorry, not seeing that last. The PR just says (or was meant to say) to pad to some multiple of 16 in that case which I agree isn't much guidance, but does allow doing something that works. (As well as allowing things that don't work well;-) I agree that all this really needs to be driven by the client. Well, yes and no. I don't believe a server config is useful for that, (as I've argued before and still do;-) ISTM the max server name value will almost always be set to 254. May as well tell the client to pad as do that IMO. Not quite sure if I agree with that last para or not TBH! S.
Well, if we were satisfied just padding names to a multiple of 16, we wouldn't need any of this. We'd just say to pad to a multiple 16 and move on. :-) In the current name-focused spelling, the client is always able to apply a smarter padding decision based on the server's knowledge of the name distribution. With this PR, clients whose local configuration exceeds or is near lose this and hit the baseline multiple of 16 behavior. Clients whose local configuration is decently below do hide the name distribution, but using many more bytes than they would with the current text. We have some metrics in Chrome on the distribution of DNS names. It's nowhere near 254. But, regardless, if you don't believe a server config is even useful for the name and agree with me that other extensions ought to be client-driven, I'm confused, why this PR? This PR seems to go in the opposite direction. Hehe. Which part?
HIya, Yes. That's IMO the downside of having any server config. (To answer your question below, I prefer not having any server config at all but proposed this as I think it's better than draft-06.) Having also looked at some passive DNS stuff, I fully agree. But ISTM for many scenarios the entity that generates the ECHOConfig won't know the distribution of names in use (e.g. whoever configures OpenSSL won't, same with Apache etc.) so it's likely they'll have to go for whatever is the max (i.e. 254). Same is true for anyone with a wild-card server cert in play somewhere. See above. I'm trying for either a modest improvement over draft-06 or for us all to arrive at a real improvement by ditching the server config entirely:-) I like the last sentence. I think I dislike the 1st:-) Cheers, S.
It's not a downside of the draft-06 formulation, is it? The client learns something targeted to the name and can pad accordingly. Even with a wildcard server cert, the server should still know the distribution. For instance, isn't going to see anything terribly long most of the time. (Looks like the registration limit is 39 characters.) For reference, this is how long a 254-character hostname is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa In order to enjoy wide adoption, ECHO can't be too much of a waste of resources. I think it thus makes sense to target a different maximum here. I guess my view is that, because of this issue above, this is a regression over the draft-06 formulation, even though it looks more general.
Hiya, Draft-06 assumes that no other inner CH content has the property that server guidance will help. My claim is that that guidance is useless in practice, and therefore unnecessary. I think the server config'd length in the PR is a little less useless:-) Some servers will. Some will not. Many (most?) server ECHOConfig instances will make use of default settings. Those'll pick 254 because adding a new VirtualHost to an apache instance (or similar) won't be co-ordinated with making a new ECHOConfig in general. And even it it were, (but it won't!) we get a TTL's worth of mismatch. If we don't provide a way for clients to handle the case where the server config is too short, again servers will publish 254. I am more interested in random smaller web sites/hosters myself. I think ECHO should work for those as well as we can make it, (albeit with smaller anonymity sets), and this tie between web server config and ECHOConfig is just a bad plan for such. AFAIK, all current deployments do just that. To be fair, that's largely driven by CF's draft-02 deployment, but I think that backs up my argument that if there's a max, that'll almost always be chosen, which implies it's a useless field that leads to the inefficiency you note. Then it can't be the max:-) The 254 value matches the max for servername IIRC. Ok. We disagree. But what do you think the client should do? Draft-06 is IMO plainly incorrect in that it says to pad in a way that'd expose other lengths should those be sensitive. If your answer were pad the SNI to at least ECHOConfig.maximumname_length and then make the overall a multiple of 16, with as many added 16 octets blocks as the client chooses, then a) that's != draft-06 and b) is quite close to this PR and c) just failing if the actual SNI in the inner CH is longer than the config setting seems quite wrong to me and d) hardcodes the assumption that SNI is the only thing where the server may know better. Cheers, S.
If we come up with other places where server guidance is useful, that can be addressed with extensions. But, gotcha, I suppose that is where we disagree. I think server guidance on the overall ClientHello size is entirely useless, while server guidance on the name is may be useful. Agreed that it should also work for smaller things. I don't follow how this PR helps in that regard. It seems they still need to come up with a random value or a default, but now it's even less clear how to set it well. Er, yes, sorry I meant to say target a different public length. That is, 254 is so far from the maximum domain name in practice (As it should be! Hard length limits ought to be comfortably away from the actual requirement.), so padding up to it is wasteful. I think it would be better to pad up to a tighter value and, if we exceed it, accept that we only have the fallback multiple of 16 padding. (Or maybe a different strategy.) It does result in smaller anonymity sets in edge cases, but I think that a reasonable default tradeoff given other desires like broader deployment and not wasting too much of users' data. I'm thinking something along the lines of: For each field, determine how much it makes sense to pad given what kinds of things it sends. If it varies ALPN, maybe round up to the largest of those. Most of this can be determined without server help. For fields where server help is useful, like the name, apply that help. Right now it's simply a function. I'm also open to other strategies. Sum all that padding together. In order to generally reduce entropy across different kinds of clients, maybe apply some additional overall padding, like rounding up to a multiple of 16, which cuts down the state space by 16x and doesn't cost much. (Or maybe we should round up to the nearest ? That avoids higher resolution on longer values while bounding the fraction of bytes wasted by this step.) That said, it's worth keeping in mind that clients already vary quite a bit in the cleartext portions of the ClientHello. There's a bit of tension between wanting to look like the other clients and wanting to ship new security improvements. This is different from this PR because this PR asks the server to report a value including things it doesn't know anything about (how large the client-controlled parameters are). I don't quite follow (c). It seems this PR and the above proposal has roughly the same failure modes when something is too long. The difference is that 's failure mode is only tripped on particular long names (something the server knows the distribution of), while this PR's equivalent failure mode is based on factors outside the server control, yet the server is responsible for the value.
Clarification: this is for each field where the client doesn't reference the outer ClientHello. If the client wishes to do that, it means the client doesn't consider that field secret so there isn't anything to pad.
I like NAME suggested algorithm, as an ideal padding function requires input from both the client and server. (Ideally, servers would send padding recommendations for each extension that might vary specifically for them, such as the server name. They don't have insight into anything else, so clients need to make padding decisions based on local configuration.) NAME what do you think?
Could live with it, but still prefer no server config. I'm looking a bit at some numbers and will try make a concrete suggestion later today. If I don't get that done, it seems fair to accept NAME algo and move on. Cheers, S.
If we can get away with no server config, I'm also entirely happy with that. Fewer moving parts is always great. We certainly could do that by saying names are padded up to 254, but I think that's too wasteful. But if we're happy with some global set of buckets that makes everyone happy (be it multiples of 16, some funny exponential thing), great!
(trimming violently and responding slowly:-) So your steps 1-6 is a better scheme than draft-06. I still think step 2 would be better as something like: ECHOConfig contains maxnamelen as before but we RECOMMEND it be zero and a) if the name to be padded is longer than maxnamelen, then names will be padded as follows: P=32-(len(name)%32)+headsortails*32, or b) if the name to be padded is shorter than maxnamelen then we just do as the server asked and pad to that length. That (hopefully:-) means a default of "pad out to the next multiple of 32, then toss a coin and add another 32 if the coin landed as heads." If we landed somewhere there, I'd be happy to make this PR say that or to make a new one or whatever. According to some data I have the CDFs for names and for these padded lengths would be as follows: Len, CDF, Padded-CDF 32, 81.28, 40.64 64, 97.87, 89.57 96, 99.31, 98.59 128, 99.87, 99.59 That means that 81.28 of names are <32 octets long and 40.64% of name+namepadding will be 32 octets long. 97.87% of names are <64 octets and 89.57% of name+namepadding are 64 octets long. I think we should RECOMMEND setting maxnamelen to zero unless an ESNI key generator has a specific reason to set it to a non-zero value. ISTM the use-case for non-zero values is where the anonymity set has only a few very long names that with length differences of ECHO. I'm basically fine that we default to not serving that use-case wellmby default, as I don't believe it's real. (But I could be wrong;-) Cheers, S.
Could the sender always pad their packets to at least 1200 bytes or something, using an encrypted extension in the ClientHello? I don't understand the focus on server input to a padding function that would ideally fill out one packet.
NAME what's the value in adding zero or one 32B blocks after rounding? Why not just stick with what was done, say, in RFC8467? (We could make it read something like, "clients may add zero or one blocks." Either way, I'm more or less fine with the suggested change. Would you mind updating this PR to match?)
Per above, clients could use help from servers in choosing appropriate padding lengths. (Only servers know their name anonymity set.)
Hiya, Say if the anonymity set has lots of names <32 length (~81% of names in the data I have) but a small number between 32 and 64 (~16% in my data). Then this should disguise the use of the longer names at the expense of sending more octets. Would be v. happy to know if that made sense to others. Cheers, S.
A friendly amendment below (but one I think is important)... I think that last really needs to be "Only servers can know their name anonymity set. But many servers will not know that, either due to wildcard certs or because names/vhosts are added and removed all the time independent of whatever is in the DNS." Cheers, S.
It makes sense, I'm just not not sure it's worth the cost. That said, this will always be an imperfect solution, so I'm happy either way.
Yep. Me neither. It is cheaper than padding to 254 octets for everyone though;-) Partly, I'm not that sympathetic towards anyone who wants to hide a crazily-long server_name. OTOH, I guess there may be a few who can't easily change names so we probably ought try do something for 'em. Cheers, S.
Agree that only servers could know their name anonymity set. But what is the cost of always padding out the ClientHello so it approaches the MTU? Just trying to understand why the spec attempts to economize on the number of bytes in the ClientHello packet.
As far as I know, there's no reason other than folks might not want to always "waste" these bytes.
Padding the ClientHello up to an MTU isn't free. See the numbers here on what a 400-byte increase costs. URL Likewise, also from that post and a , post-quantum key shares will likely exceed a packet anyway. I think our padding scheme should be designed with that expectation in mind (e.g., the mechanism fails this because a PQ key share in the inner ClientHello will blow past the built-in server assumptions on client behavior). Canary builds of Chrome already have code for such a thing behind a flag. Edit: Added a link to the later experiment, which I'd forgotten was a separate post.
It's not quite clear what's going on in those results. For example, the mobile results are close to zero. Without seeing confidence intervals, and the distributions of the full packet sizes, I don't think this experiment settles this issue (although it could, with more detail). Also, is there a theory on /why/ 400 bytes might add latency? If we're going to design the padding mechanism with PQ key shares in mind, but not conventional ones, that should be in the document.
NAME would know the details of that experiment, but I don't think the idea that sending more bytes takes more time would be terribly surprising! :-P I don't think anyone's suggested designing without conventional key shares in mind. They are what's deployed today, after all. However, we shouldn't design only for a small unpadded ClientHello. PQ key shares will need larger ones. Session tickets also go in the ClientHello, and it's common for TLS servers to stick client certificates inside tickets, so you can already get large ones today already.
Let's assume the results for "SI" in the first link actually do show a significant delta. The question is whether per-packet costs dominate or per-byte costs do, and whether the experiment sometimes increased the number of packets (e.g. by sometimes bumping the ultimate ClientHello size above 1280). See Section 5.1 in URL for device performance metrics on bytes vs packets. Looking at the ClientHello traffic on my computer, I can see that Safari is sending ClientHello messages that are about 500-600 bytes. My copy of Chrome seems to be sending CurveCECPQ2 (16696?) shares, and its ClientHello messages are fragmented.
NAME will you be able to update this as above?
would the spec allow me to put an arbitrarily-sized extension in the encrypted part of the ClientHello? if so, I don't care about the padding schemes.
Yes, of course! The padding policies described here are guidance at best.
I've updated the PR to try reflect the discussion above. Please take a peek and see if it seems useful now.
This looks like the right idea. I'll review this again as well, but it's probably better to wait for NAME suggestions to be addressed.
Thanks for all the changes Chris. I think I've actioned all those as requested. If not, I tried, but failed:-)
NAME do you need any help moving this forward?
Doing other stuff today but feel free to take the text and then do more edits. Or I can look at it tomorrow. Either's fine by me. S.
Thanks for taking the time. None of my comments are strongly-held opinions (meaning they only need to be addressed at all if others agree that the issues are important).
Strong +1 to NAME -- thank you for the work here, NAME
NAME can you please resolve conflicts? NAME NAME can you please review?
Fair point. The argument I'd make for keeping this is that if an anonymity set has ~80% of names <32 octets, then if we do nothing, passive observation will probably reveal when the server name is in the longest ~20%. And I'd guess that only a few names in that set would be popular/common, so we could be giving away the game whenever an ECHO is 32 octets longer than the usual. The random padding could mitigate that passive attack but yes would be vulnerable to an active reset based counter. I'd also be fine with just living with the issue in which case we might want to note that using ECHO with uncommonly long names is a bad idea.
Let's just drop the random addition. Servers don't (can't) do a padding check anyway, so clients can always choose to make this longer if desired.
NAME can you update this PR and resolve the conflicts?
"Fair point. The argument I'd make for keeping this is that if an anonymity set has ~80% of names <32 octets, then if we do nothing, passive observation will probably reveal when the server name is in the longest ~20%. " Which is precisely why we want the server to provide the longest name, so the client can pad to it.
As discussed on today's call, let's do the following: Resolve merge conflicts. Drop random padding for the SNI. And add text which says that if the client's name is larger than maxnamelength, it rounds up to the nearest 32B or 64B boundary. NAME do you need, or would you like, any help with this?
I think that this approach is generally better, but it runs afoul of divergence in client configuration that could dominate the calculation. For instance, a client that sends two key shares will have very different padding requirements to one that sends only one. For that to work, we need to assume that implementation-/deployment-specific variation of the inner CH is largely eliminated as a result of the compression scheme we adopt. That also assumes that these variations in client behaviour are not privacy-sensitive. I think that we should be directly acknowledging those assumptions if that is indeed the case. If there is a significant variation in size due to client-specific measures, then we're in a bit of an awkward position. That might render any similarly simple scheme ineffective. For instance, a client that later supports a set of ALPN identifiers that could vary in length depending on context cannot use this signal directly. It has to apply its own logic about the padding of that extension. That a client is doing this won't be known to a server that deploys this today. In that case, the advice from the server (which knows most about the anonymity set across which it is hoping to spread the resulting CH), isn't going to be forced through an additional filter at the client. The results are unlikely to be good without a great deal of care.I am generally fine with this, with the exception of the random padding, which I think should be omitted. It's hard to analyze and the value is unclear. In particular, many clients will retry if they receive TCP errors, and so the attacker can learn information about the true minimum value by forging TCP RSTs and looking at the new CH.

encrypt the ClientHello.  See hpke-map for information on how a cipher suite maps to corresponding HPKE algorithm identifiers. <del> the largest name the server expects to support.  If the server supports arbitrary wildcard names, it SHOULD set this value to 256.  Clients SHOULD reject ESNIConfig as invalid if maximum_name_length is greater than 256. </del> <ins> The largest name the server expects to support, if known.  If this value is not known it can be set to zero, in which case clients SHOULD use the inner ClientHello padding scheme described below. That could happen if wildcard names are in use, or if names can be added or removed from the anonymity set during the lifetime of a particular resource record value. </ins> A list of extensions that the client can take into consideration when generating a Client Hello message.  The purpose of the field


Question:
I've tried to capture what I think is a reasonable way to handle padding now we've changed from ESNI->ECHO. If we could do something like this, that'd be better than what's in -06. Note that I'd be even happier if we entirely eliminated ECHOConfig.minimuminnerlength - I don't think it actually adds any value and it represents yet another way to get a configuration wrong.
Thanks for the fixes. On the general point, I think that if we keep the flexibility for the client to vary the inner/outer CH however it chooses, then we will also have to depend on clients to figure out how to pad well for whatever they do. If we constrain the inner/outer variance a lot, then we could do better. It also strikes me that the minimuminnerlength is sort of in tension with the idea of compression - if a server has to set the minimuminnerlength to 300ish to handle clients that don't compress, then clients that do compress either don't get the benefit or have to ignore the minimuminnerlength.
I don't think this PR works. The server does not have enough information to report a useful value, and the value the server reports is not useful to maintain good anonymity sets. The server does not know that the client supports some large extension or key share type (or lots of cipher suites, ALPN protocols, etc). are especially fun. It also doesn't know which extensions the client will compress from the outer ClientHello and which it will reencode. Conversely, the value the server sets isn't useful. If the client implementation has a smaller baseline compression and extensions, we waste bytes without much benefit. Worse, if the client implementation has a larger baseline compression and extensions, this PR regresses anonymity. The ClientHello will then exceed and we don't hide the lengths of the sensitive bits. Stepping back, we want to hide the distribution of ClientHelloInner lengths within some anonymity set. Most of the contributors to that length come from local client configuration: how many ciphers you support, what ALPN protocols, etc. The client is the one that knows, e.g., it sometimes asks servers for protocols A and B and sometimes for A and C. It largely has enough information to pad itself. The main exception is the server name. Realistically we need to trim anonymity sets down to colocated services, and the client doesn't know that distribution of names. Thus, we want servers to report the value in ECHOConfig. Maybe we'll need more such statistics later, which is what extensions are for. It's annoying this is a bit complicated, but we've signing up to encrypt far more things now. I should note this presumes an anonymity set of similarly-configured clients. I think, realistically, that's all we can say rigorous things about. It's nice to reduce visible artifacts of configuration, which is why we additionally round up to multiples of 16, but that's something we can burn into the protocol without ECHOConfig support.
Hiya, Sorry, not seeing that last. The PR just says (or was meant to say) to pad to some multiple of 16 in that case which I agree isn't much guidance, but does allow doing something that works. (As well as allowing things that don't work well;-) I agree that all this really needs to be driven by the client. Well, yes and no. I don't believe a server config is useful for that, (as I've argued before and still do;-) ISTM the max server name value will almost always be set to 254. May as well tell the client to pad as do that IMO. Not quite sure if I agree with that last para or not TBH! S.
Well, if we were satisfied just padding names to a multiple of 16, we wouldn't need any of this. We'd just say to pad to a multiple 16 and move on. :-) In the current name-focused spelling, the client is always able to apply a smarter padding decision based on the server's knowledge of the name distribution. With this PR, clients whose local configuration exceeds or is near lose this and hit the baseline multiple of 16 behavior. Clients whose local configuration is decently below do hide the name distribution, but using many more bytes than they would with the current text. We have some metrics in Chrome on the distribution of DNS names. It's nowhere near 254. But, regardless, if you don't believe a server config is even useful for the name and agree with me that other extensions ought to be client-driven, I'm confused, why this PR? This PR seems to go in the opposite direction. Hehe. Which part?
HIya, Yes. That's IMO the downside of having any server config. (To answer your question below, I prefer not having any server config at all but proposed this as I think it's better than draft-06.) Having also looked at some passive DNS stuff, I fully agree. But ISTM for many scenarios the entity that generates the ECHOConfig won't know the distribution of names in use (e.g. whoever configures OpenSSL won't, same with Apache etc.) so it's likely they'll have to go for whatever is the max (i.e. 254). Same is true for anyone with a wild-card server cert in play somewhere. See above. I'm trying for either a modest improvement over draft-06 or for us all to arrive at a real improvement by ditching the server config entirely:-) I like the last sentence. I think I dislike the 1st:-) Cheers, S.
It's not a downside of the draft-06 formulation, is it? The client learns something targeted to the name and can pad accordingly. Even with a wildcard server cert, the server should still know the distribution. For instance, isn't going to see anything terribly long most of the time. (Looks like the registration limit is 39 characters.) For reference, this is how long a 254-character hostname is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa In order to enjoy wide adoption, ECHO can't be too much of a waste of resources. I think it thus makes sense to target a different maximum here. I guess my view is that, because of this issue above, this is a regression over the draft-06 formulation, even though it looks more general.
Hiya, Draft-06 assumes that no other inner CH content has the property that server guidance will help. My claim is that that guidance is useless in practice, and therefore unnecessary. I think the server config'd length in the PR is a little less useless:-) Some servers will. Some will not. Many (most?) server ECHOConfig instances will make use of default settings. Those'll pick 254 because adding a new VirtualHost to an apache instance (or similar) won't be co-ordinated with making a new ECHOConfig in general. And even it it were, (but it won't!) we get a TTL's worth of mismatch. If we don't provide a way for clients to handle the case where the server config is too short, again servers will publish 254. I am more interested in random smaller web sites/hosters myself. I think ECHO should work for those as well as we can make it, (albeit with smaller anonymity sets), and this tie between web server config and ECHOConfig is just a bad plan for such. AFAIK, all current deployments do just that. To be fair, that's largely driven by CF's draft-02 deployment, but I think that backs up my argument that if there's a max, that'll almost always be chosen, which implies it's a useless field that leads to the inefficiency you note. Then it can't be the max:-) The 254 value matches the max for servername IIRC. Ok. We disagree. But what do you think the client should do? Draft-06 is IMO plainly incorrect in that it says to pad in a way that'd expose other lengths should those be sensitive. If your answer were pad the SNI to at least ECHOConfig.maximumname_length and then make the overall a multiple of 16, with as many added 16 octets blocks as the client chooses, then a) that's != draft-06 and b) is quite close to this PR and c) just failing if the actual SNI in the inner CH is longer than the config setting seems quite wrong to me and d) hardcodes the assumption that SNI is the only thing where the server may know better. Cheers, S.
If we come up with other places where server guidance is useful, that can be addressed with extensions. But, gotcha, I suppose that is where we disagree. I think server guidance on the overall ClientHello size is entirely useless, while server guidance on the name is may be useful. Agreed that it should also work for smaller things. I don't follow how this PR helps in that regard. It seems they still need to come up with a random value or a default, but now it's even less clear how to set it well. Er, yes, sorry I meant to say target a different public length. That is, 254 is so far from the maximum domain name in practice (As it should be! Hard length limits ought to be comfortably away from the actual requirement.), so padding up to it is wasteful. I think it would be better to pad up to a tighter value and, if we exceed it, accept that we only have the fallback multiple of 16 padding. (Or maybe a different strategy.) It does result in smaller anonymity sets in edge cases, but I think that a reasonable default tradeoff given other desires like broader deployment and not wasting too much of users' data. I'm thinking something along the lines of: For each field, determine how much it makes sense to pad given what kinds of things it sends. If it varies ALPN, maybe round up to the largest of those. Most of this can be determined without server help. For fields where server help is useful, like the name, apply that help. Right now it's simply a function. I'm also open to other strategies. Sum all that padding together. In order to generally reduce entropy across different kinds of clients, maybe apply some additional overall padding, like rounding up to a multiple of 16, which cuts down the state space by 16x and doesn't cost much. (Or maybe we should round up to the nearest ? That avoids higher resolution on longer values while bounding the fraction of bytes wasted by this step.) That said, it's worth keeping in mind that clients already vary quite a bit in the cleartext portions of the ClientHello. There's a bit of tension between wanting to look like the other clients and wanting to ship new security improvements. This is different from this PR because this PR asks the server to report a value including things it doesn't know anything about (how large the client-controlled parameters are). I don't quite follow (c). It seems this PR and the above proposal has roughly the same failure modes when something is too long. The difference is that 's failure mode is only tripped on particular long names (something the server knows the distribution of), while this PR's equivalent failure mode is based on factors outside the server control, yet the server is responsible for the value.
Clarification: this is for each field where the client doesn't reference the outer ClientHello. If the client wishes to do that, it means the client doesn't consider that field secret so there isn't anything to pad.
I like NAME suggested algorithm, as an ideal padding function requires input from both the client and server. (Ideally, servers would send padding recommendations for each extension that might vary specifically for them, such as the server name. They don't have insight into anything else, so clients need to make padding decisions based on local configuration.) NAME what do you think?
Could live with it, but still prefer no server config. I'm looking a bit at some numbers and will try make a concrete suggestion later today. If I don't get that done, it seems fair to accept NAME algo and move on. Cheers, S.
If we can get away with no server config, I'm also entirely happy with that. Fewer moving parts is always great. We certainly could do that by saying names are padded up to 254, but I think that's too wasteful. But if we're happy with some global set of buckets that makes everyone happy (be it multiples of 16, some funny exponential thing), great!
(trimming violently and responding slowly:-) So your steps 1-6 is a better scheme than draft-06. I still think step 2 would be better as something like: ECHOConfig contains maxnamelen as before but we RECOMMEND it be zero and a) if the name to be padded is longer than maxnamelen, then names will be padded as follows: P=32-(len(name)%32)+headsortails*32, or b) if the name to be padded is shorter than maxnamelen then we just do as the server asked and pad to that length. That (hopefully:-) means a default of "pad out to the next multiple of 32, then toss a coin and add another 32 if the coin landed as heads." If we landed somewhere there, I'd be happy to make this PR say that or to make a new one or whatever. According to some data I have the CDFs for names and for these padded lengths would be as follows: Len, CDF, Padded-CDF 32, 81.28, 40.64 64, 97.87, 89.57 96, 99.31, 98.59 128, 99.87, 99.59 That means that 81.28 of names are <32 octets long and 40.64% of name+namepadding will be 32 octets long. 97.87% of names are <64 octets and 89.57% of name+namepadding are 64 octets long. I think we should RECOMMEND setting maxnamelen to zero unless an ESNI key generator has a specific reason to set it to a non-zero value. ISTM the use-case for non-zero values is where the anonymity set has only a few very long names that with length differences of ECHO. I'm basically fine that we default to not serving that use-case wellmby default, as I don't believe it's real. (But I could be wrong;-) Cheers, S.
Could the sender always pad their packets to at least 1200 bytes or something, using an encrypted extension in the ClientHello? I don't understand the focus on server input to a padding function that would ideally fill out one packet.
NAME what's the value in adding zero or one 32B blocks after rounding? Why not just stick with what was done, say, in RFC8467? (We could make it read something like, "clients may add zero or one blocks." Either way, I'm more or less fine with the suggested change. Would you mind updating this PR to match?)
Per above, clients could use help from servers in choosing appropriate padding lengths. (Only servers know their name anonymity set.)
Hiya, Say if the anonymity set has lots of names <32 length (~81% of names in the data I have) but a small number between 32 and 64 (~16% in my data). Then this should disguise the use of the longer names at the expense of sending more octets. Would be v. happy to know if that made sense to others. Cheers, S.
A friendly amendment below (but one I think is important)... I think that last really needs to be "Only servers can know their name anonymity set. But many servers will not know that, either due to wildcard certs or because names/vhosts are added and removed all the time independent of whatever is in the DNS." Cheers, S.
It makes sense, I'm just not not sure it's worth the cost. That said, this will always be an imperfect solution, so I'm happy either way.
Yep. Me neither. It is cheaper than padding to 254 octets for everyone though;-) Partly, I'm not that sympathetic towards anyone who wants to hide a crazily-long server_name. OTOH, I guess there may be a few who can't easily change names so we probably ought try do something for 'em. Cheers, S.
Agree that only servers could know their name anonymity set. But what is the cost of always padding out the ClientHello so it approaches the MTU? Just trying to understand why the spec attempts to economize on the number of bytes in the ClientHello packet.
As far as I know, there's no reason other than folks might not want to always "waste" these bytes.
Padding the ClientHello up to an MTU isn't free. See the numbers here on what a 400-byte increase costs. URL Likewise, also from that post and a , post-quantum key shares will likely exceed a packet anyway. I think our padding scheme should be designed with that expectation in mind (e.g., the mechanism fails this because a PQ key share in the inner ClientHello will blow past the built-in server assumptions on client behavior). Canary builds of Chrome already have code for such a thing behind a flag. Edit: Added a link to the later experiment, which I'd forgotten was a separate post.
It's not quite clear what's going on in those results. For example, the mobile results are close to zero. Without seeing confidence intervals, and the distributions of the full packet sizes, I don't think this experiment settles this issue (although it could, with more detail). Also, is there a theory on /why/ 400 bytes might add latency? If we're going to design the padding mechanism with PQ key shares in mind, but not conventional ones, that should be in the document.
NAME would know the details of that experiment, but I don't think the idea that sending more bytes takes more time would be terribly surprising! :-P I don't think anyone's suggested designing without conventional key shares in mind. They are what's deployed today, after all. However, we shouldn't design only for a small unpadded ClientHello. PQ key shares will need larger ones. Session tickets also go in the ClientHello, and it's common for TLS servers to stick client certificates inside tickets, so you can already get large ones today already.
Let's assume the results for "SI" in the first link actually do show a significant delta. The question is whether per-packet costs dominate or per-byte costs do, and whether the experiment sometimes increased the number of packets (e.g. by sometimes bumping the ultimate ClientHello size above 1280). See Section 5.1 in URL for device performance metrics on bytes vs packets. Looking at the ClientHello traffic on my computer, I can see that Safari is sending ClientHello messages that are about 500-600 bytes. My copy of Chrome seems to be sending CurveCECPQ2 (16696?) shares, and its ClientHello messages are fragmented.
NAME will you be able to update this as above?
would the spec allow me to put an arbitrarily-sized extension in the encrypted part of the ClientHello? if so, I don't care about the padding schemes.
Yes, of course! The padding policies described here are guidance at best.
I've updated the PR to try reflect the discussion above. Please take a peek and see if it seems useful now.
This looks like the right idea. I'll review this again as well, but it's probably better to wait for NAME suggestions to be addressed.
Thanks for all the changes Chris. I think I've actioned all those as requested. If not, I tried, but failed:-)
NAME do you need any help moving this forward?
Doing other stuff today but feel free to take the text and then do more edits. Or I can look at it tomorrow. Either's fine by me. S.
Thanks for taking the time. None of my comments are strongly-held opinions (meaning they only need to be addressed at all if others agree that the issues are important).
Strong +1 to NAME -- thank you for the work here, NAME
NAME can you please resolve conflicts? NAME NAME can you please review?
Fair point. The argument I'd make for keeping this is that if an anonymity set has ~80% of names <32 octets, then if we do nothing, passive observation will probably reveal when the server name is in the longest ~20%. And I'd guess that only a few names in that set would be popular/common, so we could be giving away the game whenever an ECHO is 32 octets longer than the usual. The random padding could mitigate that passive attack but yes would be vulnerable to an active reset based counter. I'd also be fine with just living with the issue in which case we might want to note that using ECHO with uncommonly long names is a bad idea.
Let's just drop the random addition. Servers don't (can't) do a padding check anyway, so clients can always choose to make this longer if desired.
NAME can you update this PR and resolve the conflicts?
"Fair point. The argument I'd make for keeping this is that if an anonymity set has ~80% of names <32 octets, then if we do nothing, passive observation will probably reveal when the server name is in the longest ~20%. " Which is precisely why we want the server to provide the longest name, so the client can pad to it.
As discussed on today's call, let's do the following: Resolve merge conflicts. Drop random padding for the SNI. And add text which says that if the client's name is larger than maxnamelength, it rounds up to the nearest 32B or 64B boundary. NAME do you need, or would you like, any help with this?
I think that this approach is generally better, but it runs afoul of divergence in client configuration that could dominate the calculation. For instance, a client that sends two key shares will have very different padding requirements to one that sends only one. For that to work, we need to assume that implementation-/deployment-specific variation of the inner CH is largely eliminated as a result of the compression scheme we adopt. That also assumes that these variations in client behaviour are not privacy-sensitive. I think that we should be directly acknowledging those assumptions if that is indeed the case. If there is a significant variation in size due to client-specific measures, then we're in a bit of an awkward position. That might render any similarly simple scheme ineffective. For instance, a client that later supports a set of ALPN identifiers that could vary in length depending on context cannot use this signal directly. It has to apply its own logic about the padding of that extension. That a client is doing this won't be known to a server that deploys this today. In that case, the advice from the server (which knows most about the anonymity set across which it is hoping to spread the resulting CH), isn't going to be forced through an additional filter at the client. The results are unlikely to be good without a great deal of care.I am generally fine with this, with the exception of the random padding, which I think should be omitted. It's hard to analyze and the value is unclear. In particular, many clients will retry if they receive TCP errors, and so the attacker can learn information about the true minimum value by forging TCP RSTs and looking at the new CH.

an "echo_nonce" extension <del> TLS padding Padding SHOULD be P = L - D bytes, where L = ECHOConfig.maximum_name_length, rounded up to the nearest multiple of 16 D = len(dns_name), where dns_name is the DNS name in the ClientHelloInner "server_name" extension </del> <ins> TLS padding RFC7685 (see section padding) </ins> When offering an encrypted ClientHello, the client MUST NOT offer to resume any non-ECHO PSKs.  It additionally MUST NOT offer to resume


Question:
I've tried to capture what I think is a reasonable way to handle padding now we've changed from ESNI->ECHO. If we could do something like this, that'd be better than what's in -06. Note that I'd be even happier if we entirely eliminated ECHOConfig.minimuminnerlength - I don't think it actually adds any value and it represents yet another way to get a configuration wrong.
Thanks for the fixes. On the general point, I think that if we keep the flexibility for the client to vary the inner/outer CH however it chooses, then we will also have to depend on clients to figure out how to pad well for whatever they do. If we constrain the inner/outer variance a lot, then we could do better. It also strikes me that the minimuminnerlength is sort of in tension with the idea of compression - if a server has to set the minimuminnerlength to 300ish to handle clients that don't compress, then clients that do compress either don't get the benefit or have to ignore the minimuminnerlength.
I don't think this PR works. The server does not have enough information to report a useful value, and the value the server reports is not useful to maintain good anonymity sets. The server does not know that the client supports some large extension or key share type (or lots of cipher suites, ALPN protocols, etc). are especially fun. It also doesn't know which extensions the client will compress from the outer ClientHello and which it will reencode. Conversely, the value the server sets isn't useful. If the client implementation has a smaller baseline compression and extensions, we waste bytes without much benefit. Worse, if the client implementation has a larger baseline compression and extensions, this PR regresses anonymity. The ClientHello will then exceed and we don't hide the lengths of the sensitive bits. Stepping back, we want to hide the distribution of ClientHelloInner lengths within some anonymity set. Most of the contributors to that length come from local client configuration: how many ciphers you support, what ALPN protocols, etc. The client is the one that knows, e.g., it sometimes asks servers for protocols A and B and sometimes for A and C. It largely has enough information to pad itself. The main exception is the server name. Realistically we need to trim anonymity sets down to colocated services, and the client doesn't know that distribution of names. Thus, we want servers to report the value in ECHOConfig. Maybe we'll need more such statistics later, which is what extensions are for. It's annoying this is a bit complicated, but we've signing up to encrypt far more things now. I should note this presumes an anonymity set of similarly-configured clients. I think, realistically, that's all we can say rigorous things about. It's nice to reduce visible artifacts of configuration, which is why we additionally round up to multiples of 16, but that's something we can burn into the protocol without ECHOConfig support.
Hiya, Sorry, not seeing that last. The PR just says (or was meant to say) to pad to some multiple of 16 in that case which I agree isn't much guidance, but does allow doing something that works. (As well as allowing things that don't work well;-) I agree that all this really needs to be driven by the client. Well, yes and no. I don't believe a server config is useful for that, (as I've argued before and still do;-) ISTM the max server name value will almost always be set to 254. May as well tell the client to pad as do that IMO. Not quite sure if I agree with that last para or not TBH! S.
Well, if we were satisfied just padding names to a multiple of 16, we wouldn't need any of this. We'd just say to pad to a multiple 16 and move on. :-) In the current name-focused spelling, the client is always able to apply a smarter padding decision based on the server's knowledge of the name distribution. With this PR, clients whose local configuration exceeds or is near lose this and hit the baseline multiple of 16 behavior. Clients whose local configuration is decently below do hide the name distribution, but using many more bytes than they would with the current text. We have some metrics in Chrome on the distribution of DNS names. It's nowhere near 254. But, regardless, if you don't believe a server config is even useful for the name and agree with me that other extensions ought to be client-driven, I'm confused, why this PR? This PR seems to go in the opposite direction. Hehe. Which part?
HIya, Yes. That's IMO the downside of having any server config. (To answer your question below, I prefer not having any server config at all but proposed this as I think it's better than draft-06.) Having also looked at some passive DNS stuff, I fully agree. But ISTM for many scenarios the entity that generates the ECHOConfig won't know the distribution of names in use (e.g. whoever configures OpenSSL won't, same with Apache etc.) so it's likely they'll have to go for whatever is the max (i.e. 254). Same is true for anyone with a wild-card server cert in play somewhere. See above. I'm trying for either a modest improvement over draft-06 or for us all to arrive at a real improvement by ditching the server config entirely:-) I like the last sentence. I think I dislike the 1st:-) Cheers, S.
It's not a downside of the draft-06 formulation, is it? The client learns something targeted to the name and can pad accordingly. Even with a wildcard server cert, the server should still know the distribution. For instance, isn't going to see anything terribly long most of the time. (Looks like the registration limit is 39 characters.) For reference, this is how long a 254-character hostname is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa In order to enjoy wide adoption, ECHO can't be too much of a waste of resources. I think it thus makes sense to target a different maximum here. I guess my view is that, because of this issue above, this is a regression over the draft-06 formulation, even though it looks more general.
Hiya, Draft-06 assumes that no other inner CH content has the property that server guidance will help. My claim is that that guidance is useless in practice, and therefore unnecessary. I think the server config'd length in the PR is a little less useless:-) Some servers will. Some will not. Many (most?) server ECHOConfig instances will make use of default settings. Those'll pick 254 because adding a new VirtualHost to an apache instance (or similar) won't be co-ordinated with making a new ECHOConfig in general. And even it it were, (but it won't!) we get a TTL's worth of mismatch. If we don't provide a way for clients to handle the case where the server config is too short, again servers will publish 254. I am more interested in random smaller web sites/hosters myself. I think ECHO should work for those as well as we can make it, (albeit with smaller anonymity sets), and this tie between web server config and ECHOConfig is just a bad plan for such. AFAIK, all current deployments do just that. To be fair, that's largely driven by CF's draft-02 deployment, but I think that backs up my argument that if there's a max, that'll almost always be chosen, which implies it's a useless field that leads to the inefficiency you note. Then it can't be the max:-) The 254 value matches the max for servername IIRC. Ok. We disagree. But what do you think the client should do? Draft-06 is IMO plainly incorrect in that it says to pad in a way that'd expose other lengths should those be sensitive. If your answer were pad the SNI to at least ECHOConfig.maximumname_length and then make the overall a multiple of 16, with as many added 16 octets blocks as the client chooses, then a) that's != draft-06 and b) is quite close to this PR and c) just failing if the actual SNI in the inner CH is longer than the config setting seems quite wrong to me and d) hardcodes the assumption that SNI is the only thing where the server may know better. Cheers, S.
If we come up with other places where server guidance is useful, that can be addressed with extensions. But, gotcha, I suppose that is where we disagree. I think server guidance on the overall ClientHello size is entirely useless, while server guidance on the name is may be useful. Agreed that it should also work for smaller things. I don't follow how this PR helps in that regard. It seems they still need to come up with a random value or a default, but now it's even less clear how to set it well. Er, yes, sorry I meant to say target a different public length. That is, 254 is so far from the maximum domain name in practice (As it should be! Hard length limits ought to be comfortably away from the actual requirement.), so padding up to it is wasteful. I think it would be better to pad up to a tighter value and, if we exceed it, accept that we only have the fallback multiple of 16 padding. (Or maybe a different strategy.) It does result in smaller anonymity sets in edge cases, but I think that a reasonable default tradeoff given other desires like broader deployment and not wasting too much of users' data. I'm thinking something along the lines of: For each field, determine how much it makes sense to pad given what kinds of things it sends. If it varies ALPN, maybe round up to the largest of those. Most of this can be determined without server help. For fields where server help is useful, like the name, apply that help. Right now it's simply a function. I'm also open to other strategies. Sum all that padding together. In order to generally reduce entropy across different kinds of clients, maybe apply some additional overall padding, like rounding up to a multiple of 16, which cuts down the state space by 16x and doesn't cost much. (Or maybe we should round up to the nearest ? That avoids higher resolution on longer values while bounding the fraction of bytes wasted by this step.) That said, it's worth keeping in mind that clients already vary quite a bit in the cleartext portions of the ClientHello. There's a bit of tension between wanting to look like the other clients and wanting to ship new security improvements. This is different from this PR because this PR asks the server to report a value including things it doesn't know anything about (how large the client-controlled parameters are). I don't quite follow (c). It seems this PR and the above proposal has roughly the same failure modes when something is too long. The difference is that 's failure mode is only tripped on particular long names (something the server knows the distribution of), while this PR's equivalent failure mode is based on factors outside the server control, yet the server is responsible for the value.
Clarification: this is for each field where the client doesn't reference the outer ClientHello. If the client wishes to do that, it means the client doesn't consider that field secret so there isn't anything to pad.
I like NAME suggested algorithm, as an ideal padding function requires input from both the client and server. (Ideally, servers would send padding recommendations for each extension that might vary specifically for them, such as the server name. They don't have insight into anything else, so clients need to make padding decisions based on local configuration.) NAME what do you think?
Could live with it, but still prefer no server config. I'm looking a bit at some numbers and will try make a concrete suggestion later today. If I don't get that done, it seems fair to accept NAME algo and move on. Cheers, S.
If we can get away with no server config, I'm also entirely happy with that. Fewer moving parts is always great. We certainly could do that by saying names are padded up to 254, but I think that's too wasteful. But if we're happy with some global set of buckets that makes everyone happy (be it multiples of 16, some funny exponential thing), great!
(trimming violently and responding slowly:-) So your steps 1-6 is a better scheme than draft-06. I still think step 2 would be better as something like: ECHOConfig contains maxnamelen as before but we RECOMMEND it be zero and a) if the name to be padded is longer than maxnamelen, then names will be padded as follows: P=32-(len(name)%32)+headsortails*32, or b) if the name to be padded is shorter than maxnamelen then we just do as the server asked and pad to that length. That (hopefully:-) means a default of "pad out to the next multiple of 32, then toss a coin and add another 32 if the coin landed as heads." If we landed somewhere there, I'd be happy to make this PR say that or to make a new one or whatever. According to some data I have the CDFs for names and for these padded lengths would be as follows: Len, CDF, Padded-CDF 32, 81.28, 40.64 64, 97.87, 89.57 96, 99.31, 98.59 128, 99.87, 99.59 That means that 81.28 of names are <32 octets long and 40.64% of name+namepadding will be 32 octets long. 97.87% of names are <64 octets and 89.57% of name+namepadding are 64 octets long. I think we should RECOMMEND setting maxnamelen to zero unless an ESNI key generator has a specific reason to set it to a non-zero value. ISTM the use-case for non-zero values is where the anonymity set has only a few very long names that with length differences of ECHO. I'm basically fine that we default to not serving that use-case wellmby default, as I don't believe it's real. (But I could be wrong;-) Cheers, S.
Could the sender always pad their packets to at least 1200 bytes or something, using an encrypted extension in the ClientHello? I don't understand the focus on server input to a padding function that would ideally fill out one packet.
NAME what's the value in adding zero or one 32B blocks after rounding? Why not just stick with what was done, say, in RFC8467? (We could make it read something like, "clients may add zero or one blocks." Either way, I'm more or less fine with the suggested change. Would you mind updating this PR to match?)
Per above, clients could use help from servers in choosing appropriate padding lengths. (Only servers know their name anonymity set.)
Hiya, Say if the anonymity set has lots of names <32 length (~81% of names in the data I have) but a small number between 32 and 64 (~16% in my data). Then this should disguise the use of the longer names at the expense of sending more octets. Would be v. happy to know if that made sense to others. Cheers, S.
A friendly amendment below (but one I think is important)... I think that last really needs to be "Only servers can know their name anonymity set. But many servers will not know that, either due to wildcard certs or because names/vhosts are added and removed all the time independent of whatever is in the DNS." Cheers, S.
It makes sense, I'm just not not sure it's worth the cost. That said, this will always be an imperfect solution, so I'm happy either way.
Yep. Me neither. It is cheaper than padding to 254 octets for everyone though;-) Partly, I'm not that sympathetic towards anyone who wants to hide a crazily-long server_name. OTOH, I guess there may be a few who can't easily change names so we probably ought try do something for 'em. Cheers, S.
Agree that only servers could know their name anonymity set. But what is the cost of always padding out the ClientHello so it approaches the MTU? Just trying to understand why the spec attempts to economize on the number of bytes in the ClientHello packet.
As far as I know, there's no reason other than folks might not want to always "waste" these bytes.
Padding the ClientHello up to an MTU isn't free. See the numbers here on what a 400-byte increase costs. URL Likewise, also from that post and a , post-quantum key shares will likely exceed a packet anyway. I think our padding scheme should be designed with that expectation in mind (e.g., the mechanism fails this because a PQ key share in the inner ClientHello will blow past the built-in server assumptions on client behavior). Canary builds of Chrome already have code for such a thing behind a flag. Edit: Added a link to the later experiment, which I'd forgotten was a separate post.
It's not quite clear what's going on in those results. For example, the mobile results are close to zero. Without seeing confidence intervals, and the distributions of the full packet sizes, I don't think this experiment settles this issue (although it could, with more detail). Also, is there a theory on /why/ 400 bytes might add latency? If we're going to design the padding mechanism with PQ key shares in mind, but not conventional ones, that should be in the document.
NAME would know the details of that experiment, but I don't think the idea that sending more bytes takes more time would be terribly surprising! :-P I don't think anyone's suggested designing without conventional key shares in mind. They are what's deployed today, after all. However, we shouldn't design only for a small unpadded ClientHello. PQ key shares will need larger ones. Session tickets also go in the ClientHello, and it's common for TLS servers to stick client certificates inside tickets, so you can already get large ones today already.
Let's assume the results for "SI" in the first link actually do show a significant delta. The question is whether per-packet costs dominate or per-byte costs do, and whether the experiment sometimes increased the number of packets (e.g. by sometimes bumping the ultimate ClientHello size above 1280). See Section 5.1 in URL for device performance metrics on bytes vs packets. Looking at the ClientHello traffic on my computer, I can see that Safari is sending ClientHello messages that are about 500-600 bytes. My copy of Chrome seems to be sending CurveCECPQ2 (16696?) shares, and its ClientHello messages are fragmented.
NAME will you be able to update this as above?
would the spec allow me to put an arbitrarily-sized extension in the encrypted part of the ClientHello? if so, I don't care about the padding schemes.
Yes, of course! The padding policies described here are guidance at best.
I've updated the PR to try reflect the discussion above. Please take a peek and see if it seems useful now.
This looks like the right idea. I'll review this again as well, but it's probably better to wait for NAME suggestions to be addressed.
Thanks for all the changes Chris. I think I've actioned all those as requested. If not, I tried, but failed:-)
NAME do you need any help moving this forward?
Doing other stuff today but feel free to take the text and then do more edits. Or I can look at it tomorrow. Either's fine by me. S.
Thanks for taking the time. None of my comments are strongly-held opinions (meaning they only need to be addressed at all if others agree that the issues are important).
Strong +1 to NAME -- thank you for the work here, NAME
NAME can you please resolve conflicts? NAME NAME can you please review?
Fair point. The argument I'd make for keeping this is that if an anonymity set has ~80% of names <32 octets, then if we do nothing, passive observation will probably reveal when the server name is in the longest ~20%. And I'd guess that only a few names in that set would be popular/common, so we could be giving away the game whenever an ECHO is 32 octets longer than the usual. The random padding could mitigate that passive attack but yes would be vulnerable to an active reset based counter. I'd also be fine with just living with the issue in which case we might want to note that using ECHO with uncommonly long names is a bad idea.
Let's just drop the random addition. Servers don't (can't) do a padding check anyway, so clients can always choose to make this longer if desired.
NAME can you update this PR and resolve the conflicts?
"Fair point. The argument I'd make for keeping this is that if an anonymity set has ~80% of names <32 octets, then if we do nothing, passive observation will probably reveal when the server name is in the longest ~20%. " Which is precisely why we want the server to provide the longest name, so the client can pad to it.
As discussed on today's call, let's do the following: Resolve merge conflicts. Drop random padding for the SNI. And add text which says that if the client's name is larger than maxnamelength, it rounds up to the nearest 32B or 64B boundary. NAME do you need, or would you like, any help with this?
I think that this approach is generally better, but it runs afoul of divergence in client configuration that could dominate the calculation. For instance, a client that sends two key shares will have very different padding requirements to one that sends only one. For that to work, we need to assume that implementation-/deployment-specific variation of the inner CH is largely eliminated as a result of the compression scheme we adopt. That also assumes that these variations in client behaviour are not privacy-sensitive. I think that we should be directly acknowledging those assumptions if that is indeed the case. If there is a significant variation in size due to client-specific measures, then we're in a bit of an awkward position. That might render any similarly simple scheme ineffective. For instance, a client that later supports a set of ALPN identifiers that could vary in length depending on context cannot use this signal directly. It has to apply its own logic about the padding of that extension. That a client is doing this won't be known to a server that deploys this today. In that case, the advice from the server (which knows most about the anonymity set across which it is hoping to spread the resulting CH), isn't going to be forced through an additional filter at the client. The results are unlikely to be good without a great deal of care.I am generally fine with this, with the exception of the random padding, which I think should be omitted. It's hard to analyze and the value is unclear. In particular, many clients will retry if they receive TCP errors, and so the attacker can learn information about the true minimum value by forging TCP RSTs and looking at the new CH.

7.2. <ins> Future extensions could reveal sensitive information through their length.  Consequently, padding should be flexible and support arbitrary extension changes. For each field in the inner ClientHello, clients need to determine how much to pad given the semantics of that field.  For example, if a client can propose various ALPN values, it could add padding to round up to the longest of those. The target padding length of most ClientHello extensions can be determined without server help.  However, the "server_name" extension could benefit from server input (ECHOConfig.maximum_name_length). Clients SHOULD compute the padding for this extension as follows: If ECHOConfig.maximum_name_length is longer than the actual server_name then clients SHOULD add padding to make up that difference. Otherwise, if ECHOConfig.maximum_name_length is zero or less than the length of the actual server_name then round the server_name up to a multiple of 32 octets and randomly add another 32 octets 50% of the time and then include that amount of additional padding. The amount of padding applied to the ClientHello is then computed as the sum of all per-extension padding values, rounded up to the nearest multiple of 32.  (This additional rounding step aims to hide variance across different client implementations.) In addition to padding ClientHelloInner, clients and servers will also need to pad all other handshake messages that have sensitive- length fields.  For example, if a client proposes ALPN values in ClientHelloInner, the server-selected value will be returned in an EncryptedExtension, so that handshake message also needs to be padded using TLS record layer padding. 7.3. </ins> As described in server-behavior, the server MAY either accept ECHO and use ClientHelloInner or reject it and use ClientHelloOuter. However, there is no indication in ServerHello of which one the server has done and the client must therefore use trial decryption in order to determine this. <del> 7.2.1. </del> <ins> 7.3.1. </ins> If the server used ClientHelloInner, the client proceeds with the connection as usual, authenticating the connection for the origin server. <del> 7.2.2. </del> <ins> 7.3.2. </ins> If the server used ClientHelloOuter, the client proceeds with the handshake, authenticating for ECHOConfig.public_name as described in