How to adapt a user application to ROT for STM32H5

There are four ways to develop an application that is compatible with a secure boot:

  • Develop the application without taking into account the secure boot in a first step then adapt the application to the secure boot path. This article explains how to do this.
  • Add your code to the ROT template projects (OEMiROT_Appli or STiROT_Appli). These projects have already been adapted to the secure bootpath.
  • Update existing ROT applications projects (OEMiROT_Appli or STiROT_Appli). These projects have already been adapted to the secure bootpath.
  • Use the STM32CubeMX Boot path functionality. Refer to the how to start with STM32CubeMX and STM32H5 security wiki article.


With STM32H5, several kinds of secure bootpath can be selected. This article is applicable to:

  • One boot stage: STiRoT
  • One boot stage: OEMiRoT
  • Two boot stages: STiRoT + OEMuRoT

This article uses an STM32H573-DK board, but it applies to other STM32H5 boards.

1. Prerequisites

As shown below, STMicroelectronics provide different scripts to facilitate application configuration and firmware image generation.

The application folder structure must match the standard one available in the STM32CubeH5 package, whether it is for a fully secure application or for a secure and nonsecure application. The names of the files and folders underlined in red must be compliant.

Security H5 Folder Structure ewarm.png

Security H5 Folder Structure mdkarm.png

Security H5 Folder Structure cubeide.png



To create this folder structure, when generating the application with STM32CubeMX, ensure that the option "Generate Under Root" is not selected.

Security H5 CubeMx generation 1.png

2. One boot stage: STiRoT

At reset, STiRoT checks the authenticity and integrity of the user application before executing it. The STiRoT_for_STM32H5 article provides a detailed description of STiRoT.

STiRoT supports the installation of two kinds of application:

  • Without isolation: secure-only application. An example is provided in Firmware/Projects/STM32H573-DK/Applications/ROT/STiROT_Appli.
  • With isolation: secure and nonsecure applications. An example is provided in Firmware/Projects/STM32H573-DK/Applications/ROT/STiROT_Appli_TrustZone.

When the application runs without secure boot and the user wants to use STiRoT to secure it, follow these steps:

  • The memory mapping of the user application must be adapted. The user application booted by STiRoT is always executed in flash memory. The memory mapping of the user application depends on the STiRoT configuration.
  • The user application binary must be signed and encrypted. At each boot, STiRoT controls the integrity and authenticity of the user application binary based on TLV added during the image generation.
  • Note that a default memory protection unit (MPU) configuration is already applied by STiRoT when jumping to the application. To ensure the security of the device, the MPU is configured to allow execution of the user application code area only. This minimizes the risk of unauthorized code execution. It is the responsibility of the user application to reconfigure the MPU to meet the security requirements.


A set of scripts is available in the Firmware/Projects/STM32H573-DK/ROT_Provisioning folder to activate and configure the STiRoT bootpath. These scripts are designed to adapt the configuration files automatically, such as STiROT_Code_Image.xml and the ob_flash_programming.bat (.sh) script, but also the application linker files based on the STiRoT configuration.

Before executing these scripts, update the stirot_boot_path_project variable in Firmware/Projects/STM32H573-DK/ROT_Provisioning/env.bat (.sh), which must point to the user application folder. As this path is relative from Firmware/Projects/STM32H573-DK it may be necessary to add several "../" (parent directory) to navigate to the drive.

Security H5 STiRoT Appli env.png
Warning white.png Warning
Do not insert any space characters into the application path or name.

2.1. Application without isolation: STiRoT_Appli example

When an application is designed to run without isolation, it must be 'fully secure'. To meet this requirement, define the project as a secure project:


Security H5 STiRoT Appli secure ewarm.png

Security H5 STiRoT Appli secure mdkarm.png

Change nature of your project:

To change the nature of the project, open the .project file with a text editor and replace lines 27 and 28 from the picture below with the new line 27 provided.

Security H5 STiRoT Appli secure project cubeide 1.png

		<nature>com.st.stm32cube.ide.mcu.MCUSecureProjectNature</nature>


Select the secure compilation option

Security H5 STiRoT Appli secure gcc cubeide.png

Remove secure gateway generation


Security H5 STiRoT Appli secure linker cubeide.png

2.1.1. User application adaptation

This chapter highlights several parts of the linker file to explain the most important points to consider, but if this file was not modified, it is recommended to use the complete mapping file template provided for STiRoT_Appli and skip the ROM/RAM region adaptation described below.


ROM region adaptation:

When started by STiRoT, the user application is always executed from the flash memory. Moreover, the user application binary must be included in an image including a header, as described in the image generation wiki page. Therefore, the vector table is shifted by 0x400 bytes.

As explained in the Firmware/Projects/STM32H573-DK/Templates/ROT/STiROT_Appli example, the S_CODE_OFFSET, S_CODE_SIZE, and IMAGE_HEADER_SIZE symbols must be added to the linker file. These three symbols are automatically updated during the provisioning process, taking into account the memory configuration of STiROT_Boot. The vector table address and the ROM code section must be defined using the S_CODE_OFFSET, S_CODE_SIZE, and IMAGE_HEADER_SIZE symbols.
Add the code below to the mapping file:


