en / de
Expertisen
Methoden
Dienstleistungen
Referenzen
Jobs & Karriere
Firma
Technologie-Trends TechCast WebCast TechBlog News Events Academy

First run of the Trusted Firmware (TFM) application

STMicroelectronics delivers a TFM application to test and understand its implementation of the Trusted Firmware. Let’s see what the first run of the Trusted Firmware application provides.

The second article of the series on Trusted Firmware shows how to import the TFM application of STMicroelectronics and the first run of the application on a STM32L562E-DK.

The other articles of the series are:

  1. Security management with Trusted Firmware presents the theoretical part of Trusted Firmware and of Secure Boot and Secure Firmware Update
  2. (This article) First run of the Trusted Firmware (TFM) application presents the first run of the TFM application
  3. Focus on the Secure Storage service of Trusted Firmware (TFM) focuses on the Secure Storage service

Tools installation

The TFM application is available for STM32CubeIDE, Keil and IAR. In this example STM32CubeIDE is going to be used as it is provided for free, does not require any license and integrates STM32CubeMX and STM32CubeProgrammer which facilitates the configuration of the micro-controller and its programming.

STMicroelectronics provides, through its STM32Cube ecosystem, every tool necessary to compile the TFM application and to program a development kit.

To avoid any path issue, it is recommended to install these tools (at least the IDE) in a path not containing spaces, i.e. «C:\ST\». The installation steps are:

  1. Download and install STM32CubeIDE (v1.7.0) which is the IDE of STMicroelectronics.
  2. Download and install STM32CubeProgrammer (v2.8.1) which is the programmer of STMicroelectronics. STM32CubeIDE already contains it but having it as stand-alone tool facilitates its use.
  3. If you use Microsoft Windows 7, 8 or 10, download and install STSW-LINK009 (v2.0.2) which is the USB driver for the embedded STLINK-V3.
  4. Download and install Tera Term (v4.106) which is used to display the TFM application output. This tool is accessible for free and understands the ymodem protocol that STMicroelectronics uses.

Import code in STM32CubeIDE

The TFM source code example contains three subprojects:

These subprojects can be imported in STM32CubeIDE after having installed the STM32Cube MCU & MPU Package for the STM32L5 (v1.4.0). To do so in STM32CubeIDE, open «Help > Manage Embedded Software Packages», scroll down until «STM32L5» and select version 1.4.0. Finally, click on «Install Now».

The import procedure of the code examples must be repeated for all three subprojects. In STM32CubeIDE:

  1. Open «File > Import…»
  2. Select «General > Import STM32Cube Example»
  3. In field «Name», write «TFM»

    Project examples found after entering TFM in Name

    Project examples found after entering TFM in Name

  4. Select one of the three projects (the procedure must anyway be repeated for all three of them), e.g. TFM_Appli. On the right panel of the window, select the project example targeting the STM32L562E-DK and click Next.

    Select the TFM_Appli example targeting the STM32L562E-DK

    Select the TFM_Appli example targeting the STM32L562E-DK

  5. Select the location where to store the project (or leave the default location) and click Finish.

Repeat the same process for TFM_SBSFU_Boot and TFM_Loader. After importing the three subprojects, the Project Explorer of STM32CubeIDE should look like the following image.

Project Explorer after importing the three TFM subprojects

Project Explorer after importing the three TFM subprojects

Building and programming

Step 1: Initialize the STM32L5

The STM32L562E-DK must be initialized first before being able to load the TFM applications.

Connect the STM32L562E-DK via USB to the computer. Use the micro-USB port named “STLK USB” on the right side of the board. STMicroelectronics suggests using a script to do this automatically, which is a good idea to avoid any wrong configuration [UM2671, §10.1]. Simply drag and drop the script

C:\Users\…\STM32Cube\Repository\STM32Cube_FW_L5_V1.4.0\Projects\STM32L562E-DK\Applications\TFM\TFM_SBSFU_Boot\STM32CubeIDE\regression.sh

in STM32CubeIDE and verify that the script has been correctly executed!

The configuration can be manually verified by connecting the STM32CubeProgrammer. Select the Hot Plug Mode and click Connect. The programmer should show the following target information.

Target information of the STM32L562E-DK

Target information of the STM32L562E-DK

The configuration is present in the OB (Option Bytes) tabulation. The table below summarises the configuration present in [UM2671, §10.1] and that should now be applied to your board.

