Mbed TLS
Mbed TLS is the cryptography and TLS library ST integrates through CubeMX. It is usable on parts with enough memory — budget at least 60 KB flash and 64 KB SRAM for a minimal build, more once a full TLS handshake is involved.
The examples below use SHA-1 because it is the smallest thing to wire up and verify. SHA-1 is broken for signatures and certificates; use SHA-256 or better in real code. It survives here only as a self-contained "is the library linked and running" check.
With STM32CubeMX
Enable, in the .ioc:
RNG— Mbed TLS needs an entropy source, and the hardware RNG is it.Mbed TLSunder the middleware list.
Then set the modes:
MBEDTLS_SSL_CLI_C: Defined — TLS client support.MBEDTLS_SHA1_C: Defined — for the example below.
If the RTC is disabled, turn off the time-dependent features, or the build
pulls in gettimeofday and fails to link:
MBEDTLS_HAVE_TIME: Not DefinedMBEDTLS_HAVE_TIME_DATE: Not Defined
Certificate validity checking needs a real clock. Leaving time disabled is fine for hashing or for a client that pins a key, but a full certificate chain validation cannot check expiry without it — enable the RTC and set it before the first TLS session in that case.
Example
/* USER CODE BEGIN Includes */
#include "mbedtls/sha1.h"
/* USER CODE END Includes */
void StartDefaultTask(void const * argument)
{
MX_USB_HOST_Init();
/* USER CODE BEGIN 5 */
for (;;)
{
osDelay(10000);
printf("Mbed TLS port on STM32F746G-DISCO board\r\n");
const char *source_cxt = "Rojar Smith";
unsigned char digest[20]; /* SHA-1 is exactly 20 bytes */
printf("source context is: %s\r\n", source_cxt);
mbedtls_sha1_context sha1_ctx;
mbedtls_sha1_init(&sha1_ctx);
mbedtls_sha1_starts(&sha1_ctx);
mbedtls_sha1_update(&sha1_ctx, (const unsigned char *)source_cxt, strlen(source_cxt));
mbedtls_sha1_finish(&sha1_ctx, digest);
mbedtls_sha1_free(&sha1_ctx);
printf("sha1 digest is: [");
for (int i = 0; i < 20; i++) { /* < 20, not <= 20 */
printf("%02x", digest[i]);
}
printf("]\r\n");
/* Expected: 82b1e6dc4fb9b011b4ecae116f694359d262ebc5 */
}
/* USER CODE END 5 */
}
Two corrections over the naive version of this loop:
- The digest buffer must be
unsigned char. Printing a signedcharwith%02xsign-extends any byte ≥ 0x80 toffffffxx, so the hex string comes out wrong for exactly the inputs that matter. - The loop bound is
i < 20. SHA-1 produces 20 bytes;i <= 20reads and prints one byte past the end.
printf here goes to the UART — see
UART and virtual COM port for the retarget.
Stack and heap
Give the RTOS default task and the heap room, or the handshake overflows a stack it shares with cryptographic scratch buffers:
Minimum Heap Size: 0x1000
Minimum Stack Size: 0x1000
These are _Min_Heap_Size / _Min_Stack_Size in the linker script; CubeMX
exposes them under Project Manager ▸ Linker Settings. A full TLS session needs
considerably more than a bare hash — several kilobytes of stack for the
handshake alone.
gettimeofday_r at link time
A recent STM32CubeIDE toolchain reporting an unresolved _gettimeofday_r means
a time-dependent Mbed TLS feature is still enabled while newlib-nano provides no
gettimeofday stub. Either turn off MBEDTLS_HAVE_TIME and
MBEDTLS_HAVE_TIME_DATE as above, or provide a _gettimeofday implementation
backed by the RTC. Editing the linker script does not help — the missing symbol
is a syscall stub, not a memory-layout problem.
Manual integration
When not using the CubeMX middleware, add the sources by hand:
-
Copy
include/andlibrary/into the project. -
Copy one config header from
configs/intoinclude/. -
Add the
library/*.cfiles as linked sources, and add the include paths. -
Add the config-file preprocessor symbol:
MBEDTLS_CONFIG_FILE=<config-mini-tls1_1.h>The angle brackets are part of the value — Mbed TLS uses them in the
#include MBEDTLS_CONFIG_FILEdirective, so define it literally asMBEDTLS_CONFIG_FILE=<config-mini-tls1_1.h>.
Trim the chosen config to what a microcontroller has. In
config-mini-tls1_1.h:
//#define MBEDTLS_HAVE_TIME
//#define MBEDTLS_HAVE_TIME_DATE
//#define MBEDTLS_NET_C /* no BSD sockets on bare metal */
//#define MBEDTLS_SHA1_C /* enable only what you use */
/* No OS entropy source; feed the hardware RNG instead */
#define MBEDTLS_NO_PLATFORM_ENTROPY
MBEDTLS_NET_C assumes a POSIX socket layer, which bare-metal targets do not
have — leave it off and supply your own send/receive callbacks.
MBEDTLS_NO_PLATFORM_ENTROPY tells Mbed TLS there is no OS entropy pool, so you
must register a hardware entropy source (the RNG) with
mbedtls_entropy_add_source.
Validate the configuration
Add this at the end of the config header. It fails the compile with a clear message if the selected options are inconsistent, which is far easier to debug than a link error later:
#include "mbedtls/check_config.h"