Security H5 STiRoT Appli mapping file ewarm.png
define symbol S_CODE_OFFSET = 0x00000000; /* Firmware execution area offset from STiROT_Config.xml */
define symbol S_CODE_SIZE = 0x00020000; /* Firmware area size from STiROT_Config.xml */
define exported symbol IMAGE_HEADER_SIZE = 0x400; /* mcuboot header size */

define exported symbol __ICFEDIT_intvec_start__ = 0x0C000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE;
/*-Memory Regions-*/
define exported symbol __ICFEDIT_region_ROM_start__     = 0x0C000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE;
define symbol __ICFEDIT_region_ROM_end__       = 0x0C000000 + S_CODE_OFFSET + S_CODE_SIZE - 1;

Security H5 STiRoT Appli mapping file mdkarm.png

Due to the use of #define, the first line below is also mandatory and must be the first line of the .sct file.

#! armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -xc
#define S_CODE_OFFSET 0x00000000    /* Firmware execution area offset from STiROT_Config.xml */
#define S_CODE_SIZE 0x00020000      /* Firmware area size from STiROT_Config.xml */
#define IMAGE_HEADER_SIZE 0x400     /* mcuboot header size */

#define CODE_START 0x0C000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE
#define APP_CODE_SIZE S_CODE_SIZE - IMAGE_HEADER_SIZE

Security H5 STiRoT Appli mapping file CubeIDE.png
S_CODE_OFFSET = 0x00000000;       /* Firmware execution area offset from STiROT_Config.xml */
S_CODE_SIZE = 0x00020000;         /* Firmware area size from STiROT_Config.xml */
IMAGE_HEADER_SIZE = 0x400;       /* mcuboot header size */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x30000000,    LENGTH = 0x40000    /* Memory is divided. Actual start is 0x30000000 and actual length is 256K */
  FLASH    (rx)    : ORIGIN = (0xc000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE),    LENGTH = S_CODE_SIZE - IMAGE_HEADER_SIZE  /* Memory is divided. Actual start is 0x8000000 and actual length is 2048K */
}


RAM region adaptation:

No adaptation is required for STiRoT bootpath.

2.1.2. Image generation

STM32TrustedPackageCreator uses STiRoT_Code_Image.xml (in the Firmware/Projects/STM32H573-DK/ROT_Provisioning/STiROT/Images folder) to generate the image. It contains all required parameters, including the location of the user application binary file (appli.bin). This parameter is automatically updated during the provisioning sequence based on the stirot_boot_path_project variable.

Therefore, the IDE must be configured to generate a .bin file in the My_Appli/Appli/Binary folder (make sure that the correct project tree has been selected).


Security H5 STiRoT Appli bin ewarm 1.png

..\..\..\Binary\appli.bin

Security H5 STiRoT Appli bin mdkarm 1.png

fromelf #L --bin --output=$L"\..\..\..\Binary\appli.bin"

Security H5 STiRoT Appli bin CubeIDE 2.png

To meet the binary name and location requirements, a postbuild script is implemented to copy the binary file generated by the IDE. This script must be updated with the generated binary name to perform this operation.

Security H5 STiRoT Appli bin postbuild CubeIDE.png


The image generation can be started manually with STM32TrustedPackageCreator, but a more efficient way of working is to modify the user application project to generate the image automatically at the end of each compilation as a postbuild command.


Security H5 STiRoT Appli postbuild ewarm.png

$PROJ_DIR$\postbuild.bat "secure"

Security H5 STiRoT Appli postbuild mdkarm.png

postbuild.bat "secure"

Security H5 STiRoT Appli postbuild CubeIDE.png

"../postbuild.sh" "${ConfigName}"


An example of postbuild.bat/.sh is provided in the Firmware/Projects/STM32H573-DK/Templates/ROT/STiROT_Appli and Firmware/Projects/STM32H573-DK/Applications/ROT/STiROT_Appli examples. The image generation is performed based on STiRoT_Code_Image.xml, which is stored in the Firmware/Projects/STM32H573-DK/ROT_Provisioning/STiROT/Images folder. Depending on the location of your application, the postbuild script may be updated to access the STiRoT_Code_Image.xml file.


Security H5 STiRoT Appli postbuild bat ewarm.png

Security H5 STiRoT Appli postbuild bat mdkarm.png

Security H5 STiRoT Appli postbuild sh CubeIDE.png

2.1.3. Security management

For security robustness, when STiRoT jumps to the user application, the MPU is configured to ensure that only the user application code area can be executed (execution surface controlled via MPU configuration). It is the responsibility of the application to reconfigure the MPU to meet the security requirements. Security H5 STiRoT Appli mpu.png

2.1.4. Miscellaneous

The STiRoT system clock is set to 64, 200, or 250 Mhz by the user through the STiRoT configuration step. The application inherits the STiRoT system clock value if the configuration of the system clock is not updated by the application.