Category Option Value
Read Out Protection RDP AA
User Configuration SWAP_BANK Unchecked
DBANK Checked
SRAM2_RST Unchecked
TZEN Checked
HDP1EN Unchecked
HDP1_PEND Value 0x00, Address 0x08000000
HDP2EN Unchecked
HDP2_PEND Value 0x00, Address 0x08000000
SECBOOTADD0 Value 0x180052, Address 0x0c002900
Secure Area 1 SECWM1_PSTRT Value 0x00, Address 0x08000000
SECWM1_PEND Value 0x7f, Address 0x0803f800
Write Protection 1 WRP1A_PSTRT Value 0x7f, Address 0x0803f800
WRP1A_PEND Value 0x00, Address 0x08000000
WRP1B_PSTRT Value 0x7f, Address 0x0803f800
WRP1B_PEND Value 0x00, Address 0x08000000
Secure Area 2 SECWM2_PSTRT Value 0x00, Address 0x08040000
SECWM2_PEND Value 0x7f, Address 0x0807f800
Write Protection 2 WRP2A_PSTRT Value 0x7f, Address 0x0807f800
WRP2A_PEND Value 0x00, Address 0x08040000
WRP2B_PSTRT Value 0x7f, Address 0x0807f800
WRP2B_PEND Value 0x00, Address 0x08040000

Step 2: Compile the software

The compilation procedure requires 4 sub steps [UM2671, §10.2] as depicted in Figure 24.

Build process

Build process

Build TFM_SBSFU_Boot application

The file boot_hal_cfg.h contains the configuration of the TFM_SBSFU_Boot application. However, when importing the project using STM32CubeIDE as we did earlier in this article, the configuration file is not added to the workspace. This can fortunately be fixed easily:

Add the include folder to the project, step 1

Add the include folder to the project, step 1

Add the include folder to the project, step 2

Add the include folder to the project, step 2

Once done, open the configuration file. According to [UM2671, §10.1], the user should verify its content and adapt it based on his/her needs:

In addition, make sure that flag TFM_DEV_MODE is present in the «Paths and Symbols»; this makes the software compile in development mode, allowing some automatic configurations of the static protections and logging of TFM_SBSFU_Boot on the terminal emulation. To do so, open the properties of the project and then «C/C++ General > Paths and Symbols > Symbols» as shown in figure below.

Paths and Symbols of TFM_SBSFU_Boot

Paths and Symbols of TFM_SBSFU_Boot

Of course, this configuration does not ensure a secured device, but let’s keep in mind that this is a first attempt to use and understand the trusted firmware. The configuration will be hardened later. The diff of the modifications is:

diff --git a/TFM_SBSFU_Boot/Inc/boot_hal_cfg.h b/TFM_SBSFU_Boot/Inc/boot_hal_cfg.h
index c3e1ce2c5e26453330583333876737d20aa4eca0..720d97e458b3293c16049822530542fcc669190d 100644
--- a/TFM_SBSFU_Boot/Inc/boot_hal_cfg.h
+++ b/TFM_SBSFU_Boot/Inc/boot_hal_cfg.h
@@ -39,7 +39,7 @@
 /* Static protection checking  Flag */
 #define TFM_WRP_PROTECT_ENABLE  /*!< Write Protection  */
 #define TFM_HDP_PROTECT_ENABLE /*!< HDP protection   */
-#define TFM_OB_RDP_LEVEL_VALUE OB_RDP_LEVEL_1 /*!< RDP level */
+#define TFM_OB_RDP_LEVEL_VALUE OB_RDP_LEVEL_0 /*!< RDP level */
 #define TFM_SECURE_USER_SRAM2_ERASE_AT_RESET /*!< SRAM2 clear at Reset  */
 #ifdef TFM_DEV_MODE
 #define TFM_OB_BOOT_LOCK 0 /*!< BOOT Lock expected value  */

An additional modification is still required because the postbuild script (postbuild.sh) contains some errors that must be corrected. Edit the file according to these changes:

diff --git a/TFM_SBSFU_Boot/STM32CubeIDE/postbuild.sh b/TFM_SBSFU_Boot/STM32CubeIDE/postbuild.sh
index 58145eb8abe309eadff1d201579daa6385dc29ca..da3b5ba0bbb30c5074274d2633413da7cfe9448f 100644
--- a/TFM_SBSFU_Boot/STM32CubeIDE/postbuild.sh
+++ b/TFM_SBSFU_Boot/STM32CubeIDE/postbuild.sh
@@ -11,7 +11,7 @@ postbuild=$projectdir/../../TFM_Appli/STM32CubeIDE/postbuild.sh
 
 current_directory=`pwd`
 echo $current_directory
-cd $projectdir"/../../Middlewares/Third_Party/mcuboot"
+cd $projectdir"/../Middlewares/Third_Party/mcuboot"
 mcuboot=`pwd`
 cd $current_directory
 
@@ -196,7 +196,6 @@ if [ $ret != 0 ]; then
 echo "postbuild.sh failed"
 exit 1
 fi
-echo $hardeningbat" updated"
 echo $hardening" updated"
 echo $postbuild" updated"
 exit 0

Finally, build the project by clicking on «Project > Build Project»:

