Subject: [TLS] DTLS Handshake race condition

From: Michael Tuexen <[email-masked]>
Date: Sun, 11 Aug 2013 15:17:54 +0200

Dear all,

while fixing a bug in OpenSSL regarding the DTLS handshake, I thought about
the following scenario (both sides decide to renegotiate at about the same
time):

* A DTLS connection is established.
* The server sends a HelloRequest(MsgSeqNo = 0) and starts the retransmission
  timer, since this is a flight.
* The HelloRequest is dropped by the network.
* The client sends a ClientHello(MsgSeqNo = 0) and start a retransmission timer,
  since it is its first flight.
* The server receives the ClientHello, stops the retransmission timer
  and sends the next flight starting with ServerHello(MsgSeqNo = 1) 
  since it considers the received ClientHello as an ack for the flight.
* The client doesn't process the ServerHello, since it expects the
  MsgSeqNo == 0.

Therefore the client retransmits its ClientHello and the server retransmits
its flight containing the ServerHello. Am I missing something?

The problem is that the server has no way to figure out if the received
ClientHello is a reaction to a HelloRequest or not.
The only way out I see is that the client accepts ServerHellos with
MsgSeqNo=0 and MsgSeqNo=1.
I don't think this is covered in http://tools.ietf.org/html/rfc6347

Any opinions?

Best regards
Michael

---

From: Andy Wilson <[email-masked]>
Date: Mon, 12 Aug 2013 02:19:29 +1200

After looking over the RFC a bit, wouldn't the client be expecting a
HelloVerifyRequest
after its ClientHello?

On 12 August 2013 01:17, Michael Tuexen <[email-masked]>wrote:

> _______________________________________________
> TLS mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/tls
>

-- 
Regards

Andy

---

From: Michael Tuexen <[email-masked]>
Date: Sun, 11 Aug 2013 19:08:56 +0200

On Aug 11, 2013, at 4:19 PM, Andy Wilson <[email-masked]> wrote:

> After looking over the RFC a bit, wouldn't the client be expecting a HelloVerifyRequest after its ClientHello?
I don't think this is necessary, since the client and the server have already
a relation. So there is no need to use the cookie mechanism.

However, the question is the same. In your case
* The server sends a HelloRequest(MsgSeqNo = 0) and starts the retransmission
  timer, since this is a flight.
* The HelloRequest is dropped by the network.
* The client sends a ClientHello(MsgSeqNo = 0) and start a retransmission timer,
  since it is its first flight.
* The server sends a HelloVerifyRequest(MsgSeqNo = 1)
* The client doesn't process the ServerHello, since it expects the
  MsgSeqNo == 0.

Therefore, the server retransmits the flight consisting of the HelloVerifyRequest
and the client retransmits the flight containing the ClientHello.
So the solution would be that the client accepts
* ServerHellos with MsgSeqNo=0 and MsgSeqNo=1.
* HelloVerifyRequest with MsgSeqNo=0 and MsgSeqNo=1.

Am I missing something?

Best regards
Michael
> 
> On 12 August 2013 01:17, Michael Tuexen <[email-masked]> wrote:
> Dear all,
>

---

From: Andy Wilson <[email-masked]>
Date: Mon, 12 Aug 2013 22:28:56 +1200

Section 4.2.2 states:

The first message each side transmits in each handshake always has
   message_seq = 0.  Whenever each new message is generated, the
   message_seq value is incremented by one.  Note that in the case of a
   rehandshake, this implies that the HelloRequest will have message_seq
   = 0 and the ServerHello will have message_seq = 1

This would imply that the client WOULD process the ServerHello with seq==1
as this is a re-handshake.

That's the way i'm reading the spec..

On 12 August 2013 05:08, Michael Tuexen <[email-masked]>wrote:

> HelloVerifyRequest after its ClientHello?

-- 
Regards

Andy

---

From: Michael Tuexen <[email-masked]>
Date: Mon, 12 Aug 2013 12:46:23 +0200

On Aug 12, 2013, at 12:28 PM, Andy Wilson <[email-masked]> wrote:

> This would imply that the client WOULD process the ServerHello with seq==1 as this is a re-handshake.
> 
Me too.

I think the RFC does cover the race condition I'm referring to...
What if the HelloRequest(message_seq=0) is lost and the client sends
a ClientHello(message_seq=0) on its own (since the local user initates
a re-handshake). The server accepts the ClientHello and responds with
a ServerHello(message_seq=1). The client however expects a
ServerHello(message_seq=0), since it never saw the HelloRequest.
The HelloRequest is also not retransmitted, since the server considers
it acked by the ClientHello.

It is only the collision case I'm considering and I think which is
not covered by the RFC.

Best regards
Michael
> 
> 
> 
> 
> On 12 August 2013 05:08, Michael Tuexen <[email-masked]> wrote:

---

From: Michael Tuexen <[email-masked]>
Date: Mon, 12 Aug 2013 12:57:42 +0200

> I think the RFC does cover the race condition I'm referring to...
... I meant "does NOT cover"

---

From: [email-masked] (Martin Rex)
Date: Mon, 12 Aug 2013 20:08:11 +0200 (CEST)

Michael Tuexen wrote:
> 
> I think the RFC does not cover the race condition I'm referring to...

Your observation seems correct.

The original TLS handshake is only half duplex.  Properly dealing
with renegotiation is therefore non-trivial.  The original TLS spec
addresses the overlapping of the renegotiation handshake by

  - omitting HelloRequests from the Handshake message hash computation.

  - require the TLS client to ignore any HelloRequests that
    are be received during the handshake (which includes the one
    received after the client has already requested a new handshake
    by sending a ClientHello from your scenario.

Another "grey" area, that may not work particularly well with
some TLS implementations, is what happens if one side requests
a renegotiation while the other is still sending application data.

While the TLS spec itself this should be OK when renegotiation handshake
messages are interleaved with application data, it may not actually
work with all implementations.  Taken to the extreme, with TLS APIs
that perform peer certificate validation in an event-based fashion,
it may open a potential vulnerability (for servers doing delayed
client authentication) when the client starts the renegotiation
handshake, but stops sending handshake messages after the
client's certificate handshake message and then continues sending
application data under the original/enclosing TLS session.

-Martin

---

From: Michael Tuexen <[email-masked]>
Date: Tue, 13 Aug 2013 13:44:47 +0200

>  - omitting HelloRequests from the Handshake message hash computation.
So this applies also to DTLS.
>    by sending a ClientHello from your scenario.
In my scenario the client never receives it, since it is
* dropped by the network
* but sort of ACKed by the client by sending the ClientHello and
  therefore it is never retransmitted.
So currently, the DTLS connection is stalled until it is taken
down due to the retransmission timer firing too often...

Best regards
Michael

---

From: [email-masked] (Martin Rex)
Date: Tue, 13 Aug 2013 23:42:00 +0200 (CEST)

Michael Tuexen wrote:
> Martin Rex <[email-masked]> wrote:
>> 

If HelloRequest changes the DTLS MsgSeqNo, then simply "ignoring it"
seems no longer an option (that it was in TLS).

Ignoring it was really supposed to mean "will not affect state".
MsgSeqNo. looks like state that is relevant to the DTLS handshake
state machine.

In case the server _did_ send a HelloRequest, would glueing/prefixing another
HelloRequest to the front of the HelloVerifyRequest help?

-Martin