Subject: [TLS] DTLS 1.0 and DTLS 1.2 issues with retransmission

From: Nikos Mavrogiannopoulos <[email-masked]>
Date: Sat, 19 Feb 2011 17:50:21 +0100

Hello,
 While trying to implement DTLS 1.0, I had some issues
with the way DTLS handles packet loss and retransmission
during the handshake process. There is not an
explicit acknowledgement per packet flight,
but rather, an implicit acknowledgement is done
by waiting for the the peer's next flight.

This however has the following issues:
1. Retransmission timers depend on the time required
for the peer to do calculations (if an explicit
ACK is used then the timers only depend on peer's
packet processing).

2. The last message sent by the client expects
no reply from the server, thus there is not
an implicit ACK.

DTLS 1.2 tries to solve issue 2, by reading the next
packet, checking whether it is application data, or
handshake data, and if it is the latter retransmit.

I find the above solution a hack, rather than a
solution. That is because:
* the retransmission code might have to receive and parse a
packet (Application data) that is not intended for it,
blurring the separation of the handshake process and the
application data protocol.

* If a packet (application data) is not received then
the retransmission code has to wait for an unspecified
amount of time for the peer's retransmission to occur (if
packet was lost).

For these reason I'd suggest to add explicit acknowledgement
packets, at least for the last packet from client.

regards,
Nikos

---

From: Eric Rescorla <[email-masked]>
Date: Sat, 19 Feb 2011 17:48:43 -0800

> by waiting for the the peer's next flight.

Hi Nikos,

I'm glad to hear you're implementing DTLS.

> ACK is used then the timers only depend on peer's

I agree that this is true, but I don't think it's really a big deal.
You should be using
initial retransmit times in the area of 200-500 ms, and this is really
a lot faster than
pretty much any computation the other side would be expected to do. And even in
the worst case, if you assume processing time is 0 you just end up
doing a spurious
retransmit. That doesn't seem bad.

> no reply from the server, thus there is not

You must mean during resumption, since in the full handshake, the last
message from
the client is ACKed by the server's Finished. Regardless, I don't
understand why this
is an issue: both sides maintain retransmission timers and so if you
sent message
A and expect B and you don't get it, you retransmit A. So, in this
case the server
would retransmit his Finished in the expectation that the client would
respond by
resending the client's Finished. Obviously, someone has to speak last and the
other side needs to enforce the receipt of the last message, but
there's nothing unusual
about that.

Can you explain why this isn't adequate?

> handshake data, and if it is the latter retransmit.

For the reasons above this seems to me to be merely an optimization to
shortcut the
timer above.

-Ekr

---

From: Nikos Mavrogiannopoulos <[email-masked]>
Date: Mon, 21 Feb 2011 10:11:55 +0100

On Sun, Feb 20, 2011 at 2:48 AM, Eric Rescorla <[email-masked]> wrote:

Hello and thank you for the reply. Please don't take my comments
as vicious or so, they just reflect my point of view after working on
implementation. This might be different but not necessary better.

> retransmit. That doesn't seem bad.

Indeed. I just didn't like that the retransmission timers are (and
cannot be) specified precisely and they are left to the implementor,
who is not more qualified to specify them.

> Can you explain why this isn't adequate?

Sorry I meant on server side.. Also in that case I think that the timers should
be more precisely specified. For how long should a server wait for a client
to resend? If a client has a retransmit timer of 2 seconds, and I wait for only
1, then the protocol negotiation will fail. Since there is not an
explicit negotiation
of timers, there should be at least some upper or lower limits for the
implementers
to follow.

This makes the protocol look unstable, in the sense that there might be protocol
failures depending on the network status. Another issue that might be is,
if a ChangeCipherSpec is transmitted as a separate DTLS record. If received
out of order there is no way for the DTLS server or client to distinguish
whether this is a replay a future, or an old packet (there is no handshake
sequence number there). What should such a server do? I expect that ignoring
it would be the right answer but maybe the protocol should be explicit.

Also the document specifies what to do when invalid records are
received. But what
if a "lost" handshake message is received during application data exchange? I.E.

    Client                                          Server
    ------                                          ------
    Finished                -------->

[lost]                                   [ChangeCipherSpec]
[lost]                       <--------             Finished

    Finished                -------->

                                        [ChangeCipherSpec]
                            <--------             Finished

<- Application data exchange ->
[replay of lost]                             [ChangeCipherSpec]
[replay of lost]                   <--------             Finished

The ChangeCipherSpec will be rejected by record
layer since the epoch will be old, but the finished
has the correct epoch, a correct MAC, and a correct
sequence number (was not received before).

What should an implementation do then? Discard
it as a valid but unexpected message?

regards,
Nikos

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 21 Feb 2011 05:22:27 -0800

> implementation. This might be different but not necessary better.

I'm not taking them that way at all. It's really important to get this
kind of implementor
feedback. Sorry if my response didn't come off like that.

> who is not more qualified to specify them.

There is some guidance in 4.2.4.1 (1 second doubling up to 60 seconds.).
Can you give me an idea of what sort of more detailed guidance you woud
like?

> of timers, there should be at least some upper or lower limits for the

Sorry, I'm not following you here: if there is a timer mismatch this
just creates a
race condition in which case there might be a spurious retransmit. Yes, if the
sides have mismatched total duration timers, then one might kill the connection
before the other expects it, but what's wrong with that.

> failures depending on the network status.

Isn't this always true with any packet protocol, even TCP?

> Another issue that might be is,
> sequence number there).

Doesn't the epoch make this clear?

> if a "lost" handshake message is received during application data exchange? I.E.

No, it should trigger a retransmit of the last handshake message that was
sent , though the packet itself isn't processed since it's a replay
(due to the handshake sequence number). I'll see about making this
clear.

-Ekr

---

From: Nikos Mavrogiannopoulos <[email-masked]>
Date: Mon, 21 Feb 2011 15:26:10 +0100

> Can you give me an idea of what sort of more detailed guidance you woud

How long would the client need to wait for the last flight retransmit (in order
to retransmit his finished)? If the application protocol requires the client
to start sending application data this is an issue.

> Doesn't the epoch make this clear?

The changecipherspec has the same epoch as the handshake exchange, so
if it is received out-of-order during the handshake, the server can
not know when
it was supposed to be sent. Maybe it should be explicit that replays
or out-of-order
receival of that message should be discarded..

> (due to the handshake sequence number). I'll see about making this

Note that the handshake at that point is over and data have been
already exchanged (e.g. I did an HTTP request got a page, and
I receive this replay now).

regards,
Nikos