A Trusted Execution Environment (TEE) is an environment where the code executed and the data accessed is isolated and protected in terms of confidentiality (no one have access to the data) and integrity (no one can change the code and its behavior).

We may not be aware, but a lot of devices around us make use of a Trusted Execution Environment, including smartphones, set-top-boxes, videogame consoles and Smart TVs.

This article will be an introduction to TEE concepts and ARM’s TrustZone technology. In the next article, we will put in practice these concepts and learn how to run and use an open source TEE implementation called OP-TEE.

But before talking about TEE concepts, let’s start with why.

Why do we need a TEE?

Software is getting more and more complex. Larger projects like the Linux kernel and the Android Open Source Project (AOSP) have millions of lines of code. And this means lots of bugs.

Fixing bugs is always a cat-and-mouse game. We fix bugs and sometimes cause regressions. We add new features, and with them some bugs. Although we can work to prevent some types of bugs, we will always have bugs in software. And some of these bugs may expose a security vulnerability. Worse, if the bug is in the kernel, the entire system is compromised.

So how to work around this issue? How to protect your assets in the system if the software is compromised?

One way to solve this problem is to create an isolated environment where, even if the operating system is compromised, your data is protected. This is what we call a Trusted Execution Environment or TEE.

And there are several use cases for a TEE.

TEE usages

TEE would be a good solution to storage and manage the device encryption keys that could be used to verify the integrity of the operating system.

TEE is well-suited for implementing biometric authentication methods (facial recognition, fingerprint sensor and voice authorization), isolating resources within a device to store the biometric algorithm, user credentials and associated data.

TEE could be used in mobile e-commerce applications like mobile wallets, peer-to-peer payments or contactless payments to store and manage credentials and sensitive data.

TEE is also a suitable environment for protecting digital copyrighted information (books, movies, audio, etc) on connected devices such as smartphones, tablets and smart TVs. While the digital content is protected during transmission or streaming using encryption, a TEE would protect the content once it has been decrypted on the device by ensuring that decrypted content is not exposed to the operating system environment.

So, how does a Trusted Execution Environment work?

TEE terminology and operation

In a system with a TEE, we have untrusted applications running on a Rich Execution Environment (REE) and trusted applications (TAs) running on a Trusted Execution Environment (TEE).

Only trusted applications running on a TEE (Secure World) have complete access to the main processor, peripherals and memory, while hardware isolation protects these from untrusted applications running on the main operating system (Non-Secure World).

Although the diagram above exemplifies a TEE with an operating system (Trusted OS), we could just have a bare-metal firmware exposing an interface with exclusive access to certain hardware resources.

In a TEE, all trusted applications (TAs) and associated data is completely isolated from the normal (untrusted) operating system and their applications. Also, trusted applications must run in isolation from other trusted applications and from the TEE itself.

Also, TEE only accept code for execution that has been appropriately authorized and checked by other authorized code. So in TEE, we need a secure boot feature to check the integrity and authenticity of all operating system components (bootloaders, kernel, filesystems, trusted applications, etc). This ensures that nobody has tampered with the operating system’s code when the device was powered off.

TEE is really an execution environment (with or without an operating system) that has exclusive access to certain hardware resources. But how it is implemented? How to prevent an untrusted application from accessing a resource from a trusted application?

How to implement a TEE?

We could isolate applications in a “sandbox”, for example using containers. This would prevent an application from seeing and accessing data from other applications.

But what about the kernel? How to prevent a code running in kernel space from being exploited to access a certain peripheral or memory region used by a trusted application?

Software can’t protect software!

So we need support in the hardware to implement a TEE. We need a way to partition and isolate the hardware (busses, peripherals, memory regions, interrupts, etc) so that the running code does not have access to protected resources.

That’s where ARM’s TrustZone, RISC-V’s MultiZone and many other solutions come in.

Hardware support to implement a TEE

There are a lot of technologies available in modern processors to implement a TEE:

Arm’s TrustZone technology offers an efficient, system-wide approach to security with hardware-enforced isolation built into the CPU.

MultiZone Security is the first trusted execution environment for RISC-V created by Hex Five Security.

The AMD Platform Security Processor (PSP), officially known as AMD Secure Technology, is a trusted execution environment subsystem incorporated into AMD microprocessors.

Intel Software Guard Extensions (SGX) is a set of security-related instruction codes that are built into some modern Intel CPUs that could be used to implement a TEE.

Apple uses a dedicated processor called SEP (Secure Enclave Processor) for features like data protection, Touch ID, and Face ID. The SEP is responsible for handling keys and other information such as biometrics that is sensitive enough to not be handled by the application processor.

Google also has a similar solution called Titan M, an external chip available on some Android Pixel devices to implement a TEE and handle features like secure boot, lock screen protection, disk encryption, etc.

As you can see, there are a lot of hardware implementations that could support a Trusted Execution Environment. Let’s focus here on ARM’s TrustZone implementation.

How ARM’s TrustZone works?

Usually, an ARM Cortex-A processor has 3 execution modes: user mode, kernel mode and hypervisor mode.

In a typical system running GNU/Linux, the applications run in user mode, the Linux kernel runs in kernel mode and the hypervisor mode is not used.

ARM’s TrustZone introduces a new mode: the secure monitor mode.

When operating in this new mode, the CPU is in the Secure World and can access all of the device’s peripherals and memory. When not operating in this mode, the CPU is in the Non-Secure World and only a subset of peripherals and specific ranges of physical memory can be accessed.

The idea here is to partition the hardware (memory regions, busses, peripherals, interrupts, etc) between the Secure World and the Non-Secure World in a way that only trusted applications running on a TEE in the Secure World have access to protected resources.

The transition from the Secure World to the Non-Secure World is via a dedicated instruction called Secure Monitor Call (SMC). When this instruction is executed, the CPU will enter in monitor mode and will have access to all hardware, including the protected peripherals and memory regions. At this moment, we can run the TEE firmware/operating system.

As an example, imagine an untrusted application running on Linux that wants a service from a trusted application running on a TEE OS. The untrusted application will use an API to send the request to the Linux kernel, that will use the TrustZone drivers to send the request to the TEE OS via SMC instruction, and the TEE OS will pass along the request to the trusted application.

Implementing the TEE software stack is not an easy task. That’s why we can leverage existing implementations to develop a solution with a Trusted Execution Environment.

TEE implementations

Several commercial TEE implementations have been developed over the years:

Kinibi is the TEE implementation from Trustonic that is used to protect application-level processors, such as the ARM Cortex-A range, and are used on several smartphone devices like the Samsung Galaxy S series.

On newer smartphones, Samsung is using its own implementation called TEEGRIS, a system-wide security solution that allows you to run applications in a trusted execution environment based on TrustZone.

Qualcomm has its own TEE implementation called Qualcomm Secure Execution Environment (QSEE) that is also used on a lot of smartphone devices.

iTrustee is the Huawei implementation of a TEE operating system for ARM’s TrustZone.

We have also some open source TEE implementations:

Trusty is an open source project from Google that implements a TEE for Android. It is compatible with ARM’s TrustZone and Intel’s Virtualization Technology.

OP-TEE (Open Portable Trusted Execution Environment) is an open source TEE designed as a companion to a non-secure Linux kernel running on ARM Cortex-A cores using the TrustZone technology.

And there are many more implementations. Although we can implement a TEE anyway we want, an organization called GlobalPlatform is behind the standards for TEE interfaces and implementation.

As we can see, the TEE technology is consolidated and many devices we use every day are based on it to protect our personal and sensitive data. So we are safe, right?

Nothing is 100% secure

A TEE implementation is just another layer of security and has its own attack surfaces that could be exploited. And numerous vulnerabilities were already found in different implementations of a TEE using TrustZone!

For example, several vulnerabilities were found by Gal Beniamini including userland privilege escalation to gain code execution in the Secure World.

In a presentation at Black Hat USA 2019 called Breaking Samsung’s ARM TrustZone, Maxime Peterlin talks about how his team at Quarkslab exploited a vulnerability in Kinibi (TEE used on some Samsung devices) to obtaining code execution in monitor mode.

In another talk at CCC 2017 called Microarchitectural Attacks on Trusted Execution Environments, Keegan Ryan provides an overview of different attacks applied to TEEs based on TrustZone implementations.

As we can see, TEE is not the solution to all of our security problems. It is just another layer to make it harder to exploit a vulnerability in the operating system. But nothing is 100% secure.

On the one hand, the security model implemented with the TrustZone technology provides additional segmentation through the separation of Secure World and Non-Secure World, protecting against a hostile environment such as an infected system on both user-land and kernel-land.

On the other hand, the development of an entire operating system is a daunting task that often involves many bugs, and operating systems running TrustZone are no exception to the rule. A bug in the Secure World could cause total system corruption, and then all its security goes away.

Also, compromising the TEE OS can be done before it is even executed if a vulnerability is found in the secure boot chain, as has been the case several times like the vulnerabilities found on the High Assurance Booting (HAB) used to implement (un)secure boot on NXP’s i.MX6 SoCs.

In the next article, we will learn how to build a system with TEE using an open source implementation called OP-TEE (Open Portable Trusted Execution Environment), part of the Trusted Firmware Project maintained by Linaro.

About the author: Sergio Prado has been working with embedded systems for more than 20 years. If you want to know more about his work, please visit the About page or Embedded Labworks website.

Please email your comments to sergio at embeddedbits.org or sign up the newsletter to receive updates.