2.1.5. Ready to start

The application has now been adapted to STiRoT Boot path without isolation. To test it, run the provisioning.bat/.sh script stored in the Firmware/Projects/STM32H573-DK/ROT_Provisioning/STiROT folder and follow the instructions.
For more details refer to the Security:How to start with STiRoT on STM32H573#STiRoT and debug authentication configuration wiki page.

2.2. Application with isolation: STiRoT_Appli_TrustZone example

STiRoT_Appli_TrustZone example can be chosen by the user in order to design an application with both a secure and a nonsecure part. For this purpose, update the STiRoT configuration as follows:

  • Disable the fully secure image option.
  • Update the size of the secure part.
Security H5 STiRoT Appli TZ configuration tpc.png


STiRoT_Appli_TrustZone consists of two projects, which must be compiled in a specific order (secure then nonsecure). The image is generated at the end of the nonsecure project compilation.

Before executing these scripts, it is mandatory to update the stirot_boot_path_project variable in Firmware/Projects/STM32H573-DK/ROT_Provisioning/env.bat (.sh), which must point to the user application folder. As this path is relative from Firmware/Projects/STM32H573-DK', it may be necessary to add several "../" (parent directory) to navigate to the drive.

Security H5 STiRoT Appli TZ env.png

Warning white.png Warning
Do not insert any space characters into the application path or name.

2.2.1. User application adaptation

This chapter highlights several parts of the linker file to explain the most important points to consider, but if this file was not modified, it is recommended to use the complete mapping file template provided for STiRoT_Appli_TrustZone and skip the ROM/RAM region adaptation described below.

ROM region adaptation:

When started by STiRoT, the user application is always executed from the flash memory. Moreover the user application binary must be included in an image including a header, as described in the image generation wiki page. Therefore, the vector table is shifted by 0x400 bytes.

As explained in the Firmware/Projects/STM32H573-DK/Templates/ROT/STiROT_Appli_TrustZone example, the S_CODE_OFFSET, S_CODE_SIZE, NS_CODE_OFFSET, NS_CODE_SIZE, IMAGE_HEADER_SIZE, and CMSE_VENEER_REGION_SIZE symbols must be added to the secure and nonsecure linker files. The vector table address and the ROM code section must be defined using the S_CODE_OFFSET, S_CODE_SIZE, NS_CODE_OFFSET, NS_CODE_SIZE, IMAGE_HEADER_SIZE, and CMSE_VENEER_REGION_SIZE symbols:

  • IMAGE_HEADER_SIZE is configured by default; do not udpate its value.
  • CMSE VENEER_REGION_SIZE defines the region used to switch safely between the secure and nonsecure application. It ensures that the transition is controlled and that sensitive data is protected. This value can be configured by the user even if it is recommended to keep the default value.
  • NS_CODE_OFFSET is configured in the examples as the beginning of the area just after the secure area. This value can be updated by the user if they decided to change the partitioning logic.
  • S_CODE_OFFSET, S_CODE_SIZE, and NS_CODE_SIZE are automatically updated during the provisioning process, taking into account the memory configuration of STiRoT.

Security H5 STiRoT Appli TZ mapping file s ewarm.png
define exported symbol S_CODE_OFFSET = 0x00000000; /* This define is updated automatically from update_appli_setup.bat/sh */
define exported symbol S_CODE_SIZE = 0x00006000; /* This define is updated automatically from update_appli_setup.bat/sh */
define exported symbol IMAGE_HEADER_SIZE = 0x400; /* mcuboot headre size */
define symbol CMSE_VENEER_REGION_SIZE = 0x400;  /* user configurable */

define exported symbol __ICFEDIT_intvec_start__ = 0x0C000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE;
/*-Memory Regions-*/
define exported symbol __ICFEDIT_region_ROM_start__     = 0x0C000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE;
define symbol __ICFEDIT_region_ROM_end__       = 0x0C000000 + S_CODE_OFFSET + S_CODE_SIZE - CMSE_VENEER_REGION_SIZE  - 1;
define symbol __ICFEDIT_region_ROM_NSC_start__ = 0x0C000000 + S_CODE_OFFSET + S_CODE_SIZE - CMSE_VENEER_REGION_SIZE ;
define symbol __ICFEDIT_region_ROM_NSC_end__   = 0x0C000000 + S_CODE_OFFSET + S_CODE_SIZE - 1;


Security H5 STiRoT Appli TZ mapping file ns ewarm.png

define exported symbol S_CODE_OFFSET =0x00000000; /* This define is updated automatically from update_appli_setup.bat/sh */
define exported symbol S_CODE_SIZE = 0x00006000; /* This define is updated automatically from update_appli_setup.bat/sh */
define exported symbol NS_CODE_OFFSET = S_CODE_OFFSET + S_CODE_SIZE; /* Non secure code Offset */
define exported symbol NS_CODE_SIZE = 0x1A000; /* This define is updated automatically from update_appli_setup.bat/sh */
define exported symbol IMAGE_HEADER_SIZE = 0x400; /* mcuboot headre size */

