Skip to content

Commit

Permalink
Merge #19142
Browse files Browse the repository at this point in the history
19142: sock_dtls: move common code into sock_dtls_establish_session() r=benpicco a=benpicco



Co-authored-by: Benjamin Valentin <benpicco@beuth-hochschule.de>
  • Loading branch information
bors[bot] and benpicco authored Feb 19, 2023
2 parents 810f8a8 + df4ef80 commit 96a7d0d
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 147 deletions.
14 changes: 0 additions & 14 deletions sys/include/net/nanocoap_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,20 +145,6 @@
extern "C" {
#endif

/**
* @brief Timeout for CoAP over DTLS queries in milliseconds
*/
#ifndef CONFIG_NANOCOAP_SOCK_DTLS_TIMEOUT_MS
#define CONFIG_NANOCOAP_SOCK_DTLS_TIMEOUT_MS (1000U)
#endif

/**
* @brief Number of CoAP over DTLS handshake retries
*/
#ifndef CONFIG_NANOCOAP_SOCK_DTLS_RETRIES
#define CONFIG_NANOCOAP_SOCK_DTLS_RETRIES (2)
#endif

/**
* @brief Credman tag used for NanoCoAP
* Tag together with the credential type (PSK) needs to be unique
Expand Down
42 changes: 42 additions & 0 deletions sys/include/net/sock/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
#include "net/sock/udp.h"
#include "net/sock/tcp.h"

#ifdef MODULE_SOCK_DTLS
#include "net/credman.h"
#include "net/sock/dtls.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -268,6 +273,29 @@ static inline bool sock_udp_ep_equal(const sock_udp_ep_t *a,
return sock_tl_ep_equal(a, b);
}

#if defined(MODULE_SOCK_DTLS) || DOXYGEN
/**
* @brief Helper function to establish a DTLS connection
*
* @param[out] sock_udp Struct to store the underlying UDP socket
* @param[out] sock_dtls Struct for the actual DTLS socket
* @param[out] session Struct to store DTLS session information
* @param[in] tag Credential tag to use
* @param[in] local Local endpoint, must not be NULL
* @param[in] remote Server endpoint to connect to
* @param[in] work_buf Buffer used to negotiate connection
* @param[in] work_buf_len Size of @p work buf. Should be at least
* 160 bytes for AES_128_CCM_8 with PSK
*
* @return 0 on success
* @return negative error otherwise (see @ref sock_dtls_recv_aux)
*/
int sock_dtls_establish_session(sock_udp_t *sock_udp, sock_dtls_t *sock_dtls,
sock_dtls_session_t *session, credman_tag_t tag,
sock_udp_ep_t *local, const sock_udp_ep_t *remote,
void *work_buf, size_t work_buf_len);
#endif

/**
* @defgroup net_sock_util_conf SOCK utility functions compile configurations
* @ingroup net_sock_conf
Expand Down Expand Up @@ -297,6 +325,20 @@ static inline bool sock_udp_ep_equal(const sock_udp_ep_t *a,
#endif
/** @} */

/**
* @brief Timeout in milliseconds for sock_dtls_establish_session()
*/
#ifndef CONFIG_SOCK_DTLS_TIMEOUT_MS
#define CONFIG_SOCK_DTLS_TIMEOUT_MS (1000U)
#endif

/**
* @brief Number of DTLS handshake retries for sock_dtls_establish_session()
*/
#ifndef CONFIG_SOCK_DTLS_RETRIES
#define CONFIG_SOCK_DTLS_RETRIES (2)
#endif

#ifdef __cplusplus
}
#endif
Expand Down
81 changes: 6 additions & 75 deletions sys/net/application_layer/nanocoap/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,92 +62,23 @@ typedef struct {
bool more;
} _block_ctx_t;