Build project

Build project

The release folder should contain a binary file named TFM_SBSFU_Boot.bin.

Build TFM_Appli secure and TFM_Appli non-secure applications

The build of the TFM_Appli Secure and Non-Secure applications do not require any specific configuration. The Secure application must be built first and the Non-Secure application second (click on «Project > Build Project», for each project, as shown in the previous section).

At the end of the build, the respective release folder should contain a binary file; TFM_Appli_Secure.bin for the Secure application and TFM_Appli_NonSecure.bin for the Non-Secure application. In addition, the postbuild script creates two new binaries per application, thus four in total: the first is a signed binary and the second is a signed and encrypted binary. The script saves them in a folder named «Binary» in the root directory of TFM_Appli. The script currently uses default signature and encryption keys. Let’s keep them to ease the test of TFM and change them on a second stage.

Build TFM_Loader application

Similar to the build of TFM_Appli applications, the build of TFM_Loader is quite easy; just click on «Project > Build Project». The release folder should contain the binary file TFM_Loader.bin. Another similarity is that a postbuild script creates a derived binary (the loader image) and saves it in a folder named «Binary» in the root directory of TFM_Loader.

Step 3: Program the firmware into the STM32L5 microcontroller

The project provides a script (TFM_UPDATE.sh) that programs all binaries generated during the build process [UM2671, §10.3]. The script is updated during the postbuild of TFM_SBSFU_Boot application to ensure that binaries are programmed at the correct memory locations.

If you installed the tools in the non-default path, two little changes to the script are necessary as it contains the full path to STM32CubeProgrammer. Modify the value of PATH and external_loader as suggested in the patch below.

diff --git a/TFM_SBSFU_Boot/STM32CubeIDE/TFM_UPDATE.sh b/TFM_SBSFU_Boot/STM32CubeIDE/TFM_UPDATE.sh
index fe5d7cbaef08284da59f010c188c14356a13223b..c58e9e0e86effddb2e307b14a0587e1a877da2f4 100644
--- a/TFM_SBSFU_Boot/STM32CubeIDE/TFM_UPDATE.sh
+++ b/TFM_SBSFU_Boot/STM32CubeIDE/TFM_UPDATE.sh
@@ -4,9 +4,9 @@ echo "TFM_UPDATE started"
 SCRIPT=$(readlink -f $0)
 # Absolute path this script
 SCRIPTPATH=`dirname $SCRIPT`
-PATH="/C/Program Files/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/":$PATH
+PATH="/C/ST/STM32CubeProgrammer/bin/":$PATH
 stm32programmercli="STM32_Programmer_CLI"
-external_loader="C:\PROGRA~1\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin\ExternalLoader\MX25LM51245G_STM32L562E-DK.stldr"
+external_loader="C:\ST\STM32CubeProgrammer\bin\ExternalLoader\MX25LM51245G_STM32L562E-DK.stldr"
 connect_no_reset="-c port=SWD mode=UR -el $external_loader"
 connect="-c port=SWD mode=UR --hardRst -el $external_loader"
 slot0=0xc017000

Finally, connect the STM32F562E-DK and execute TFM_UPDATE.sh. Verify that the script was correctly executed, it must display:

[…]
TFM_Appli Secure Written
[…]
TFM_Appli NonSecure Written
[…]
TFM_Loader Written
[…]
TFM_SBSFU_Boot Written
[…]
TFM_UPDATE script Done, press a key

First Run

Open Tera Term and configure the new connection [UM2671, §10.5] with:

Then, click on menu «Setup», choose «Serial port…» and configure the serial port with:

Click on «New setting» to validate.

Press the reset button on the board. As the security mechanisms have been configured on purpose to the lowest level, the board shouldn’t have any problem to boot because the RDP (read protection option bytes) was set to level 0. The TFM_SBSFU_Boot application starts, verifies the configuration, and corrects it if necessary as we set the flag TFM_DEV_MODE. The first boot should look like

