extmod/mbedtls: Implement recommended DTLS features, make optional.

- DTLS spec recommends HelloVerify and Anti Replay protection be enabled,
  and these are enabled in the default mbedTLS config. Implement them here.

- To help compensate for the possible increase in code size, add a
  MICROPY_PY_SSL_DTLS build config macro that's enabled for EXTRA and
  above by default.

This allows bare metal mbedTLS ports to use DTLS with HelloVerify support.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
This commit is contained in:
Angus Gratton
2025-06-05 15:32:38 +10:00
committed by Damien George
parent 41e0ec96cb
commit 9b7d85227e
6 changed files with 84 additions and 21 deletions

View File

@@ -26,6 +26,8 @@
#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H
#define MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H
#include "py/mpconfig.h"
// If you want to debug MBEDTLS uncomment the following and
// pass "3" to mbedtls_debug_set_threshold in socket_new.
// #define MBEDTLS_DEBUG_C
@@ -89,12 +91,18 @@
#define MBEDTLS_SHA384_C
#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_PROTO_DTLS
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_X509_CRT_PARSE_C
#define MBEDTLS_X509_USE_C
#if MICROPY_PY_SSL_DTLS
#define MBEDTLS_SSL_PROTO_DTLS
#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
#define MBEDTLS_SSL_COOKIE_C
#endif
// A port may enable this option to select additional bare-metal configuration.
#if MICROPY_MBEDTLS_CONFIG_BARE_METAL

View File

@@ -78,7 +78,7 @@
#define MP_PROTOCOL_TLS_CLIENT 0
#define MP_PROTOCOL_TLS_SERVER MP_ENDPOINT_IS_SERVER
#define MP_PROTOCOL_DTLS_CLIENT MP_TRANSPORT_IS_DTLS
#define MP_PROTOCOL_DTLS_SERVER MP_ENDPOINT_IS_SERVER | MP_TRANSPORT_IS_DTLS
#define MP_PROTOCOL_DTLS_SERVER (MP_ENDPOINT_IS_SERVER | MP_TRANSPORT_IS_DTLS)
// This corresponds to an SSLContext object.
typedef struct _mp_obj_ssl_context_t {
@@ -96,6 +96,7 @@ typedef struct _mp_obj_ssl_context_t {
mp_obj_t ecdsa_sign_callback;
#endif
#ifdef MBEDTLS_SSL_DTLS_HELLO_VERIFY
bool is_dtls_server;
mbedtls_ssl_cookie_ctx cookie_ctx;
#endif
} mp_obj_ssl_context_t;
@@ -328,14 +329,17 @@ static mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args
#endif
#ifdef MBEDTLS_SSL_DTLS_HELLO_VERIFY
mbedtls_ssl_cookie_init(&self->cookie_ctx);
ret = mbedtls_ssl_cookie_setup(&self->cookie_ctx, mbedtls_ctr_drbg_random, &self->ctr_drbg);
if (ret != 0) {
mbedtls_raise_error(ret);
self->is_dtls_server = (protocol == MP_PROTOCOL_DTLS_SERVER);
if (self->is_dtls_server) {
mbedtls_ssl_cookie_init(&self->cookie_ctx);
ret = mbedtls_ssl_cookie_setup(&self->cookie_ctx, mbedtls_ctr_drbg_random, &self->ctr_drbg);
if (ret != 0) {
mbedtls_raise_error(ret);
}
mbedtls_ssl_conf_dtls_cookies(&self->conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check,
&self->cookie_ctx);
}
mbedtls_ssl_conf_dtls_cookies(&self->conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check,
&self->cookie_ctx);
#endif
#endif // MBEDTLS_SSL_DTLS_HELLO_VERIFY
return MP_OBJ_FROM_PTR(self);
}
@@ -664,19 +668,18 @@ static mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
#ifdef MBEDTLS_SSL_PROTO_DTLS
mbedtls_ssl_set_timer_cb(&o->ssl, o, _mbedtls_timing_set_delay, _mbedtls_timing_get_delay);
#endif
#ifdef MBEDTLS_SSL_DTLS_HELLO_VERIFY
if (client_id != mp_const_none) {
if (ssl_context->is_dtls_server) {
// require the client_id parameter for DTLS (as per mbedTLS requirement)
ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
mp_buffer_info_t buf;
if (mp_get_buffer(client_id, &buf, MP_BUFFER_READ)) {
ret = mbedtls_ssl_set_client_transport_id(&o->ssl, buf.buf, buf.len);
} else {
ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
}
if (ret != 0) {
goto cleanup;
}
} else {
// TODO: should it be an error not to provide this argument for DTLS server?
}
#endif