Skip to main content
Version: 5.0

Datagram Transport Security Layer

The DTLS layer is a private interface of Acklio FllSDK to encrypt uplinks between the device (empowered by Acklio FullSDK) and Acklio IPCore and to decrypt downlinks in the other direction using DTLS protocol version 1.2.

The DTLS layer sits between the fragmentation/reassembly layer and the compression/decompression layer, as illustrated in the Layers and Interfaces page.

FullSDK Implementation

The encryption and decryption of packets happens in the DTLS folder of Acklio FullSDK.

The header file for the DTLS layer is fullsdkdtls.h and contains two private functions that are called from the C/D layer when sending and receiving data. They cannot be accessed from the application layer.

DTLS Compression

A basic SCHC compression/decompression is performed on DTLS payload.

Layer Parameters

The DTLS layer must be configured with some parameters to be able to start. They are grouped into a structure of dtls_options_t type.

ParameterDescription
const uint8_t *psk_idThe identifier of the Pre-Shared Key (PSK) used to establish the DTLS session.
const uint8_t *pskThe PSK used to establish the DTLS session.
uint8_t psk_id_sizeThe size of the PSK identifier.
uint8_t psk_sizeThe size of the PSK.
uint8_t nbr_tryThe number of times the DTLS layer should retry a hanshake.
uint32_t handshake_timeoutThe delay after which the DTLS layer considers that a handshake exceeded the expected time and should be aborted.

Callbacks

The DTLS layer relies on the following callback functions from the application layers.

Required Functions

This callback is called at the end of the handshaking procedure in order to inform the application layer whether the DTLS handshake succeeded or failed.

void (*dtls_handshake_result_t)(dtls_status_t status) 

This callback has to be provided for internal functioning.

int (*dtls_platform_entropy_hardware_poll_t)(void *data, unsigned char *output, size_t len, size_t *olen)

Optional Functions

When the two callbacks below are provided to Acklio FullSDK then the DTLS session resumption feature can be used which consists in saving a session ID in flash/a file that can be reloaded when the application starts again.

This allows doing a shorter handshake with the server by resuming the previously existing one.

This callback must serialize the data that is pointed by the session variable to persistent storage.

bool (*dtls_save_session_t)(dtls_session_t *session, uint16_t session_size)

This callback must load the data previously saved in the session variable and pass it back to the calling context.

bool (*dtls_load_session_t)(dtls_session_t *session, uint16_t session_size) 

Both functions return true if the operation has succeeded and false if it has failed.

Timer

The mbedTLS layer requires a timer that will increment the number of timers that have to be provided to Acklio FullSDK by 1.

Public Functions

This function is used to give the optional callbacks to the DTLS layer:

void dtls_conf_session_persistence(dtls_save_session_t save_session, dtls_load_session_t load_session) 

This function is used to pass the required callbacks and the DTLS options to the DTLS layer.

caution

This function must be called before mgt_initialize.

dtls_status_t dtls_set_options(const dtls_callbacks_t *callbacks, dtls_options_t *options) 

This function should be called before initiating a handshake, it will call the session loading callback in order to prepare a resumption handshake.

dtls_status_t dtls_load_session() 

This function should be called after a successful handshake, it will call the session saving callback to allow a resumption handshake on application restart.

dtls_status_t dtls_save_session()

This function resets mbedTLS SSL context, it will try to send an alert message to the server to inform it that the session should be closed.
After a call to this function a new DTLS handshake is necessary in order to continue operating.

dtls_status_t dtls_session_reset() 

This function reinitializes the SSL context with the same session previously used, making the next handshake attempt become a resumption handshake.

dtls_status_t dtls_resume_session() 

This function allows to set the value of the DTLS SNI extension to the one passed as parameter.

dtls_status_t dtls_set_sni_hostname(const char *sni_hostname) 

This function deinitializes the DTLS layer.

dtls_status_t dtls_close(void) 

This function allows to provide a callback to mbedTLS in order to write debug logs and make this feature available. The MBEDTLS_DEBUG_C macro should be defined in mbedtls_config.h.

void dtls_set_debug_callback(void (*new_f_dbg)(void *ctx, int level, const char *file, int line, const char *str));

Provisioning

When a device wants to establish a secured connection by doing a handshake, the device needs to be provisioned on Acklio IPCore with its associated PSK configuration.

The provisioning is done as follows:

  1. The device is provisioned by uploading a CSV containing the PSK information (psk_id and psk_value as hexadecimal strings) using the Web interface of Acklio IPCore.
  2. Acklio IPCore Web interface transmits the CSV to IPCoreCDP which stores all the device information in a Postgres database.
  3. After storing these information, IPCoreCDP transmits the necessary information (device_id, organization_name, psk_id and psk_value) to the DTLS Server using a gRPC stream PullDeviceDTLSInfo.
  4. The DTLS Server stores this information in a Redis database in order to handle the device.
info

Another gRPC call exists between the DTLS Server and IPCoreCDP. It is used in case the information of a given device were not successfully provisioned during step 3.
This could happen if the DTLS Server is not available (for example, when an upgrade occurs) at the time the device is provisioned.

Sequence Diagram

The illustration below shows the sequence from Handshake to the reception of the encrypted downlink.

Sequence Diagram

Acklio FullSDK DTLS layer must be configured before performing the handshake: The device must be provided with a pre-shared key, a retry number and a timeout period.
Then:

  1. Acklio FullSDK initiates the handshake and the IP/DTLS Server returns the status of the handshake, and a CID (Cyphering ID).
  2. Acklio FullSDK finalizes the handshake procedure with the IP/DTLS server to secure the link.
  3. The data exchange can starts (either in uplink or in downlink):
    • Acklio FullSDK sends data with an encrypted uplink to the IP/DTLS server that decrypts is and then forwards it to Acklio IPCore.
    • Acklio IPCore sends decrypted data including the Device ID with a plain downlink to the IP/DTLS Server, which encrypts the downlink before forwarding the data to Acklio FullSDK.