#if IS_USED(MODULE_NANOCOAP_DTLS)
int nanocoap_sock_dtls_connect(nanocoap_sock_t *sock, sock_udp_ep_t *local,
const sock_udp_ep_t *remote, credman_tag_t tag)
{
int res;
uint32_t timeout_ms = CONFIG_NANOCOAP_SOCK_DTLS_TIMEOUT_MS;
uint8_t retries = CONFIG_NANOCOAP_SOCK_DTLS_RETRIES;

bool auto_port = local->port == 0;
do {
if (auto_port) {
/* choose random ephemeral port, since DTLS requires a local port */
local->port = random_uint32_range(IANA_DYNAMIC_PORTRANGE_MIN,
IANA_DYNAMIC_PORTRANGE_MAX);
}
/* connect UDP socket */
res = nanocoap_sock_connect(sock, local, remote);
} while (auto_port && (res == -EADDRINUSE));

if (res < 0) {
return res;
}
#if IS_USED(MODULE_NANOCOAP_DTLS)
uint8_t buf[CONFIG_NANOCOAP_DTLS_HANDSHAKE_BUF_SIZE];

/* create DTLS socket on to of UDP socket */
res = sock_dtls_create(&sock->dtls, &sock->udp, tag,
SOCK_DTLS_1_2, SOCK_DTLS_CLIENT);
if (res < 0) {
DEBUG("Unable to create DTLS sock: %s\n", strerror(-res));
nanocoap_sock_close(sock);
return res;
}
sock->type = COAP_SOCKET_TYPE_DTLS;

while (1) {
uint8_t buf[CONFIG_NANOCOAP_DTLS_HANDSHAKE_BUF_SIZE];
mutex_t lock = MUTEX_INIT_LOCKED;
ztimer_t timeout;

/* unlock lock after timeout */
ztimer_mutex_unlock(ZTIMER_MSEC, &timeout, timeout_ms, &lock);

/* create DTLS session */
res = sock_dtls_session_init(&sock->dtls, remote, &sock->dtls_session);
if (res >= 0) {
/* handle handshake */
res = sock_dtls_recv(&sock->dtls, &sock->dtls_session, buf,
sizeof(buf), timeout_ms * US_PER_MS);
if (res == -SOCK_DTLS_HANDSHAKE) {
DEBUG("DTLS handshake successful\n");
ztimer_remove(ZTIMER_MSEC, &timeout);
return 0;
}
DEBUG("Unable to establish DTLS handshake: %s\n", strerror(-res));

} else {
DEBUG("Unable to initialize DTLS session: %s\n", strerror(-res));
}

sock_dtls_session_destroy(&sock->dtls, &sock->dtls_session);

if (retries--) {
/* wait for timeout to expire */
mutex_lock(&lock);
} else {
ztimer_remove(ZTIMER_MSEC, &timeout);
break;
}

/* see https://datatracker.ietf.org/doc/html/rfc6347#section-4.2.4.1 */
timeout_ms *= 2U;
}

nanocoap_sock_close(sock);
return res;
}
return sock_dtls_establish_session(&sock->udp, &sock->dtls, &sock->dtls_session,
tag, local, remote, buf, sizeof(buf));
#else
int nanocoap_sock_dtls_connect(nanocoap_sock_t *sock, const sock_udp_ep_t *local,
const sock_udp_ep_t *remote, credman_tag_t tag)
{
(void)sock;
(void)local;
(void)remote;
(void)tag;
return -ENOTSUP;
}
#endif
}

