Azeria Labs Azeria Labs
  • ARM Assembly
    • Part 1: Introduction to ARM Assembly
    • Part 2: ARM Data Types and Registers
    • Part 3: ARM Instruction Set
    • Part 4: Memory Instructions: LDR/STR
    • Part 5: Load and Store Multiple
    • Part 6: Conditional Execution and Branching
    • Part 7: Stack and Functions
    • Assembly Basics Cheatsheet
  • Online Assembler
  • Exploitation
    • Writing ARM Shellcode
    • TCP Bind Shell in Assembly (ARM 32-bit)
    • TCP Reverse Shell in Assembly (ARM 32-bit)
    • Process Memory and Memory Corruption
    • Stack Overflows (Arm32)
    • Return Oriented Programming (Arm32)
    • Stack Overflow Challenges
    • Process Continuation Shellcode
    • Glibc Heap – malloc
    • Glibc Heap – free, bins, tcache
    • Part 1: Heap Exploit Development
    • Part 2: Heap Overflows and the iOS Kernel
    • Part 3: Grooming the iOS Kernel Heap
  • Lab Environment
    • ARM Lab VM 1.0
    • ARM Lab VM 2.0
    • Debugging with GDB and GEF
    • Emulate Raspberry Pi with QEMU
    • Running Arm Binaries on x86 with QEMU-User
    • Emulating Arm Firmware
  • TrustZone Research
    • TEEs and Arm TrustZone
    • Trustonic’s Kinibi TEE
  • Self-Improvement
    • Deep Work & The 30-Hour Method
    • Paradox of Choice
    • The Process of Mastering a Skill
  • About
Azeria Labs Azeria Labs
  • ARM Assembly
    • Part 1: Introduction to ARM Assembly
    • Part 2: ARM Data Types and Registers
    • Part 3: ARM Instruction Set
    • Part 4: Memory Instructions: LDR/STR
    • Part 5: Load and Store Multiple
    • Part 6: Conditional Execution and Branching
    • Part 7: Stack and Functions
    • Assembly Basics Cheatsheet
  • Online Assembler
  • Exploitation
    • Writing ARM Shellcode
    • TCP Bind Shell in Assembly (ARM 32-bit)
    • TCP Reverse Shell in Assembly (ARM 32-bit)
    • Process Memory and Memory Corruption
    • Stack Overflows (Arm32)
    • Return Oriented Programming (Arm32)
    • Stack Overflow Challenges
    • Process Continuation Shellcode
    • Glibc Heap – malloc
    • Glibc Heap – free, bins, tcache
    • Part 1: Heap Exploit Development
    • Part 2: Heap Overflows and the iOS Kernel
    • Part 3: Grooming the iOS Kernel Heap
  • Lab Environment
    • ARM Lab VM 1.0
    • ARM Lab VM 2.0
    • Debugging with GDB and GEF
    • Emulate Raspberry Pi with QEMU
    • Running Arm Binaries on x86 with QEMU-User
    • Emulating Arm Firmware
  • TrustZone Research
    • TEEs and Arm TrustZone
    • Trustonic’s Kinibi TEE
  • Self-Improvement
    • Deep Work & The 30-Hour Method
    • Paradox of Choice
    • The Process of Mastering a Skill
  • About

Trusted Execution Environments and Arm TrustZone

February 10, 2020

This post is the first part of a larger series and aims to ease the process of getting started with TrustZone security research. If you ever wondered how Trusted Execution Environments on modern Android phones work and want to learn about their attack surface, you will find enough information in this series to get you started. In this introduction post, you will learn what the TrustZone technology is and what Trusted Execution Environments (TEE) are for. You can use this post as a reference for TrustZone and TEE concepts you don’t understand or remember when reading the follow-up posts.

The next parts of this series will cover topics like

  • The Kinibi TEE implementation used in Samsung devices
  • The Qualcomm TEE implementation
  • Reverse Engineering TEE components
  • The TEE attack surface
  • TEE Design flaws that have been published in recent years
  • How input handling vulnerabilities in certain TEE components can lead to privilege escalation
  • Exploit mitigations on current TEE implementations
