There are 3 ways of developing an application compatible with a secure boot:
- Develop your application without taking into account the secure boot as a first step, then adapt the application to the secure boot path. This is the object of this article.
- Or add your code into the ROT template project (Templates_ROT). These projects are already adapted to the secure bootpath.
- Or update existing ROT application projects (OEMuROT_Appli). These projects are already adapted to the secure bootpath.
This article uses the STM32N6570-DK board as an example but the process remains valid for other STM32N6 boards.
1. Prerequisites
As shown below, different scripts are provided to facilitate the application configuration and firmware image generation.
The application folder structure should match the standard one which is available in the STM32CubeN6 package, whether for a full secure application or for a secure and non-secure application. The names of the files and folders underlined in red must be compliant.
To create this folder structure, when generating the application with STM32CubeMX, make sure that the option "Generate Under Root" is not selected.
2. OEMuRoT
When your application runs without secure boot and you want to use OEMuRoT to secure it, you need to do the following adaptations:
- Configure OEMuRoT according to your application requirements (number of images, size of images...).
- The memory mapping of the user application must be adapted. The memory mapping depends on OEMuRoT configuration.
- The user application binary must be signed and encrypted. At each boot, OEMuRoT 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 OEMuRoT when jumping in your application. To ensure the security of the device, the MPU is configured to allow only the user application code area to be executed, minimizing the risk of unauthorized code execution. It is the user application responsibility to reconfigure the MPU to fit with its security needs.
A set of scripts is provided in the Firmware/Projects/STM32N6570-DK/ROT_Provisioning folder to activate and configure OEMuRoT. These scripts are designed to adapt automatically the configuration files such as OEMuROT_XX_Code_Image.xml, OEMuROT_XX_Data_Image.xml, the flash_programming.bat (.sh) script but also the application linker files based on OEMuRoT configuration.
Before executing these scripts, it is mandatory to update the oemurot_boot_path_project variable in Firmware/Projects/STM32N6570-DK/ROT_Provisioning/env.bat (.sh) which must point to the user application folder. As this path is relative from Firmware/Projects/STM32N6570-DK you may have to add several "../" (parent directory) to navigate into your drive.
2.1. OEMuRoT configuration
To configure OEMuRoT to your application requirements, you must edit the file Firmware/Projects/STM32N6570-DK/Applications/ROT/OEMuROT_Boot/Inc/flash_layout.h
Here are some of the key parameters you might find in the flash_layout.h file:
In our example, we use the default flash layout as defined:
- Load and run in internal RAM mode
- Overwrite mode
- S data image enabled.
- NS data image enabled.
- FLASH_S_PARTITION_SIZE 0x10000
- FLASH_NS_PARTITION_SIZE 0x20000
- FLASH_S_DATA_PARTITION_SIZE 0x10000
- FLASH_NS_DATA_PARTITION_SIZE 0x10000
OEMuRoT_Boot postbuild command will propagate the flash layout configuration to the provisioning scripts and application linker files. It can also automatically propagate it to an application header file. It could be useful for your 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, you have to copy file Firmware\Projects\STM32N6570-DK\Applications\ROT\OEMuROT_Appli\Secure_nsclib\appli_flash_layout.h into your application directory My_Appli\Secure_nsclib\appli_flash_layout.h
2.2. User application adaptation
In this chapter, we highlight some parts of the linker file to explain the most important points to take care of, but, if you didn't modify this file, we recommend to use the complete mapping file template provided for OEMuRoT_Appli and thus skip the regions adaptation described below.
Region adaptation:
When started by OEMuRoT, the user application binary must be included in an image including a header as described in Image generation chapter. Therefore, the vector table is shifted of 0x400 bytes.
As done in Firmware/Projects/STM32N6570-DK/Templates/ROT/OEMuROT_Appli example, CODE_S_ADDRESS, CODE_S_SIZE, DATA_S_ADDRESS, DATA_S_SIZE, CODE_NS_ADDRESS, CODE_NS_SIZE, DATA_NS_ADDRESS and DATA_NS_SIZE symbols must be added in the linker files of the secure and non-secure projects. These symbols get automatically updated during the OEMuROT_Boot project compilation, taking into account the memory configuration of OEMuROT_Boot which depends on MCUBOOT_OVERWRITE_ONLY, MCUBOOT_S_DATA_IMAGE_NUMBER and MCUBOOT_NS_DATA_IMAGE_NUMBER compilation switches. The vector table address, code and data sections must be defined using CODE_S_ADDRESS, CODE_S_SIZE, DATA_S_ADDRESS, DATA_S_SIZE, CODE_NS_ADDRESS, CODE_NS_SIZE, DATA_NS_ADDRESS and DATA_NS_SIZE symbols:
- IMAGE_HEADER_SIZE is configured by default, and its value must not be updated.
- CODE_NS_ADDRESS 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 he decided to change partitioning logic.
- CODE_S_ADDRESS, CODE_S_SIZE, DATA_S_ADDRESS, DATA_S_SIZE, CODE_NS_ADDRESS, CODE_NS_SIZE, DATA_NS_ADDRESS and DATA_NS_SIZE symbols are automatically updated during OEMuROT_Boot project compilation.
define exported symbol CODE_S_ADDRESS = 0x34100400; /* This define is updated automatically from OEMuROT_Boot project */
define exported symbol CODE_S_SIZE = 0x10000; /* This define is updated automatically from OEMuROT_Boot project */
define exported symbol DATA_S_ADDRESS = 0x341e0000; /* This define is updated automatically from OEMuROT_Boot project */
define exported symbol DATA_S_SIZE = 0x10000; /* This define is updated automatically from OEMuROT_Boot project */
define symbol IMAGE_HEADER_SIZE = 0x400; /* mcuboot header size */
define symbol TRAILER_MAX_SIZE = 0x2000; /* mcuboot trailer max size */
define symbol __ICFEDIT_intvec_start__ = CODE_S_ADDRESS;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = CODE_S_ADDRESS;
define symbol __ICFEDIT_region_ROM_end__ = CODE_S_ADDRESS + CODE_S_SIZE - IMAGE_HEADER_SIZE - TRAILER_MAX_SIZE - 1;
define symbol __ICFEDIT_region_RAM_start__ = DATA_S_ADDRESS;
define symbol __ICFEDIT_region_RAM_end__ = DATA_S_ADDRESS + DATA_S_SIZE - 1;
Firmware/Projects/STM32N6570-DK/Templates_ROT/EWARM/AppliNonSecure
define exported symbol CODE_NS_ADDRESS = 0x24064400; /* This define is updated automatically from OEMuROT_Boot project */
define exported symbol CODE_NS_SIZE = 0x20000; /* This define is updated automatically from OEMuROT_Boot project */
define exported symbol DATA_NS_ADDRESS = 0x240e4000; /* This define is updated automatically from OEMuROT_Boot project */
define exported symbol DATA_NS_SIZE = 0xc000; /* This define is updated automatically from OEMuROT_Boot project */
define symbol IMAGE_HEADER_SIZE = 0x400; /* mcuboot header size */
define symbol TRAILER_MAX_SIZE = 0x2000; /* mcuboot trailer max size */
define symbol __ICFEDIT_intvec_start__ = CODE_NS_ADDRESS;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = CODE_NS_ADDRESS;
define symbol __ICFEDIT_region_ROM_end__ = CODE_NS_ADDRESS + CODE_NS_SIZE - IMAGE_HEADER_SIZE - TRAILER_MAX_SIZE - 1;
define symbol __ICFEDIT_region_RAM_start__ = DATA_NS_ADDRESS;
define symbol __ICFEDIT_region_RAM_end__ = DATA_NS_ADDRESS + DATA_NS_SIZE - 1;
2.3. Image generation
The image generation is done by STM32TrustedPackageCreator with OEMuRoT_XX_Code_Image.xml and OEMuRoT_XX_Data_Image.xml(Firmware/Projects/STM32N6570-DK/ROT_Provisioning/STM32N6570-DK/OEMuROT/Images folder) containing all the required parameters, especially the location of the user application secure (rot_tz_s_app.bin) and non-secure (rot_tz_ns_app.bin) binary files. This parameter is automatically updated during the provisioning sequence based on oemurot_boot_path_project variable.
Therefore, the IDE must be configured to generate a .bin file.
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.
An example of postbuild.bat/.sh is provided in Firmware/Projects/STM32N6570-DK/Templates_ROT example and Firmware/Projects/STM32N6570-DK/Applications/ROT/OEMuROT_Appli examples. The image generation is performed based on OEMuROT_XX_Code_Image.xml and OEMuROT_XX_Data_Image.xml stored in Firmware/Projects/STM32N6570-DK/ROT_Provisioning/OEMuROT/Images folder. Depending on the location of your application, the postbuild script may be updated to access OEMuROT_XX_Code_Image.xml and OEMuROT_XX_Data_Image.xml files.
2.4. Security management
For security robustness, when OEMuRoT jumps into the user application, the MPU is configured to ensure that only the user application code area is allowed to be executed (execution surface controlled via MPU configuration). It is the application responsibility to reconfigure the MPU to fit with its security needs.
2.5. Ready to start
Now, your application is adapted to OEMuRoT bootpath. To test your application, you must run the provisioning.bat/sh script stored in Firmware/Projects/STM32N6570-DK/ROT_Provisioning/OEMuROT and follow the instructions.
For more details refer to How to start with OEMuRoT on STM32N6 MCUs.