summaryrefslogtreecommitdiff
path: root/docs/library/ssl.rst
diff options
context:
space:
mode:
authorAngus Gratton <angus@redyak.com.au>2025-06-05 15:32:38 +1000
committerDamien George <damien@micropython.org>2025-07-23 15:47:16 +1000
commit9b7d85227e67a7edd608aab4ff7eb4a838651f75 (patch)
tree4a4681d5567f3782771c7c68367890b66fc56059 /docs/library/ssl.rst
parent41e0ec96cb10580c8d77156ed51c2e34bc2fc0ac (diff)
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>
Diffstat (limited to 'docs/library/ssl.rst')
-rw-r--r--docs/library/ssl.rst48
1 files changed, 42 insertions, 6 deletions
diff --git a/docs/library/ssl.rst b/docs/library/ssl.rst
index 4327c74ba..c86101872 100644
--- a/docs/library/ssl.rst
+++ b/docs/library/ssl.rst
@@ -66,7 +66,7 @@ class SSLContext
Set the available ciphers for sockets created with this context. *ciphers* should be
a list of strings in the `IANA cipher suite format <https://wiki.mozilla.org/Security/Cipher_Suites>`_ .
-.. method:: SSLContext.wrap_socket(sock, *, server_side=False, do_handshake_on_connect=True, server_hostname=None)
+.. method:: SSLContext.wrap_socket(sock, *, server_side=False, do_handshake_on_connect=True, server_hostname=None, client_id=None)
Takes a `stream` *sock* (usually socket.socket instance of ``SOCK_STREAM`` type),
and returns an instance of ssl.SSLSocket, wrapping the underlying stream.
@@ -89,6 +89,9 @@ class SSLContext
server certificate. It also sets the name for Server Name Indication (SNI), allowing the server
to present the proper certificate.
+ - *client_id* is a MicroPython-specific extension argument used only when implementing a DTLS
+ Server. See :ref:`dtls` for details.
+
.. warning::
Some implementations of ``ssl`` module do NOT validate server certificates,
@@ -117,6 +120,8 @@ Exceptions
This exception does NOT exist. Instead its base class, OSError, is used.
+.. _dtls:
+
DTLS support
------------
@@ -125,16 +130,47 @@ DTLS support
This is a MicroPython extension.
-This module supports DTLS in client and server mode via the `PROTOCOL_DTLS_CLIENT`
-and `PROTOCOL_DTLS_SERVER` constants that can be used as the ``protocol`` argument
-of `SSLContext`.
+On most ports, this module supports DTLS in client and server mode via the
+`PROTOCOL_DTLS_CLIENT` and `PROTOCOL_DTLS_SERVER` constants that can be used as
+the ``protocol`` argument of `SSLContext`.
In this case the underlying socket is expected to behave as a datagram socket (i.e.
like the socket opened with ``socket.socket`` with ``socket.AF_INET`` as ``af`` and
``socket.SOCK_DGRAM`` as ``type``).
-DTLS is only supported on ports that use mbed TLS, and it is not enabled by default:
-it requires enabling ``MBEDTLS_SSL_PROTO_DTLS`` in the specific port configuration.
+DTLS is only supported on ports that use mbedTLS, and it is enabled by default
+in most configurations but can be manually disabled by defining
+``MICROPY_PY_SSL_DTLS`` to 0.
+
+DTLS server support
+^^^^^^^^^^^^^^^^^^^
+
+MicroPython's DTLS server support is configured with "Hello Verify" as required
+for DTLS 1.2. This is transparent for DTLS clients, but there are relevant
+considerations when implementing a DTLS server in MicroPython:
+
+- The server should pass an additional argument *client_id* when calling
+ `SSLContext.wrap_socket()`. This ID must be a `bytes` object (or similar) with
+ a transport-specific identifier representing the client.
+
+ The simplest approach is to convert the tuple of ``(client_ip, client_port)``
+ returned from ``socket.recv_from()`` into a byte string, i.e.::
+
+ _, client_addr = sock.recvfrom(1, socket.MSG_PEEK)
+ sock.connect(client_addr) # Connect back to the client
+ sock = ssl_ctx.wrap_socket(sock, server_side=True,
+ client_id=repr(client_addr).encode())
+
+- The first time a client connects, the server call to ``wrap_socket`` will fail
+ with a `OSError` error "Hello Verify Required". This is because the DTLS
+ "Hello Verify" cookie is not yet known by the client. If the same client
+ connects a second time then ``wrap_socket`` will succeed.
+
+- DTLS cookies for "Hello Verify" are associated with the `SSLContext` object,
+ so the same `SSLContext` object should be used to wrap a subsequent connection
+ from the same client. The cookie implementation includes a timeout and has
+ constant memory use regardless of how many clients connect, so it's OK to
+ reuse the same `SSLContext` object for the lifetime of the server.
Constants
---------