Arm TrustZone Technology

Let’s start with the most important question: Why does the TrustZone technology exist and what does it defend against? Defending large programs written in C and C++ from hackers can be a challenge. Memory-corruption vulnerabilities are a common problem, and although eliminating them is a core goal for security engineers, eliminating them completely from large applications such as operating system kernels has consistently proven to be elusive.

For normal applications, one solution to this problem is to isolate large programs in a “sandbox”, and then constrain all interactions between that program and the rest of the system via a sandbox “broker”. An attacker who finds and exploits a vulnerability inside this large program is then limited to interacting with system only via the broker. Since the broker process can be made much smaller than the rest of the application, securing its code against compromise is a much more tractable task.

Modern operating system kernels are also large, and have similar problems avoiding memory-corruption vulnerabilities. Isolating these kernels is a lot more complicated than for normal programs. To do this, device developers can make use of a “Trusted Execution Environment” (TEE). These TEEs isolate critical code and data away from the main operating system, so that even if the main operating system is compromised, the data and code residing inside the TEE remains isolated. Use-cases for TEEs include verifying the integrity of the operating system itself, managing user credentials such as via a fingerprint sensor, and the storage and management of device encryption keys. High-value assets are not limited to kernel-mode components. Video Digital Rights Management (DRM) applications, banking applications and secure messengers may also want to protect their code and data from devices that may have malware installed.

Introduction to Arm TrustZone

Keeping data secure even when the operating system kernel is compromised requires special hardware support. Devices running on Arm, such as smartphones, can use TrustZone to perform the hardware-level isolation to keep the TEE secure. The Armv8-A profile provides TrustZone Extensions that can be used for SoCs with an integrated V6 or above MMU. TrustZone-protected code and data is isolated from malicious peripherals and non-TrustZone code. It can be used to construct a fully-featured Trusted Execution Environment (TEE), comprised of a TEE OS running at S-EL1, Trusted Drivers (TDs) that securely interact with peripherals, and even Trusted Applications (TAs) that run at S-EL0. TrustZone also provides for a Secure Monitor that operates at the highest privilege level of S-EL3 with full access to the device in all modes.

TrustZone works by introducing a new “secure” mode in which the CPU can operate. When operating in this new mode the CPU can access all of the device’s hardware and memory. When operating in the non-TrustZone (“normal”) mode, only a subset of peripherals and specific ranges of physical memory can be accessed. A TEE can make use of this technology to place its own code and data into this “secure memory”, preventing any code running in the “normal mode” from accessing or modifying it, even if that code is running in the kernel. Although the kernel cannot access TEE memory, the code running in TEE can read, modify, and choose to process data in the normal world.

TrustZone also expands the standard “Exception Level” privilege model for the CPU. Before TrustZone, three levels existed: EL0 (user-mode), EL1 (kernel-mode) and EL2 (hypervisor-mode). TrustZone adds a new EL3 (secure monitor mode), which is the most privileged level and controls the entire system. But TrustZone also allows the CPU to run in the secure mode at lower privileges, allowing privilege isolation within the TEE itself. The CPU can therefore also run in S-EL0 (secure user-mode) and S-EL1 (secure kernel-mode).


S-EL3
operates the code for the Secure Monitor, which is the highest privilege level for the CPU. The Secure Monitor runs code from the Arm Trusted Firmware (ATF) provided by the device manufacturer. This code performs context switching between the Rich Execution Environment (REE) and TEE kernels, and provides basic services to both via the secure monitor call (SMC) handler which can be requested by REE and TEE OSes via the SMC instruction.

S-EL1 runs the code for the Trusted Execution Environment’s operating system. Depending on the TEE implementation, Trusted Drivers may also run as S-EL1. No EL2 equivalent exists in Secure World (SWd), and consequently it is not possible to run multiple virtual TEE OSes within a hypervisor inside the SWd. Support for S-EL2 has been proposed for inclusion in the Armv8.4-A profile.