[INF] BANK 1 secure flash [0, 117] : OB [0, 127]
[ERR] Unexpected value for secure flash protection: set wmsec1
[INF] BANK 2 secure flash [127, 0] : OB [0, 127]
[INF] BANK 1 flash write protection [4, 35] : OB [127, 0]
[ERR] Unexpected value for write protection : set wrp1
[INF] BANK 2 flash write protection [116, 127] : OB [127, 0]
[ERR] Unexpected value for write protection : set wrp2
[INF] BANK 1 secure user flash [0, 34] : OB [0, 0]
[ERR] Unexpected value for secure user flash protection : set hdp1
[INF] Starting bootloader
[INF] Initializing BL2 NV area : Power down/reset not supported...
[INF] Init BL2 NV Header area: Done
[INF] Initializing BL2 NV Counters
[INF] Init BL2 NV counters to 0 : Done
[INF] BL2 NV Area Initialized : Power Down/reset supported
[INF] Checking BL2 NV area
[INF] Checking BL2 NV area header
[INF] Checking BL2 NV Counter consistency
[INF] Consistent BL2 NV Counter 3  = 0x0
[INF] Consistent BL2 NV Counter 4  = 0x0
[INF] Swap type: none
[INF] Swap type: none
[INF] verify counter  0 1000000 0
[INF] counter  0 : ok
[INF] verify sig key id 0
[INF] signature OK
[INF] Counter 3 set to 0x1000000
[INF] verify counter  1 1000000 0
[INF] counter  1 : ok
[INF] verify sig key id 1
[INF] signature OK
[INF] 2f, fd, 66, 8e, b6, 87 , af ,8c,
[INF] 62, e6, e3, f5, d1, b9 , f3 ,a3,
[INF] Counter 4 set to 0x1000000
[INF] Bootloader chainload address offset: 0x17000
[INF] Jumping to the first image slot
 set to BL2 SHARED DATA2XX_HUK_CUSTOMIZATION_
[INF] Code c002900 c011bee
[INF] hash TFM_SBSFU_Boot  f27557 .. e8fc7444
[INF] otfdec key …
[INF] otfdec key …
[Sec Thread] Secure image initializing!

Then the non-secure application should take over and display

======================================================================
=              (C) COPYRIGHT 2019 STMicroelectronics                 =
=                                                                    =
=                          User App #A                               =
======================================================================


=================== Main Menu ============================

  Test Protections -------------------------------------- 1

  Test TFM ---------------------------------------------- 2

  Selection :

Two options are available:

Follow the execution of Test AES-GCM

TFM has a very complex source code. Therefore, it is not the goal to understand it in this article. However, it may be interesting after this set up to understand some steps that TFM takes.

The short example below follows the execution of PSA_CONNECT() for the test of AES-GCM:

  1. In main.c, function main()calls tfm_app_menu() to enter «Test TFM» after key 2 is pressed
  2. In tfm_app.c, function tfm_app_menu() calls psa_aead_test() to enter «AES GCM Test» after key 0 is pressed
  3. In crypto_test_common.c, function psa_aead_test() calls psa_allocate_key() to allocate a transient key
  4. In tfm_crypto_ipc_api.c, function psa_allocate_key() calls PSA_CONNECT(TFM_CRYPTO) to connect to PSA
  5. In tfm_crypto_ipc_api.c, define PSA_CONNECT() calls psa_connect(TFM_CRYPTO_SID, TFM_CRYPTO_VERSION)
  6. In tfm_psa_ns_api.c, function psa_connect() calls tfm_ns_interface_dispatch(tfm_psa_connect_veneer)
  7. In tfm_ns_lock.c, function tfm_ns_interface_dispatch() calls tfm_psa_connect_veneer(…)
  8. In tfm_psa_api_veneers.c, function tfm_psa_connect_veneer() calls TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_connect)
  9. In tfm_psa_api_veneers.c, define TFM_CORE_NS_IPC_REQUEST_VENEER calls tfm_core_ns_ipc_request(tfm_svcall_psa_connect)
  10. In tfm_psa_api_veneers.c, function tfm_core_ns_ipc_request() calls tfm_core_ipc_request(tfm_svcall_psa_connect)
  11. In tfm_psa_api_veneers.c, function tfm_core_ipc_request() calls
    1. ASM SVC TFM_SVC_IPC_REQUEST() which is the Supervisor call: the «argument» is ignored by the processor but can be retrieved by the exception handler to determine which service is being called
    2. ASM BX LR which is a branch and exchange instruction set operation: the address to jump to is held in register LR (Link Register) which is used to store the return address when a subroutine call is made

The Secure Application retrieves the supervisor call with:

  1. In tfm_core_svcalls_ipc.c, function tfm_core_svc_handler() calls tfm_psa_ipc_request_handler(svc_args)which handles IPC requests
  2. In tfm_psa_api_veneers.c, function tfm_psa_ipc_request_handler() handles the request and calls function from SVC context

Conclusion

This article presented the set up of the STM32L562E-DK with the TFM application.

The set up itself was quite easy as it followed the steps given by the user manual. The good configuration and the use of TFM are, however, more difficult to master, and the code itself is quite complex to understand.

In the next article we will try to take advantage of TFM by using some secure services.

Kommentare

Eine Antwort zu “First run of the Trusted Firmware (TFM) application”

  1. […] First run of the Trusted Firmware (TFM) application presents the first run of the TFM application […]

Schreiben Sie einen Kommentar

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Newsletter - aktuelle Angebote, exklusive Tipps und spannende Neuigkeiten

 Jetzt anmelden
NACH OBEN
Zur Webcast Übersicht