How to start with STM32CubeMX Secure Manager on STM32H57

Revision as of 12:43, 21 October 2023 by Registered User

The purpose of this article is to show an integration of the Secure Manager in a STM32CubeMX ecosystem.


Read Secure Manager for STM32H5 before starting the practical example described below.

During this step by step article, we produce the following boot scheme:


SECURITY SM Boot scheme 3.png

1. Introduction

User application description
This step by step article describes how to use the STM32CubeMX to generate a nonsecure application in the Secure Manager environment. This application uses RTC calendar, Timestamp, USART1, and GPIOs. When the User button in the discovery board is pressed, the corresponding date and date information is sent by USART1 in a message.

SECURITY STM32CubeMX description userr app SM.png

The use of the Secure Manager cryptography service to encrypt the message transmitted via UART1 is also described in this article.

2. Prerequisites

  • Hardware
    • STM32H573 discovery board: Discovery MB1677- STM32H573 (USB-C cable not included). The STM32H573 devices have all the available security features, including the HW crypto accelerator.

Note: the Secure Manager is not supported on STM32H56x devices, as HW crypto is not available.


STM32H573 DK MB1677.png
  • In case your board has already been used for other handsons:
  • If the board is in another state other than OPEN, perform a regression using the script provided in the last handson.
  • If the board is in OPEN state, check that the SECBOOT_LOCK option byte is not set. Use STM32CubeProgrammer.
  • Required tools
    • STM32CubeMX 6.9.2 or later
    • STM32Cube_H5_V1.1.0 with STM32Cube_H5_V1.1.1 patch, or later
    • STM32CubeProgrammer_rev2.14.0 or later (Select STM32TrustedPackageCreator (TPC) during the installation).
    • One of the supported IDE:
      • EWARM (IAR) : V9.20.1 and the patch EWARMv8_STM32H5xx_V1.1.0 or later, to support the STM32H5 series
      • STM32CubeIDE : 1.13.0 or later
      • MDK_ARM : V5.37.0.0 and the patch Keil_STM32H5_DFP.1.0.0 or later, to support the STM32H5 series
    • Tera Term / Putty or equivalent UART terminal emulator
  • STM32Cube Firmware
    • Download the STM32CubeFW_H5 Cube firmware
      • With STM32Cube_H5_V1.1.0 you must also download the STM32Cube_H5_V1.1.1 patch and copy all the files into V1.1.0
      • Later versions of STM32Cube_H5_V1.1.x are delivered as a single zip file.
      • The IDE patches can be found in the STM32CubeFW_H5 Cube firmware: Extract the zip file corresponding to the IDE patch to use, and follow the instructions in the readme.txt file to install it.
        SECURITY STM32CubeH5FW patches.png
    • The “Projects” directory includes the STM32H573I-DK directory. If the STM32CubeProgrammer tool is not installed in the default folder C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer, the customized installation path must be updated in the environment variable: env.bat. Refer to the example in the figure below.
SECURITY STM32CubeH5 env bat maj.png

3. Configuration of the project with STM32CubeMX

3.1. Setting up the STM32CubeMX project

Launch STM32CubeMX

  1. Click on Access to MCU Selector. For this example, it is easier to enable only the necessary GPIOs, so it is advised to use the MCU selector instead of the board selector.
  2. Enter STM32H573 in Commercial part number.
  3. Select the device used in STM32H5-DK.
  4. Click Start project.
  5. Enable TrustZone.


SECURITY STM32CubeMX MCU selector.png


Create the STM32CubeMX project:

  1. Go to Project Manager tab.
  2. Type the name of the project. The related folder is created, if it did not exist previously.
  3. Choose a folder for the project, avoiding long paths.
  4. Select the relevant toolchain. This example uses EWARM.
SECURITY STM32CubeMX project parameters SM.png


Secure project

  1. Check only the Non Secure Project checkbox
SECURITY STM32CubeMX project non secure SM.png

