mbedtls: Add full platform implementation of timing

When MBEDTLS_TIMING_C and MBEDTLS_TIMING_ALT are enabled,
the Arm Compiler generates errors like the following (one for
each missing symbol):

    Error: L6218E: Undefined symbol mbedtls_timing_get_delay

Reason:

The function `mbedtls_timing_self_test()` in the Mbed TLS default
`timing.c` always gets compiled, if MBEDTLS_SELF_TEST is defined.
And MBEDTLS_SELF_TEST is always defined, as we have a Greentea test
to run some of the Mbed TLS self tests. (In the future we should try
not to enable MBEDTLS_SELF_TEST except for tests, but it requires
a rework in our test flow.)

`mbedtls_timing_self_test()` tests (calls) the full API declared in
`timing.h`, and the ARM Compiler requires all symbols referenced by
all functions to be defined, even those not used by the final
application. This is unlike GCC_ARM which resolves what are required.

Solution:

To fix the "undefined symbol" errors, we add an implementation of
`mbedtls_timing_get_timer()` based on Mbed OS `LowPowerTimer` or
`Timer` (depending on which one is available), and copy Mbed TLS's
default `mbedtls_timing_set_delay()` and `mbedtls_timing_get_delay()`
which are built on top of `mbedtls_timing_get_timer()`. This will also
benefit user applications that need to enable timing in Mbed TLS.
pull/14772/head
Lingkai Dong 2021-06-11 12:17:47 +01:00
parent f96f98e60e
commit 17ae051075
1 changed files with 69 additions and 8 deletions

View File

@ -1,6 +1,7 @@
/*
* timing.cpp
*
* Copyright The Mbed TLS Contributors
* Copyright (C) 2021, Arm Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
@ -46,20 +47,23 @@ extern "C" void mbedtls_set_alarm(int seconds)
t.attach(handle_alarm, std::chrono::seconds(seconds));
}
#if !defined(HAVE_HARDCLOCK)
#define HAVE_HARDCLOCK
static int timer_init = 0;
extern "C" unsigned long mbedtls_timing_hardclock(void)
{
// The static Mbed timer here is initialized once only.
// Mbed TLS can have multiple timers (mbedtls_timing_hr_time) derived
// from the Mbed timer.
#if DEVICE_LPTICKER
static mbed::LowPowerTimer timer;
static mbed::LowPowerTimer timer;
#elif DEVICE_USTICKER
static mbed::Timer timer;
static mbed::Timer timer;
#else
#error "MBEDTLS_TIMING_C requires either LPTICKER or USTICKER"
#endif
static int timer_init = 0;
#if !defined(HAVE_HARDCLOCK)
#define HAVE_HARDCLOCK
extern "C" unsigned long mbedtls_timing_hardclock(void)
{
if (timer_init == 0) {
timer.reset();
timer.start();
@ -69,3 +73,60 @@ extern "C" unsigned long mbedtls_timing_hardclock(void)
return timer.elapsed_time().count();
}
#endif /* !HAVE_HARDCLOCK */
extern "C" unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset)
{
if (timer_init == 0) {
timer.reset();
timer.start();
timer_init = 1;
}
if (reset) {
val->start = std::chrono::duration_cast<std::chrono::milliseconds>(timer.elapsed_time()).count();
return 0;
} else {
return std::chrono::duration_cast<std::chrono::milliseconds>(timer.elapsed_time()).count() - val->start;
}
}
/**
* Note: The following implementations come from the default timing.c
* from Mbed TLS. They are disabled in timing.c when MBEDTLS_TIMING_ALT
* is defined, but the implementation is nonetheless applicable to
* Mbed OS, so we copy them over.
*/
extern "C" void mbedtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms)
{
mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
ctx->int_ms = int_ms;
ctx->fin_ms = fin_ms;
if (fin_ms != 0) {
(void) mbedtls_timing_get_timer(&ctx->timer, 1);
}
}
extern "C" int mbedtls_timing_get_delay(void *data)
{
mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
unsigned long elapsed_ms;
if (ctx->fin_ms == 0) {
return -1;
}
elapsed_ms = mbedtls_timing_get_timer(&ctx->timer, 0);
if (elapsed_ms >= ctx->fin_ms) {
return 2;
}
if (elapsed_ms >= ctx->int_ms) {
return 1;
}
return 0;
}