> On Sep 17, 2024, at 5:28 PM, David Benjamin 
> <davidben=40google....@dmarc.ietf.org> wrote:
> 
> Ah, I just noticed this text at the end of Section 7.1:
> 
> > Note that in some cases it may be necessary to send an ACK which does not 
> > contain any record numbers. For instance, a client might receive an 
> > EncryptedExtensions message prior to receiving a ServerHello. Because it 
> > cannot decrypt the EncryptedExtensions, it cannot safely acknowledge it (as 
> > it might be damaged). If the client does not send an ACK, the server will 
> > eventually retransmit its first flight, but this might take far longer than 
> > the actual round trip time between client and server. Having the client 
> > send an empty ACK shortcuts this process.
> 
> https://www.rfc-editor.org/rfc/rfc9147.html#section-7.1-8
> 
> I guess then the intent is indeed that if you receive some random encrypted 
> DTLS 1.3 header, even though you don't know it's DTLS 1.3 yet, you interpret 
> as activating the ACKing mechanism? But that seems to prompt more questions 
> than it answers. For instance, what happens if you do that, but then finally 
> receive the ServerHello and it turns out this was just some junk packet and 
> we're really negotiation DTLS 1.2? Do you check that the ACK mechanism has 
> been activated and return an error? Do you just pause the ACK mechanism and 
> hope you're in an OK state? This seems quite prune to send the implementation 
> into unexpected and untested states.
> 
> 


Yeah, I think this has missed a nasty corner case here for implementations that 
support both. 

I think I also lean towards option A) (from below) here. Anyone else who has 
gotten at least their hands mildly dirty in a DTLS implementation that supports 
both 1.2 and 1.3 care to chime in as well? 