static int _get_error(const coap_pkt_t *pkt)
{
Expand Down Expand Up @@ -179,7 +110,7 @@ static int _sock_sendv(nanocoap_sock_t *sock, const iolist_t *snips)
#if IS_USED(MODULE_NANOCOAP_DTLS)
case COAP_SOCKET_TYPE_DTLS:
return sock_dtls_sendv(&sock->dtls, &sock->dtls_session, snips,
CONFIG_NANOCOAP_SOCK_DTLS_TIMEOUT_MS);
CONFIG_SOCK_DTLS_TIMEOUT_MS);
#endif
default:
assert(0);
Expand Down
64 changes: 6 additions & 58 deletions sys/net/application_layer/sock_dodtls/sock_dodtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "net/iana/portrange.h"
#include "net/sock/dtls.h"
#include "net/sock/udp.h"
#include "net/sock/util.h"
#include "net/sock/dodtls.h"
#include "random.h"
#include "ztimer.h"
Expand Down Expand Up @@ -170,28 +171,16 @@ static void _close_session(credman_tag_t creds_tag, credman_type_t creds_type)
static int _connect_server(const sock_udp_ep_t *server,
const credman_credential_t *creds)
{
int res = -EADDRINUSE;
uint32_t start, try_start, timeout = SOCK_DODTLS_SESSION_RECV_TIMEOUT_MS;
int res;
sock_udp_ep_t local = SOCK_IPV6_EP_ANY;

/* server != NULL is checked in sock_dodtls_set_server() */
assert(creds != NULL);
mutex_lock(&_server_mutex);
while (res == -EADDRINUSE) {
/* choose random ephemeral port, since DTLS requires a local port */
local.port = IANA_DYNAMIC_PORTRANGE_MIN +
(random_uint32() % (IANA_SYSTEM_PORTRANGE_MAX - IANA_DYNAMIC_PORTRANGE_MIN));
if ((res = sock_udp_create(&_udp_sock, &local, server, 0)) < 0) {
if (res != -EADDRINUSE) {
DEBUG("Unable to create UDP sock\n");
goto exit;
}
}
}

res = credman_add(creds);
if (res < 0 && res != CREDMAN_EXIST) {
DEBUG("Unable to add credential to credman\n");
_close_session(creds->tag, creds->type);
switch (res) {
case CREDMAN_NO_SPACE:
res = -ENOSPC;
Expand All @@ -205,55 +194,14 @@ static int _connect_server(const sock_udp_ep_t *server,
}
goto exit;
}
if ((res = sock_dtls_create(&_dtls_sock, &_udp_sock, creds->tag,
SOCK_DTLS_1_2, SOCK_DTLS_CLIENT)) < 0) {
puts("Unable to create DTLS sock\n");
_close_session(creds->tag, creds->type);
goto exit;
}

start = _now_ms();
try_start = start;
while (((try_start = _now_ms()) - start) < SOCK_DODTLS_SESSION_TIMEOUT_MS) {
memset(&_server_session, 0, sizeof(_server_session));
if ((res = sock_dtls_session_init(&_dtls_sock, server,
&_server_session)) >= 0) {
uint32_t try_duration;

res = sock_dtls_recv(&_dtls_sock, &_server_session, _dns_buf,
sizeof(_dns_buf), timeout * US_PER_MS);
if (res == -SOCK_DTLS_HANDSHAKE) {
break;
}
DEBUG("Unable to establish DTLS handshake: %d (timeout: %luus)\n",
-res, (long unsigned)timeout * US_PER_MS);
sock_dtls_session_destroy(&_dtls_sock, &_server_session);
try_duration = _now_ms() - try_start;
if (try_duration < timeout) {
_sleep_ms(timeout - try_duration);
}
/* see https://datatracker.ietf.org/doc/html/rfc6347#section-4.2.4.1 */
timeout *= 2U;
}
else {
DEBUG("Unable to initialize DTLS session: %d\n", -res);
sock_dtls_session_destroy(&_dtls_sock, &_server_session);
}
}
if (res != -SOCK_DTLS_HANDSHAKE) {
res = -ETIMEDOUT;
_close_session(creds->tag, creds->type);
goto exit;
}
else {
res = 0;
}

res = sock_dtls_establish_session(&_udp_sock, &_dtls_sock, &_server_session,
creds->tag, &local, server, _dns_buf,
sizeof(_dns_buf));
_cred_type = creds->type;
_cred_tag = creds->tag;
_id = (uint16_t)(random_uint32() & 0xffff);
exit:
memset(_dns_buf, 0, sizeof(_dns_buf)); /* flush-out unencrypted data */
mutex_unlock(&_server_mutex);
return (res > 0) ? 0 : res;
}
Expand Down
86 changes: 86 additions & 0 deletions sys/net/sock/sock_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,23 @@

#include "net/sock/udp.h"
#include "net/sock/util.h"
#include "net/iana/portrange.h"

#if defined(MODULE_DNS)
#include "net/dns.h"
#endif

#ifdef MODULE_RANDOM
#include "random.h"
#endif

#ifdef MODULE_FMT
#include "fmt.h"
#endif

#define ENABLE_DEBUG 0
#include "debug.h"

#define PORT_STR_LEN (5)
#define NETIF_STR_LEN (5)

Expand Down Expand Up @@ -347,3 +355,81 @@ bool sock_tl_ep_equal(const struct _sock_tl_ep *a,
return false;
}
}