define exported symbol __ICFEDIT_intvec_start__ = 0x08000000 + NS_CODE_OFFSET + IMAGE_HEADER_SIZE;
/*-Memory Regions-*/
define exported symbol __ICFEDIT_region_ROM_start__     = 0x08000000 + NS_CODE_OFFSET + IMAGE_HEADER_SIZE;
define symbol __ICFEDIT_region_ROM_end__       = 0x08000000 + NS_CODE_OFFSET + NS_CODE_SIZE - 1;

Security H5 STiRoT Appli TZ mapping file s mdkarm.png

Due to the use of #define, the first line below is also mandatory and must be the first line of the .sct file.

#! armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -xc
#define S_CODE_OFFSET 0x00000000                    /* This define is updated automatically from update_appli_setup.bat/sh */
#define S_CODE_SIZE 0x00006000                      /* This define is updated automatically from update_appli_setup.bat/sh */
#define NS_CODE_OFFSET S_CODE_OFFSET + S_CODE_SIZE  /* Non secure code Offset */
#define IMAGE_HEADER_SIZE 0x400                     /* mcuboot headre size */

#define S_CODE_START 0x0C000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE
#define S_APP_CODE_SIZE S_CODE_SIZE - CMSE_VENEER_REGION_SIZE - IMAGE_HEADER_SIZE


Security H5 STiRoT Appli TZ mapping file ns mdkarm.png
Due to the use of #define, the first line below is also mandatory and must be the first line of the .sct file.

#! armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -xc
#define S_CODE_OFFSET 0x00000000                       /* This define is updated automatically from update_appli_setup.bat/sh */
#define S_CODE_SIZE 0x00006000                         /* This define is updated automatically from update_appli_setup.bat/sh */

#define NS_CODE_OFFSET S_CODE_OFFSET + S_CODE_SIZE     /* Non secure code Offset */
#define NS_CODE_SIZE 0x1A000                           /* This define is updated automatically from update_appli_setup.bat/sh */

#define IMAGE_HEADER_SIZE 0x400                        /* mcuboot header size */

#define NS_CODE_START 0x08000000 + NS_CODE_OFFSET + IMAGE_HEADER_SIZE
#define NS_APP_CODE_SIZE NS_CODE_SIZE - IMAGE_HEADER_SIZE

Security H5 STiRoT Appli TZ mapping file s cubeide.png
S_CODE_OFFSET = 0x00000000;       /* This define is updated automatically from update_appli_setup.bat/sh  */
S_CODE_SIZE = 0x00006000;         /* This define is updated automatically from update_appli_setup.bat/sh  */
IMAGE_HEADER_SIZE = 0x400;       /* mcuboot header size */
CMSE_VENEER_REGION_SIZE = 0x400;  /* user configurable */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x30000000,    LENGTH = 0x40000    /* Memory is divided. Actual start is 0x30000000 and actual length is 256K */
  FLASH    (rx)    : ORIGIN = (0xc000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE),    LENGTH = (S_CODE_SIZE - IMAGE_HEADER_SIZE  - CMSE_VENEER_REGION_SIZE)    /* Memory is divided. Actual start is 0x8000000 and actual length is 2048K */
  FLASH_NSC    (rx)    : ORIGIN = (0xc000000 + S_CODE_OFFSET + S_CODE_SIZE - CMSE_VENEER_REGION_SIZE),    LENGTH = (CMSE_VENEER_REGION_SIZE)    /* Non-Secure Call-able region */
}


Security H5 STiRoT Appli TZ mapping file ns cubeide.png

S_CODE_OFFSET = 0x00000000;                        /* This define is updated automatically from update_appli_setup.bat/sh */
S_CODE_SIZE = 0x00006000;                           /* This define is updated automatically from update_appli_setup.bat/sh */
NS_CODE_SIZE = 0x1A000;                          /* This define is updated automatically from update_appli_setup.bat/sh */
NS_CODE_OFFSET = (S_CODE_OFFSET + S_CODE_SIZE);
IMAGE_HEADER_SIZE = 0x400;                      /* mcuboot header size */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20050000,    LENGTH = 0x50000    /* Memory is divided. Actual start is 0x20000000 and actual length is 640K */
  FLASH    (rx)    : ORIGIN = (0x08000000 + NS_CODE_OFFSET + IMAGE_HEADER_SIZE),    LENGTH = (NS_CODE_SIZE - IMAGE_HEADER_SIZE)    /* Memory is divided. Actual start is 0x8000000 and actual length is 2048K */
}

RAM region adaptation:

No adaptation is required for STiRoT Boot path. From a partitioning point of view, secure and nonsecure firmware cannot access the same physical area of the SRAM. Therefore, to simplify RAM partitioning, secure code uses SRAM1 (through secure aliases) while nonsecure code uses SRAM3 (through nonsecure aliases).

2.2.2. Image generation

STiRoT_Appli_TrustZone consists of two projects which must be compiled in a specific order (secure then nonsecure). The image is generated at the end of the nonsecure project compilation.