> On Thu, Sep 12, 2024 at 4:31 PM David Benjamin <david...@google.com> wrote:
> Hi all,
> 
> I noticed another issue with the DTLS 1.3 ACK design. :-)
> 
> So, DTLS 1.3 uses ACKs. DTLS 1.2 does not use ACKs. But you only learn what 
> version you're speaking partway through the lifetime of the connection, so 
> there are some interesting corner cases to answer. As an illustrative 
> example, I believe the diagram in section 6 is [probably] incorrect:
> https://www.rfc-editor.org/rfc/rfc9147.html#section-6
> 
> If the client loses the first packet, it never sees the ServerHello and thus 
> learns it's speaking DTLS 1.3. While it does see the second packet, that 
> packet only contains ciphertext that it cannot decrypt. Unless it decides to 
> say "this looks like a 1.3 record header, therefore I will turn on the 1.3 
> state machine", which isn't supported by the RFC (maybe TLS 1.4 will use the 
> same record header but redo ACKs once again), it shouldn't activate the 1.3 
> state machine yet. I expect what will actually happen is that the client will 
> wait for the retransmission timeout a la DTLS 1.2.
> 
> More generally, I believe these are the situations to worry about:
> 
> 1. If a DTLS 1.2 (i.e. does not implement RFC 9147 at all) implementation 
> receives an ACK record for whatever reason, what happens? This decision we 
> don't get to change. Rather, it is a design constraint. Both OpenSSL and 
> BoringSSL treat unexpected record types as a fatal error. I haven't checked 
> other implementations. So I think we must take as a constraint that you 
> cannot send an ACK unless you know the peer is 1.3-capable.
> 
> 2. Do plaintext ACKs exist? Or is the plaintext epoch permanently at the old 
> state machine? Honestly, I wish the answer here was "no". That would have 
> avoided so many problems, because then epochs never change state machines. 
> Unfortunately, the RFC does not support this interpretation. Section 4.1 
> talks about how to demux a plaintext ACK, and section 6, though wrong, 
> clearly depicts a plaintext ACK. So instead we get to worry about the 
> transition within an epoch. Keep in mind that transitions happen at different 
> times on both sides. Keep in mind that there is a portion of the plaintext 
> epoch that lasts after version negotiation in HelloRetryRequest handshakes.
> 
> 3. If a 1.3-capable server receives half of a ClientHello, does it send an 
> ACK? I believe (1) means the answer must be "no". If you haven't read the 
> ClientHello, you haven't selected the version, so you don't know if the 
> client is 1.3-capable or not. If the client is not 1.3-capable, sending an 
> ACK may be incompatible.
> 
> 4. Is it possible for a 1.3-capable client to receive an ACK before it 
> receives a ServerHello? If so, how does the client respond? I believe the 
> answer to this question, if plaintext ACKs exist, is unavoidably "yes". 
> Suppose the server receives a 1.3 ClientHello and then negotiates DTLS 1.3. 
> That is a complete flight, so Section 7.1 discourages ACKing explicitly (you 
> can ACK implicitly), but it does not forbid an explicit ACK. An explicit ACK 
> may be sent if the server cannot generate its responding flight immediately. 
> That means a server could well send ACK followed by ServerHello. Now suppose 
> ServerHello is lost but the ACK gets through. Now the client must decide what 
> it's doing. Rejecting the ACK would result in connection failure, so we must 
> either drop the ACK on the floor, or process it. While processing it would be 
> more efficient (you don't need to retransmit the whole ClientHello), it means 
> the plaintext epoch must support this hybrid state where 1.3 ACKs are 
> processed but never sent! Or perhaps receiving that ACK transitions you to 
> the 1.3 state machine even though you don't know the version yet. That all 
> sounds like a mess, so I would advocate you simply drop it on the floor.
> 
> 5. If a 1.3-capable client receives half of the server's first message (HRR 
> or ServerHello), does it send an ACK? Again, because of (1), I believe the 
> answer must be "no". If you don't know the server's selected version, the 
> server may not be 1.3-capable and may not be compatible with the ACK.
> 
> 6. What does a 1.3-capable server do if it receives an ACK prior to picking 
> the TLS version? Unlike (4), I believe this is impossible. If the client has 
> something to ACK, the server must have sent something, which the server will 
> only do once it's received the full ClientHello and thus picked the version. 
> However, given (4), I suspect an implementation will naturally just drop that 
> ACK. In this state error vs drop is kinda academic.
> 
> From what I can tell, RFC 9147 is silent on all of this. I think it should 
> say something. I believe these are the plausible options:
> 
> OPTION A -- There are no ACKs in epoch 0.
> 
> We avoid this ridiculous transition point and say that ACKs only exist 
> starting epoch 1. Epoch 0 uses the old DTLS 1.2 state machine. This is very 
> attractive from a simplicity perspective, but since RFC 9147 was already 
> published with this ambiguity, I think we need to, at minimum, say that DTLS 
> 1.3 implementations drop epoch 0 ACKs on the floor. It also means that packet 
> loss in HelloRetryRequest flows may be less efficient. That said, if your 
> HelloRetryRequest is stateless (not applicable to all DTLS uses), you're 
> probably not doing anything with ACKs anyway. Saying those ACKs avoids having 
> to think about that case, at the cost of a worse transport for stateful 
> HelloRetryRequest.
> 
> OPTION B -- Epoch 0 enables ACKing once the version is learned.
> 
> Once you know the version, you start sending and processing ACKs. Before you 
> know the version, you drop ACKs on the floor and never send them. This 
> requires convincing ourselves that the transition point works out, notably 
> when one side is still ACK-less and the other side is still ACK-ful, but I 
> believe it works out.
> 
> OPTION C -- Epoch 0 always receives and acts on ACKs, but it doesn't send 
> ACKs until the version is learned.
> 
> This is the same as above, but instead of dropping ACKs, you go ahead and let 
> that drive your state machine. But you don't send them. This makes reasoning 
> about the protocol even more complicated because there are even more states 
> you can be in w.r.t. your known version vs the state of your transport. It 
> does improve behavior around packet loss, but I think it only helps this edge 
> case in question (4) above, which is already a case where servers aren't 
> expected to send ACKs anyway.
> 
> I think I lean towards Option A for simplicity, even though it decidedly 
> contradicts a lot of text in the RFC right now. That will be hard to encode 
> in an erratum as a few things need to change. But I also have 7 other eratta 
> open against this document, so maybe it's time for rfc9147bis.
> 
> David
> _______________________________________________
> TLS mailing list -- tls@ietf.org
> To unsubscribe send an email to tls-le...@ietf.org

_______________________________________________
TLS mailing list -- tls@ietf.org
To unsubscribe send an email to tls-le...@ietf.org

Reply via email to