#if defined(MODULE_SOCK_DTLS)
int sock_dtls_establish_session(sock_udp_t *sock_udp, sock_dtls_t *sock_dtls,
sock_dtls_session_t *session, credman_tag_t tag,
sock_udp_ep_t *local, const sock_udp_ep_t *remote,
void *work_buf, size_t work_buf_len)
{
int res;
uint32_t timeout_ms = CONFIG_SOCK_DTLS_TIMEOUT_MS;
uint8_t retries = CONFIG_SOCK_DTLS_RETRIES;

bool auto_port = local->port == 0;
do {
if (auto_port) {
/* choose random ephemeral port, since DTLS requires a local port */
local->port = random_uint32_range(IANA_DYNAMIC_PORTRANGE_MIN,
IANA_DYNAMIC_PORTRANGE_MAX);
}
/* connect UDP socket */
res = sock_udp_create(sock_udp, local, remote, 0);
} while (auto_port && (res == -EADDRINUSE));

if (res < 0) {
return res;
}

/* create DTLS socket on to of UDP socket */
res = sock_dtls_create(sock_dtls, sock_udp, tag,
SOCK_DTLS_1_2, SOCK_DTLS_CLIENT);
if (res < 0) {
DEBUG("Unable to create DTLS sock: %s\n", strerror(-res));
sock_udp_close(sock_udp);
return res;
}

while (1) {
mutex_t lock = MUTEX_INIT_LOCKED;
ztimer_t timeout;

/* unlock lock after timeout */
ztimer_mutex_unlock(ZTIMER_MSEC, &timeout, timeout_ms, &lock);

/* create DTLS session */
res = sock_dtls_session_init(sock_dtls, remote, session);
if (res >= 0) {
/* handle handshake */
res = sock_dtls_recv(sock_dtls, session, work_buf,
work_buf_len, timeout_ms * US_PER_MS);
if (res == -SOCK_DTLS_HANDSHAKE) {
DEBUG("DTLS handshake successful\n");
ztimer_remove(ZTIMER_MSEC, &timeout);
return 0;
}
DEBUG("Unable to establish DTLS handshake: %s\n", strerror(-res));

} else {
DEBUG("Unable to initialize DTLS session: %s\n", strerror(-res));
}

sock_dtls_session_destroy(sock_dtls, session);

if (retries--) {
/* wait for timeout to expire */
mutex_lock(&lock);
} else {
ztimer_remove(ZTIMER_MSEC, &timeout);
break;
}

/* see https://datatracker.ietf.org/doc/html/rfc6347#section-4.2.4.1 */
timeout_ms *= 2U;
}

sock_dtls_close(sock_dtls);
sock_udp_close(sock_udp);
return res;
}
#endif

0 comments on commit 96a7d0d

Please sign in to comment.