diff --git a/ChangeLog.d/add-milliseconds-time-api.txt b/ChangeLog.d/add-milliseconds-time-api.txt new file mode 100644 index 0000000000..d9e939fadc --- /dev/null +++ b/ChangeLog.d/add-milliseconds-time-api.txt @@ -0,0 +1,5 @@ +API changes + * Add new millisecond time type `mbedtls_ms_time_t` and `mbedtls_ms_time()` + function, needed for TLS 1.3 ticket lifetimes. Alternative implementations + can be created using an ALT interface. + diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index ec0e23a8a4..f5a1bcb67a 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -495,6 +495,16 @@ #error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" #endif +#if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_MS_TIME_ALT) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_MS_TIME_ALT defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) ||\ !defined(MBEDTLS_HAVE_TIME) ) diff --git a/include/mbedtls/debug.h b/include/mbedtls/debug.h index 2b0d00e4c4..74f5d5560b 100644 --- a/include/mbedtls/debug.h +++ b/include/mbedtls/debug.h @@ -131,6 +131,10 @@ #endif \ /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */ +#if !defined(MBEDTLS_PRINTF_MS_TIME) +#define MBEDTLS_PRINTF_MS_TIME PRId64 +#endif /* MBEDTLS_PRINTF_MS_TIME */ + #ifdef __cplusplus extern "C" { #endif diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 0ad6dccb99..89231375ef 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -238,6 +238,7 @@ //#define MBEDTLS_PLATFORM_VSNPRINTF_ALT //#define MBEDTLS_PLATFORM_NV_SEED_ALT //#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT +//#define MBEDTLS_PLATFORM_MS_TIME_ALT /** * \def MBEDTLS_DEPRECATED_WARNING @@ -3675,6 +3676,8 @@ //#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO vsnprintf /**< Default vsnprintf macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ //#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO int64_t //#define MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO int64_t /**< Default milliseconds time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled. It must be signed, and at least 64 bits. If it is changed from the default, MBEDTLS_PRINTF_MS_TIME must be updated to match.*/ +//#define MBEDTLS_PRINTF_MS_TIME PRId64 /**< Default fmt for printf. That's avoid compiler warning if mbedtls_ms_time_t is redefined */ /** \def MBEDTLS_CHECK_RETURN * diff --git a/include/mbedtls/platform_time.h b/include/mbedtls/platform_time.h index eae6f5f879..c7973d9fc1 100644 --- a/include/mbedtls/platform_time.h +++ b/include/mbedtls/platform_time.h @@ -39,6 +39,29 @@ typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; typedef time_t mbedtls_time_t; #endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ +#if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO) +typedef MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO mbedtls_ms_time_t; +#else +#include +#include +typedef int64_t mbedtls_ms_time_t; +#endif /* MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO */ + +/** + * \brief Get time in milliseconds. + * + * \return Monotonically-increasing current time in milliseconds. + * + * \note Define MBEDTLS_PLATFORM_MS_TIME_ALT to be able to provide an + * alternative implementation + * + * \warning This function returns a monotonically-increasing time value from a + * start time that will differ from platform to platform, and possibly + * from run to run of the process. + * + */ +mbedtls_ms_time_t mbedtls_ms_time(void); + /* * The function pointers for time */ diff --git a/library/platform_util.c b/library/platform_util.c index f891cd48a3..e903f8ed32 100644 --- a/library/platform_util.c +++ b/library/platform_util.c @@ -219,3 +219,45 @@ extern inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x); extern inline uint64_t mbedtls_get_unaligned_uint64(const void *p); extern inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x); + +#if defined(MBEDTLS_HAVE_TIME) && !defined(MBEDTLS_PLATFORM_MS_TIME_ALT) + +#include +#if !defined(_WIN32) && \ + (defined(unix) || defined(__unix) || defined(__unix__) || \ + (defined(__APPLE__) && defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || (__APPLE__ && __MACH__)) */ +#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 199309L) +mbedtls_ms_time_t mbedtls_ms_time(void) +{ + int ret; + struct timespec tv; + mbedtls_ms_time_t current_ms; + + ret = clock_gettime(CLOCK_MONOTONIC, &tv); + if (ret) { + return time(NULL) * 1000; + } + + current_ms = tv.tv_sec; + + return current_ms*1000 + tv.tv_nsec / 1000000; +} +#elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ + defined(__MINGW32__) || defined(_WIN64) +#include +mbedtls_ms_time_t mbedtls_ms_time(void) +{ + FILETIME ct; + mbedtls_ms_time_t current_ms; + + GetSystemTimeAsFileTime(&ct); + current_ms = ((mbedtls_ms_time_t) ct.dwLowDateTime + + ((mbedtls_ms_time_t) (ct.dwHighDateTime) << 32LL))/10000; + return current_ms; +} +#else +#error "No mbedtls_ms_time available" +#endif +#endif /* MBEDTLS_HAVE_TIME && !MBEDTLS_PLATFORM_MS_TIME_ALT */ diff --git a/scripts/config.py b/scripts/config.py index 404a5eff2c..ac5f77cebe 100755 --- a/scripts/config.py +++ b/scripts/config.py @@ -230,7 +230,7 @@ def is_seamless_alt(name): Exclude alternative implementations of library functions since they require an implementation of the relevant functions and an xxx_alt.h header. """ - if name == 'MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT': + if name in ('MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT', 'MBEDTLS_PLATFORM_MS_TIME_ALT'): # Similar to non-platform xxx_ALT, requires platform_alt.h return False return name.startswith('MBEDTLS_PLATFORM_') diff --git a/tests/suites/test_suite_platform.data b/tests/suites/test_suite_platform.data new file mode 100644 index 0000000000..557b586eb6 --- /dev/null +++ b/tests/suites/test_suite_platform.data @@ -0,0 +1,12 @@ + +Time: get milliseconds +time_get_milliseconds: + +Time: get seconds +time_get_seconds: + +Time: delay milliseconds +time_delay_milliseconds:1000 + +Time: delay seconds +time_delay_seconds:1 diff --git a/tests/suites/test_suite_platform.function b/tests/suites/test_suite_platform.function new file mode 100644 index 0000000000..54ddd42c3c --- /dev/null +++ b/tests/suites/test_suite_platform.function @@ -0,0 +1,91 @@ +/* BEGIN_HEADER */ + +/* This test module exercises the platform_* module. Since, depending on the + * underlying operating system, the time routines are not always reliable, + * this suite only performs very basic sanity checks of the timing API. + */ + +#include + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" + +#ifdef WIN32 +#include +#elif _POSIX_C_SOURCE >= 199309L +#include +#else +#include +#endif +void sleep_ms(int milliseconds) +{ +#ifdef WIN32 + Sleep(milliseconds); +#elif _POSIX_C_SOURCE >= 199309L + struct timespec ts; + ts.tv_sec = milliseconds / 1000; + ts.tv_nsec = (milliseconds % 1000) * 1000000; + nanosleep(&ts, NULL); +#else + usleep(milliseconds * 1000); +#endif +} +#endif + +/* END_HEADER */ + +/* BEGIN_DEPENDENCIES */ + +/* END_DEPENDENCIES */ + + + +/* BEGIN_CASE depends_on:MBEDTLS_HAVE_TIME */ +void time_get_milliseconds() +{ + mbedtls_ms_time_t current = mbedtls_ms_time(); + (void) current; + /* This goto is added to avoid warnings from the generated code. */ + goto exit; +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_HAVE_TIME */ +void time_get_seconds() +{ + mbedtls_time_t current = mbedtls_time(NULL); + (void) current; + /* This goto is added to avoid warnings from the generated code. */ + goto exit; +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_HAVE_TIME */ +void time_delay_milliseconds(int delay_ms) +{ + mbedtls_ms_time_t current = mbedtls_ms_time(); + mbedtls_ms_time_t elapsed_ms; + + sleep_ms(delay_ms); + + elapsed_ms = mbedtls_ms_time() - current; + TEST_ASSERT(elapsed_ms >= delay_ms && elapsed_ms < 4000 + delay_ms); + /* This goto is added to avoid warnings from the generated code. */ + goto exit; +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_HAVE_TIME */ +void time_delay_seconds(int delay_secs) +{ + mbedtls_time_t current = mbedtls_time(NULL); + mbedtls_time_t elapsed_secs; + + sleep_ms(delay_secs * 1000); + + elapsed_secs = mbedtls_time(NULL) - current; + TEST_ASSERT(elapsed_secs >= delay_secs && elapsed_secs < 4 + delay_secs); + /* This goto is added to avoid warnings from the generated code. */ + goto exit; +} +/* END_CASE */