DTLS sock API

Sock submodule for DTLS. More...

Detailed Description

Sock submodule for DTLS.

DTLS sock acts as a wrapper for the underlying DTLS module to provide encryption for applications using the UDP sock API.

How To Use

Summary

Makefile Includes

First, we need to include a module that implements this API in our applications Makefile. For example the module that implements this API for tinydtls is called ‘tinydtls_sock_dtls’.

The corresponding pkg providing the DTLS implementation will be automatically included so there is no need to use USEPKG to add the pkg manually.

Each DTLS implementation may have its own configuration options and caveat. This can be found at DTLS.

Adding credentials

Before using this API, either as a server or a client, we first need to add the credentials to be used for the encryption using credman. Note that credman does not copy the credentials given into the system, it only has information about the credentials and where it is located at. So it is your responsibility to make sure that the credential is valid during the lifetime of your application.

#include <stdio.h>
#include "net/credman.h"
#define SOCK_DTLS_SERVER_TAG (10)
#define SOCK_DTLS_CLIENT_TAG (20)
static char *psk_key = "secretPSK";
static char *psk_id = "secretID";
static const unsigned char server_ecdsa_priv_key[] = {...};
static const unsigned char server_ecdsa_pub_key_x[] = {...};
static const unsigned char server_ecdsa_pub_key_y[] = {...};
static const unsigned char client_pubkey_x[] = {...};
static const unsigned char client_pubkey_y[] = {...};
static ecdsa_public_key_t other_pubkeys[] = {
{ .x = client_pubkey_x, .y = client_pubkey_y },
};
int main(void)
{
credman_credential_t psk_credential = {
.tag = SOCK_DTLS_SERVER_TAG,
.params = {
.psk = {
.key = { .s = psk_key, .len = sizeof(psk_key), },
.id = { .s = psk_id, .len = sizeof(psk_id), },
},
},
};
if (credman_add(&psk_credential) < 0) {
puts("Error cannot add credential");
}
credman_credential_t ecc_credential = {
.tag = SOCK_DTLS_SERVER_TAG,
.params = {
.ecdsa = {
.private_key = server_ecdsa_priv_key,
.public_key = {
.x = server_ecdsa_pub_key_x,
.y = server_ecdsa_pub_key_y,
},
.client_keys = other_pubkeys,
.client_keys_size = ARRAY_SIZE(other_pubkeys),
},
},
};
if (credman_add(&ecc_credential) < 0) {
puts("Error cannot add credential");
}
// start server/client
// [...]
}
(D)TLS credentials management module definitions
int credman_add(const credman_credential_t *credential)
Adds a credential to the credential pool.
@ CREDMAN_TYPE_ECDSA
ECDSA credential type.
Definition: credman.h:114
@ CREDMAN_TYPE_PSK
PSK credential type.
Definition: credman.h:113
#define ARRAY_SIZE(a)
Calculate the number of elements in a static array.
Credential information.
Definition: credman.h:120
credman_type_t type
Type of the credential.
Definition: credman.h:121
ECDSA public keys.
Definition: credman.h:78
const void * x
X part of the public key.
Definition: credman.h:79

Above we see an example of how to register a PSK and an ECC credential.

First, we need to include the header file for the API.

#include "net/credman.h"
int main(void)
{
credman_credential_t psk_credential = {
.tag = SOCK_DTLS_SERVER_TAG,
.params = {
.psk = {
.key = { .s = psk_key, .len = sizeof(psk_key), },
.id = { .s = psk_id, .len = sizeof(psk_id), },
},
},
};
[...]
}

We tell credman which credential to add by filling in the credentials information in a struct credman_credential_t. For PSK credentials, we use enum CREDMAN_TYPE_PSK for the type.

Next, we must assign a tag for the credential. Tags are unsigned integer values used to identify which DTLS sock has access to which credentials. Each DTLS sock will also be assigned a list of tags. As a result, a sock can only use credentials that have the same tag as the ones in the list.

if (credman_add(&psk_credential) < 0) {
puts("Error cannot add credential");
}

After credential information is filled, we can add it to the credential pool using credman_add().

For adding credentials of other types, you can follow the steps above except credman_credential_t::type and credman_credential_t::params depend on the type of credential used.

Server Operation

After credentials are added, we can start the server.