S-EL0 runs unprivileged “Trusted Applications” (TAs) and in certain TEE implementations even Trusted Drivers (TDs) within the TEE. By default, TAs cannot operate in the context of other TAs, directly communicate with device peripherals or interact with other processes in the Normal World (NWd) or Secure World (SWd), except as explicitly allowed by the TEE OS.

Normal World vs. Secure World

In the TrustZone architecture, each logical processor core operates as if it had two different “virtual cores”; one operating inside TrustZone and the other running outside of it. The “Normal World” (NWd) core runs the traditional operating system as before, complete with its rich functionality and normal applications. In TrustZone terminology, this entire environment is referred to as the Rich Execution Environment (REE). By contrast, the TrustZone virtual core hosts and runs a Trusted Execution Environment (TEE) in the “Secure World” (SWd). In practice, TrustZone virtual cores are implemented by fast context switching performed inside the Secure Monitor.

The SCR Register
At the hardware level, the CPU determines whether it is running in SWd or NWd via the NS bit of the Secure Configuration Register (SCR) in CP15. If the bit is enabled, the CPU is operating in the NWd; otherwise it is running in the SWd. The Secure Monitor ensures that this bit cannot be written by non-secure programs in order to maintain the integrity of the SWd.

Protected Peripheral Access via the System Bus
The CPU can also mark pages of memory as either TrustZone-protected (“Secure”) or belonging to the Normal World (“Non-Secure”). The NS bit (bit 19) of a Page Table Entry (PTE) determines whether or not the page belongs either to the Secure World (SWd) or Normal World (NWd). This bit determines whether the AxPROT[1] secure bit is set when accessing the underlying physical memory via the system bus, allowing TrustZone-protected operating systems and processes to access both TrustZone-protected secure memory and NWd memory in the same address space. When the processor is running outside of the TrustZone mode, memory accesses always ignore the NS bit; operating as if the NS bit is set.

The hardware logic present in the TrustZone-enabled AMBA3 AXI bus fabric protects SWd resources from being accessed by the NWd by allowing reads and writes on the system bus to be marked either “secure” or “non-secure” during bus transfers. When a secure bus master initiates a bus transfer operation, the ARPROT[1] or AWPROT[1] bit determines whether or not the transfer should be considered a secure or non-secure transaction. Additionally, the NS bit is set high in hardware, preventing Non-securebus masters from accessing Secure bus slaves (secure masters can still issue secure transfers).

TrustZone Protected Memory

TZASC
In order to strictly limit TrustZone-protected code and data from untrusted code and peripherals, the TrustZone Access Space Controller (TZASC) hardware allows for specific regions of physical memory to be marked as “secure only”. These TrustZone domains are set through TZASC registers, which are configured by the Arm Trusted Firmware (ATF) on the device. Changing the start or end address inside the access table is a privileged operation and must be performed carefully; misconfigurations can allow untrusted memory access to regions of physical memory in use inside the TrustZone.

Page Tables
As in the NWd, SWd kernels and programs can have their own address spaces, which are managed via sparse lookup tables called Page Tables. These Page Tables enable the MMU to perform fast translation between virtual addresses used by the CPU into their corresponding physical pages, and perform a permissions-check when the memory is accessed.

Virtual MMUs
In the TrustZone architecture, each CPU has two virtual MMUs —one managing the SWd address space and the other managing the NWd address space— each with their own corresponding TTBRx registers. This means that the operating systems for both worlds can independently create and manage their own set of virtual page tables for use by themselves and their respective processes.

Non-Secure Memory
TrustZone page tables can mark specific virtual addresses as “non-secure”. This is done by setting the NS bit in the corresponding virtual address Page Table Entry (PTE). SWd code can use this to map views of NWd memory into its own (or a TA’s) address space which can be used for monitoring or communicating with the NWd. In the NWd, the NS flag in PTEs is ignored; all memory accesses from the NWd are treated as non-secure.

Secure Boot

Devices that use TrustZone can also leverage a technology called SecureBoot to enforce the integrity of the operating system when it loads from disk. This ensures that nobody has tampered with the operating system’s code when the device was powered off. Modern boot sequences operate as a series of stages, each loading and verifying the integrity of the next. Secure Boot provides for a hardware-root-of-trust mechanism that allows the first stage to be verified by the device ROM. So long as all of the various boot stages load and check the signatures of the next follow-on stage correctly, and so long as the digital signing keys are kept safe, this boot chain can give users confidence that their device has booted an unaltered copy of the operating system, even if they left their device unattended. 

For Arm Trusted Firmware, the sequence of bootloaders is named as follows, with each stage verifying the next:

  • Boot Loader stage 1 (BL1) AP Trusted ROM
  • Boot Loader stage 2 (BL2) Trusted Boot Firmware
  • Boot Loader stage 3-1 (BL3-1) EL3 Runtime Firmware
  • Boot Loader stage 3-2 (BL3-2) Secure-EL1 Payload (optional)
  • Boot Loader stage 3-3 (BL3-3) Non-trusted Firmware

Trusted Execution Environments


TrustZone is one of many hardware features that can be used to build a “Trusted Execution Environment” (TEE), aiming to provide hardware and memory isolation of code and data from the rest of the operating system. Not all TEEs use TrustZone. For example, Apple’s Secure Enclave and Intel’s SGX protect their code and data using non-TrustZone hardware. 

A number of different major TEEs exist that can leverage Arm TrustZone extensions:

  • NVidia’s Trusted Little Kernel for Tegra (TLK) 
  • Qualcomm Trusted Execution Environment (QTEE) 
  • The Open Portable Trusted Execution Environment (OP-TEE) 
  • Huawei iTrustee, based on the HiSilicon platform
  • Trustonic Kinibi TEE-OS for the Trustonic Secured Platform (TSP)
  • Samsung’s Teegris TEE
  • Sierra TEE 
  • ProvenCore TEE 
  • Trusty TEE for Android 
  • TrustKernel T6 

Evolution of Trusted Execution Environments
Trusted Execution Environments were initially developed primarily as a mechanism to provide secure boot functionality. Since then, TEEs have evolved to offer a much greater set of functionality and expose services to the NWd. For instance, support for functionalities as diverse as secure fingerprint authentication, encryption services, protected mobile payments such as Samsung Pay, DRM, runtime integrity protection, and protected corporate services on employee devices, such as providing secure communication between mobile devices and corporate infrastructure through the TEE’s sockets API. Modern TEEs can also protect sensitive data on the device through the Trusted User Interface, which allows users to enter PINs and passwords directly into TEE, preventing the user credentials from being visible to code running in the REE. Moreover, TEEs can also be used to protect sensitive data in case the device is lost or stolen. For example, a device can choose to keep decryption keys exclusively inside the TEE to prevent extraction, and can design the device decryption system so that password guesses must be validated and rate-limited inside the TEE. GlobalPlatform proposed APIs to communicate between the REE and TEE and became the new standard.

TEE Components
TEEs rely on hardware to enforce isolation. This hardware component provides the base primitives that allow for separation and initialization of secure code. The TEE software then runs on top of this hardware, extending these primitives to provide a fully-featured execution environment with support for diverse features like Secure Boot, the Secure Monitor, and a lightweight TEE OS. A TEE will also often provide support for REE applications to isolate critical parts of their own code and data into an isolated Trusted Application (TA). Third-party TAs are not directly part of the TEE; they are executed inside the TEE by the TEE OS. It is the combination of hardware isolation, secure boot, and the trusted TEE OS that together make up a fully-featured TEE on which TAs can be loaded and run.

TEE Operating System
The TEE OS is the Secure World (SWd) complement of the Normal World’s (NWd) operating system. It runs at a higher privilege level than Trusted Applications (TAs) and Trusted Drivers (TDs). The TEE OS supports communication with the REE, provides core services and access to TAs, and provides an environment for Trusted Drivers. The TEE OS handles Secure Monitor Calls (SMC) dispatched from EL3, and handles Supervisor Call (SVC) requests from TAs running in S-EL0.

Trusted Applications and Trusted Drivers

Normal TAs
Trusted Applications (TAs) run at S-EL0 and enable NWd applications to provide application-specific functionality such as DRM, trusted UI, as well as storage of secrets and keys. TAs are loaded and scheduled for execution by the TEE OS and are isolated from the NWd applications, the NWd kernel, as well as from other TAs. A given TA is not, however, isolated from the TEE OS, and must implicitly trust the TEE available on the device. A compromise of the TEE OS necessarily affects the integrity and confidentiality of data and code in TAs operating inside the TEE. Originally, devices only permitted TAs that came pre-installed on the device. Modern devices, however, support the dynamic deployment of TAs included in apps downloaded from a TA app store. 

System TAs
System TAs are a subclass of TAs that provide critical TEE OS services like Secure Storage, Crypto Services and TA authentication and decryption. System TAs are typically shipped by the TEE OS manufacturer or OEMs. Huawei, for example, has a privileged system TA called “GlobalTask” that implements some of the trusted OS functionality and controls the life-cycle of normal TAs.  

Trusted Drivers
Trusted drivers contain code needed to access secure peripherals, such as the fingerprint reader, or which provide privileged services inside the TrustZone. Depending on the TEE, Trusted Drivers either operate in S-EL0 (e.g. Trustonic, Nvidia TEEs) or are loaded directly into the TEE OS kernel’s address space and operate in S-EL1 (e.g. Qualcomm, Huawei, Linaro TEEs). Trusted Drivers can provide additional services to TAs and have access to more functionality than TAs.

Communication between Secure World and Normal World

Apps that make use of TAs, such as mobile payments applications, need a mechanism to communicate between the NWd app in REE and the TA in TEE. To do so, the app in REE goes through a process to load and communicate with the TA inside TEE over specific communication channels and APIs available to both the REE and TEE. These communication channels enlarge the attack surface and introduce new attack vectors. Failure to validate inputs arriving from REE over these communication interfaces can result in critical privilege escalation attacks. The next part of this series will introduce you to the Kinibi TEE and describe the communication between NWd and SWd in more detail. 

SMC-based Communication
Communication between trusted code in a TEE and code in a REE must take place via one of two mechanisms. The first mechanism is to use the SMC interface. A REE OS running at EL1 (or EL2 if a hypervisor is in use) can use the Secure Monitor Call (SMC) instruction to request a system service from the Secure Monitor running inside S-EL3, which will then be relayed down to the TEE OS.

Hardware-specific Services
As well as providing services to allow EL0 applications to load and communicate with S-EL0 trusted applications, TEEs will usually also provide hardware-specific and TEE-specific services that can be used directly by NWd operating system code in EL1. For example, TEEs might provide mechanisms to create a watchdog timer to reboot a device when it becomes non-responsive, interact with on-board SoCs, or share memory between the NWd and the SWd. Secure code running in S-EL3 and S-EL1 provides these services that can be requested using the SMC instruction. This instruction is privileged and must be invoked from EL1 and is handled by the secure monitor’s SMC dispatch handler.

Shared Memory Communication
The second method of communication is to make use of shared memory, i.e. where code running in the NWd maps some physical memory into its address space, and the code inside the TEE maps the same physical memory addresses into its own address space, taking care to mark the memory as “non-secure”. Memory written to this shared memory buffer from either world is then visible to both processes. Shared memory is an efficient form of communication because it allows fast transfer of large amounts of data to and from TrustZone without context switching.

TrustZone Research

  • TEEs and Arm TrustZone
  • Trustonic’s Kinibi TEE

Twitter: @Fox0x01 and @azeria_labs

New ARM Assembly Cheat Sheet

Poster Digital

Cheat Sheet
© 2017-2022 Azeria Labs™ | All Rights Reserved.