Subject: Re: [TLS] DTLS 1.3 ACKs

From: Ilari Liusvaara <[email-masked]>
Date: Sat, 1 Jul 2017 20:01:03 +0300

On Sat, Jun 24, 2017 at 12:05:44PM -0700, Eric Rescorla wrote:
> On Sat, Jun 24, 2017 at 9:47 AM, Ilari Liusvaara <[email-masked]>
> wrote:
> 
> It seems ACKs work in terms of RSNs. This generates a weirdness that
> > a fragment can be known with multiple IDs, in case a packet gets
> > delayed enough to trigger retransmission but the original is then
> > accepted. But OTOH, retransmission at fragment granularity is useful
> > with potentially "obese" messages like Certificate.
> >
> 
> This is the calculation I made as well. Note that removing aliasing in this
> fashion actually is useful in measuring packet loss (this is what QUIC
> does).

IMO, since handshake only occurs once per connection and DTLS needs to
be implemented on all kinds of constrained devices (on both client and
server sides), simplicity is more important than performance. Also,
packet loss estimates do not seem useful: There are far too few packets
to get useful statistics.

-Ilari

---

From: Eric Rescorla <[email-masked]>
Date: Sat, 1 Jul 2017 10:26:17 -0700

> to get useful statistics.

I think we definitely want to allow acknowledgements of subcomponents of
messages, because otherwise you have to retransmit the entire message,
which is painful in the case of the obese messages. This seems to leave
one with the option of acknowledging either fragments (which we then
need to invent labels for) or records (which already have labels
but need a map of RSN to fragment). My feeling is that on balance the
latter is a better choice, but I'll have a better sense once we've
implemented....

-Ekr

---

From: Ilari Liusvaara <[email-masked]>
Date: Sun, 2 Jul 2017 00:00:00 +0300

> latter is a better choice, but I'll have a better sense once we've

Just noticed that DTLS allows packing multiple independent fragments
into one record (and then multiple records into one packet).

Which impiles that an implementation that only prcesses one message at
a time is not guaranteed to even be able to generate a valid list of
RSNs to ACK, in case the peer sends sufficiently twisted (but still
seemingly in-spec) input.

What's the alert code for dropping in-spec connection detected as
attack traffic? :-)

-Ilari

---

From: Eric Rescorla <[email-masked]>
Date: Sat, 1 Jul 2017 15:52:37 -0700

> seemingly in-spec) input.

I'm not following how that's true. When you decrypt, you record the received
RSNs and when you send an ACK you send the entire list. Then when you
finish a flight, you reset the list. Can you maybe show me a sequence of
events
that would cause an error here?

-Ekr

---

From: Ilari Liusvaara <[email-masked]>
Date: Sun, 2 Jul 2017 10:54:16 +0300

On Sat, Jul 01, 2017 at 03:52:37PM -0700, Eric Rescorla wrote:
> events that would cause an error here?

I think I figured out a case that doesn't involve peer intentionally
generating very dubious input:

Suppose that certificate is rather big (needs spliting to four parts),
and:

* The server preprares its flight, giving:

- RSN 2:0 -> EncryptedExtensions, Certificate part 1/4
- RSN 2:1 -> Certificate part 2/4
- RSN 2:2 -> Certificate part 3/4
- RSN 2:3 -> Certificate part 4/4, CertificateVerify, Finished.

* Now, RSNs 2:1, 2:3 disappear, 2:0 and 2:2 make it through.

* Client ACKs RSNs 2:0 and 2:2.

* Server sees the ACK, and re-encrypts the offending packets:

- RSN 2:4 -> Certificate part 2/4
- RSN 2:5 -> Certificate part 4/4, CertificateVerify, Finished.

* Now, RSN 2:4 disappears, 2:5 makes it through.

* Client is one-message at a time. It can't ACK anything new. RSNs 2:1,
  2:3 and 2:4 are lost.  RSN 2:5 can not be ACKed, because that would
  imply the client received CV and F, which it did not.

-Ilari

---

From: Eric Rescorla <[email-masked]>
Date: Sun, 2 Jul 2017 12:30:09 -0700

>   imply the client received CV and F, which it did not.

Thanks for clarifying your case. I think what you're assuming here is
that when the client receives out of order handshake messages, it discards
them rather than buffering them. Is that correct? In that case, yes, it
should
pretend it didn't get the records as well, and I think the right answer
would
be to not generate a new ACK and rely on the server's retransmission timer
(which needs to run anyway).

-Ekr

---

From: Ilari Liusvaara <[email-masked]>
Date: Sun, 2 Jul 2017 23:13:24 +0300

On Sun, Jul 02, 2017 at 12:30:09PM -0700, Eric Rescorla wrote:
> them rather than buffering them. Is that correct? 

Yes, that is what one message at a time means.

> In that case, yes, it
> should pretend it didn't get the records as well, and I think the right
> answer would be to not generate a new ACK and rely on the server's
> retransmission timer (which needs to run anyway).

One thing to note that there is no way for either side to say: "I
received _something_, but nothing useful". One could presumably trigger
fast retransmit on that. However, using that to trigger fast retransmits
of ServerHello might be a bit dubious...

There can also be interactions with giving up on fragment transmissions
(in order to limit memory usage).

Suppose similar case as before, but 2:1 gets lost instead of disappearing,
and is found after 2:5 is received by the client.

The client will then generate second ACK, which ACKs 2:1. The server then
receives the ACK and has no idea what the client is talking about, since
server has dropped the state. But presumably fast-retransmits 2:4 and 2:5,
now as 2:6 and 2:7 (3rd transmission for both).

-Ilari

---

From: Eric Rescorla <[email-masked]>
Date: Sun, 2 Jul 2017 14:00:51 -0700

> Yes, that is what one message at a time means.

Well it could mean other things. That's why I asked.

> received _something_, but nothing useful".

Well, we could in fact use an ACK for that, which is basically what TCP
does.

> now as 2:6 and 2:7 (3rd transmission for both).

It's not clear to me it's useful for implementations to delete state in
this case.

-Ekr

---

From: Ilari Liusvaara <[email-masked]>
Date: Tue, 4 Jul 2017 16:36:47 +0300

> It's not clear to me it's useful for implementations to delete state in

As said, this would be to limit memory usage. I suppose real cheap
implementation could check for the first missing fragment and retransmit
from that point onwards, regardless if any subsequent fragment was ACKed.

I suppose if one really wants to scrimp on state, one combine the
fragments of small messages (basically, everything except Certificate)
in fixed way (ClientHello, HelloRetryRequest and ServerHello likely fit
into one fragment, EncryptedExtensions and CertificateRequest likely
jointly fit into one record, the same for CertificateVerify and
Finished). And then assign RSNs for retrasmissions with fixed base
(which impiles that RSN sequence might have gaps).

-Ilari