DTLS Connection Renegotiation vs. Resumption - eclipse-californium/californium GitHub Wiki

We have had a lot of discussions around the question when and how a DTLS client would like to re-connect to a DTLS server. It turns out that the TLS 1.2 and DTLS 1.2 specs describe only a subset of potential use cases explicitly so we want to use this page to provide an overview of use cases we consider relevant for real world applications employing DTLS and how Scandium supports them (or not).

Terminology

The glossary of the TLS 1.2 spec uses the following definitions of the terms Connection and Session respectively:

A connection is a transport (in the OSI layering model definition) that provides a suitable type of service. For TLS, such connections are peer-to-peer relationships. The connections are transient. Every connection is associated with one session.

and

A TLS session is an association between a client and a server. Sessions are created by the handshake protocol. Sessions define a set of cryptographic security parameters that can be shared among multiple connections. Sessions are used to avoid the expensive negotiation of new security parameters for each connection.

DTLS re-uses these definitions, i.e. a DTLS session has the same semantics as defined for a TLS session and a DTLS connection has the same meaning as a TLS connection.

Scandium uniquely identifies each connection by means of

  • the client's IP address and port used for communicating with the server and
  • the server's IP address and port used for communicating with the client

In particular this means that no two connections managed by Scandium can have the same values for these four parameters. When a client tries to start a handshake using an IP address and port that is already used in an existing connection, Scandium follows the cookie exchange protocol described in the DTLS 1.2 spec to verify the client's ability to respond to messages sent to that IP address/port. If the verification is successful Scandium terminates the existing connection and starts a new handshake to negotiate a new session and establish a new connection with the client.

NOTE Scandium currently does not support the sharing of sessions between connections. This implies that a client cannot create an additional connection to a server using an abbreviated handshake based on an existing session. However, a client can create an additional connection using the same IP address with a different port number doing a full handshake.

Use Cases

Now that we have the terminology established we can describe uses cases we see in real world applications and how Scandium supports them. The following use cases are all dealing with re-connecting to a DTLS server, i.e. they all assume that a connection has already been established between the client and the server.

Client Crash

tbd

Client Hibernation

The assumption here is that the client has established a connection with a server and wants to re-use that connection across its hibernation cycles. We also assume that hibernation does not involve termination of the JVM process in which Scandium is used.

Scandium supports this use case by providing start and stop methods on the DTLSConnector class. A client should invoke DTLSConnector.stop() before it goes to sleep and invoke DTLSConnector.start() after it has woken up.

There are two cases to consider here. In the first case the IP address and port of the network interface Scandium has bound to on the client have not changed over the hibernation cycle. In this case the client can simply continue to send data to the server by means of DTLSConnector.send(). Scandium will re-use the already established connection and no new handshake will be performed.

In the second case the IP address and/or port of the network interface Scandium has bound to on the client have changed over the hibernation cycle, e.g. because the network interface is attached to a mobile network and gets assigned a new IP address periodically. Scandium (on the client) will detect this by comparing the IP address/port it is currently bound to with the IP address/port it has been bound to before the last stop/start (hibernation) cycle. When client code invokes DTLSConnector.send() to send data to the server, Scandium will negotiate a new connection to the server using an abbreviated handshake based on the previously established connection. Technically speaking this means that the client will initiate a handshake using a ClientHello message using epoch=0 and including the previously established connection's sessionID.

The DTLSConnector running on the server side will recognize that the client's IP address/port has changed and will silently discard the previously established connection after the handshake has completed.

Once the new connection has been established the client side DTLSConnector discards the previously established connection and will continue to encrypt and send application data to the server based on the cipher and security parameters negotiated for the new connection.

The whole procedure will be performed for each stop/start (hibernation) cycle.

Client behind NAT Firewall

This is not explicitly supported by Scandium yet because we currently only compare the IP address of the local network interface Scandium has bound to with the previous one (see Hibernation use case).

However, client code (at the application layer) can invoke DTLSConnector.forceResumeSessionFor() to indicate to Scandium that the public IP address/port has changed. Scandium will then start an abbreviated handshake with the server the next time the connection is used in the same way as described in the Hibernation use case.

As an example how this could like like consider a device managed using LWM2M that is on a private network behind a NAT firewall. In this case the device should use LWM2M's queued mode to have the server buffer messages targeted at the device until the device re-connects with the server. Additionally, the device should use DTLSConnector.forceResumeSessionFor() each time it wakes up.

In the future Scandium may be able to support this use case natively by using e.g. STUN to determine whether the client's public IP address/port has changed.

Server Crash

Scandium currently does not support (transparent) connection fail-over between server nodes. In the remainder of this section we therefore assume that the server side process is monitored (e.g. by a watchdog) and is automatically restarted after a crash.

The application layer on the client side can determine that a server has crashed by means of not receiving responses to its requests anymore (e.g. by running into appropriately set time-outs). It can then force resumption of a connection to the server using DTLSConnector.forceResumeSessionFor(). Once the connection has been marked for resumption, Scandium will negotiate a new connection with the server when DTLSConnector.send() is invoked again (by the application layer). Technically speaking this means that Scandium will initiate a handshake using a ClientHello message using epoch=0 and including the previously established connection's sessionID.

The DTLSConnector running on the server side will try to find the session ID provided by the client in its session cache but will not find it (because the server has lost all of its state due to the crash). It will then perform a full handshake with the client and thus establish a new connection with the client.

Once the new connection has been established the client side DTLSConnector discards the previously established connection and will continue to encrypt and send application data to the server based on the cipher and security parameters negotiated for the new connection.

Renegotiation vs. Resumption

THIS IS DRAFT ONLY

The existing connection between a client and server may be renegotiated due to arbitrary reasons either triggered by the client or the server. Regardless of the particular reason the overall intention of renegotiating a connection is to continue to use the connection and only switch to a new set of negotiated security parameters.

The DTLS spec explicitly notes that a DTLS server should initiate the renegotiation of a connection if the record sequence numbers or epoch counters are about to wrap. In such a case the DTLS server is supposed to send a HelloRequest handshake message to the client (using the existing connection).

The client must react to such a request by initiating a handshake with the server, i.e. by sending a ClientHello message to the server. The client has two options to do the handshake:

  • The client can include the existing connection's session ID in the ClientHello message in order to indicate to the server that it only wants to negotiate new encryption keys based on the cipher already in use.
  • The client can omit the session ID from the ClientHello message in order to request a new full handshake which might also entail negotiation of a different cipher.

Californium 2.0.x

That's the way very close to TLS.

Though DTLS doesn't use a connection, the decision is to continue to use the old encryption/keys to exchange the new ones, or, to exchange them without encryption using epoch 0. Though the clients too frequently want to execute an handshake, because the state of the other peer is unclear, using encryption may be in vain. Therefore californium decided, to NOT SUPPORT RENEGOTIATION at all. There are also vulnerabilities reported for renegotiation, but with the crypto-context reported with each record, californium would not really be effected of that. So a client may start a new handshake with a session id (resumption, so not renew the premaster secret) or without (full-handshake). A server will drop the records, if the 48 bits counter wrap, but that is very optimistic, that this is reached.