From 86eac795c9b42874b7df89a8931f18f00754252f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 19 Feb 2026 16:26:18 +0100 Subject: [PATCH 1/8] Have MBEDTLS_TIMING_C require MBEDTLS_HAVE_TIME Nowadays, the timing module just builds on a function that provides a timer with millisecond resolution. In terms of platform requirements, this is almost exactly equivalent to `mbedtls_ms_time()` provides (`mbedtls_ms_time()` is arguably a little stronger because it is supposed to last longer than a single timer object, but an application could start a timer when it starts, so there's no real difference.) So it's a bit silly that `timing.c` essentially reimplements this. Rely on `mbedtls_ms_time()` instead. This is an API break because in Mbed TLS 4.0, it was possible to enable `MBEDTLS_TIMING_C` without `MBEDTLS_HAVE_TIME`. However, `timing.c` only provided an implementation for Windows and Unix-like platforms, and on those platforms, it is very likely that the default implementation of `MBEDTLS_HAVE_TIME` would also work. (The main exception would be a platform that has the traditional Unix function `gettimeofday()`, but not the 1990s novelty `clock_gettime()`.) So make this an official requirement, as a belated change that really should have gone into 4.0 if we'd taken the time to dig into it. Signed-off-by: Gilles Peskine --- ChangeLog.d/timing.txt | 5 +++++ configs/config-ccm-psk-dtls1_2.h | 2 +- configs/config-symmetric-only.h | 2 +- configs/crypto-config-ccm-psk-tls1_2.h | 3 ++- configs/crypto-config-thread.h | 1 + include/mbedtls/mbedtls_config.h | 17 ++--------------- library/mbedtls_check_config.h | 5 +++++ 7 files changed, 17 insertions(+), 18 deletions(-) create mode 100644 ChangeLog.d/timing.txt diff --git a/ChangeLog.d/timing.txt b/ChangeLog.d/timing.txt new file mode 100644 index 0000000000..f7d9f1a42b --- /dev/null +++ b/ChangeLog.d/timing.txt @@ -0,0 +1,5 @@ +API changes + * MBEDTLS_TIMING_C now requires MBEDTLS_HAVE_TIME to be enabled in the + TF-PSA-Crypto configuration, unless MBEDTLS_TIMING_ALT is enabled. + As a benefit, platforms where the default implementation is not + supported now only need to implement MBEDTLS_PLATFORM_MS_TIME_ALT. diff --git a/configs/config-ccm-psk-dtls1_2.h b/configs/config-ccm-psk-dtls1_2.h index 6712c331b0..8aaa884b4a 100644 --- a/configs/config-ccm-psk-dtls1_2.h +++ b/configs/config-ccm-psk-dtls1_2.h @@ -29,7 +29,7 @@ #define MBEDTLS_SSL_COOKIE_C #define MBEDTLS_SSL_SRV_C #define MBEDTLS_SSL_TLS_C -#define MBEDTLS_TIMING_C +#define MBEDTLS_TIMING_C //Only used by test programs /* TLS protocol feature support */ #define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED diff --git a/configs/config-symmetric-only.h b/configs/config-symmetric-only.h index 606f4a1bf5..5199489c21 100644 --- a/configs/config-symmetric-only.h +++ b/configs/config-symmetric-only.h @@ -12,5 +12,5 @@ #define MBEDTLS_ERROR_STRERROR_DUMMY #define MBEDTLS_VERSION_FEATURES -#define MBEDTLS_TIMING_C +#define MBEDTLS_TIMING_C //Only for benchmarking #define MBEDTLS_VERSION_C diff --git a/configs/crypto-config-ccm-psk-tls1_2.h b/configs/crypto-config-ccm-psk-tls1_2.h index c2dabc28e8..817835e33e 100644 --- a/configs/crypto-config-ccm-psk-tls1_2.h +++ b/configs/crypto-config-ccm-psk-tls1_2.h @@ -26,7 +26,8 @@ #define MBEDTLS_PSA_CRYPTO_C /* System support */ -//#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */ +/* Optionally used in Hello messages. Needed for DTLS testing. */ +#define MBEDTLS_HAVE_TIME /* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */ #define MBEDTLS_CTR_DRBG_C diff --git a/configs/crypto-config-thread.h b/configs/crypto-config-thread.h index 1b2621cf58..5e0df736e9 100644 --- a/configs/crypto-config-thread.h +++ b/configs/crypto-config-thread.h @@ -48,6 +48,7 @@ /* System support */ #define MBEDTLS_HAVE_ASM +#define MBEDTLS_HAVE_TIME //Only used by test programs #define MBEDTLS_AES_ROM_TABLES #define MBEDTLS_ECP_NIST_OPTIM diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index ad843c70c3..a38b61c147 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -63,22 +63,9 @@ /** * \def MBEDTLS_TIMING_C * - * Enable the semi-portable timing interface. + * Enable a timer interface used by some sample and test programs. * - * \note The provided implementation only works on POSIX/Unix (including Linux, - * BSD and OS X) and Windows. On other platforms, you can either disable that - * module and provide your own implementations of the callbacks needed by - * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide - * your own implementation of the whole module by setting - * \c MBEDTLS_TIMING_ALT in the current file. - * - * \note The timing module will include time.h on suitable platforms - * regardless of the setting of MBEDTLS_HAVE_TIME, unless - * MBEDTLS_TIMING_ALT is used. See timing.c for more information. - * - * \note See also our Knowledge Base article about porting to a new - * environment: - * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * Requires: MBEDTLS_HAVE_TIME or MBEDTLS_TIMING_ALT * * Module: library/timing.c */ diff --git a/library/mbedtls_check_config.h b/library/mbedtls_check_config.h index 855e4e3674..f92c79c0da 100644 --- a/library/mbedtls_check_config.h +++ b/library/mbedtls_check_config.h @@ -363,5 +363,10 @@ #error "MBEDTLS_PKCS7_C is defined, but not all prerequisites" #endif +#if defined(MBEDTLS_TIMING_C) && \ + !(defined(MBEDTLS_HAVE_TIME) || defined(MBEDTLS_TIMING_ALT)) +#error "MBEDTLS_TIMING_C requires either MBEDTLS_HAVE_TIME or MBEDTLS_TIMING_ALT" +#endif + /* *INDENT-ON* */ #endif /* MBEDTLS_CHECK_CONFIG_H */ From 137b5b776dbfb8dd1df8eeeb0bb88b8d2d344b33 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 18 Feb 2026 22:50:07 +0100 Subject: [PATCH 2/8] Simplify MBEDTLS_TIMING_C to use mbedtls_ms_time() Don't ship two slightly different wheels. This reduces our platform adherence by using only `clock_gettime()` in the library and not `gettimeofday()` as well. Signed-off-by: Gilles Peskine --- include/mbedtls/timing.h | 4 +- library/timing.c | 84 ++-------------------------------------- 2 files changed, 6 insertions(+), 82 deletions(-) diff --git a/include/mbedtls/timing.h b/include/mbedtls/timing.h index 62ae1022d9..6b7848c268 100644 --- a/include/mbedtls/timing.h +++ b/include/mbedtls/timing.h @@ -23,11 +23,13 @@ extern "C" { // Regular implementation // +#include + /** * \brief timer structure */ struct mbedtls_timing_hr_time { - uint64_t MBEDTLS_PRIVATE(opaque)[4]; + mbedtls_ms_time_t MBEDTLS_PRIVATE(ms); }; /** diff --git a/library/timing.c b/library/timing.c index 1ed88639ef..45a3ae1575 100644 --- a/library/timing.c +++ b/library/timing.c @@ -13,95 +13,17 @@ #if !defined(MBEDTLS_TIMING_ALT) -#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ - !defined(__HAIKU__) && !defined(__midipix__) -#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in mbedtls_config.h" -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - -#include -#include - -struct _hr_time { - LARGE_INTEGER start; -}; - -#else - -#include -#include -#include -/* time.h should be included independently of MBEDTLS_HAVE_TIME. If the - * platform matches the ifdefs above, it will be used. */ -#include -#include -struct _hr_time { - struct timeval start; -}; -#endif /* _WIN32 && !EFIX64 && !EFI32 */ - -/** - * \brief Return the elapsed time in milliseconds - * - * \warning May change without notice - * - * \param val points to a timer structure - * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. - * - * \return Elapsed time since the previous reset in ms. When - * restarting, this is always 0. - * - * \note To initialize a timer, call this function with reset=1. - * - * Determining the elapsed time and resetting the timer is not - * atomic on all platforms, so after the sequence - * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = - * get_timer(0) }` the value time1+time2 is only approximately - * the delay since the first reset. - */ -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset) { - struct _hr_time *t = (struct _hr_time *) val; - if (reset) { - QueryPerformanceCounter(&t->start); + val->ms = mbedtls_ms_time(); return 0; } else { - unsigned long delta; - LARGE_INTEGER now, hfreq; - QueryPerformanceCounter(&now); - QueryPerformanceFrequency(&hfreq); - delta = (unsigned long) ((now.QuadPart - t->start.QuadPart) * 1000ul - / hfreq.QuadPart); - return delta; + mbedtls_ms_time_t now = mbedtls_ms_time(); + return now - val->ms; } } -#else /* _WIN32 && !EFIX64 && !EFI32 */ - -unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset) -{ - struct _hr_time *t = (struct _hr_time *) val; - - if (reset) { - gettimeofday(&t->start, NULL); - return 0; - } else { - unsigned long delta; - struct timeval now; - gettimeofday(&now, NULL); - delta = (now.tv_sec - t->start.tv_sec) * 1000ul - + (now.tv_usec - t->start.tv_usec) / 1000; - return delta; - } -} - -#endif /* _WIN32 && !EFIX64 && !EFI32 */ - /* * Set delays to watch */ From 7ea318246c0bd68f959ff74d4e0fab71fdbfbd83 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 19 Feb 2026 12:30:00 +0100 Subject: [PATCH 3/8] Fix build error when MBEDTLS_TIMING_C and MBEDTLS_HAVE_TIME are both disabled Signed-off-by: Gilles Peskine --- include/mbedtls/timing.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/timing.h b/include/mbedtls/timing.h index 6b7848c268..01364dd0ba 100644 --- a/include/mbedtls/timing.h +++ b/include/mbedtls/timing.h @@ -29,7 +29,14 @@ extern "C" { * \brief timer structure */ struct mbedtls_timing_hr_time { - mbedtls_ms_time_t MBEDTLS_PRIVATE(ms); +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_ms_time_t ms; +#else + /* Without MBEDTLS_HAVE_TIME, we expose the type definitions and + * function declarations, but they can't be implemented. We do + * need to write something here. */ + unsigned MBEDTLS_PRIVATE(unused); +#endif }; /** From 5890b22b828cfb3f76060691d31e492a174f32e3 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 19 Feb 2026 14:16:42 +0100 Subject: [PATCH 4/8] Fix a build error with MSVC Also fixes a minor bug on Windows with timers running over ~49 days. Signed-off-by: Gilles Peskine --- ChangeLog.d/timing.txt | 8 ++++++++ include/mbedtls/timing.h | 2 +- library/timing.c | 4 ++-- programs/test/udp_proxy.c | 4 +++- programs/x509/load_roots.c | 4 ++-- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/ChangeLog.d/timing.txt b/ChangeLog.d/timing.txt index f7d9f1a42b..96f4feb0e4 100644 --- a/ChangeLog.d/timing.txt +++ b/ChangeLog.d/timing.txt @@ -3,3 +3,11 @@ API changes TF-PSA-Crypto configuration, unless MBEDTLS_TIMING_ALT is enabled. As a benefit, platforms where the default implementation is not supported now only need to implement MBEDTLS_PLATFORM_MS_TIME_ALT. + * When MBEDTLS_TIMING_ALT is enabled, the function + mbedtls_timing_get_timer() now returns unsigned long long instead + of unsigned long. + +Bugfix + * mbedtls_timing_get_delay() now correctly treats a timer as expired + after more than 2^32 ms (about 49 days) on platforms where long is + a 32-bit type. diff --git a/include/mbedtls/timing.h b/include/mbedtls/timing.h index 01364dd0ba..7a2eb938de 100644 --- a/include/mbedtls/timing.h +++ b/include/mbedtls/timing.h @@ -53,7 +53,7 @@ typedef struct mbedtls_timing_delay_context { #endif /* MBEDTLS_TIMING_ALT */ /* Internal use */ -unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset); +unsigned long long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset); /** * \brief Set a pair of delays to watch diff --git a/library/timing.c b/library/timing.c index 45a3ae1575..6273f44c00 100644 --- a/library/timing.c +++ b/library/timing.c @@ -13,7 +13,7 @@ #if !defined(MBEDTLS_TIMING_ALT) -unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset) +unsigned long long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset) { if (reset) { val->ms = mbedtls_ms_time(); @@ -45,7 +45,7 @@ void mbedtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms) int mbedtls_timing_get_delay(void *data) { mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; - unsigned long elapsed_ms; + unsigned long long elapsed_ms; if (ctx->fin_ms == 0) { return -1; diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c index 81de042a50..eab15feb38 100644 --- a/programs/test/udp_proxy.c +++ b/programs/test/udp_proxy.c @@ -360,7 +360,9 @@ static unsigned elapsed_time(void) return 0; } - return mbedtls_timing_get_timer(&hires, 0); + /* Wraps after ~49.7 days (assuming 32-bit int). + * Don't run udp_proxy that long! */ + return (unsigned) mbedtls_timing_get_timer(&hires, 0); } typedef struct { diff --git a/programs/x509/load_roots.c b/programs/x509/load_roots.c index 0222d0f795..8fdccdd6ab 100644 --- a/programs/x509/load_roots.c +++ b/programs/x509/load_roots.c @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) int exit_code = MBEDTLS_EXIT_FAILURE; unsigned i, j; struct mbedtls_timing_hr_time timer; - unsigned long ms; + unsigned long long ms; psa_status_t status = psa_crypto_init(); if (status != PSA_SUCCESS) { @@ -151,7 +151,7 @@ int main(int argc, char *argv[]) mbedtls_printf("."); } ms = mbedtls_timing_get_timer(&timer, 0); - mbedtls_printf("\n%u iterations -> %lu ms\n", opt.iterations, ms); + mbedtls_printf("\n%u iterations -> %llu ms\n", opt.iterations, ms); exit_code = MBEDTLS_EXIT_SUCCESS; exit: From e2b04b68473d020b392d268df42e75cbbfafc4da Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 19 Feb 2026 14:55:25 +0100 Subject: [PATCH 5/8] Don't use printf("%llu") We can't easily printf a `long long` on MingW yet, pending the work on https://github.com/Mbed-TLS/TF-PSA-Crypto/issues/675 for which this is an early stage. A `long` is enough here anyway. Signed-off-by: Gilles Peskine --- programs/x509/load_roots.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/programs/x509/load_roots.c b/programs/x509/load_roots.c index 8fdccdd6ab..215d9453e2 100644 --- a/programs/x509/load_roots.c +++ b/programs/x509/load_roots.c @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) int exit_code = MBEDTLS_EXIT_FAILURE; unsigned i, j; struct mbedtls_timing_hr_time timer; - unsigned long long ms; + unsigned long ms; psa_status_t status = psa_crypto_init(); if (status != PSA_SUCCESS) { @@ -150,8 +150,10 @@ int main(int argc, char *argv[]) } mbedtls_printf("."); } - ms = mbedtls_timing_get_timer(&timer, 0); - mbedtls_printf("\n%u iterations -> %llu ms\n", opt.iterations, ms); + /* On 64-bit Windows and 32-bit platforms, this wraps after about + * 49.7 days. This shouldn't be a problem in practice. */ + ms = (unsigned long) mbedtls_timing_get_timer(&timer, 0); + mbedtls_printf("\n%u iterations -> %lu ms\n", opt.iterations, ms); exit_code = MBEDTLS_EXIT_SUCCESS; exit: From ed642cab9e6ee5891ab88bc34651194c4ab016c7 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 19 Feb 2026 17:24:34 +0100 Subject: [PATCH 6/8] Fix inclusion of when MBEDTLS_HAVE_TIME is disabled Signed-off-by: Gilles Peskine --- include/mbedtls/timing.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/mbedtls/timing.h b/include/mbedtls/timing.h index 7a2eb938de..8c15df58e8 100644 --- a/include/mbedtls/timing.h +++ b/include/mbedtls/timing.h @@ -23,7 +23,9 @@ extern "C" { // Regular implementation // +#if defined(MBEDTLS_HAVE_TIME) #include +#endif /** * \brief timer structure From f004998303611f9514d1e7c9d3dbfe1f726632ea Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Sat, 21 Feb 2026 21:20:22 +0100 Subject: [PATCH 7/8] Add issue number Signed-off-by: Gilles Peskine --- ChangeLog.d/timing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.d/timing.txt b/ChangeLog.d/timing.txt index 96f4feb0e4..b3943cdcf2 100644 --- a/ChangeLog.d/timing.txt +++ b/ChangeLog.d/timing.txt @@ -10,4 +10,4 @@ API changes Bugfix * mbedtls_timing_get_delay() now correctly treats a timer as expired after more than 2^32 ms (about 49 days) on platforms where long is - a 32-bit type. + a 32-bit type. Fixes #10613. From 99c4159681ef5e7ebfce3ca2daf1efc93f0718b2 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Sat, 21 Feb 2026 21:19:42 +0100 Subject: [PATCH 8/8] Disable Unix-like integration code in baremetal builds in all.sh Signed-off-by: Gilles Peskine --- tests/scripts/components-configuration-crypto.sh | 2 +- tests/scripts/components-configuration.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/scripts/components-configuration-crypto.sh b/tests/scripts/components-configuration-crypto.sh index aee412c4a8..baa59fb5f5 100644 --- a/tests/scripts/components-configuration-crypto.sh +++ b/tests/scripts/components-configuration-crypto.sh @@ -528,7 +528,7 @@ component_test_crypto_for_psa_service () { component_build_crypto_baremetal () { msg "build: make, crypto only, baremetal config" scripts/config.py crypto_baremetal - CFLAGS="-O1 -I$PWD/framework/tests/include/baremetal-override/" cmake . + CFLAGS="-O1 -I$PWD/framework/tests/include/baremetal-override/ -DMBEDTLS_TEST_PLATFORM_IS_NOT_UNIXLIKE" cmake . cmake --build . ctest are_empty_libraries library/libmbedx509.* library/libmbedtls.* diff --git a/tests/scripts/components-configuration.sh b/tests/scripts/components-configuration.sh index 89104a3bab..dcd01c7e58 100644 --- a/tests/scripts/components-configuration.sh +++ b/tests/scripts/components-configuration.sh @@ -220,7 +220,7 @@ component_test_full_deprecated_warning () { component_build_baremetal () { msg "build: make, baremetal config" scripts/config.py baremetal - $MAKE_COMMAND CFLAGS="-O1 -Werror -I$PWD/framework/tests/include/baremetal-override/" + $MAKE_COMMAND CFLAGS="-O1 -Werror -I$PWD/framework/tests/include/baremetal-override/ -DMBEDTLS_TEST_PLATFORM_IS_NOT_UNIXLIKE" } support_build_baremetal () {