Merge pull request #10607 from gilles-peskine-arm/timing-use-mstime

Simplify MBEDTLS_TIMING_C to use mbedtls_ms_time()
This commit is contained in:
Bence Szépkúti
2026-02-26 14:38:50 +00:00
committed by GitHub
13 changed files with 51 additions and 107 deletions

13
ChangeLog.d/timing.txt Normal file
View File

@@ -0,0 +1,13 @@
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.
* 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. Fixes #10613.

View File

@@ -29,7 +29,7 @@
#define MBEDTLS_SSL_COOKIE_C #define MBEDTLS_SSL_COOKIE_C
#define MBEDTLS_SSL_SRV_C #define MBEDTLS_SSL_SRV_C
#define MBEDTLS_SSL_TLS_C #define MBEDTLS_SSL_TLS_C
#define MBEDTLS_TIMING_C #define MBEDTLS_TIMING_C //Only used by test programs
/* TLS protocol feature support */ /* TLS protocol feature support */
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED #define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED

View File

@@ -12,5 +12,5 @@
#define MBEDTLS_ERROR_STRERROR_DUMMY #define MBEDTLS_ERROR_STRERROR_DUMMY
#define MBEDTLS_VERSION_FEATURES #define MBEDTLS_VERSION_FEATURES
#define MBEDTLS_TIMING_C #define MBEDTLS_TIMING_C //Only for benchmarking
#define MBEDTLS_VERSION_C #define MBEDTLS_VERSION_C

View File

@@ -26,7 +26,8 @@
#define MBEDTLS_PSA_CRYPTO_C #define MBEDTLS_PSA_CRYPTO_C
/* System support */ /* 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 */ /* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */
#define MBEDTLS_CTR_DRBG_C #define MBEDTLS_CTR_DRBG_C

View File

@@ -48,6 +48,7 @@
/* System support */ /* System support */
#define MBEDTLS_HAVE_ASM #define MBEDTLS_HAVE_ASM
#define MBEDTLS_HAVE_TIME //Only used by test programs
#define MBEDTLS_AES_ROM_TABLES #define MBEDTLS_AES_ROM_TABLES
#define MBEDTLS_ECP_NIST_OPTIM #define MBEDTLS_ECP_NIST_OPTIM

View File

@@ -63,22 +63,9 @@
/** /**
* \def MBEDTLS_TIMING_C * \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, * Requires: MBEDTLS_HAVE_TIME or MBEDTLS_TIMING_ALT
* 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
* *
* Module: library/timing.c * Module: library/timing.c
*/ */

View File

@@ -23,11 +23,22 @@ extern "C" {
// Regular implementation // Regular implementation
// //
#if defined(MBEDTLS_HAVE_TIME)
#include <mbedtls/platform_time.h>
#endif
/** /**
* \brief timer structure * \brief timer structure
*/ */
struct mbedtls_timing_hr_time { struct mbedtls_timing_hr_time {
uint64_t MBEDTLS_PRIVATE(opaque)[4]; #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
}; };
/** /**
@@ -44,7 +55,7 @@ typedef struct mbedtls_timing_delay_context {
#endif /* MBEDTLS_TIMING_ALT */ #endif /* MBEDTLS_TIMING_ALT */
/* Internal use */ /* 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 * \brief Set a pair of delays to watch

View File

@@ -358,5 +358,10 @@
#error "MBEDTLS_PKCS7_C is defined, but not all prerequisites" #error "MBEDTLS_PKCS7_C is defined, but not all prerequisites"
#endif #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* */ /* *INDENT-ON* */
#endif /* MBEDTLS_CHECK_CONFIG_H */ #endif /* MBEDTLS_CHECK_CONFIG_H */

View File

@@ -13,95 +13,17 @@
#if !defined(MBEDTLS_TIMING_ALT) #if !defined(MBEDTLS_TIMING_ALT)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ unsigned long long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset)
!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 <windows.h>
#include <process.h>
struct _hr_time {
LARGE_INTEGER start;
};
#else
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
/* time.h should be included independently of MBEDTLS_HAVE_TIME. If the
* platform matches the ifdefs above, it will be used. */
#include <time.h>
#include <sys/time.h>
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) { if (reset) {
QueryPerformanceCounter(&t->start); val->ms = mbedtls_ms_time();
return 0; return 0;
} else { } else {
unsigned long delta; mbedtls_ms_time_t now = mbedtls_ms_time();
LARGE_INTEGER now, hfreq; return now - val->ms;
QueryPerformanceCounter(&now);
QueryPerformanceFrequency(&hfreq);
delta = (unsigned long) ((now.QuadPart - t->start.QuadPart) * 1000ul
/ hfreq.QuadPart);
return delta;
} }
} }
#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 * Set delays to watch
*/ */
@@ -123,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) int mbedtls_timing_get_delay(void *data)
{ {
mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) 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) { if (ctx->fin_ms == 0) {
return -1; return -1;

View File

@@ -360,7 +360,9 @@ static unsigned elapsed_time(void)
return 0; 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 { typedef struct {

View File

@@ -150,7 +150,9 @@ int main(int argc, char *argv[])
} }
mbedtls_printf("."); mbedtls_printf(".");
} }
ms = mbedtls_timing_get_timer(&timer, 0); /* 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); mbedtls_printf("\n%u iterations -> %lu ms\n", opt.iterations, ms);
exit_code = MBEDTLS_EXIT_SUCCESS; exit_code = MBEDTLS_EXIT_SUCCESS;

View File

@@ -528,7 +528,7 @@ component_test_crypto_for_psa_service () {
component_build_crypto_baremetal () { component_build_crypto_baremetal () {
msg "build: make, crypto only, baremetal config" msg "build: make, crypto only, baremetal config"
scripts/config.py crypto_baremetal 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 . cmake --build .
ctest ctest
are_empty_libraries library/libmbedx509.* library/libmbedtls.* are_empty_libraries library/libmbedx509.* library/libmbedtls.*

View File

@@ -220,7 +220,7 @@ component_test_full_deprecated_warning () {
component_build_baremetal () { component_build_baremetal () {
msg "build: make, baremetal config" msg "build: make, baremetal config"
scripts/config.py baremetal 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 () { support_build_baremetal () {