STM32WBA Bluetooth® LE & TrustZone

Revision as of 12:42, 2 November 2023 by Registered User (→‎How to disable the TrustZone)

1. Introduction

As the STM32WBA is based on an Arm® Cortex®-M33, it embeds the Arm® TrustZone® security feature.

The TrustZone introduces hardware isolation allowing a developer to split its application between a Secure and a NonSecure part (sometimes referred to as Trusted and Nontrusted).

The basis of the isolation brought by the TrustZone, is to identify critical code & data (keys, private user data, …) and isolate it from the rest of the application which does not contains valuables assets.

The majority of the code (Application, Operating system, librairies) should run on the NonSecure side: if a vulnerability would to be found and exploted by an attacker, the malicious code will execute in the NonSecure side, thus will not be able to break the isolation to access critical assets put in the Secure side.

While it is technically possible to put a big amount of code in the secure world, it is generally not recommended. The secure world is designed to be a small, highly secure environment that is used to protect sensitive data and processes. Putting a large amount of code in the secure world can increase the attack surface and potentially introduce vulnerabilities that could be exploited by attackers.

For more information, see TrustZone for Cortex-M reference[1]

2. Bluetooth® Low Energy

The Bluetooth® Low Energy (BLE) protocol being complex, a lot of code is written in order to establish the Bluetooth®LE protocol stack. Putting this stack in the Secure side of the STM32WBA would break the principle of critical/not critical isolation of the TrustZone.

That’s why, in our architecture, the Bluetooth® LE stack is put in the NonSecure side.

As the Bluetooth® LE stack uses several cryptographical keys, these keys will also be put in the NonSecure side. These keys will protect the application from an external attacker willing to eavesdrop on the Bluetooth® LE exchange or trying to conduct a MITM (Man-in-the-Middle) attacks.

In regard to your application and the potential threats it may face, if one of those threats involves an attacker having the ability to remotely execute code, simply having the Bluetooth® LE keys stored in the non-secure area may not be sufficient to classify your application as secure. To ensure security, it will be necessary to implement application-level encryption that utilizes keys isolated by the TrustZone architecture and managed by the Secure

Example architecture
Connectivity:Connectivity WBA BLE TZ Illustration.png


3. The Example

In order to build connected IoT devices with isolation properties leveraged by the TrustZone, several configuration steps have to be followed to allow the Bluetooth® LE stack to run one the NonSecure side of the STM32WBA.

To illustrate such a configuration the example BLE_p2pServer_TZ has been created.

This example is similar to BLE_p2pServer with the TrustZone being activated and the Blue LED being connected to the Secure side of the MCU: The NonSecure application runs the same application as the basic BLE_p2pServer. When a LED switch is required, the NonSecure application will call a Secure function in the Secure side. This Secure function will then handle the GPIO connected to the blue LED.

This example illustrates the following points:

  • How to properly configure the STM32WBA when the TrustZone is activated in order to run the Bluetooth® LE stack.
  • How to connect a peripheral to the Secure side (here, the GPIO connected to the blue LED).
  • How to make a Secure function call (here, the Secure function managing the LED).

4. Configuration

When using the TrustZone, most of the STM32WBA subsystems (Flash, RAM, Peripherals, ...) will be attached to the Secure world. The MCU will boot on the Secure side and configure some of the subsystems as NonSecure for the NonSecure application to use them.

This section will describe how to configure a project using CubeMX in order to create a NonSecure application using the Bluetooth® LE stack. To create the overall NonSecure application as a CubeMX project, you can follow the dedicated page STM32WBA Bluetooth® Low Energy - STM32CubeMX Application Conception

The main differences relative to the addition of the TrustZone will be described in this section.

4.1. Starting the CubeMX project

When creating a new project, the TrustZone must be enabled at first:

TrustZone enabled


From here, you will have the same panel described in the BLE_p2pServer page, but every section will have a Secure and/or NonSecure configuration (M33S for the Secure and M33NS NonSecure):

Security attribution example


Some of the individual panels will also have new configuration options relative to Secure/NonSecure world. From here, it is now possible to attach some of the MCU part to Secure/NonSecure side.

4.2. IP Configuration

When the TrustZone security is activated by the TZEN option bit in the FLASH_OPTR, the default system security state is detailed below:

  • CPU

– Cortex®-M33 is in secure state after reset. The boot address must be at a secure address.

  • Memory map

– SAU is fully secure after reset. Consequently, all memory map is fully secure. Up to height SAU configurable regions are available for security attribution.

  • Flash memory

– The Flash memory security area is defined by watermark user options.

– Flash block-based security attributions are non-secure after reset.

  • SRAMs

– All SRAMs are secure after reset. MPCBBx (block-based memory protection controller) are secure.

  • Peripherals