STM32TrustedPackageCreator uses STiRoT_Code_Image.xml (in the Firmware/Projects/STM32H573-DK/ROT_Provisioning/STiROT/Images folder) to generate the image. It contains all required parameters, including the location of the user application binary file (appli.bin). This parameter is automatically updated during the provisioning sequence based on the stirot_boot_path_project variable.

Therefore, the IDE must be configured to generate a .bin file.

Secure
Security H5 STiRoT Appli TZ bin s ewarm 2.png
..\..\..\..\Binary\appli_s.bin


Nonsecure
Security H5 STiRoT Appli TZ bin ns ewarm 1.png

..\..\..\..\Binary\appli_ns.bin
Warning white.png Warning
STiRoT manages only one code firmware image. Consequently, in the case of a TrustZone® application, the secure and nonsecure firmware must be assembled in a single image.


The assembly is performed at the postbuild stage of the nonsecure project.

Secure
Security H5 STiRoT Appli TZ bin s mdkarm 1.png

fromelf #L --bincombined  --output=$L"\..\..\..\..\Binary\appli_s.bin"


Nonsecure
Security H5 STiRoT Appli TZ bin ns mdkarm 1.png

fromelf #L --bincombined  --output=$L"\..\..\..\..\Binary\appli_ns.bin"
Warning white.png Warning
STiRoT manages only one code firmware image. Consequently, in the case of a TrustZone® application, the secure and nonsecure firmware must be assembled in a single image.


The assembly is performed at the postbuild stage of the nonsecure project.

Secure
Security H5 STiRoT Appli TZ bin s cubeide 1.png

Nonsecure
Security H5 STiRoT Appli TZ bin ns cubeide 1.png

Warning white.png Warning
STiRoT manages only one code firmware image. As a consequence, in case of trust zone application, the secure and non-secure firmwares must be assembled in a single image.


The assembly is performed at the postbuild stage of the nonsecure project.

To perform the assembly, the postbuild script must be updated with the generated binary names.

Security H5 STiRoT Appli TZ bin sh cubeide.png


The image generation can be started manually using STM32TrustedPackageCreator but a more efficient way of working is to modify the user application project to generate the image automatically at the end of each compilation as a postbuild command.

Secure
Security H5 STiRoT Appli TZ postbuild s ewarm.png
$PROJ_DIR$\..\postbuild.bat "secure"


Nonsecure
Security H5 STiRoT Appli TZ postbuild ns ewarm.png

$PROJ_DIR$\..\postbuild.bat "nonsecure"
Secure
Security H5 STiRoT Appli TZ postbuild s mdkarm.png
..\postbuild.bat "secure"


Nonsecure
Security H5 STiRoT Appli TZ postbuild ns mdkarm.png

..\postbuild.bat "nonsecure"
Secure
Security H5 STiRoT Appli TZ postbuild s cubeide.png
"../../postbuild.sh" "secure" "${ConfigName}"


Nonsecure
Security H5 STiRoT Appli TZ postbuild ns cubeide.png

"../../postbuild.sh" "nonsecure" "${ConfigName}"
.


An example of postbuild.bat/.sh is provided in the Firmware/Projects/STM32H573-DK/Templates/ROT/STiROT_Appli_TrustZone and Firmware/Projects/STM32H573-DK/Applications/ROT/STiROT_Appli_TrustZone examples. The image generation is performed based on STiRoT_Code_Image.xml, which is stored in the Firmware/Projects/STM32H573-DK/ROT_Provisioning/STiROT/Images folder. Depending on the location of the application, the postbuild script may be updated to access the STiRoT_Code_Image.xml file.


Security H5 STiRoT Appli TZ postbuild bat ewarm.png

Security H5 STiRoT Appli TZ postbuild bat mdkarm.png

Security H5 STiRoT Appli TZ postbuild sh cubeide.png

2.2.3. Security management

For security robustness, when STiRoT jumps to the user application, the MPU is configured to ensure that only the user application code area can be executed (execution surface controlled via MPU configuration). It is the responsibility of the application to reconfigure the MPU to meet the security requirements. Security H5 STiRoT Appli TZ mpu.png

2.2.4. Miscellaneous

The STiRoT system clock is set to 64, 200, or 250 Mhz by the user through the STiRoT configuration step. The application inherits the STiRoT system clock value if the configuration of the system clock is not updated by the application.

2.2.5. Ready to start

The application has now been adapted to STiRoT Boot path with isolation. To test it, run the provisioning.bat/.sh script stored in the Firmware/Projects/STM32H573-DK/ROT_Provisioning/STiROT folder and follow the instructions.
For more details, refer to the Security:How to start with STiRoT on STM32H573#STiRoT and debug authentication configuration wiki page.

3. One boot stage: OEMiRoT

