1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

sys/net/sock_util: add sock_dtls_establish_session()

This commit is contained in:
Benjamin Valentin 2023-01-13 08:36:20 +01:00
parent a27231fc9e
commit 46764727ab
2 changed files with 128 additions and 0 deletions

View File

@ -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
@ -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
@ -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

View File

@ -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)
@ -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