Save Project

  1. Go to File > Save Project. The project folder (if it doesn't already exist) and the Secure_Manager_Integration.ioc file will be created.
SECURITY STM32CubeMX save pj SM 2.png

3.2. Boot path configuration

To configure the boot path proceed as follows:

  • 1) Click on "Boot Path and Debug Authentication".
  • 2) Click on "Select".
SECURITY STM32CubeMX boot path selection SM.png


  • 1) Select the ST immutable Root of Trust. The TZ activation is already chosen. This selection defines the UBE option byte (but you do not need to take care of the setting of this option byte).
  • 2) Click on "Next".
  • 3) Select Updatable Root of Trust(since for this example there is a second uRoT boot stage).
  • 4) Click on "Next".
  • 5) Select Secure Manager Non Secure Application.
  • 6) Click Finish.
SECURITY STM32CubeMX boot path SM.png



When clicking Finish, ROT_Provisioning folder is added to the project. Boot path configuration is done :

SECURITY STM32CubeMX boot path selection OK SM 2.png

The Secure Manager is integrated in the project, and launches the User application that will be configured in the next steps. Here is a description of the boot process configured :

SECURITY STM32CubeMX boot path process SM 2.png

3.3. User application configuration

The next steps detail the configuration of the parameters used in the user application. We need to change the clocking, configure USART1 and RTC to send messages, and activate ICACHE.

3.3.1. Modify the default clocking

Open Clock Configuration and modify HCLK to 250MHz. STM32CubeMX will automatically find a solution to configure the System clock source.

SECURITY STM32CubeMX clock SM.png

3.3.2. USART1 configuration to display events to the terminal

3.3.2.1. USART1 Configuration

In Pinout & Configuration tab select USART1 and edit the parameters as described below :

SECURITY STM32CubeMX USART1 config SM.png
3.3.2.2. Mapping of the USART1

To use USART1 with PA9 and PA10 pins (STLINK pinout) :

  • Change PB6 to PA9
SECURITY STM32CubeMX USART1 mapping PA9 SM.png
  • Change PB7 to PA10
SECURITY STM32CubeMX USART1 mapping PA10 SM.png

3.3.3. Configure and activate RTC

Activate RTC Clock source, Calendar and Timestamp, and keep RTC in nonsecure side. RTC interrupt must trigger as soon as an input event is detected on user button (PC13), so RTC non-secure interrupt must be enabled.

SECURITY STM32CubeMX RTC config SM.png

Check in GPIO Settings that User button PC13 is associated to RTC:

SECURITY STM32CubeMX RTC config 2 SM.png











3.3.4. Activate the ICACHE

Still in Pinout & Configuration tab activate ICACHE :

SECURITY STM32CubeMX ICACHE SM.png

3.4. Code generation

Now that User application is configured you can generate code and check the structure of the project :

SECURITY STM32CubeMX generate code SM.png
SECURITY STM32CubeMX Folder Project CubeMX SM.png

4. Secure Manager Provisioning

  • On the STM32H573-DK, check that the switch (SW1) is set to 0 to boot from user flash
Figure 4 SW1 switch to set to 0 (user flash boot)
  • Connect the STM32H573-DK using the USB-C cable
  • Execute the provisioning_auto.bat script
SECURITY STM32CubeMX Provisioning script folder SM.png

