Thanks to visit codestin.com
Credit goes to github.com

Skip to content

extmod/mbedtls: Implement DTLS HelloVerify, update test for MSG_PEEK #17441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

projectgus
Copy link
Contributor

@projectgus projectgus commented Jun 6, 2025

Summary

  • Updates the DTLS support initially added in extmod/modussl_mbedtls: Updated Wire in support for DTLS. #15764.
  • DTLS 1.2 requires the HelloVerify protocol. This was already enabled on esp32 port (part of ESP-IDF config), and this PR enables it on bare metal ports as well as anti-replay attack protection.
  • HelloVerify requires a cookie store to be implemented in the server application that calls mbedTLS. We're using the cookie implementation from mbedTLS (implemented in C), the only Python-facing addition is a new client_id argument for wrap_socket(). MicroPython DTLS server code has to pass a transport-specific client identifier (as bytes) here, in order for HelloVerify to work correctly. The same SSLContext should be reused for all incoming connections.
  • Add a config flag to disable DTLS on bare metal ports that don't need it. Enabled on "Extra" and above by default, so I think all ports with mbedTLS will get DTLS by default.
  • Updated the multi_net test to work with HelloVerify and the new MSG_PEEK receive flag added in extmod/modlwip,esp32,unix: Add support for socket recv flags argument #17312. No longer needs an additional byte to be sent at the start of each connection.

Testing

  • Ran multi_net tests, including updated dtls test, on rp2, stm32 (PYBD_SF2) and esp32 ports. I'm still having (seemingly unrelated) issues with high outgoing UDP packet loss on rp2, but stm32 and esp32 ports passed the test in both directions.
  • Manually tested the mbedTLS in-tree dtls_server and dtls_client programs against a MicroPython client and server (adapted from the multi_net test, with the mbedTLS test certificates swapped in). Tests worked, suggesting MicroPython should now work with any DTLS 1.2 peer.

Trade-offs and Alternatives

  • It's not clear how high the risk of MicroPython DTLS servers amplifying a DDoS attack is, so perhaps the HelloVerify support is not needed on the server side. However, connecting to a (compliant) DTLS 1.2 server requires the DTLS client to implement HelloVerify, and mbedTLS (reasonably) treats HelloVerify as enabled for both server and client concurrently so we need to implement something on the server side or remove DTLS server support (see below for some discussion of this). The "best case" code size impact of only supporting DTLS client is still about half of what's added by this PR.

This work was funded through GitHub sponsors.

@projectgus projectgus added the extmod Relates to extmod/ directory in source label Jun 6, 2025
@projectgus
Copy link
Contributor Author

While reviewing this myself I realised the server DTLS cookie support I implemented is far too naive. Have marked as draft until I have time to improve it.

Copy link

codecov bot commented Jun 6, 2025

Codecov Report

Attention: Patch coverage is 95.00000% with 1 line in your changes missing coverage. Please review.

Project coverage is 98.56%. Comparing base (dc8daad) to head (ac751f1).
Report is 5 commits behind head on master.

Files with missing lines Patch % Lines
extmod/modtls_mbedtls.c 95.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master   #17441   +/-   ##
=======================================
  Coverage   98.56%   98.56%           
=======================================
  Files         169      169           
  Lines       21948    21968   +20     
=======================================
+ Hits        21633    21653   +20     
  Misses        315      315           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

github-actions bot commented Jun 6, 2025

Code size report:

   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64: +2400 +0.281% standard
      stm32:    +0 +0.000% PYBV10
     mimxrt:    +0 +0.000% TEENSY40
        rp2: +1304 +0.142% RPI_PICO_W
       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS
  qemu rv32:    +0 +0.000% VIRT_RV32

@projectgus projectgus force-pushed the bugfix/dtls_session_cookies branch from 1722c92 to 4f55510 Compare June 6, 2025 01:45
@projectgus
Copy link
Contributor Author

projectgus commented Jun 12, 2025

  • The current session cookie algorithm is too naive and doesn't achieve the purpose of HelloVerify (and can be used to DoS the server by creating too many cookies). It should be updated along the lines of the suggestion in the DTLS specification (Cookie = HMAC(Secret, Client-IP, Client-Parameters)).