#include <stdio.h>
#include "net/sock/dtls.h"
#define SOCK_DTLS_SERVER_TAG (10)
int main(void)
{
// Add credentials
// [...]
// initialize server
sock_udp_t udp_sock;
local.port = 20220;
if (sock_udp_create(&udp_sock, &local, NULL, 0) < 0) {
puts("Error creating UDP sock");
return -1;
}
sock_dtls_t dtls_sock;
if (sock_dtls_create(&dtls_sock, &udp_sock,
SOCK_DTLS_SERVER_TAG,
puts("Error creating DTLS sock");
return -1;
}
while (1) {
int res;
char buf[128];
res = sock_dtls_recv(&dtls_sock, &session, buf, sizeof(buf),
if (res > 0) {
printf("Received %d bytes\n", res);
if (sock_dtls_send(&dtls_sock, &session, buf, res) < 0) {
puts("Error sending reply");
}
}
}
return 0;
}
int sock_dtls_create(sock_dtls_t *sock, sock_udp_t *udp_sock, credman_tag_t tag, unsigned version, unsigned role)
Creates a new DTLS sock object.
static ssize_t sock_dtls_send(sock_dtls_t *sock, sock_dtls_session_t *remote, const void *data, size_t len, uint32_t timeout)
Encrypts and sends a message to a remote peer.
Definition: dtls.h:979
static ssize_t sock_dtls_recv(sock_dtls_t *sock, sock_dtls_session_t *remote, void *data, size_t maxlen, uint32_t timeout)
Receive handshake messages and application data from remote peer.
Definition: dtls.h:799
@ SOCK_DTLS_SERVER
Endpoint server role.
Definition: dtls.h:595
@ SOCK_DTLS_1_2
DTLS version 1.2.
Definition: dtls.h:583
int sock_udp_create(sock_udp_t *sock, const sock_udp_ep_t *local, const sock_udp_ep_t *remote, uint16_t flags)
Creates a new UDP sock object.
#define SOCK_IPV6_EP_ANY
Address to bind to any IPv6 address.
Definition: sock.h:165
#define SOCK_NO_TIMEOUT
Special value meaning "wait forever" (don't timeout)
Definition: sock.h:172
DTLS sock definitions.
Common IP-based transport layer end point.
Definition: sock.h:214
uint16_t port
transport layer port (in host byte order)
Definition: sock.h:246
Information about remote client connected to the server.
Information about DTLS sock.
UDP sock type.
Definition: sock_types.h:128

This is an example of a DTLS echo server.

DTLS sock uses an initialized UDP sock to send and receive encrypted packets. Therefore, the listening port for the server also needs to be set here.

sock_udp_t udp_sock;
local.port = 20220;
if (sock_udp_create(&udp_sock, &local, NULL, 0) < 0) {
puts("Error creating UDP sock");
return -1;
}

Using the initialized UDP sock, we can then create our DTLS sock. We use SOCK_DTLS_SERVER_TAG, which is defined as 10 in our application code beforehand, as our tag. Using SOCK_DTLS_1_2 and SOCK_DTLS_SERVER, we set our DTLS endpoint to use DTLS version 1.2 and act as a DTLS server.

Note that some DTLS implementation do not support earlier versions of DTLS. In this case, sock_dtls_create() will return an error. A list of supported DTLS version for each DTLS implementation can be found at this page. In case of error, the program is stopped.

#define SOCK_DTLS_SERVER_TAG (10)
[...]
sock_dtls_t dtls_sock;
if (sock_dtls_create(&dtls_sock, &udp_sock,
SOCK_DTLS_SERVER_TAG,
puts("Error creating DTLS sock");
return -1;
}

Now we can listen to incoming packets using sock_dtls_recv(). The application waits indefinitely for new packets. If we want to timeout this wait period we could alternatively set the timeout parameter of the function to a value != SOCK_NO_TIMEOUT. If an error occurs we just ignore it and continue looping. We can reply to an incoming message using its session.

while (1) {
int res;
char buf[128];
res = sock_dtls_recv(&dtls_sock, &session, buf, sizeof(buf),
if (res > 0) {
printf("Received %d bytes -- echo!\n", res);
if (sock_dtls_send(&dtls_sock, &session, buf, res) < 0) {
puts("Error sending reply");
}
}
}
return 0;

Client Operation

#include "net/sock/udp.h"
#include "net/sock/dtls.h"
#include "net/ipv6/addr.h"
#include "net/credman.h"
#define SOCK_DTLS_CLIENT_TAG (20)
#ifndef SERVER_ADDR
#define SERVER_ADDR "fe80::aa:bb:cc:dd" // replace with the server address
#endif
int main(void)
{
// Add credentials
// [...]
// initialize client
char rcv[128];
sock_udp_t udp_sock;
local.port = 12345;
remote.port = DTLS_DEFAULT_PORT;
remote.netif = gnrc_netif_iter(NULL)->pid; // only if gnrc_netif_highlander() returns true
sock_dtls_t dtls_sock;
if (!ipv6_addr_from_str((ipv6_addr_t *)remote.addr.ipv6, SERVER_ADDR)) {
puts("Error parsing destination address");
return -1;
}
if (sock_udp_create(&udp_sock, &local, NULL, 0) < 0) {
puts("Error creating UDP sock");
return -1;
}
if (sock_dtls_create(&dtls_sock, &udp_sock,
SOCK_DTLS_CLIENT_TAG,
puts("Error creating DTLS sock");
sock_udp_close(&udp_sock);
return -1;
}
if (sock_dtls_session_init(&dtls_sock, &remote, &session) < 0) {
puts("Error initiating session");
sock_dtls_close(&dtls_sock);
sock_udp_close(&udp_sock);
return -1;
}
if (sock_dtls_recv(&dtls_sock, &session, rcv, sizeof(rcv),
puts("Error completing handshake");
sock_dtls_close(&dtls_sock);
sock_udp_close(&udp_sock);
return -1;
}
const char data[] = "HELLO";
int res = sock_dtls_send(&dtls_sock, &session, data, sizeof(data), 0);
if (res >= 0) {
printf("Sent %d bytes\n", res);
res = sock_dtls_recv(&dtls_sock, &session, rcv, sizeof(rcv),
if (res > 0) {
printf("Received %d bytes\n", res);
}
}
else {
puts("Error sending data");
}
sock_dtls_session_destroy(&dtls_sock, &session);
sock_dtls_close(&dtls_sock);
sock_udp_close(&udp_sock);
return 0;
}
gnrc_netif_t * gnrc_netif_iter(const gnrc_netif_t *prev)
Iterate over all network interfaces.
ipv6_addr_t * ipv6_addr_from_str(ipv6_addr_t *result, const char *addr)
Converts an IPv6 address string representation to a byte-represented IPv6 address.
#define SOCK_DTLS_HANDSHAKE
Return value for a successful handshake.
Definition: dtls.h:574
void sock_dtls_close(sock_dtls_t *sock)
Closes a DTLS sock.
void sock_dtls_session_destroy(sock_dtls_t *sock, sock_dtls_session_t *remote)
Destroys an existing DTLS session.
int sock_dtls_session_init(sock_dtls_t *sock, const sock_udp_ep_t *ep, sock_dtls_session_t *remote)
Initialize session handshake.
@ SOCK_DTLS_CLIENT
Endpoint client role.
Definition: dtls.h:594
void sock_udp_close(sock_udp_t *sock)
Closes a UDP sock object.
Definitions for IPv6 addresses.
UDP sock definitions.
union _sock_tl_ep::@357 addr
address
uint16_t netif
stack-specific network interface ID
Definition: sock.h:245
uint8_t ipv6[16]
IPv6 address mode.
Definition: sock.h:229
kernel_pid_t pid
PID of the network interface's thread.
Definition: netif.h:187
Data type to represent an IPv6 address.
Definition: addr.h:72

This is an example of a DTLS echo client.

Like the server, we must first create the UDP sock.

sock_udp_t udp_sock;
local.port = 12345;
sock_udp_create(&udp_sock, &local, NULL, 0);

After that, we set the address of the remote endpoint and its listening port, which is DTLS_DEFAULT_PORT (20220).

remote.port = DTLS_DEFAULT_PORT;
remote.netif = gnrc_netif_iter(NULL)->pid; // only if gnrc_netif_highlander() returns true
if (!ipv6_addr_from_str((ipv6_addr_t *)remote.addr.ipv6, SERVER_ADDR)) {
puts("Error parsing destination address");
return -1;
}

After the UDP sock is created, we can proceed with creating the DTLS sock. Before sending the packet, we must first initiate a session handshake with the remote endpoint using sock_dtls_session_init(). We will need to call sock_dtls_recv() to receive and process all the handshake packets. If the handshake is successful and the session is created, we send packets to it using sock_dtls_send(). As we already know the session exists, we can set the timeout to 0 and listen to the reply with sock_dtls_recv().

Alternatively, set the timeout to of sock_dtls_send() to the duration we want to wait for the handshake process. We can also set the timeout to SOCK_NO_TIMEOUT to block indefinitely until handshake is complete. After handshake completes, the packet will be sent.

sock_dtls_init(), sock_dtls_recv and sock_dtls_close() only manages the DTLS layer. That means we still have to clean up the created UDP sock from before by calling sock_udp_close() on our UDP sock in case of error or we reached the end of the application.

char rcv[128];
sock_dtls_t dtls_sock;
[...]
if (sock_dtls_create(&dtls_sock, &udp_sock,
SOCK_DTLS_CLIENT_TAG,
puts("Error creating DTLS sock");
sock_udp_close(&udp_sock);
return -1;
}
if (sock_dtls_session_init(&dtls_sock, &remote, &session) < 0) {
puts("Error initiating session");
sock_dtls_close(&dtls_sock);
sock_udp_close(&udp_sock);
return -1;
}
if (sock_dtls_recv(&dtls_sock, &session, rcv, sizeof(rcv),
puts("Error completing handshake");
sock_dtls_close(&dtls_sock);
sock_udp_close(&udp_sock);
return -1;
}
const char data[] = "HELLO";
int res = sock_dtls_send(&dtls_sock, &session, data, sizeof(data), 0);
if (res >= 0) {
printf("Sent %d bytes: %*.s\n", res, res, data);
res = sock_dtls_recv(&dtls_sock, &session, rcv, sizeof(rcv),
if (res > 0) {
printf("Received %d bytes: %*.s\n", res, res, rcv);
}
}
else {
puts("Error sending data");
}
sock_dtls_session_destroy(&dtls_sock, &session);
sock_dtls_close(&dtls_sock);
sock_udp_close(&udp_sock);
return 0;

Multi-credential handling

Each sock needs at least one credential tag to operate. sock_dtls_create allows to optionally assign an initial credential. Extra credentials can be added and removed using sock_dtls_add_credential and sock_dtls_remove_credential respectively (found in net/sock/dtls/creds.h).

Pre-shared Keys Cipher Suites

In the case of PSK, a server can optionally indicate a hint to help the client to decide which PSK Identity to use, using sock_dtls_set_server_psk_id_hint (see https://tools.ietf.org/html/rfc4279#section-5.2). The client application can decide which credential to use based on the sent hint and/or the session information, by registering a callback with sock_dtls_set_client_psk_cb. If no callback is registered, or fails to chose a tag (i.e. it returns CREDMAN_TAG_EMPTY), the credential is chosen as follows: if a hint is sent by the server, all credentials registered to the sock are checked for a matching hint. A credential is selected on matching hint. If no credential matches the hint or no hint is provided, the first PSK credential registered in the sock is used.

Elliptic Curve Cryptography Cipher Suites

When using ECC both client and server applications can register a callback to decide which of the registered credentials should be used, based on the session information. This is done using sock_dtls_set_rpk_cb.

In both cases, if no callbacks are registered, the sock implementation will try to find a registered credential in the Sock's credential list, that matches the needed type. The first one that matches is used.

Modules

 DTLS sock credentials API
 Credential handling for DTLS sock.
 
 SOCK DTLS compile configuration
 

Files

file  dtls.h
 DTLS sock definitions.
 

Macros

#define DTLS_HANDSHAKE_BUFSIZE   (1 << CONFIG_DTLS_HANDSHAKE_BUFSIZE_EXP)
 Size buffer used in handshake to hold credentials.
 
#define SOCK_DTLS_HANDSHAKE   (EXDEV)
 Return value for a successful handshake.
 

Typedefs

typedef struct sock_dtls sock_dtls_t
 Type for a DTLS sock object. More...
 
typedef struct sock_dtls_session sock_dtls_session_t
 Information about a created session.
 
typedef sock_udp_aux_rx_t sock_dtls_aux_rx_t
 Auxiliary data provided when receiving using an DTLS sock object. More...
 
typedef sock_udp_aux_tx_t sock_dtls_aux_tx_t
 Auxiliary data provided when sending using an DTLS sock object. More...
 

Functions

void sock_dtls_init (void)
 Called exactly once during auto_init. More...
 
int sock_dtls_create (sock_dtls_t *sock, sock_udp_t *udp_sock, credman_tag_t tag, unsigned version, unsigned role)
 Creates a new DTLS sock object. More...
 
sock_udp_tsock_dtls_get_udp_sock (sock_dtls_t *sock)
 Get underlying UDP sock. More...
 
int sock_dtls_session_init (sock_dtls_t *sock, const sock_udp_ep_t *ep, sock_dtls_session_t *remote)
 Initialize session handshake. More...
 
void sock_dtls_session_destroy (sock_dtls_t *sock, sock_dtls_session_t *remote)
 Destroys an existing DTLS session. More...
 
void sock_dtls_session_get_udp_ep (const sock_dtls_session_t *session, sock_udp_ep_t *ep)
 Get the remote UDP endpoint from a session. More...
 
void sock_dtls_session_set_udp_ep (sock_dtls_session_t *session, const sock_udp_ep_t *ep)
 Set the remote UDP endpoint from a session. More...
 
ssize_t sock_dtls_recv_aux (sock_dtls_t *sock, sock_dtls_session_t *remote, void *data, size_t maxlen, uint32_t timeout, sock_dtls_aux_rx_t *aux)
 Receive handshake messages and application data from remote peer. More...
 
static ssize_t sock_dtls_recv (sock_dtls_t *sock, sock_dtls_session_t *remote, void *data, size_t maxlen, uint32_t timeout)
 Receive handshake messages and application data from remote peer. More...
 
ssize_t sock_dtls_recv_buf_aux (sock_dtls_t *sock, sock_dtls_session_t *remote, void **data, void **buf_ctx, uint32_t timeout, sock_dtls_aux_rx_t *aux)
 Decrypts and provides stack-internal buffer space containing a message from a remote peer. More...
 
static ssize_t sock_dtls_recv_buf (sock_dtls_t *sock, sock_dtls_session_t *remote, void **data, void **buf_ctx, uint32_t timeout)
 Decrypts and provides stack-internal buffer space containing a message from a remote peer. More...
 
ssize_t sock_dtls_send_aux (sock_dtls_t *sock, sock_dtls_session_t *remote, const void *data, size_t len, uint32_t timeout, sock_dtls_aux_tx_t *aux)
 Encrypts and sends a message to a remote peer. More...
 
static ssize_t sock_dtls_send (sock_dtls_t *sock, sock_dtls_session_t *remote, const void *data, size_t len, uint32_t timeout)
 Encrypts and sends a message to a remote peer. More...
 
void sock_dtls_close (sock_dtls_t *sock)
 Closes a DTLS sock. More...
 
enum  { SOCK_DTLS_1_0 = 1 , SOCK_DTLS_1_2 = 2 , SOCK_DTLS_1_3 = 3 }
 DTLS version number . More...
 
enum  { SOCK_DTLS_CLIENT = 1 , SOCK_DTLS_SERVER = 2 }
 DTLS role . More...
 

Typedef Documentation

◆ sock_dtls_aux_rx_t

Auxiliary data provided when receiving using an DTLS sock object.

Warning
Implementations of this API may rely on this type to be compatible with sock_udp_aux_rx_t. These implementations need to be updated, if this is no longer the case. Users of this API should not rely on this compatibility

Definition at line 624 of file dtls.h.

◆ sock_dtls_aux_tx_t

Auxiliary data provided when sending using an DTLS sock object.

Warning
Implementations of this API may rely on this type to be compatible with sock_udp_aux_rx_t. These implementations need to be updated, if this is no longer the case. Users of this API should not rely on this compatibility

Definition at line 634 of file dtls.h.

◆ sock_dtls_t

typedef struct sock_dtls sock_dtls_t

Type for a DTLS sock object.

Note
API implementors: struct sock_dtls needs to be defined by an implementation-specific sock_dtls_types.h.

Definition at line 1 of file dtls.h.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

DTLS version number .

Enumerator
SOCK_DTLS_1_0 

DTLS version 1.0.

SOCK_DTLS_1_2 

DTLS version 1.2.

SOCK_DTLS_1_3 

DTLS version 1.3.

Definition at line 581 of file dtls.h.

◆ anonymous enum

anonymous enum

DTLS role .

Enumerator
SOCK_DTLS_CLIENT 

Endpoint client role.

SOCK_DTLS_SERVER 

Endpoint server role.

Definition at line 593 of file dtls.h.

Function Documentation

◆ sock_dtls_close()

void sock_dtls_close ( sock_dtls_t sock)

Closes a DTLS sock.

Releases any memory allocated by sock_dtls_create(). This function does NOT close the UDP sock used by the DTLS sock. After the call to this function, user will have to call sock_udp_close() to close the UDP sock.

Precondition
(sock != NULL)
Parameters
sockDTLS sock to close

◆ sock_dtls_create()

int sock_dtls_create ( sock_dtls_t sock,
sock_udp_t udp_sock,
credman_tag_t  tag,
unsigned  version,
unsigned  role 
)

Creates a new DTLS sock object.

Takes an initialized UDP sock and uses it for the transport. Memory allocation functions required by the underlying DTLS stack can be called in this function.

See also
(D)TLS Credential Manager.
Parameters
[out]sockThe resulting DTLS sock object
[in]udp_sockExisting UDP sock initialized with sock_udp_create() to be used underneath.
[in]tagCredential tag of sock. The sock will only use credentials with the tags registered to it (see sock_dtls_add_credential). Set to CREDMAN_TAG_EMPTY to create a sock with an empty tag list.
[in]versionDTLS version to use.
[in]roleRole of the endpoint.
Returns
0 on success.
-1 on error

◆ sock_dtls_get_udp_sock()

sock_udp_t* sock_dtls_get_udp_sock ( sock_dtls_t sock)

Get underlying UDP sock.

Precondition
sock != NULL.
Parameters
[in]sockDTLS sock to get UDP sock from.
Returns
The underlying UDP sock.

◆ sock_dtls_init()

void sock_dtls_init ( void  )

Called exactly once during auto_init.

Calls the initialization function required by the DTLS stack used.

◆ sock_dtls_recv()

static ssize_t sock_dtls_recv ( sock_dtls_t sock,
sock_dtls_session_t remote,
void *  data,
size_t  maxlen,
uint32_t  timeout 
)
inlinestatic

Receive handshake messages and application data from remote peer.

Parameters
[in]sockDTLS sock to use.
[out]remoteRemote DTLS session of the received data. Cannot be NULL.
[out]dataPointer where the received data should be stored.
[in]maxlenMaximum space available at data.
[in]timeoutReceive timeout in microseconds. If 0 and no data is available, the function returns immediately. May be SOCK_NO_TIMEOUT to wait until data is available.
Note
Function may block if data is not available and timeout != 0
Returns
The number of bytes received on success
-SOCK_DTLS_HANDSHAKE when new handshake is completed
-EADDRNOTAVAIL, if the local endpoint of sock is not set.
-EAGAIN, if timeout is 0 and no data is available.
-EINVAL, if remote is invalid or sock is not properly initialized (or closed while sock_dtls_recv() blocks).
-ENOBUFS, if buffer space is not large enough to store received data.
-ENOMEM, if no memory was available to receive data.
-ETIMEDOUT, if timeout expired.

Definition at line 799 of file dtls.h.

◆ sock_dtls_recv_aux()

ssize_t sock_dtls_recv_aux ( sock_dtls_t sock,
sock_dtls_session_t remote,
void *  data,
size_t  maxlen,
uint32_t  timeout,
sock_dtls_aux_rx_t aux 
)

Receive handshake messages and application data from remote peer.

Parameters
[in]sockDTLS sock to use.
[out]remoteRemote DTLS session of the received data. Cannot be NULL.
[out]dataPointer where the received data should be stored.
[in]maxlenMaximum space available at data.
[in]timeoutReceive timeout in microseconds. If 0 and no data is available, the function returns immediately. May be SOCK_NO_TIMEOUT to wait until data is available.
[out]auxAuxiliary data about the received datagram. May be NULL, if it is not required by the application.
Note
Function may block if data is not available and timeout != 0
Returns
The number of bytes received on success
-SOCK_DTLS_HANDSHAKE when new handshake is completed
-EADDRNOTAVAIL, if the local endpoint of sock is not set.
-EAGAIN, if timeout is 0 and no data is available.
-EINVAL, if remote is invalid or sock is not properly initialized (or closed while sock_dtls_recv() blocks).
-ENOBUFS, if buffer space is not large enough to store received data.
-ENOMEM, if no memory was available to receive data.
-ETIMEDOUT, if timeout expired.

◆ sock_dtls_recv_buf()

static ssize_t sock_dtls_recv_buf ( sock_dtls_t sock,
sock_dtls_session_t remote,
void **  data,
void **  buf_ctx,
uint32_t  timeout 
)
inlinestatic

Decrypts and provides stack-internal buffer space containing a message from a remote peer.

Parameters
[in]sockDTLS sock to use.
[out]remoteRemote DTLS session of the received data. Cannot be NULL.
[out]dataPointer to a stack-internal buffer space containing the received data.
[in,out]buf_ctxStack-internal buffer context. If it points to a NULL pointer, the stack returns a new buffer space for a new packet. If it does not point to a NULL pointer, an existing context is assumed to get a next segment in a buffer.
[in]timeoutReceive timeout in microseconds. If 0 and no data is available, the function returns immediately. May be SOCK_NO_TIMEOUT to wait until data is available.
Warning
This feature is experimental!
This function is quite new, not implemented for all stacks yet, and may be subject to sudden API changes. Do not use in production if this is unacceptable.
Note
Function may block if data is not available and timeout != 0
Function blocks if no packet is currently waiting.
Returns
The number of bytes received on success. May not be the complete payload. Continue calling with the returned buf_ctx to get more buffers until result is 0 or an error.
0, if no received data is available, but everything is in order. If buf_ctx was provided, it was released.
-EADDRNOTAVAIL, if the local endpoint of sock is not set.
-EAGAIN, if timeout is 0 and no data is available.
-EINVAL, if remote is invalid or sock is not properly initialized (or closed while sock_dtls_recv() blocks).
-ENOMEM, if no memory was available to receive data.
-ETIMEDOUT, if timeout expired.

Definition at line 893 of file dtls.h.

◆ sock_dtls_recv_buf_aux()

ssize_t sock_dtls_recv_buf_aux ( sock_dtls_t sock,
sock_dtls_session_t remote,
void **  data,
void **  buf_ctx,
uint32_t  timeout,
sock_dtls_aux_rx_t aux 
)

Decrypts and provides stack-internal buffer space containing a message from a remote peer.

Parameters
[in]sockDTLS sock to use.
[out]remoteRemote DTLS session of the received data. Cannot be NULL.
[out]dataPointer to a stack-internal buffer space containing the received data.
[in,out]buf_ctxStack-internal buffer context. If it points to a NULL pointer, the stack returns a new buffer space for a new packet. If it does not point to a NULL pointer, an existing context is assumed to get a next segment in a buffer.
[in]timeoutReceive timeout in microseconds. If 0 and no data is available, the function returns immediately. May be SOCK_NO_TIMEOUT to wait until data is available.
[out]auxAuxiliary data about the received datagram. May be NULL, if it is not required by the application.
Warning
This feature is experimental!
This function is quite new, not implemented for all stacks yet, and may be subject to sudden API changes. Do not use in production if this is unacceptable.
Note
Function may block if data is not available and timeout != 0
Function blocks if no packet is currently waiting.
Returns
The number of bytes received on success. May not be the complete payload. Continue calling with the returned buf_ctx to get more buffers until result is 0 or an error.
0, if no received data is available, but everything is in order. If buf_ctx was provided, it was released.
-EADDRNOTAVAIL, if the local endpoint of sock is not set.
-EAGAIN, if timeout is 0 and no data is available.
-EINVAL, if remote is invalid or sock is not properly initialized (or closed while sock_dtls_recv() blocks).
-ENOMEM, if no memory was available to receive data.
-ETIMEDOUT, if timeout expired.

◆ sock_dtls_send()

static ssize_t sock_dtls_send ( sock_dtls_t sock,
sock_dtls_session_t remote,
const void *  data,
size_t  len,
uint32_t  timeout 
)
inlinestatic

Encrypts and sends a message to a remote peer.

Parameters
[in]sockDTLS sock to use
[in]remoteDTLS session to use. A new session will be created if no session exist between client and server.
[in]dataPointer where the data to be send are stored
[in]lenLength of data to be send
[in]timeoutHandshake timeout in microseconds. If timeout > 0, will start a new handshake if no session exists yet. The function will block until handshake completed or timed out. May be SOCK_NO_TIMEOUT to block indefinitely until handshake complete.
Note
When blocking, we will need an extra thread to call sock_dtls_recv() function to handle the incoming handshake messages. An example for a blocking handshake is:
  1. Create an empty sock_dtls_session_t object.
  2. Set the UDP endpoint of the peer you want to connect to in the session object with sock_dtls_session_set_udp_ep().
  3. Call sock_dtls_send() with a timeout greater than 0. The send function blocks until the handshake completes or the timeout expires. If the handshake was successful the data has been sent.
Returns
The number of bytes sent on success
-ENOTCONN, if timeout == 0 and no existing session exists with remote
-EADDRINUSE, if sock_dtls_t::udp_sock has no local end-point.
-EAFNOSUPPORT, if remote->ep != NULL and sock_dtls_session_t::ep::family of remote is != AF_UNSPEC and not supported.
-EINVAL, if sock_udp_ep_t::addr of remote->ep is an invalid address.
-EINVAL, if sock_udp_ep_t::port of remote->ep is 0.
-ENOMEM, if no memory was available to send data.
-ETIMEDOUT, 0 < timeout < SOCK_NO_TIMEOUT and timed out.

Definition at line 979 of file dtls.h.

◆ sock_dtls_send_aux()

ssize_t sock_dtls_send_aux ( sock_dtls_t sock,
sock_dtls_session_t remote,
const void *  data,
size_t  len,
uint32_t  timeout,
sock_dtls_aux_tx_t aux 
)

Encrypts and sends a message to a remote peer.

Parameters
[in]sockDTLS sock to use
[in]remoteDTLS session to use. A new session will be created if no session exist between client and server.
[in]dataPointer where the data to be send are stored
[in]lenLength of data to be send
[in]timeoutHandshake timeout in microseconds. If timeout > 0, will start a new handshake if no session exists yet. The function will block until handshake completed or timed out. May be SOCK_NO_TIMEOUT to block indefinitely until handshake complete.
[out]auxAuxiliary data about the transmission. May be NULL, if it is not required by the application.
Note
When blocking, we will need an extra thread to call sock_dtls_recv() function to handle the incoming handshake messages.
Returns
The number of bytes sent on success
-ENOTCONN, if timeout == 0 and no existing session exists with remote
-EADDRINUSE, if sock_dtls_t::udp_sock has no local end-point.
-EAFNOSUPPORT, if remote->ep != NULL and sock_dtls_session_t::ep::family of remote is != AF_UNSPEC and not supported.
-EINVAL, if sock_udp_ep_t::addr of remote->ep is an invalid address.
-EINVAL, if sock_udp_ep_t::port of remote->ep is 0.
-ENOMEM, if no memory was available to send data.
-ETIMEDOUT, 0 < timeout < SOCK_NO_TIMEOUT and timed out.

◆ sock_dtls_session_destroy()

void sock_dtls_session_destroy ( sock_dtls_t sock,
sock_dtls_session_t remote 
)

Destroys an existing DTLS session.

Precondition
(sock != NULL) && (ep != NULL)
Parameters
[in]socksock_dtls_t, which the session is created on
[in]remoteRemote session to destroy
Note
For tinyDTLS this function destroys the session object right after notifying the remote peer about the closing. This is an interim solution, preventing endlessly blocked session slots, but allows as a consequence truncation attacks. More details in the issue.

◆ sock_dtls_session_get_udp_ep()

void sock_dtls_session_get_udp_ep ( const sock_dtls_session_t session,
sock_udp_ep_t ep 
)

Get the remote UDP endpoint from a session.

Precondition
(session != NULL) && (ep != NULL)
Parameters
[in]sessionDTLS session
[out]epUDP endpoint

◆ sock_dtls_session_init()

int sock_dtls_session_init ( sock_dtls_t sock,
const sock_udp_ep_t ep,
sock_dtls_session_t remote 
)

Initialize session handshake.

Sends a ClientHello message to initialize the handshake. Call sock_dtls_recv() to finish the handshake.

Parameters
[in]sockDTLS sock to use
[in]epRemote endpoint to start a handshake with
[out]remoteResulting session
Returns
1, if new handshake is started
0, if there is an existing session
-ENOMEM, not enough memory to allocate for new peer
-EADDRNOTAVAIL, if the local endpoint of sock is not set.
-EINVAL, if remote is invalid or sock is not properly initialized (or closed while sock_udp_recv() blocks).

◆ sock_dtls_session_set_udp_ep()

void sock_dtls_session_set_udp_ep ( sock_dtls_session_t session,
const sock_udp_ep_t ep 
)

Set the remote UDP endpoint from a session.

Precondition
(session != NULL) && (ep != NULL)
Parameters
[in]sessionDTLS session
[in]epUDP endpoint
Note
Function should only be needed when doing a blocking handshake with sock_dtls_send() to set the remote UDP endpoint.