Note:
In the figure above two scripts are shown:
- The provisioning_auto.bat to install the default configuration (used in this article).
- The provisioning.bat to customize the configuration (used in the How to start with Secure Manager customized config on STM32H5 article

After installation you should see:

  • The message saying the board is correctly confirmed
  • On the discovery board the led1, led2, led3 and led4 must blink (default installed code by the script)

5. User application modification and generation

5.1. Project configuration

Open the generated project with IAR and select Project → Options.
Modify the Flash loader. Here is the path of the flashloader to be used : $TOOLKIT_DIR$\config\flashloader\ST\FlashSTM32H5_SEC.board

Connect under reset is not possible : Debugger can only attach when target is running in non secure : Change Reset connection configuration.

SECURITY STM32CubeMX IAR pj config SM.png

You can proceed the same way with an other IDE.

5.2. Build the application

SECURITY STM32CubeMX build userr app SM.png

5.3. Customize the code

  • Create an empty file detection.c and save it in Secure_Manager_Integration\NonSecure\Core\Src folder.

This file contain functions to write text via USART1 . In the second part of the step by step when we will include the Cryptography API we will define OUTPUT_ENC_DATA to use the cryptography functions.
Copy paste all this code in the file and save it :

/* Includes */
#include "main.h"
#include "detection.h"
#include "stdio.h"
#include "string.h"

// TODO : uncomment to enable encryption
//#define OUTPUT_ENC_DATA

#define OUT_BUFFER_SIZE (4 * 16)
#define ENC_BUF_SIZE OUT_BUFFER_SIZE + PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES)
#ifdef OUTPUT_ENC_DATA
#include "crypto.h"
#endif

extern RTC_HandleTypeDef hrtc;
uint32_t  g_EventDetected = 0;
RTC_DateTypeDef sDate;
RTC_TimeTypeDef sTime;

#define OUT_BUFFER_SIZE (4 * 16)
char OutBuffer[OUT_BUFFER_SIZE];

void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *RTC_Handle)
{
  if ( g_EventDetected == 0 )
  {
    HAL_RTCEx_GetTimeStamp(&hrtc, &sTime, &sDate, RTC_FORMAT_BIN);
    g_EventDetected = 1;
  }
}



char OutBuffer[OUT_BUFFER_SIZE];

char *BuildOutputEvent(void);
static void OutputEventInClear(char *buffer);
#ifdef OUTPUT_ENC_DATA
static void Encrypt_data(uint8_t *input, size_t inSize, uint8_t *output, size_t *outSize);
static void OutputEventInEncrypted(char *buffer);
#endif

char *BuildOutputEvent(void)
{
	memset(OutBuffer, 0, OUT_BUFFER_SIZE);
	sprintf(OutBuffer, "Detect button\r\nTime : %.2d:%.2d:%.2d\n\rDate : %.2d-%.2d-%.2d\n\r",
			 sTime.Hours, sTime.Minutes, sTime.Seconds,sDate.Month, sDate.Date, 2023);
	return OutBuffer;
}

#ifdef OUTPUT_ENC_DATA
static void Encrypt_data(uint8_t *input, size_t inSize, uint8_t *output, size_t *outSize)
{
	  psa_status_t psa_status;
	  size_t size = 0;

	  /* Encrypt single part functions */
	  psa_status = psa_cipher_encrypt(0x23, PSA_ALG_CBC_NO_PADDING, (uint8_t const*) input, inSize, output, *outSize, &size);
	  if (psa_status != PSA_SUCCESS)
	  {
	    printf("Error encrypting with the single-shot API\n\r");
	  }
	  else
	  {
            if (size != *outSize)
            {
                    printf("Issue out size ...\r\n");
            }
            *outSize=size;
	  }
}
static void OutputEventInEncrypted(char *buffer)
{
uint8_t encBuffer[ENC_BUF_SIZE] = {0};
size_t encBufferSize=ENC_BUF_SIZE;

	Encrypt_data((uint8_t *)buffer, OUT_BUFFER_SIZE, encBuffer, &encBufferSize);
	printf("\n\r*************Event detected (encrypted) ********************\n\r");
	for(uint32_t i=0; i<encBufferSize;i++)
	{
		printf("%02x", encBuffer[i]);
	}
	printf("\r\n");
}
#endif

static void OutputEventInClear(char *buffer)
{
	  printf("\n\r****************Event detected (clear)********************\n\r");
	  printf(buffer);
}

void ProcessEventDetection()
{
	if (g_EventDetected)
	{
		char *event = BuildOutputEvent();
		OutputEventInClear(event);
#ifdef OUTPUT_ENC_DATA
		OutputEventInEncrypted(event);
#endif
		g_EventDetected=0;
	}
}
  • Create an empty file trace.c and save it in Secure_Manager_Integration\NonSecure\Core\Src folder.