This is a lot harder than I initially thought, because in MicroPython modmbedtls works with an abstract stream and doesn't have any knowledge of the client IP. Also, adding this will probably add even more code size. But what's currently in this draft is woefully inadequate.

There's two possible ways forward:

  1. Add another Python API extension, so the server code does something like s = ctx.wrap_socket(s, server_side=1, client_cookie=hmac_result) or s = ctx.dtls_wrap_socket(...). This offloads the responsibility (and code size cost) for calculating a secure cookie to Python code (and we could provide a sample implementation or a thin wrapper in micropython-lib that does it correctly). The server code can choose to pass a constant string here, at the cost of potentially becoming a DDoS vector if exposed to untrusted clients.
  2. Drop DTLS server support, support DTLS client only. This makes testing a little harder as we'll need a DTLS server endpoint, but a simple no-op server should be easy enough to stand up (and safe to stand up on the public internet if it implements Hello Verify!)

Leaning towards (2) at the moment because I think the use case for DTLS client in MicroPython is much stronger than the case for needing a DTLS server, but that would mean removing functionality that was in v1.25 (albeit not fully compliant in that version). @keenanjohnson you implemented the original DTLS support in #15764, do you have any thought about this?

@keenanjohnson
Copy link
Contributor

In regards to your question @projectgus , I personally don't see a lot of use for the DTLS server on an embedded device. However, I do think that having the server implemented in micropython does make the unit testing vastly less brittle. Every time I have tied unit tests to some sort of live public service (like you suggest in option 2), I have personally regretted the choice in the long run as it tends to be brittle, people start to encounter all sorts of spurious local test failiures, etc etc.

Given that our main usecase for the server is just unit tests, I feel like moving the cookie calculation to python isn't the worst as long as we caveat the potential for a DDOS in the docs or something in case anyone ever comes along and has a real use case for the server.

Thanks for thinking of me and great work on the project as always.

@projectgus projectgus force-pushed the bugfix/dtls_session_cookies branch from 4f55510 to 25d8871 Compare June 12, 2025 05:47
@projectgus

This comment was marked as outdated.

@projectgus

This comment was marked as outdated.

@projectgus projectgus force-pushed the bugfix/dtls_session_cookies branch from 25d8871 to f333105 Compare June 19, 2025 05:35
This is already enabled in the ESP-IDF mbedTLS config, so provide an
implementation of the cookie store functions. This allows DTLS connections
between two esp32 boards.

The session cookie store is a very simple dictionary associated with the
SSLContext. To work, the server needs to reuse the same SSLContext (but
cookies are never cleaned up, so a server with a high number of clients
should recycle the context periodically.)

Server code still needs to handle the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
error by waiting for the next UDP packet from the client.

Signed-off-by: Angus Gratton <[email protected]>
- 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 <[email protected]>
The original version of this test had to exchange a 1 byte UDP packet
before the DTLS handshake. This is no longer needed due to MSG_PEEK
support.

The test also doesn't work with HelloVerify enabled, as the first
connection attempt always fails with an
MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED result. Anticipate this by listening
for the client twice on the server side.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <[email protected]>
This is an annoying regression caused by including mpconfig.h in 36922df -
the mimxrt platform headers define ARRAY_SIZE and mbedtls also defines in
some source files, using a different parameter name which is a warning in
gcc.

Technically mimxrt SDK is to blame here, but as this isn't a named warning
in gcc the only way to work around it in the mimxrt port would be to
disable all warnings when building this particular mbedTLS source file.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <[email protected]>
@projectgus projectgus force-pushed the bugfix/dtls_session_cookies branch from f333105 to ac751f1 Compare June 20, 2025 05:14
@projectgus
Copy link
Contributor Author

Attention: Patch coverage is 95.00000% with 1 line in your changes missing coverage. Please review.

The line missing coverage here will only be hit if a heap allocation fails part-way through setting up the SSL context, not an easy code path to cover with unit testing.

@projectgus projectgus marked this pull request as ready for review June 20, 2025 06:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extmod Relates to extmod/ directory in source
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants