TrustZone
TrustZone is a security hardware extension to the ARMv8-M architecture that has been included with the Arm Cortex-M33 processor in the RSL15 device. This extension provides hardware isolation between secure and non-secure components, and can separate safe applications from unsafe ones, protecting underlying system components from being accessed or changed by untrusted code. For more information about Arm TrustZone, refer to the TrustZone technology for the ARMv8-M architecture manual from Arm.
IMPORTANT: Developers creating TrustZone applications need to be aware of best practices for security when using TrustZone, including Stack Sealing and other recommendations from Arm. |
Secure Execution
System execution starts in the secure execution state. Secure execution has access to all components of the RSL15 system, including the banked instances of several system control, GPIO, and private peripheral registers used for non-secure execution at an offset of 0x20000 from their secure forms.
System configuration, including configuration of the non-secure execution environment, must be implemented in secure execution. Items that the can only be configured in a secure application include:
-
All system control elements controlled by registers in the SYSCTRL group, except the activity counters controlled by the SYSCTRL_CNT_CTRL register and their values stored to the SYSCTRL_*_CNT registers
-
GPIO configuration using the GPIO_CFG registers (the configuration of each GPIO can be read by non-secure code), and configuration of the GPIO pads for JTAG mode using the GPIO_JTAG_SW_PAD_CFG register as described in Functional Configuration
-
GPIO interrupt debounce filter configuration (GPIO_INT_DEBOUNCE) and the GPIO interrupt summary (GPIO_INT_STATUS_S)
Most other system components can be configured to allow or deny access in non-secure code. Secure application configuration of the components that non-secure firmware may access includes:
-
The RAM memories using the SYSCTRL_NS_ACCESS_RAM_CFG* registers
-
Interfaces and peripherals that may be accessed by non-secure firmware, using the SYSCTRL_NS_PERIPH_CFG* registers
-
The GPIOs that can be accessed by non-secure firmware, using the GPIO_CFG_NS_ACCESS_GPIO bits from the GPIO_CFG registers
-
The GPIO interrupt sources that can be accessed by non-secure firmware, using the GPIO_INT_CFG_NS_ACCESS bits from the GPIO_CFG registers
-
The interrupts that can be accessed by the non-secure firmware, using the NVIC_ITNS* registers
NOTE: The default configuration for all of these components denies access in non-secure mode.
Non-Secure Execution
Care must be taken in a non-secure application to ensure that no elements that remain secure are accessed in the non-secure application, as the non-secure execution has limited access to many system components as configured by the secure application. Any attempts to access a component that remains secure results in control reverting to the secure application's secure exception handler. For more information about secure exceptions, refer to Nested Vector Interrupt Controller (NVIC) and the Arm Cortex-M33 Processor Technical Reference Manual.
The non-secure portion of an application has separate:
- Register header files (use rsl15_hw_cid*_ns.h, rsl15_hw_flat_cid*_ns.h)
- These register files contain the updated mappings for the GPIO registers and remove the protected SYSCTRL registers.
- Vector table defining the non-secure application's own interrupt handlers
Non-Secure Use of Secured Features
Secure and non-secure firmware applications can be built to work together. However, non-secure application components cannot access secure resources directly. Instead, any access to secure resources can go through APIs provided by secure software, and these APIs can implement authentications to decide if the access to the secured components is permitted. By having this arrangement, even if there are vulnerabilities in the non-secure applications, the secure components of the device are not compromised.
To create a function that is accessible to the non-secure components of your application, assign the cmse_nonsecure_entry
attribute to your function, as shown in the following example:
int __attribute__ ((cmse_nonsecure_entry)) NonSecureCallback_ExampleFunction(int x)