Skip to content

Commit 41a04d0

Browse files
committed
extmod/modussl_mbedtls: Wire in support for DTLS.
Signed-off-by: Damien Tournoud <damien@platform.sh> & Keenan Johnson <keenan.johnson@gmail.com>
1 parent 1897fe6 commit 41a04d0

File tree

4 files changed

+104
-4
lines changed

4 files changed

+104
-4
lines changed

docs/library/ssl.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,32 @@ Exceptions
117117

118118
This exception does NOT exist. Instead its base class, OSError, is used.
119119

120+
DTLS support
121+
------------
122+
123+
.. admonition:: Difference to CPython
124+
:class: attention
125+
126+
This is a MicroPython extension.
127+
128+
This module supports DTLS in client and server mode via the `PROTOCOL_DTLS_CLIENT`
129+
and `PROTOCOL_DTLS_SERVER` constants that can be used as the ``protocol`` argument
130+
of `SSLContext`.
131+
132+
In this case the underlying socket is expected to behave as a datagram socket (i.e.
133+
like the socket opened with ``socket.socket`` with ``socket.AF_INET`` as ``af`` and
134+
``socket.SOCK_DGRAM`` as ``type``).
135+
136+
DTLS is only supported on ports that use mbed TLS, and it is not enabled by default:
137+
it requires enabling ``MBEDTLS_SSL_PROTO_DTLS`` in the specific port configuration.
138+
120139
Constants
121140
---------
122141

123142
.. data:: ssl.PROTOCOL_TLS_CLIENT
124143
ssl.PROTOCOL_TLS_SERVER
144+
ssl.PROTOCOL_DTLS_CLIENT (when DTLS support is enabled)
145+
ssl.PROTOCOL_DTLS_SERVER (when DTLS support is enabled)
125146

126147
Supported values for the *protocol* parameter.
127148

extmod/modtls_mbedtls.c

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#include "py/stream.h"
3838
#include "py/objstr.h"
3939
#include "py/reader.h"
40+
#include "py/smallint.h"
41+
#include "py/mphal.h"
4042
#include "extmod/vfs.h"
4143

4244
// mbedtls_time_t
@@ -46,6 +48,9 @@
4648
#include "mbedtls/pk.h"
4749
#include "mbedtls/entropy.h"
4850
#include "mbedtls/ctr_drbg.h"
51+
#ifdef MBEDTLS_SSL_PROTO_DTLS
52+
#include "mbedtls/timing.h"
53+
#endif
4954
#include "mbedtls/debug.h"
5055
#include "mbedtls/error.h"
5156
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
@@ -56,6 +61,14 @@
5661

5762
#define MP_STREAM_POLL_RDWR (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)
5863

64+
#define MP_ENDPOINT_IS_SERVER (1 << 0)
65+
#define MP_TRANSPORT_IS_DTLS (1 << 1)
66+
67+
#define MP_PROTOCOL_TLS_CLIENT 0
68+
#define MP_PROTOCOL_TLS_SERVER MP_ENDPOINT_IS_SERVER
69+
#define MP_PROTOCOL_DTLS_CLIENT MP_TRANSPORT_IS_DTLS
70+
#define MP_PROTOCOL_DTLS_SERVER MP_ENDPOINT_IS_SERVER | MP_TRANSPORT_IS_DTLS
71+
5972
// This corresponds to an SSLContext object.
6073
typedef struct _mp_obj_ssl_context_t {
6174
mp_obj_base_t base;
@@ -79,6 +92,12 @@ typedef struct _mp_obj_ssl_socket_t {
7992

8093
uintptr_t poll_mask; // Indicates which read or write operations the protocol needs next
8194
int last_error; // The last error code, if any
95+
96+
#ifdef MBEDTLS_SSL_PROTO_DTLS
97+
mp_uint_t timer_start_ms;
98+
mp_int_t timer_fin_ms;
99+
mp_int_t timer_int_ms;
100+
#endif
82101
} mp_obj_ssl_socket_t;
83102

84103
static const mp_obj_type_t ssl_context_type;
@@ -223,7 +242,10 @@ static mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args
223242
mp_arg_check_num(n_args, n_kw, 1, 1, false);
224243

225244
// This is the "protocol" argument.
226-
mp_int_t endpoint = mp_obj_get_int(args[0]);
245+
mp_int_t protocol = mp_obj_get_int(args[0]);
246+
247+
int endpoint = (protocol & MP_ENDPOINT_IS_SERVER) ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT;
248+
int transport = (protocol & MP_TRANSPORT_IS_DTLS) ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM;
227249

228250
// Create SSLContext object.
229251
#if MICROPY_PY_SSL_FINALISER
@@ -260,7 +282,7 @@ static mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args
260282
}
261283

262284
ret = mbedtls_ssl_config_defaults(&self->conf, endpoint,
263-
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
285+
transport, MBEDTLS_SSL_PRESET_DEFAULT);
264286
if (ret != 0) {
265287
mbedtls_raise_error(ret);
266288
}
@@ -494,6 +516,41 @@ static int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
494516
}
495517
}
496518