– Securable peripherals are non-secure after reset.

– TrustZone-aware peripherals are non-secure after reset. Their secure configuration registers are secure.

  • All GPIO are secure after reset
  • Interrupts

– NVIC: All interrupts are secure after reset. NVIC is banked for secure and NonSecure state.

– TZIC: All illegal access interrupts are disabled after reset

This section will describe how to properly configure these peripherals.

4.2.1. GTZC_S

The Global TrustZone Controller (GTZC) module configuration includes several submodules:

  • TrustZone illegal access Controller (TZIC)

This module allows to generate an illegal access interrupt (GTZC_IRQHandler) when an illegal access is detected on a peripheral. In our example we let it deactivated.

TZIC configuration



  • TrustZone Security Controller (TZSC) – Privilegeable Peripherals

This module allows to create priviledge/unpriviledge access on peripherals. In our example, we don't use the different priviledge level.

TZSC configuration - Privilegeable Peripherals


Info white.png Information

Note: The GTZC_NS can be used to only manage privileges on a NonSecure side Peripheral.


  • TrustZone Security Controller (TZSC) – Securable Peripherals

This module allows to attach peripherals to the Secure/NonSecure context. In our example, apart from the GPIO, no peripherals are attached to the Secure side.

TZSC configuration - Securable Peripherals


  • Block-Based Memory Protection Controller (MPCBB)

This module allows to configure part of the SRAM to the desired attribution (Secure/NonSecure & Privileged/Unprivileged). MPCBBx allows the configuration for SRAMx :

  • SRAM6 being used by the Bluetooth® LE IP (in NonSecure side), it must be configured as NonSecure & NonPrivileged, with MPCBB6
MPCBB6 configuration


  • SRAM2 being used by the NonSecure application, it must be configured as NonSecure & NonPrivileged, with MPCBB2
MPCBB2 configuration


Other configurations of SRAM2 & SRAM1 are left to the user depending on your application requirements.

4.2.2. GPDMA1

In the BLE_p2pServer_TZ example, the GPDMA1 is used by the UART logger.

With the addition of the TrustZone, the peripheral parameters (Channel, Source & Destination) can now have security attribution. In our example, as the logging is done on the NonSecure side, all of the DMA parameters have to be NonPriviledged and NonSecure.

GPDMA1 configuration


4.2.3. GPIO

In the BLE_p2pServer_TZ project, the pin PB4 is connected to the Blue LED and controlled by the Secure world. This GPIO should be connected to the Secure world, the others GPIO being connected to the NonSecure world

GPIO configuration


4.2.4. RTC

As the other peripherals, parts of the RTC can be defined to be accessed only by the Secure world. In our example we let everything accessible by the NonSecure world

Interrupt configuration


4.2.5. NVIC

There are three different kinds of interrupt:

  • Banked the interrupt will trigger in the current state context.
  • Secured the interrupt will trigger in the Secure state context.
  • Configurable it is possible to choose the security state in which the interrupt will trigger.

For configurable interrupt, the register NVIC→ITNS manage its attribution. By correctly setting the attribution of your IRQ in the STM32CubeMX project, the right ITNS value will be generated.

Once the correct security attribution has been set, it is possible to set the priority of the interrupt in the NVIC_S/NVIC_NS panel.

Interrupt configuration


4.2.6. SAU

The SAU(Secure Attribution Unit) configuration is created by default on the project and it's not possible to configure it with CubeMX.

The SAU configuration is aligned with the Secure and NonSecure project Linker file.

Here the project basic configuration:

Description Region Attribution
NonSecure code 0x08080000 - 0x080FFFFF Non-Secure
Bootloader, OTP, DESIG, Flash user options 0x0BF88000 - 0x0BF97FFF Non-Secure
NSC region 0x0C07E000 - 0x0C07FFFF Non-Secure Callable
NonSecure SRAM 0x20010000 - 0x2001FFFF Non-Secure
NonSecure Peripheral 0x40000000 - 0x4FFFFFFF Non-Secure


This configuration is made in the function TZ_SAU_Setup in the file partition_stm32wba52xx.h

4.2.7. Heap & Stack size

The Secure & NonSecure side have their own Stack & Heap. It is possible to set them independently in the Project Manager panel:

Heap & Stack configuration


4.3. Secure Service creation

In our example, we will create a function in the Secure side to manage the LED1, which will be called by the NonSecure side. Such function is called a Secure function which realizes a Secure service.

As described previously, the goal of a Secure service is to provide a secure and isolated execution environment within the device. This allows sensitive data and processes to be protected from unauthorized access or tampering by other software or hardware components in the system.

In our example, it will be impossible for the NonSecure side to change the LED state without calling the Secure side. This example is simple, but more complex Service could be built to prevent the NonSecure side to access critical data while realizing the application it has been built for (example: A Secure service signing data from the NonSecure world while keeping the keys inside the Secure world)

