2024-03-27 01:27 PM
Dear community,
I have been experimenting with secure boot on the STM32H573I-DK using the latest git checkout of STM32CubeH5 (see https://github.com/STMicroelectronics/STM32CubeH5).
The STiROT and OEMiROT examples run fine out-of-the-box. However, when I try to provision and run the STiROT_OEMuROT example, then the board seems to be in a boot loop. When I insert a "while (1) {};" line after https://github.com/STMicroelectronics/STM32CubeH5/blob/main/Projects/STM32H573I-DK/Applications/ROT/OEMiROT_Appli_TrustZone/Secure/Src/main.c#L135 , the boot loop stops. So it seems to be a hard fault when the jump to non secure code is made.
Note that I am using the code as it is checked in with Git: no changes were made to the example code.
Can anyone help me in debugging this code? I have already followed the tutorial on https://wiki.st.com/stm32mcu/wiki/Security:How_to_start_with_STiRoT_OEMuRoT_on_STM32H573 multiple times, line by line.
Best,
Jens
2024-04-01 04:35 PM
Hi @jens-vdb
Can you check if you correctly set the path of STM32CubeProgrammer and that the selected application path is correct in env.bat script ?
According to the Wiki, in which step the issue is seen ?
Best regards
2024-04-05 06:05 PM
Hi,
I have verified the correctness of the path of STM32CubeProgrammer. To confirm that, I set it to a non-existent path and then the provisioning script failed. For what it's worth, I'm using Linux. So instead of the *.bat files, I'm using the *.sh files.
The tutorial on https://wiki.st.com/stm32mcu/wiki/Security:How_to_start_with_STiRoT_OEMuRoT_on_STM32H573 fails in step 4. The crash happens after the line "[INF] Jumping to the first image slot" is printed, then the board resets. The following output can be seen on the serial console:
[INF] TAMPER Activated
[INF] Flash operation: Op=0x0, Area=0x0, Address=0x0
[INF] Starting bootloader
[INF] Swap type: none
[INF] verify counter 0 1000000 1000000
[INF] counter 0 : ok
[INF] verify sig key id 0
[INF] checking public key 48 5b
[INF] verifying signature hlen 20
[INF] signature OK
[INF] Swap type: none
[INF] verify counter 1 1000000 1000000
[INF] counter 1 : ok
[INF] verify sig key id 1
[INF] checking public key 46 5b
[INF] verifying signature hlen 20
[INF] signature OK
[INF] Swap type: none
[INF] verify counter 2 1000000 1000000
[INF] counter 2 : ok
[INF] verify sig key id 2
[INF] checking public key 46 5b
[INF] verifying signature hlen 20
[INF] signature OK
[INF] Swap type: none
[INF] verify counter 3 1000000 1000000
[INF] counter 3 : ok
[INF] verify sig key id 3
[INF] checking public key 46 5b
[INF] verifying signature hlen 20
[INF] signature OK
[INF] verify counter 0 1000000 1000000
[INF] counter 0 : ok
[INF] hash ref OK
[INF] verify counter 1 1000000 1000000
[INF] counter 1 : ok
[INF] hash ref OK
[INF] verify counter 2 1000000 1000000
[INF] counter 2 : ok
[INF] hash ref OK
[INF] verify counter 3 1000000 1000000
[INF] counter 3 : ok
[INF] hash ref OK
[INF] Bootloader chainload address offset: 0x1a000
[INF] Jumping to the first image slot
[INF] TAMPER Activated
[INF] Flash operation: Op=0x0, Area=0x0, Address=0x0
(...)
I can break that reset cycle by changing the code as described in my original post. If I put the while(1){}-loop from my original post at the beginning of the HardFault handler function in https://github.com/STMicroelectronics/STM32CubeH5/blob/main/Projects/STM32H573I-DK/Applications/ROT/OEMiROT_Appli_TrustZone/Secure/Src/stm32h5xx_it.c#L57, I am able to break the reset loop (thus confirming that the reset loop is triggered by a hard fault), and I can do some fault analysis according to the Cortex-M33 manual at https://www.st.com/resource/en/programming_manual/pm0264-stm32-cortexm33-mcus-programming-manual-stmicroelectronics.pdf :
From the linker script of the non-secure application, BFAR indicates the highest word on the stack (0x20050000-0x200A0000). So it looks like the non-secure application cannot access its own stack for some reason.
Note that the STiROT example code works out of the box with the default application selected (env.sh: stirot_boot_path_project=Applications/ROT/STiROT_Appli). But the STiROT example does *not* work anymore If I configure it to use the TrustZone application instead:
No output is provided on the serial console, and discovery of the provisioned device indicates that only STiROT init and config are done (ST HDPL1 status):
discovery: target ID.......................:0x484
discovery: SoC ID..........................:0x5b003f 0x3332510a 0x35353537 0x0
discovery: SDA version.....................:2.4.0
discovery: Vendor ID.......................:STMicroelectronics
discovery: PSA lifecycle...................:ST_LIFECYCLE_IROT_PROVISIONED
discovery: PSA auth version................:1.0
discovery: ST HDPL1 status.................:0x3
discovery: ST HDPL2 status.................:0xffffffff
discovery: ST HDPL3 status.................:0xffffffff
discovery: Token Formats...................:0x200
discovery: Certificate Formats.............:0x201
discovery: cryptosystems...................:Ecdsa-P256 SHA256
discovery: ST provisioning integrity status:0xeaeaeaea
No idea if this STiROT exmaple information is on-topic, but I thought it might be relevant.
2024-04-05 07:03 PM
Extending on the seemingly inaccessible stack address, could it be that the call to unsecure_sram3 does not behave as expected (if I understand the code correctly, then that function should "unsecure" the memory to be used by the nonsecure application)? I don't really understand why that call is needed anyways, because the SAU does not configure SRAM3 (0x20000000->...) to be secure.
2024-04-10 12:30 AM
By the way, @CMYL , I have tested the STiROT_Appli_TrustZone I mentioned in my previous post on Windows as well, and also there it does not work.
After some more debugging, I found that there is a difference between:
In the CubeMX generated code, 0xFFFFFFFF is written to MPCBB_PrivConfig_array. In the *_TrustZone applications, 0 is stored there.
Changing that part, however, does not fix the problem still.
2024-04-12 04:08 PM
As an experiment, I tried to use CubeMX for OEMiROT as described on https://wiki.st.com/stm32mcu/wiki/Security:How_to_start_with_STM32CubeMX_OEMiRoT_Boot_path_on_STM32H573
There it fails in step 8:
2024-04-14 01:41 PM
Hi @CMYL ,
I think I have found a possible solution. However, I cannot explain the problem currently.
To summarize all above posts:
As one of many attempts to try to find out what is going wrong, I tried to read each memory region by:
From this experiment, it looks like the memory region 0x20090000 - 0x200A0000 is not accessible on the device: memory can not be read:
./STM32_Programmer.sh -c port=SWD speed=fast ap=1 mode=Hotplug -r32 0x20090000 4
-------------------------------------------------------------------
STM32CubeProgrammer v2.14.0
-------------------------------------------------------------------
ST-LINK SN : 004E00253431510937393937
ST-LINK FW : V3J14M5
Board : STM32H573I-DK
Voltage : 3.31V
SWD freq : 8000 KHz
Connect mode: Hot Plug
Reset mode : Software reset
Device ID : 0x484
Revision ID : --
Device name : STM32H5xx
Flash size : 2 MBytes (default)
Device type : MCU
Device CPU : Cortex-M33
BL Version : 0xE4
SFSP Version: v2.5.0
Debug in Low Power mode enabled
Reading 32-bit memory content
Size : 4 Bytes
Address: : 0x20090000
Error: failed to read the requested memory content
The solution I found is the following:
By doing that, the example works.
But why? Is there something in that memory region that is protected by maybe STiROT?