519+
#ifdef MBEDTLS_SSL_PROTO_DTLS
520+
static void _mbedtls_timing_set_delay(void *ctx, uint32_t int_ms, uint32_t fin_ms) {
521+
mp_obj_ssl_socket_t *o = (mp_obj_ssl_socket_t *)ctx;
522+
523+
o->timer_int_ms = int_ms;
524+
o->timer_fin_ms = fin_ms;
525+
526+
if (fin_ms != 0) {
527+
o->timer_start_ms = mp_hal_ticks_ms() & (MICROPY_PY_TIME_TICKS_PERIOD - 1);
528+
}
529+
}
530+
531+
static int _mbedtls_timing_get_delay(void *ctx) {
532+
mp_obj_ssl_socket_t *o = (mp_obj_ssl_socket_t *)ctx;
533+
534+
if (o->timer_fin_ms == 0) {
535+
return -1;
536+
}
537+
538+
mp_uint_t now = mp_hal_ticks_ms() & (MICROPY_PY_TIME_TICKS_PERIOD - 1);
539+
mp_int_t elapsed_ms = ((now - o->timer_start_ms + MICROPY_PY_TIME_TICKS_PERIOD / 2) & (MICROPY_PY_TIME_TICKS_PERIOD - 1))
540+
- MICROPY_PY_TIME_TICKS_PERIOD / 2;
541+
542+
if (elapsed_ms >= o->timer_fin_ms) {
543+
return 2;
544+
}
545+
546+
if (elapsed_ms >= o->timer_int_ms) {
547+
return 1;
548+
}
549+
550+
return 0;
551+
}
552+
#endif
553+
497554
static mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock,
498555
bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname) {
499556

@@ -533,6 +590,12 @@ static mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
533590
mp_raise_ValueError(MP_ERROR_TEXT("CERT_REQUIRED requires server_hostname"));
534591
}
535592

593+
#ifdef MBEDTLS_SSL_PROTO_DTLS
594+
mbedtls_ssl_set_timer_cb(&o->ssl, o,
595+
_mbedtls_timing_set_delay,
596+
_mbedtls_timing_get_delay);
597+
#endif
598+
536599
mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
537600

538601
if (do_handshake_on_connect) {
@@ -735,6 +798,12 @@ static const mp_rom_map_elem_t ssl_socket_locals_dict_table[] = {
735798
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
736799
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
737800
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
801+
#ifdef MBEDTLS_SSL_PROTO_DTLS
802+
{ MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&mp_stream_read1_obj) },
803+
{ MP_ROM_QSTR(MP_QSTR_recv_into), MP_ROM_PTR(&mp_stream_readinto_obj) },
804+
{ MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&mp_stream_write1_obj) },
805+
{ MP_ROM_QSTR(MP_QSTR_sendall), MP_ROM_PTR(&mp_stream_write_obj) },
806+
#endif
738807
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
739808
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
740809
#if MICROPY_PY_SSL_FINALISER
@@ -775,8 +844,12 @@ static const mp_rom_map_elem_t mp_module_tls_globals_table[] = {
775844

776845
// Constants.
777846
{ MP_ROM_QSTR(MP_QSTR_MBEDTLS_VERSION), MP_ROM_PTR(&mbedtls_version_obj)},
778-
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_CLIENT), MP_ROM_INT(MBEDTLS_SSL_IS_CLIENT) },
779-
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_SERVER), MP_ROM_INT(MBEDTLS_SSL_IS_SERVER) },
847+
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_CLIENT), MP_ROM_INT(MP_PROTOCOL_TLS_CLIENT) },
848+
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_SERVER), MP_ROM_INT(MP_PROTOCOL_TLS_SERVER) },
849+
#ifdef MBEDTLS_SSL_PROTO_DTLS
850+
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_DTLS_CLIENT), MP_ROM_INT(MP_PROTOCOL_DTLS_CLIENT) },
851+
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_DTLS_SERVER), MP_ROM_INT(MP_PROTOCOL_DTLS_SERVER) },
852+
#endif
780853
{ MP_ROM_QSTR(MP_QSTR_CERT_NONE), MP_ROM_INT(MBEDTLS_SSL_VERIFY_NONE) },
781854
{ MP_ROM_QSTR(MP_QSTR_CERT_OPTIONAL), MP_ROM_INT(MBEDTLS_SSL_VERIFY_OPTIONAL) },
782855
{ MP_ROM_QSTR(MP_QSTR_CERT_REQUIRED), MP_ROM_INT(MBEDTLS_SSL_VERIFY_REQUIRED) },

ports/esp32/boards/sdkconfig.base

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ CONFIG_MBEDTLS_HAVE_TIME_DATE=y
6363
CONFIG_MBEDTLS_PLATFORM_TIME_ALT=y
6464
CONFIG_MBEDTLS_HAVE_TIME=y
6565

66+
# Enable DTLS
67+
CONFIG_MBEDTLS_SSL_PROTO_DTLS=y
68+
6669
# Disable ALPN support as it's not implemented in MicroPython
6770
CONFIG_MBEDTLS_SSL_ALPN=n
6871

ports/unix/mbedtls/mbedtls_config_port.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
// Enable mbedtls modules
3333
#define MBEDTLS_TIMING_C
3434

35+
// Enable DTLS
36+
#define MBEDTLS_SSL_PROTO_DTLS
37+
3538
// Include common mbedtls configuration.
3639
#include "extmod/mbedtls/mbedtls_config_common.h"
3740

0 commit comments

Comments
 (0)