The Secure services are written in the file secure_nsc.c.

CMSE_NS_ENTRY void SECURE_LED_Blue_Off()
{
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);
}

CMSE_NS_ENTRY void SECURE_LED_Blue_On()
{
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
}


The attributes CMSE_NS_ENTRY will tell the compiler that this function is callable from the NonSecure world (i.e. associated veneer and SG instruction will be created)

5. Option Bytes Configuration

Once the correct configuration in the Secure project has been done, in order to allow the Secure project to boot and the NonSecure side to execute, some Option bytes have to be correctly set.

  • TrustZone enabling
TZEN


You have to first "Apply" this Option Byte to then have access to the next Options Byte of this section.

  • Secure Boot

The SECBOOTADD0 will define where the initial MSP value and Reset_Handler address will be fetch for the Secure project boot, it has to be correctly set according to our project linker file. In our example 0x0c000000

SECBOOTADD0



  • Secure Watermark

The Flash memory can be protected against NonSecure read and write accesses. The Secure flash region used in the project should be set as Secure by the Secure Watermark registers and match the project linker file. In our example the range 0x08000000 - 0x0807ffff is dedicated to the Secure side

SECWM1


6. Booting Sequence

This section will sum-up how the previous mentioned configuration is done during the booting phase on a project generated by STM32CubeMX and how it is ordered.

Overall booting sequence


puce1.png
Reset_Handler

The MCU will launch the application at the Reset_Handler address present in the VTOR specified by the Option byte SECBOOTADD0

puce2.png
TZ_SAU_Setup() called

This function will handle the initialization of SAU region, SCR & AIRCR configuration and Interrupt attribution (NVIC.ITNS)

puce3.png
Peripheral Initialization

GTZC_S Initialization with the MPCBB configuration

puce4.png
Booting NonSecure application

Setting the MSP of the NonSecure application and getting the NonSecure Reset_Handler from the NonSecure VTOR

Info white.png Information

Note: The NonSecure VTOR address is fixed in main.c file (VTOR_TABLE_NS_START_ADDR) and should match the VTOR address specified in the NonSecure linker file.

puce5.png
Secure service calling

Once the NonSecure side booted, Secure function can be called if they have been created with the attribute CMSE_NS_ENTRY

7. How to Debug ?

As the whole example is split into two different subprojects (Secure/NonSecure), the debugging of the example requieres to debug the two projects at once.

7.1. IAR

With IAR, the right configuration is already present to flash & debug the two projects at once.

When selecting the Secure project, in Options > Debugger > Images, the NonSecure image is listed as an extra image.

When the debug and the flash of the Secure project will be done from the IAR panel, the NonSecure project will be also flashed, and its symbols will be loaded in case of debug.

IAR - Extra Image Download


The project Secure have to be compiled before the project NonSecure. The Download & Debug of the project Secure has to be used to correctly debug the entire example.

IAR - Debug


7.2. STM32CubeIDE

With STM32CubeIDE, the configuration to flash & debug the two projects at once have to be done.

When selecting the Secure project, in Debug as > Debug Configurations > startup, the NonSecure have to be added. Select "Add" and choose the NonSecure project.

STM32CubeIDE - Extra Image Download


When the debug and the flash of the Secure project will be done from the STM32CubeIDE panel, the NonSecure project will be also flashed, and its symbols will be loaded in case of debug.

STM32CubeIDE - Debug


8. How to disable the TrustZone

Warning, if not done correctly, this step could brick your STM32WBA.

The ObtionByte TZEN can only be disable when doing a RDP regression from RDP1 to RDP0.

If the STM32WBA is already in RDP 2, as this RDP level is final and the OptionBytes are read-only, no RDP regression and TrustZone deactivation are possible.

As the debugger should be connected to modify the OptionByte TZEN and the RDP to 1 preventing a debugger to be connected to the Secure part, the debugger should be connected in "Hot plug" mode when the NonSecure part is booted.

You must be sure that a NonSecure part is booted by the Secure before going in RDP 1 two method can be used to achieve that:

  • With your custom application or with an example which successfully launch the NonSecure part
  • By using the bootloader with the PH3 pin, note that a wrong nSWBOOT0, nBOOT0, BOOT_LOCK configuration could prevent this method not to work.

Once this preliminary verification is done, attach STM32CubeProgrammer in Hot plug mode and do the following step to put TZEN to 0:

  • If not in RDP 1, put the RDP to 1 and "Apply" the configuration
  • Once in RDP 1, put the RDP to 0 and uncheck the TZEN ObtionByte and "Apply" the configuration in one shot.

The STM32WBA should now be with the TrustZone disabled.

9. References