This file is used to use printf with IAR.
Copy paste all this code in the file and save it :

/* Includes */
#include "main.h"

extern UART_HandleTypeDef huart1;

int32_t iar_fputc(int32_t ch);
#define PUTCHAR_PROTOTYPE int32_t iar_fputc(int32_t ch)

size_t __write(int32_t file, unsigned char const *ptr, size_t len)
{
  UNUSED(file);
  size_t idx;
  unsigned char const *pdata = ptr;

  for (idx = 0; idx < len; idx++)
  {
    (void)iar_fputc((int32_t)*pdata);
    pdata++;
  }
  return len;
}

/* @brief  Retargets the C library printf function to the USART.
* @param  None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
  
  return ch;
}


  • Create an empty file detection.h and save it in Secure_Manager_Integration\NonSecure\Core\Inc folder.

Copy paste all this code in the file and save it :

#ifndef __DETECTION_H
#define __DETECTION_H
#include "stdio.h"
void ProcessEventDetection(void);
#endif
  • Add files detection.c and trace.c to Core folder in IAR :
SECURITY STM32CubeMX add files to core SM.png
  • add these section of code in main.c as shown in figure below :
/* USER CODE BEGIN Includes */
#include "detection.h"
/* USER CODE END Includes */
 /* USER CODE BEGIN 2 */
 printf("*************************************\r\n");
 printf("Timestamped event detection version 1\r\n");
 printf("*************************************\r\n");
 /* USER CODE END 2 */
  
    /* USER CODE BEGIN WHILE */
  while (1)
  {
	ProcessEventDetection();
    /* USER CODE END WHILE */
SECURITY STM32CubeMX code to add to main SM.png
  • Build the code.

5.4. Run the application

  • Connect the STM32H573-DK using the USB-C cable
  • Click Download and debug the code :
SECURITY STM32CubeMX dwload and debug code SM.png
  • Start Tera Term or another terminal emulator. Refer to the figure below.
    • Select -> Serial -> select your COM port
    • Setup -> Serial port -> set Speed to 115200 baudrate, Data to 8 bit and Stop bit to 1bit -> New setting
SECURITY STM32CubeMX TeraTerm config SM.png
  • Press the reset button of the discovery board (B2 black button)
  • Press the user button (blue button) to trigger the event
SECURITY STM32CubeMX event displayed SM.png

6. Add Data encryption

This part will show how to add usage of Secure Storage and cryptography. We will add the encryption of the Timestamp information on the target and also the capability to decode it on your PC.

The process followed is

  • use its-blob.bat to generate the preprovisioned blob containing a secret key
  • Reinstall the Secure Manager
  • Use psa crypto api using provisionned key to encrypt the data

We choose AES-CBC cryptographic tool (Symmetric cryptography), and we will show how to

  • put encryption key in the target securely and protect it against any direct access
  • add the encryption of the data before transmission via USART

First we will store the encryption key in a prebuilt trusted storage that will be flashed at the same time as the Secure Manager (at production level for example) and then we will include PSA cryptography API with STM32CubeMX in order to use it to encrypt messages.

SECURITY STM32CubeMX boot scheme with crypto SM 2.png

6.1. Provision the AES key in the Internal Trusted Storage

We need to put encryption key in the target securely and to protect it against direct access.

6.1.1. AES key generation

First we create the AES key that will be used to encrypt datas. You can use the key you want in 256 bits. To generate a random key you can use OpenSSL for example.

  • If you have not installed OpenSSL on your PC you can download it in [OpenSSL]
  • create a new file key.bat in folder Secure_Manager_Integration\ROT_Provisioning\SM\Keys that will generate a random AES key in a file AES_256bits.bin"
  • Edit key.bat with Notepad for example and copy paste this code in the file:

TOOLDIR correspond to the folder where you have installed OpenSSL, you can customize to your own case.

SETLOCAL
SET TOOLDIR=C:\Program Files\OpenSSL-Win64\bin
SET TOOL=%TOOLDIR%\openssl.exe

SET MY_CURR_DIR=%cd%

@ECHO ON
cd %TOOLDIR%
"%TOOL%" rand -hex 32 > %MY_CURR_DIR%\AES_256bits.bin
cd %MY_CURR_DIR%

@ENDLOCAL
@PAUSE
  • Save the file and launch it (double click on it)
  • A new file AES_256bits.bin is created in Secure_Manager_Integration\ROT_Provisioning\SM\Keys folder, that contain a random AES key.

6.1.2. Personalize blob script

The script its_blob.bat is used to generate a blob binary file. Blob files (Binary Large Objects) are currently used to store keys. The MCU can use AES key to encrypt blob before storing it.

  • Edit file its_blob.bat in folder Secure_Manager_Integration\ROT_Provisioning\SM with Notepad for example and add this code to add AES key at line 64:
:: Add AES key to blob
%ItsBuilder% addkey2blob %blob% %blob% -i 0x23 -o 0xffffffff --keytype=AES -b 256 -a CBC -k Keys\AES_256bits.bin -u ENCRYPT --format=RAW 2>> %current_log_file%
if !errorlevel! neq 0 goto :error
  • save it as its_blob_perso.bat

6.1.3. Generate the ITS_Factory_Blob.bin

  • Launch the script previously edited its_blob_perso.bat (double click)
SECURITY STM32CubeMX blob folder SM.png

This script use ITS builder tool in STM32Cube_FW_H5_V1.1.1\Utilities\PC_Software\ITSbuilder :

SECURITY Blob creation pic with ITS builder SM 2.png

It generates ITS_Factory_Blob.bin file in Secure_Manager_Integration\ROT_Provisioning\SM\Binary folder.

Success message :

SECURITY blob gene success msg SM.png

6.1.4. Regression

Perform a full regression to reinitialize the device.

  • The installed Secure Manager is removed
  • The full user Flash and OBKeys are erased
  • The memory mapping for nonsecure application is no longer fixed
  • The device is set in Open state

For further information, refer to Secure Manager STM32H5 How to Intro article.

SECURITY STM32CubeMX regression script SM.png
  • Double click on regression.bat script and it automatically performs the regression.
  • When the regression is completed, the script displays the message below
regression done.png


6.1.5. Secure Manager Provisioning

  • On the STM32H573-DK, check that the switch (SW1) is set to 0 to boot from user flash
Figure 4 SW1 switch to set to 0 (user flash boot)
  • Connect the STM32H573-DK using the USB-C cable
  • Execute the provisioning_auto.bat script
SECURITY STM32CubeMX Provisioning script folder SM.png

During the installation the SFI need ITS_Factory_Blob.bin prviously generated to store OEM Keys. :

SECURITY Console installation ok provisioning blob SM.png

Below the scheme of SFI image generation done during the provisioning :

SECURITY SFI image generation SM.png


After installation you should see:

  • The message saying the board is correctly confirmed
  • On the discovery board the led1, led2, led3 and led4 must blink (default installed code by the script)

The board is now in TZ-CLOSED state. The AES key has been provisioned in Trusted storage at the same time that the Secure Manager.

6.2. Include PSA cryptography API with STM32CubeMX

Now we need to include the PSA cryptography API with STM32CubeMX and modify our application to call psa_cipher_encrypt.

Open STM32CubeMX. In Pinout & Configuration tab select Secure Manager API and add Cryptography service. Then Generate the code.

SECURITY STM32CubeMX Add crypto SM 2.png

6.3. Activate the encryption in the code

SECURITY Activate encryption in code SM.png

PSA API used : psa_cipher_encrypt :

SECURITY STM32CubeMX API crypto used SM.png

A random IV is generated for each encryption and is added before the data in the output buffer. IV is used to initialize the encryption algorithm.

6.4. Test the application

  • Click Download and debug the code :
SECURITY STM32CubeMX dwload and debug code SM.png
  • Start Tera Term or another terminal emulator; Refer to the figure below.
    • Select -> Serial -> select your COM port
    • Setup -> Serial port -> set Speed to 115200 baudrate, Data to 8 bit and Stop bit to 1bit -> New setting
SECURITY STM32CubeMX TeraTerm config SM.png
  • Press the reset button of the discovery board (B2 black button)
  • Press the user button (blue button) to trigger the event


SECURITY STM32CubeMX Console run programm event detected encrypted SM.png

The message is now crypted.

6.5. Decrypt the data

If you have installed OpenSSL on your computer you can create a file decrypt.bat in Secure_Manager_Integration\ROT_Provisioning\SM\Keys folder,
and copy paste the following script on it :

@ECHO OFF

SETLOCAL
SET TOOLDIR=c:\Program Files\OpenSSL-Win64\bin
SET TOOL=%TOOLDIR%\openssl.exe

SET MY_CURR_DIR=%cd%
SET KEY_HEX=1E50151479E14CBBD9F3B1E98EB24FB1F7B648B2BCB5B1CE3F0EED6ECF56EBE2

REM Parse command line arguments
SET /P INPUT_HEX=Enter concatenated nonce and ciphertext as hexadecimal string: 

SET NONCE_HEX=%INPUT_HEX:~0,32%
SET CIPHERTEXT_HEX=%INPUT_HEX:~32%

REM Convert hexadecimal strings to binary
SET /A CIPHERTEXT_LEN=0
if defined CIPHERTEXT_HEX (
    set "valid_hex=0123456789abcdefABCDEF"
    set "dec="
    for /l %%j in (0, 1, 15) do (
        if "!valid_hex:~%%j,1!" equ "!CIPHERTEXT_HEX:~0,1!" set "dec=!dec!%%j"
    )
    if defined dec set /a "CIPHERTEXT_LEN=(%CIPHERTEXT_HEX:~0,-1%/2)+1"
)
SET /A NONCE_LEN=(%NONCE_HEX:~0,-1%/2)+1

PowerShell -Command "$nonce = @(); For ($i = 0; $i -lt '%NONCE_HEX%'.Length; $i += 2) { $nonce += [System.Convert]::ToByte('%NONCE_HEX%'.Substring($i, 2), 16) }; Set-Content -Path '%MY_CURR_DIR%\nonce.bin' -Value $nonce -Encoding Byte"
PowerShell -Command "$ciphertext = @(); For ($i = 0; $i -lt '%CIPHERTEXT_HEX%'.Length; $i += 2) { $ciphertext += [System.Convert]::ToByte('%CIPHERTEXT_HEX%'.Substring($i, 2), 16) }; Set-Content -Path '%MY_CURR_DIR%\ciphertext.bin' -Value $ciphertext -Encoding Byte"

REM Decrypt ciphertext using hardcoded key and provided nonce
"%TOOL%" enc -d -aes-256-cbc -in %MY_CURR_DIR%\ciphertext.bin -out %MY_CURR_DIR%\plaintext.bin -K %KEY_HEX% -iv %NONCE_HEX%
  • Enter in the code the key you are using : SET KEY_HEX = .., and check that TOOLDIR corresponds to the folder you installed OpenSSL
  • Save the file and launch it (double click)
  • The script asks the encrypted text : copy paste the encrypted text you have on your console and press enter
SECURITY STM32CubeMX decrypt windows SM.png
  • plaintext.bin file is created and contains the plain text.

7. Regression

If you want to reinitialize the device you can perfom a regression :

  • The installed Secure Manager is removed
  • The full user Flash and OBKeys are erased
  • The memory mapping for nonsecure application is no longer fixed
  • The device is set in Open state

For further information, refer to Secure Manager STM32H5 How to Intro article.

SECURITY STM32CubeMX regression script SM.png
  • Double click on regression.bat script and it automatically performs the regression.
  • When the regression is completed, the script displays the message below
regression done.png