To use OEMiRoT to secure an application that runs without secure boot, follow these steps:

  • Configure OEMiRoT according to your application requirements (such as the number of images or image size).
  • The memory mapping of the user application must be adapted, depending on the OEMiRoT configuration.
  • The user application binary must be signed and encrypted. At each boot, OEMiRoT controls the integrity and the authenticity of the user application binary based on TLV added during the image generation.
  • Be aware that a default MPU configuration is already applied by OEMiRoT when jumping to the application. To ensure the security of the device, the MPU is configured to allow the execution of the user application code area only. This minimizes the risk of unauthorized code execution. It is the responsibility of the user application to reconfigure the MPU to meet the security requirements.

A set of scripts is provided in the Firmware/Projects/STM32H573-DK/ROT_Provisioning folder to activate and configure OEMiRoT Boot path. These scripts are designed to adapt the configuration files automatically, such as OEMiROT_Code_Image.xml and the ob_flash_programming.bat (.sh) script, but also the application linker files based on the OEMiRoT configuration.

Before executing these scripts it is mandatory to update the oemirot_boot_path_project variable in Firmware/Projects/STM32H573-DK/ROT_Provisioning/env.bat (.sh) which must point to the user application folder. As this path is relative from Firmware/Projects/STM32H573-DK, it may be necessary to add several "../" (parent directory) to navigate to the drive.

Security H5 OEMiROT Appli TZ env.png

Warning white.png Warning
Do not insert any space characters into the application path or name.

3.1. OEMiRoT configuration

To tailor OEMiRoT to the application requirements, edit the file Firmware/Projects/STM32H573-DK/Applications/ROT/OEMiROT_Boot/Inc/flash_layout.h. The figure below lists several key parameters from this file.

Security H5 OEMiROT BOOT flash layout.png Security H5 OEMiROT BOOT flash layout partition.png

This example uses the default flash memory layout as defined:

  • Two separate images for secure and nonsecure application binaries
  • No secure data image
  • No nonsecure data image
  • FLASH_S_PARTITION_SIZE 0x06000
  • FLASH_NS_PARTITION_SIZE 0xA0000
  • FLASH_S_DATA_PARTITION_SIZE 0x0 (as there is no secure data image)
  • FLASH_NS_DATA_PARTITION_SIZE 0x0 (as there is no nonsecure data image)

The OEMiRoT_Boot postbuild command propagates the flash memory layout configuration to the provisioning scripts and application linker files. It can also propagate it automatically to an application header file. It can be useful for the application to use it, especially to know where to program new firmware images in download slot areas.

To benefit from this automatic header file update in the application, copy the file Firmware\Projects\STM32H573I-DK\Applications\ROT\OEMiROT_Appli_TrustZone\Secure_nsclib\appli_flash_layout.h to the application directory My_Appli\Secure_nsclib\appli_flash_layout.h.

In this example:

Security H5 OEMiROT Appli TZ flash layout.png

3.2. User application adaptation

In this chapter, we will highlight some parts of the linker file to explain the most important points to consider, but if this file was not modified, it is recommended to use the complete mapping file template provided for STiRoT_Appli_TrustZone and skip the ROM/RAM region adaptation described below.

ROM region adaptation:

When started by OEMiRoT, the user application binary must be included in an image including a header, as described in the image generation wiki page. Therefore, the vector table is shifted by 0x400 bytes.

As explained in the Firmware/Projects/STM32H573-DK/Templates/ROT/OEMiROT_Appli_TrustZone example, the S_CODE_OFFSET, S_CODE_SIZE, NS_CODE_OFFSET, NS_CODE_SIZE, IMAGE_HEADER_SIZE, and CMSE_VENEER_REGION_SIZE symbols must be added to the linker files of the secure and nonsecure projects. These symbols are updated automatically during the OEMiROT_Boot project compilation, taking into account the memory configuration of OEMiROT_Boot, which depends on the MCUBOOT_OVERWRITE_ONLY, MCUBOOT_APP_IMAGE_NUMBER, MCUBOOT_S_DATA_IMAGE_NUMBER, and MCUBOOT_NS_DATA_IMAGE_NUMBER compilation switches. The vector table address and the ROM code section must be defined using the S_CODE_OFFSET, S_CODE_SIZE, NS_CODE_OFFSET, NS_CODE_SIZE, IMAGE_HEADER_SIZE, and CMSE_VENEER_REGION_SIZE symbols:

  • IMAGE_HEADER_SIZE is configured by default; do not update its value.
  • CMSE VENEER_REGION_SIZE defines the region used to switch safely between the secure and nonsecure application. It ensures that the transition is controlled and that sensitive data is protected. This value can be configured by the user even if it is recommended to keep the default value.
  • NS_CODE_OFFSET is configured in the examples as the beginning of the area just after the secure area. This value can be updated by the user if they decided to change the partitioning logic.
  • S_CODE_OFFSET, S_CODE_SIZE, and NS_CODE_SIZE are updated automatically during the OEMiROT_Boot project compilation.

