From 18329d3933b0f4997895c0440ab44bbbd689d3a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikolai=20G=C3=BCtschow?= Date: Wed, 29 Oct 2025 16:25:14 +0100 Subject: [PATCH 1/7] pkg/tinydtls: reset async_cb_session for CONN_RECV currently, sock_dtls_get_event_session would return a previous session instead of none as documented fixes an assertion failure in tests/pkg/tinydtls_sock_async on a second request --- pkg/tinydtls/contrib/sock_dtls.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/tinydtls/contrib/sock_dtls.c b/pkg/tinydtls/contrib/sock_dtls.c index b3912930e468..0d7ee1e8c3db 100644 --- a/pkg/tinydtls/contrib/sock_dtls.c +++ b/pkg/tinydtls/contrib/sock_dtls.c @@ -167,6 +167,7 @@ static int _event(struct dtls_context_t *ctx, session_t *session, break; case DTLS_EVENT_CONNECTED: /* we received a session handshake initialization */ + memset(&sock->async_cb_session, 0, sizeof(sock->async_cb_session)); sock->async_cb(sock, SOCK_ASYNC_CONN_RECV, sock->async_cb_arg); break; From 656dd991acdcf316bfa6d20c77059e52a644ca1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikolai=20G=C3=BCtschow?= Date: Wed, 29 Oct 2025 16:27:53 +0100 Subject: [PATCH 2/7] pkg/tinydtls: error on unconsumed application data This way unconsumed application data is not overwritten. --- pkg/tinydtls/contrib/sock_dtls.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/tinydtls/contrib/sock_dtls.c b/pkg/tinydtls/contrib/sock_dtls.c index 0d7ee1e8c3db..178f126d98de 100644 --- a/pkg/tinydtls/contrib/sock_dtls.c +++ b/pkg/tinydtls/contrib/sock_dtls.c @@ -97,6 +97,12 @@ static int _read(struct dtls_context_t *ctx, session_t *session, uint8_t *buf, s { sock_dtls_t *sock = dtls_get_app_data(ctx); + if (sock->buffer.data != NULL) { + DEBUG("sock_dtls: dropping decrypted message\n"); + /* anyhow ignored by tinydtls */ + return -ENOBUFS; + } + DEBUG("sock_dtls: decrypted message arrived\n"); sock->buffer.data = buf; sock->buffer.datalen = len; From 05c3bff945a350745c93546984127027d1651448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikolai=20G=C3=BCtschow?= Date: Wed, 29 Oct 2025 16:30:04 +0100 Subject: [PATCH 3/7] pkg/tinydtls: always handle connection establishment msg first also document that other messages are currently silently ignored from the mbox --- pkg/tinydtls/contrib/sock_dtls.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/pkg/tinydtls/contrib/sock_dtls.c b/pkg/tinydtls/contrib/sock_dtls.c index 178f126d98de..e74f3eb441ac 100644 --- a/pkg/tinydtls/contrib/sock_dtls.c +++ b/pkg/tinydtls/contrib/sock_dtls.c @@ -149,6 +149,8 @@ static int _event(struct dtls_context_t *ctx, session_t *session, } } if (!level && (code != DTLS_EVENT_CONNECT)) { + /* TODO: dTLS alerts and events other than DTLS_EVENT_CONNECTED + * are currently silently ignored on the receiving side */ mbox_put(&sock->mbox, &msg); } @@ -845,13 +847,17 @@ ssize_t sock_dtls_recv_aux(sock_dtls_t *sock, sock_dtls_session_t *remote, uint32_t start_recv = ztimer_now(ZTIMER_USEC); msg_t msg; + /* Check whether there is a session establishment to be acked. */ + while (mbox_try_get(&sock->mbox, &msg)) { + if (msg.type == DTLS_EVENT_CONNECTED) { + return _complete_handshake(sock, remote, msg.content.ptr); + } + /* silently ignore other potential mbox messages */ + } + /* Check whether there is decrypted data available */ if (sock->buffer.data != NULL) { return _copy_buffer(sock, remote, data, max_len); } - else if (mbox_try_get(&sock->mbox, &msg) && - msg.type == DTLS_EVENT_CONNECTED) { - return _complete_handshake(sock, remote, msg.content.ptr); - } /* Crude way to somewhat test that `sock_dtls_aux_rx_t` and * `sock_udp_aux_rx_t` remain compatible: */ static_assert(sizeof(sock_dtls_aux_rx_t) == sizeof(sock_udp_aux_rx_t), @@ -903,6 +909,14 @@ ssize_t sock_dtls_recv_buf_aux(sock_dtls_t *sock, sock_dtls_session_t *remote, uint32_t start_recv = ztimer_now(ZTIMER_USEC); msg_t msg; + /* Check whether there is a session establishment to be acked. */ + while (mbox_try_get(&sock->mbox, &msg)) { + if (msg.type == DTLS_EVENT_CONNECTED) { + return _complete_handshake(sock, remote, msg.content.ptr); + } + /* silently ignore other potential mbox messages */ + } + /* Check whether there is decrypted data available */ if (sock->buffer.data != NULL) { *data = sock->buffer.data; sock->buffer.data = NULL; @@ -910,10 +924,6 @@ ssize_t sock_dtls_recv_buf_aux(sock_dtls_t *sock, sock_dtls_session_t *remote, return sock->buffer.datalen; } - else if (mbox_try_get(&sock->mbox, &msg) && - msg.type == DTLS_EVENT_CONNECTED) { - return _complete_handshake(sock, remote, msg.content.ptr); - } /* Crude way to somewhat test that `sock_dtls_aux_rx_t` and * `sock_udp_aux_rx_t` remain compatible: */ static_assert(sizeof(sock_dtls_aux_rx_t) == sizeof(sock_udp_aux_rx_t), @@ -1058,7 +1068,9 @@ void _udp_cb(sock_udp_t *udp_sock, sock_async_flags_t flags, void *ctx) sock->buf_ctx = data_ctx; res = dtls_handle_message(sock->dtls_ctx, &remote, data, res); - if (sock->buffer.data == NULL) { + if (res < 0 || sock->buffer.data == NULL) { + /* buffer.data will point to decrypted application data, if available. + * if not or on failure, drop potential remaining udp chunks */ _check_more_chunks(udp_sock, &data, &data_ctx, &remote_ep); sock->buf_ctx = NULL; } From 98711946cef5da3f8df18f41de4f5812a399d505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikolai=20G=C3=BCtschow?= Date: Wed, 29 Oct 2025 16:30:54 +0100 Subject: [PATCH 4/7] pkg/tinydtls: fix typo, explicit NULL check --- pkg/tinydtls/contrib/sock_dtls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/tinydtls/contrib/sock_dtls.c b/pkg/tinydtls/contrib/sock_dtls.c index e74f3eb441ac..27e8f5174b6d 100644 --- a/pkg/tinydtls/contrib/sock_dtls.c +++ b/pkg/tinydtls/contrib/sock_dtls.c @@ -733,7 +733,7 @@ ssize_t sock_dtls_sendv_aux(sock_dtls_t *sock, sock_dtls_session_t *remote, #if SOCK_HAS_ASYNC /** * @brief Checks for and iterates for more data chunks within the network - * stacks anternal packet buffer + * stacks internal packet buffer * * When no more chunks exists, `data_ctx` assures cleaning up the internal * buffer state and `sock_udp_recv_buf()` returns 0. @@ -896,7 +896,7 @@ ssize_t sock_dtls_recv_buf_aux(sock_dtls_t *sock, sock_dtls_session_t *remote, sock_udp_ep_t ep; /* 2nd call to the function (with ctx set) will free the data */ - if (*buf_ctx) { + if (*buf_ctx != NULL) { int res = sock_udp_recv_buf_aux(sock->udp_sock, data, buf_ctx, timeout, &ep, (sock_udp_aux_rx_t *)aux); assert(res == 0); From 4e6c3bf45d42c10a5669b06c1ee5e0835fe130e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikolai=20G=C3=BCtschow?= Date: Wed, 29 Oct 2025 16:35:36 +0100 Subject: [PATCH 5/7] pkg/tinydtls: store correct buf_ctx after async call --- pkg/tinydtls/contrib/sock_dtls.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/tinydtls/contrib/sock_dtls.c b/pkg/tinydtls/contrib/sock_dtls.c index 27e8f5174b6d..bd403fc6e2f4 100644 --- a/pkg/tinydtls/contrib/sock_dtls.c +++ b/pkg/tinydtls/contrib/sock_dtls.c @@ -921,7 +921,13 @@ ssize_t sock_dtls_recv_buf_aux(sock_dtls_t *sock, sock_dtls_session_t *remote, *data = sock->buffer.data; sock->buffer.data = NULL; _copy_session(sock, remote); - +#ifdef SOCK_HAS_ASYNC + /* only overwrite buf_ctx if used below during call to dtls_handle_message */ + if (*buf_ctx == NULL) { + *buf_ctx = sock->buf_ctx; + sock->buf_ctx = NULL; + } +#endif /* SOCK_HAS_ASYNC */ return sock->buffer.datalen; } /* Crude way to somewhat test that `sock_dtls_aux_rx_t` and From 3a3c105787773006a357fd1e73363fb688d7de5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikolai=20G=C3=BCtschow?= Date: Wed, 29 Oct 2025 16:36:13 +0100 Subject: [PATCH 6/7] pkg/tinydtls: remove unecessary duplicated flags for async They are not needed as the sock_async_event (and potential other backends should) accumulate(s) the flags internally already, and they have been sent out on data arrival or connection establishment already. --- pkg/tinydtls/contrib/sock_dtls.c | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/pkg/tinydtls/contrib/sock_dtls.c b/pkg/tinydtls/contrib/sock_dtls.c index bd403fc6e2f4..ac0de97cb637 100644 --- a/pkg/tinydtls/contrib/sock_dtls.c +++ b/pkg/tinydtls/contrib/sock_dtls.c @@ -781,18 +781,6 @@ static ssize_t _copy_buffer(sock_dtls_t *sock, sock_dtls_session_t *remote, _copy_session(sock, remote); _check_more_chunks(sock->udp_sock, (void **)&buf, &sock->buf_ctx, &ep); - if (sock->async_cb && - /* is there a message in the sock's mbox? */ - mbox_avail(&sock->mbox)) { - if (sock->buffer.data) { - sock->async_cb(sock, SOCK_ASYNC_MSG_RECV, - sock->async_cb_arg); - } - else { - sock->async_cb(sock, SOCK_ASYNC_CONN_RECV, - sock->async_cb_arg); - } - } return buflen; } #else @@ -809,25 +797,8 @@ static ssize_t _complete_handshake(sock_dtls_t *sock, sock_dtls_session_t *remote, const session_t *session) { - memcpy(&remote->dtls_session, session, sizeof(remote->dtls_session)); -#ifdef SOCK_HAS_ASYNC - if (sock->async_cb) { - sock_async_flags_t flags = SOCK_ASYNC_CONN_RDY; - - if (mbox_avail(&sock->mbox)) { - if (sock->buffer.data) { - flags |= SOCK_ASYNC_MSG_RECV; - } - else { - flags |= SOCK_ASYNC_CONN_RECV; - } - } - memcpy(&sock->async_cb_session, session, sizeof(session_t)); - sock->async_cb(sock, flags, sock->async_cb_arg); - } -#else (void)sock; -#endif + memcpy(&remote->dtls_session, session, sizeof(remote->dtls_session)); return -SOCK_DTLS_HANDSHAKE; } From 59446cf1e84455190742d32dcda7d53d69107ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikolai=20G=C3=BCtschow?= Date: Wed, 29 Oct 2025 17:34:30 +0100 Subject: [PATCH 7/7] sys/net/sock_dtls: document SOCK_DTLS_HANDSHAKE in user guide --- sys/include/net/sock/dtls.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/include/net/sock/dtls.h b/sys/include/net/sock/dtls.h index 4955266709c6..b5cfe46d8e5c 100644 --- a/sys/include/net/sock/dtls.h +++ b/sys/include/net/sock/dtls.h @@ -284,8 +284,9 @@ * 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 != @ref SOCK_NO_TIMEOUT. If an error occurs we just - * ignore it and continue looping. We can reply to an incoming message using - * its `session`. + * ignore it and continue looping. A newly established DTLS session would be + * signaled by a return value - @ref SOCK_DTLS_HANDSHAKE, but it is also ignored + * here. We can reply to an incoming message using its `session`. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c} * while (1) {