How to start with STM32CubeMX Secure Manager on STM32H57

Revision as of 16:39, 3 October 2023 by Registered User (→‎Customize the code)
Under construction.png Coming soon

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


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

Below the boot scheme that will be produced during this step by step article.

SECURITY SM Boot scheme.png


1. Introduction

2. Prerequisites

  • Hardware
    • STM32H573 discovery board: the STM32H573 devices have all the available security features, including the HW crypto accelerator. (Note: the Secure Manager is not supported for STM32H56x devices, the HW crypto is not available)
    • Discovery MB1677- STM32H573 (USB-C cable not included)
Figure 1 STM32H573-DK MB1677.png
  • In case your board has already been used for other handsons:
    • Perform a regression in case the board is in another state than OPEN (using the script provided for the last handson done).
    • If the board is in OPEN state, verify that the SECBOOT_LOCK option byte is not set (use STM32CubeProgrammer).
  • Required tools
    • STM32Cube_H5_V1.1.0 with STM32Cube_H5_V1.1.1 patch, or later
    • STM32CubeProgrammer_rev2.14.0 or more recent (with STM32TrustedPackageCreator (TPC) selected at 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.

The IDE patches can be found in the STM32CubeFW_H5 Cube firmware:

Figure 2 IDE patches in STM32CubeH5 Firmware Package
  • 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
      • For later STM32Cube_H5_V1.1.x, when available, it is delivered as a single zip file.
    • A directory STM32H573I-DK is included in the “Projects” directory
    • If the STM32CubeProgrammer 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 (see the example in the figure below).
Figure 3 STM32CubeProgrammer installation path to update in env.bat file

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's easier to enable only the necessary GPIOs, so it's 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, as shown in Figure 3. (For the STiROT boot path, TrustZone needs to be enabled.)


SECURITY STM32CubeMX MCU selector.png


Create the STM32CubeMX project:

  1. Go to Project Manager tab
  2. Type the name of the project (if it doesn't already exist, the related folder will be created).
  3. Choose a folder for the project (avoid a long path).
  4. Select the relevant toolchain; for this example EWARM is used.
SECURITY STM32CubeMX project parameters SM.png


Secure project

  1. Check only the NonSecure 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 is added to the project. Boot path configuration is done :

SECURITY STM32CubeMX boot path selection OK SM 2.png


3.3. Modify the default clocking

SECURITY STM32CubeMX clock SM.png

3.4. USART1 configuration to display events to the terminal

3.4.1. USART1 Configuration

SECURITY STM32CubeMX USART1 config SM.png

3.4.2. Mapping of the USART1

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

3.5. Configure and activate RTC

SECURITY STM32CubeMX RTC config SM.png


3.6. Activate the ICACHE

SECURITY STM32CubeMX ICACHE SM.png

3.7. Code generation

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

4. Secure Manager Provisioning

SECURITY STM32CubeMX Provisioning script folder SM.png

5. User application modification and generation

5.1. Project configuration

SECURITY STM32CubeMX IAR pj config SM.png

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.

Add 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.

Add 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 USART2 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.

Add 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

  • Check your board is connected
  • Click Download and debug the code :
SECURITY STM32CubeMX dwload and debug code SM.png
  • Start Tera Term or another terminal emulator (see 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
Teraterm setting.png
  • Press the reset button of the discovery board (B2 black button)