Security H5 OEMiROT Appli TZ mapping file s ewarm.png
define exported symbol S_CODE_OFFSET =0x12000; /* This define is updated automatically by OEMiROT_Boot postbuild */
define exported symbol S_CODE_SIZE = 0x6000; /* This define is updated automatically by OEMiROT_Boot postbuild */
define exported symbol NS_CODE_OFFSET = S_CODE_OFFSET + S_CODE_SIZE; /* Non secure code Offset */
define exported symbol IMAGE_HEADER_SIZE = 0x400; /* mcuboot headre size */
define  symbol CMSE_VENEER_REGION_SIZE = 0x400;  /* Include TLVs and trailer. User configurable */

define exported symbol __ICFEDIT_intvec_start__ = 0x0C000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE;
/*-Memory Regions-*/
define exported symbol __ICFEDIT_region_ROM_start__     = 0x0C000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE;
define symbol __ICFEDIT_region_ROM_end__       = 0x0C000000 + S_CODE_OFFSET + S_CODE_SIZE - CMSE_VENEER_REGION_SIZE - 1;
define symbol __ICFEDIT_region_ROM_NSC_start__ = 0x0C000000 + S_CODE_OFFSET + S_CODE_SIZE - CMSE_VENEER_REGION_SIZE;
define symbol __ICFEDIT_region_ROM_NSC_end__ = 0x0C000000 + S_CODE_OFFSET + S_CODE_SIZE - 1;


Security H5 OEMiROT Appli TZ mapping file ns ewarm.png

define exported symbol S_CODE_OFFSET = 0x12000; /* This define is updated automatically by OEMiROT_Boot postbuild */
define exported symbol S_CODE_SIZE = 0x6000; /* This define is updated automatically by OEMiROT_Boot postbuild */
define exported symbol NS_CODE_OFFSET = S_CODE_OFFSET + S_CODE_SIZE; /* Non secure code Offset */
define exported symbol NS_CODE_SIZE = 0xA0000; /* This define is updated automatically by OEMiROT_Boot postbuild */
define exported symbol IMAGE_HEADER_SIZE = 0x400; /* mcuboot headre size */

define exported symbol __ICFEDIT_intvec_start__ = 0x08000000 + NS_CODE_OFFSET + IMAGE_HEADER_SIZE;
/*-Memory Regions-*/
define exported symbol __ICFEDIT_region_ROM_start__     = 0x08000000 + NS_CODE_OFFSET + IMAGE_HEADER_SIZE;
define symbol __ICFEDIT_region_ROM_end__       = 0x08000000 + NS_CODE_OFFSET + NS_CODE_SIZE - 1;

Security H5 OEMiROT Appli TZ mapping file s mdkarm.png

Due to the use of #define, the first line below is also mandatory and must be the first line of the .sct file.

#! armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -xc
#define S_CODE_OFFSET 0x12000                       /* This define is updated automatically by OEMiROT_Boot postbuild */
#define S_CODE_SIZE 0x6000                          /* This define is updated automatically by OEMiROT_Boot postbuild */
#define NS_CODE_OFFSET S_CODE_OFFSET + S_CODE_SIZE  /* Non secure code Offset */
#define IMAGE_HEADER_SIZE 0x400                     /* mcuboot headre size */
#define S_CODE_START 0x0C000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE
#define S_APP_CODE_SIZE S_CODE_SIZE - CMSE_VENEER_REGION_SIZE - IMAGE_HEADER_SIZE
#define S_CODE_LIMIT (S_CODE_START + S_APP_CODE_SIZE - 1)
#define CMSE_VENEER_REGION_START S_CODE_LIMIT + 1
#define CMSE_VENEER_REGION_SIZE 0x400


Security H5 OEMiROT Appli TZ mapping file ns mdkarm.png
Due to the use of #define, the first line below is also mandatory and must be the first line of the .sct file.

#! armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -xc
#define S_CODE_OFFSET 0x12000                          /* This define is updated automatically from OEMiROT_BOOT project */
#define S_CODE_SIZE 0x6000                             /* This define is updated automatically from OEMiROT_BOOT project */
#define NS_CODE_OFFSET S_CODE_OFFSET + S_CODE_SIZE     /* Non secure code Offset */
#define NS_CODE_SIZE 0xA0000                           /* This define is updated automatically from OEMiROT_BOOT project */
#define IMAGE_HEADER_SIZE 0x400                        /* mcuboot header size */
#define NS_CODE_START 0x08000000 + NS_CODE_OFFSET + IMAGE_HEADER_SIZE
#define NS_APP_CODE_SIZE NS_CODE_SIZE - IMAGE_HEADER_SIZE

Security H5 OEMiROT Appli TZ mapping file s cubeide.png
S_CODE_OFFSET = 0x12000;       /* This define is updated automatically by OEMiROT_Boot postbuild */
S_CODE_SIZE = 0x6000;         /* This define is updated automatically by OEMiROT_Boot postbuild */
IMAGE_HEADER_SIZE = 0x400;       /* mcuboot header size */
CMSE_VENEER_REGION_SIZE = 0x400;  /* Include TLVs and trailer. User configurable */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x30000000,    LENGTH = 0x40000    /* Memory is divided. Actual start is 0x30000000 and actual length is 256K */
  FLASH    (rx)    : ORIGIN = (0xc000000 + S_CODE_OFFSET + IMAGE_HEADER_SIZE),    LENGTH = (S_CODE_SIZE - CMSE_VENEER_REGION_SIZE)    /* Memory is divided. Actual start is 0x8000000 and actual length is 2048K */
  FLASH_NSC    (rx)    : ORIGIN = (0xc000000 + S_CODE_OFFSET + S_CODE_SIZE - 0x2000),    LENGTH = (CMSE_VENEER_REGION_SIZE)    /* Non-Secure Call-able region */
}


