Industry Article

How to Leverage the Arm TrustZone Security Features of the LPC5500

Learn how the Arm TrustZone extension for the LPC5500 series works and how to start utilizing the safety measures in custom secure and non-secure applications.

With increasingly connected devices and the increasing sophistication of hackers, many companies — like NXP Semiconductors — have recognized a need for countermeasures. NXP has developed the LPC5500 MCU series, which comes with enhanced security features that can be used to protect embedded projects. 

NXP has adopted a FIPS-compliant random number generator, selected the “Prince” decryption algorithm (permitting the core to execute symmetric-encrypted code), and they have implemented a 4096-bit ephemeral on-chip key with PUF technology. When combined with the on-chip cryptographic hardware accelerator ‘CASPER’, LPC5500 MCUs are suited to edge-of-the-network IoT applications requiring robust cyber-security countermeasures and whole life-cycle key provisioning. 

Additionally, the chip leverages the Arm TrustZone technology for Cortex-M-based devices. In this article, learn how the TrustZone extension of the LPC5500 series works and how to get started utilizing the safety measures in custom applications.

 

What is Arm TrustZone Technology for Cortex-M?

The core principle of TrustZone is best explained through an example. The MCU manufacturer often provides custom proprietary code such as security libraries, a bootloader, or fast DSP algorithms in the microcontroller’s ROM. However, the authors of these applications often have good reasons to protect their intellectual property — they might not want users or competitors to decompile the binaries to reverse-engineer the algorithms.

On the one hand, programmers want to utilize these predefined software libraries. On the other hand, however, the manufacturer does not want the code to get exposed to a possibly malicious party.

 

The non-secure user-code and the secure ROM contents reside on the same physical MCU.

Figure 1. The non-secure user-code and the secure ROM contents reside on the same physical MCU.

 

The supplier wants to hide implementation details, while still ensuring that developers can access the functions. The user-code is capable of calling the exposed methods of the hidden software, but it has no direct access to the memory owned by the secure ROM. The result is a structure that consists of two isolated subsystems. Transitions between those two worlds get governed by the TrustZone security extension.

This means that a microcontroller utilizing TrustZone is going to be architected as two separate projects. The first project starts in the Secure state. It then configures the security attributions for on-chip resources and may publish secure functions in a table accessible from the non-secure state. The second one contains the non-secure code and has limited access to the exposed functions of the secure world.

 

Differences from Earlier Architectures

The Cortex-M3 and -M4 cores know two processor modes: thread mode and handler mode. Application software runs in thread mode and the handler-mode deals with exceptions. Code can operate in either a privileged or unprivileged level, which controls access to certain CPU features.

With the TrustZone extension in Cortex-M33 cores, two new states were introduced, as discussed above. That change resulted in four different processor modes: non-secure handler, secure handler mode, non-secure thread, and secure thread.
 

The TrustZone extension in M33 core creates four processor modes.

Figure 2. The TrustZone extension in M33 core creates four processor modes.

 

Besides other updates, new SysTick timers were also introduced with the new states. So now, there are separate timers for the secure-state and the non-secure state.

 

Memory Partition

As previously mentioned, the memory of the MCU gets partitioned into secure and non-secure areas. The CPU core of the MCU can only access secure memory regions if it operates in one of the secure modes. It cannot access any instructions that reside in other memory partitions. However, it can read and write secure and non-secure segments of the data RAM. If the CPU core is in a non-secure state, it can only access the non-secure instruction and data memory blocks.

TrustZone decorates address ranges in the memory map with security attributions. There are three security attributions: secure (S), non-secure (NS), and non-secure callable (NSC). Access to each memory area is permitted or denied, depending upon the current security state of the core.

 

The CPU can access different areas in secure and non-secure mode.

Figure 3. The CPU can access different areas in secure and non-secure mode.

 

On the LPC55S69 device, the memory was split into secure and non-secure segments based on address. If the memory address bit 28 is LOW, the memory is non-secure. Otherwise, it is secure. The only exception is the program memory, which can be configured through the Security Attribution Unit.

 

The Building Blocks of a Secure Application

The non-secure code can’t make any direct calls to the secured part of the application. Instead, the secured part exposes a list of functions that a user can access. That list is named veneer-table because it is a very thin layer that’s visible from the outside, but hides the inner details. The veneer table is located in a memory region with the TrustZone attribute NonSecure Callable. 

Usually, the source of the secured part is not visible. Instead, it’s compiled, giving an object library and the veneer table as a header file. Note that neither of these files contains any of the real instructions, but together they contain the information needed to call secure functions. The veneer table only contains a gateway and a branching instruction to the secure memory location where the real instructions reside.

 

