Closed huitema closed 5 years ago
Thank you for your comments.
Servers can only assess the ESNI content after receiving the Initial content, but receiving it requires decrypting the data. My implementation uses a standard call to the AEAD library for that. The ESNI content is not known at the time of the AEAD call, and the AEAD checksum is going to not verify.
I think this is an API issue. For the API you are using (picotls!) I can provide you a nice API that deals with this. And generally speaking, people can rely on AES-CTR API to decrypt the packet payload, process ClientHello, then use GCM API to verify the packet.
Having that said, I am fine with suggesting AES-CTR + HMAC rather than AES-GCM as the preferable approach (see the Considerations section), if that helps people.
There are several ways out of that, but I think the simplest way is to add some kind of ESNI proof in a the server response. I don't think it can be sent as a TLS extension, because in server's first flight the extension are encrypted. QUIC will send them as handshake packets, which means they cannot be used to protect the Initial packet. The simplest solution is probably to invent an "ESNI proof" frame, that should be conveyed in the Initial packet if the ESNI extension is accepted.
I do not think that is the correct approach. Because a man-on-the-side attacker can still race Initial packets. For example, an attacker can race a spoofed Initial packet to the server containing the correct ClientHello and a corrupt ACK frame. Or the attacker can race a spoofed Initial packet that contains an invalid handshake message to the client. We would be required to have all the special cases for dealing with invalid Initial packets (or frames being contained), and also about distinguishing connection based on the hashed value of Client Hello.
All these band-aids that people were concerned goes away only if we protect all the Initial packets, from the first Initial packet that the client sends.
I think that the band aid go away if we make a set of changes, mostly along the lines of the "atomic initial" design. With that design, we only need a proof that the server hello comes from the intended destination.
I don't like to fold that proof into the AEAD authentication, at least not in the packets sent by the client. It can probably work for the packet sent by the server, because the client could predict it. But we have to specify that,
I think that the band aid go away if we make a set of changes, mostly along the lines of the "atomic initial" design. With that design, we only need a proof that the server hello comes from the intended destination.
Are saying that you would be fine if we change the specification to use AES-CTR for obfuscation + HMAC based on ESNI shared key? If that is not the case, I would appreciate it if you could elaborate what you mean by "atomic initial".
Assuming that the former is the case, I think we should change the protection of Initial sent in both directions to use HMAC instead of GCM. That's more natural, because then the strength of the protection would depend on the cipher-suite negotiated using ESNI.
Yes that will work. But it requires a different version number, and sticking out that way is definitely a problem.
Have you considered sending the client Initial using the default protection, and only sticking the AAD in the responses from the server? It is effectively a client side rekeying upon reception of the initial packet from the server, but it would have the advantage of being compatible with the current spec.
Yes that will work.
Thank you for the clarification.
Have you considered sending the client Initial using the default protection, and only sticking the AAD in the responses from the server? It is effectively a client side rekeying upon reception of the initial packet from the server, but it would have the advantage of being compatible with the current spec.
I had not considered that. It's interesting, but I think there are downsides.
If using the same QUIC version number is a MUST, I think I prefer doing trial decryption on the server-side for the Initial packets, because it's actually better than an ordinary "trial decryption." A server would AEAD-decrypt the initial (in the way defined in v1), and if tag verification fails, treat it as an authenticated Initial packet. Because you would have the decrypted payload at that point (due to failed AEAD decryption), you can immediately process the ClientHello being contained, and if that succeeds verify the payload tag as HMAC.
However, due to the following reasons, I do not think using a different QUIC version number is an issue we need to be worried of.
To conclude, I think using different QUIC version number is the best solution. But I am fine with adding either or both the alternative approaches (i.e. rekeying and trial decryption) to the Considerations section. WDYT?
At this stage, yes, adding more text in the consideration section makes sense. Having a first draft now will be nice, because then we can have at least two implementations and test interoperability.
Agreed. I will swap the algorithm being discussed in the main section to AES-CTR + HMAC, and add text to the Considerations section.
Done in commits up to 9aa465a. PTAL.
You propose to use the ESNI secret as input to the key generation for the "Initial" context. This is a significant departure from standard QUIC, and I am concerned that we have a circular dependency. Servers can only assess the ESNI content after receiving the Initial content, but receiving it requires decrypting the data. My implementation uses a standard call to the AEAD library for that. The ESNI content is not known at the time of the AEAD call, and the AEAD checksum is going to not verify.
There are several ways out of that, but I think the simplest way is to add some kind of ESNI proof in a the server response. I don't think it can be sent as a TLS extension, because in server's first flight the extension are encrypted. QUIC will send them as handshake packets, which means they cannot be used to protect the Initial packet. The simplest solution is probably to invent an "ESNI proof" frame, that should be conveyed in the Initial packet if the ESNI extension is accepted.