Security H5 OEMiROT Appli TZ mapping file ns cubeide.png

S_CODE_OFFSET = 0x12000;                        /* This define is updated automatically by OEMiROT_Boot postbuild */
S_CODE_SIZE = 0x6000;                           /* This define is updated automatically by OEMiROT_Boot postbuild */
NS_CODE_SIZE = 0xA0000;                          /* This define is updated automatically by OEMiROT_Boot postbuild */
NS_CODE_OFFSET = (S_CODE_OFFSET + S_CODE_SIZE);
IMAGE_HEADER_SIZE = 0x400;                      /* mcuboot header size */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20050000,    LENGTH = 0x50000    /* Memory is divided. Actual start is 0x20000000 and actual length is 320K */
  FLASH   (rx)    : ORIGIN = (0x08000000 + NS_CODE_OFFSET + IMAGE_HEADER_SIZE),    LENGTH = (NS_CODE_SIZE - IMAGE_HEADER_SIZE)    /* Memory is divided. Actual start is 0x8000000 and actual length is 2048K */
}

3.3. Image generation

STM32TrustedPackageCreator uses OEMiRoT_Code_Image.xml (in the Firmware/Projects/STM32H573-DK/ROT_Provisioning/STM32H573-DK/OEMiROT/Images folder) to generate the image. It contains all required parameters, including the location of the secure (rot_tz_s_app.bin) and nonsecure (rot_tz_ns_app.bin) binary files of the user application. This parameter is updated automatically during the provisioning sequence based on the oemirot_boot_path_project variable.

Therefore, the IDE must be configured to generate a .bin file.

Secure
Security H5 OEMiROT Appli TZ bin s ewarm.png
$PROJ_DIR$\..\..\Binary\rot_tz_s_app.bin


Nonsecure
Security H5 OEMiROT Appli TZ bin ns ewarm.png

$PROJ_DIR$\..\..\Binary\rot_tz_ns_app.bin
Secure
Security H5 OEMiROT Appli TZ bin s mdkarm.png
fromelf #L --bincombined --output=$L"\..\..\..\..\Binary\rot_tz_s_app.bin"


Nonsecure
Security H5 OEMiROT Appli TZ bin ns mdkarm.png

fromelf #L --bin --output=$L"\..\..\..\..\Binary\rot_tz_ns_app.bin"
Secure

Security H5 OEMiROT Appli TZ bin s cubeide.png

Nonsecure
Security H5 OEMiROT Appli TZ bin ns cubeide.png

To meet the binary name and location requirements, a postbuild script is implemented to copy the binaries generated by the IDE. This script must be updated with the generated binary names to perform this operation.

Security H5 OEMiROT Appli TZ bin postbuild cubeide.png


The image generation can be started manually using STM32TrustedPackageCreator, but it is more efficient to modify the user application project to generate the image automatically at the end of each compilation as a postbuild command.

Refer to the figures in the STiRoT_Appli_TrustZone example to add a postbuild command.

An example of postbuild.bat/.sh is provided in the Firmware/Projects/STM32H573-DK/Templates/ROT/OEMiROT_Appli_TrustZone and Firmware/Projects/STM32H573-DK/Applications/ROT/OEMiROT_Appli_TrustZone examples. The image generation is performed based on OEMiRoT_Code_Image.xml, stored in the Firmware/Projects/STM32H573-DK/ROT_Provisioning/OEMiROT/Images folder. Depending on the location of the application, the postbuild script may be updated to access the OEMiRoT_Code_Image.xml file.

3.4. Security management

For security robustness, when OEMiRoT jumps to the user application, the MPU is configured to ensure that only the user application code area can be executed (execution surface controlled via MPU configuration). It is the responsibility of the application to reconfigure the MPU to meet the security requirements.

3.5. Ready to start

The application has now been adapted to OEMiRoT Boot path. To testit, run the provisioning.bat/sh script stored in the Firmware/Projects/STM32H573-DK/ROT_Provisioning/OEMiROT folder and follow the instructions.


For more details, refer to the following wiki pages:

4. Two boot stages: STiRoT + OEMuRoT

The adaptation of the user application for a STiRoT + OEMuRoT Boot path with two boot stages is very similar to the one-boot-stage OEMiROT use case, with two major differences:

  • The location of the provisioning scripts: Firmware\Projects\STM32H573-DK\ROT_Provisioning\STiROT_OEMuROT.
  • OEMuRoT is generated by compiling the OEMiRoT_Boot project with the OEMUROT_ENABLE switch activated. OEMuRoT acts as a second boot stage.