Transitioning Between Secure and Non-Secure Functions 

CPUs with the TrustZone extension support two new functions for transitioning between secure and non-secure: the SG and BXNS instruction.

When the user-code wants a secure function, it makes a call through the veneer table, which is located in the NSC part of the memory. The SG instruction then gets utilized to switch the CPU into a secure mode. When the execution completes, the control gets returned to the user-code with the BXNS instruction:

 

The user code must call a secure function through the TrustZone gatekeeper.

Figure 4. The user code must call a secure function through the TrustZone gatekeeper.

 

If the user attempts an illegal security-related operation, such as directly accessing a protected area, a Secure Fault exception is raised.

 

A Secure Hello World Example

The SDK for the LPCXpresso55S69 comes with a few TrustZone examples that can be loaded in MCUXpresso. As previously mentioned, these examples consist of two separate projects: the secure part and the non-secure user code.

The secure part looks almost exactly like any other MCUXpresso project. However, there is one difference, which is the following function call:

 

the function call in secure mode

 

This function should get called as early as possible. After that, it is the secure project’s responsibility to configure the memory and the non-secure project:

 

 it is the secure project’s responsibility to configure the memory and the non-secure project

 

Because the secure project handles all the setup calls, the non-secure project doesn’t have to, so its main function is short:

 

main function is short

 

However, this application only calls secure functions that got defined in the other project. The following definition for the PRINTF_NSE function is as shown:

 

PRINTF_NSE function

 

If that definition is followed, it points to the veneer table, defined in the secured project. It is important to remember that the non-secure project only knows the header file that describes the veneer table. However, in this case, we can take a look at the corresponding function in the source code:

 

 

The “__attribute__((cmse_nonsecure_entry))” decoration forces the function to be exported into the object file.

 

Partitioning the Memory

Security attributes define which parts of the memory are secured, NSC, or unsecured. These get checked with every access. For that purpose, the MCU was extended with hardware that handles these checks and consists of three logic blocks:

  1. Security Attribution Unit (SAU)
  2. Implementation Defined Attribution Unit (IDAU)
  3. Security Attribution Logic

The SAU gets programmed by the secure project within the BOARD_InitTrustZone() function. This allows the memory to get partitioned into eight regions with different security settings. Note that any region not explicitly set remains secure by default.

The IDAU allows the MCU manufacturer — NXP in this case — to define more custom regions. Here, the regions depend on the 28th bit of the address. On the LPC55S69 MCU, the bottom of the memory map (0x0000_0000 to 0x2FFF_FFFF) defaults to non-secure, so it is free to configure with the SAU.

The arbiter ensures that the IDAU and SAU settings match. For a memory region to be marked as unsecured, both logic-blocks must be set to non-secure. Otherwise, the memory will fall back to the default secured state. The same applies to the NSC memory regions. For a section to be NSC, the SAU has to be marked as NSC, and the IDAU must be set to non-secure.

There’s a tool within MCUXpresso that enables the user to quickly and easily define memory regions. To access the tool, use the IDE’s main menu bar and open the TEE perspective:

 

This MCUXpresso tool allows the user to view and edit the MCU’s memory map.

Figure 5. This MCUXpresso tool allows the user to view and edit the MCU’s memory map.

 

The table on the left-hand side of the tool can change the security level of memory regions. The memory-map on the right-hand side illustrates how the memory gets partitioned. 

 

TrustZone Offers a Necessary Security Component 

On the LPC5500 MCU series with TrustZone technology, the memory is split into a secure and a non-secure world — it’s possible to allow users to access parts of the non-secure memory, and a secure application can also be written to be utilized by others. TrustZone acts as a gatekeeper between the two worlds and manages how the core transitions between them. 

Two new instructions were introduced for that purpose. The secure application provides a veneer-table that exposes the functions that are callable from the non-secure context. The hardware in the MCU ensures that no illegal memory access operations get carried out. This hardware can also be utilized to configure the regions in the memory map. For that purpose, MCUXpresso offers the TEE perspective. A deeper understanding of the security provided for the LPC5500 series of MCUs allows for better design experience. More information around TrustZone can be found by watching TrustZone: Calling the Secure World.

Industry Articles are a form of content that allows industry partners to share useful news, messages, and technology with All About Circuits readers in a way editorial content is not well suited to. All Industry Articles are subject to strict editorial guidelines with the intention of offering readers useful news, technical expertise, or stories. The viewpoints and opinions expressed in Industry Articles are those of the partner and not necessarily those of All About Circuits or its writers.