“We’re in a pre-9/11 moment,” warned Mike Wallace, a member of the National Infrastructure Advisory Council (NIAC), at the White House on August 22.
What Is ARM TrustZone?
TrustZone is a technology available on ARM Cortex-A and, more recently, Cortex-M series processors. ARM describes TrustZone as a “System-Wide Approach to Security.”
TrustZone divides the SoC (System-on-a-Chip: CPU + memory + connections to IO) into Trusted and Not Trusted regions. Sometimes this distinction is referred to as Secure versus Non-secure.
Transitions between trusted and non-trusted worlds are initiated by a new instruction, Secure Monitor Call (SMC). Whether the system is operating in a trusted or non-trusted world is tracked by a single bit in a system register that can only be modified by the SMC instruction.
TrustZone is well suited to systems such as phones, where the phone vendor has a suite of “trusted” services (for example: authentication, trusted boot, over-the-air updates, networking, and cellular stacks) but also wants to allow the user to install third-party, untrusted applications. It is important to the phone vendor that the third-party applications installed in the Not Trusted region are not able to disrupt the core services (located in the Secure region) distributed by the phone vendor.
ARM TrustZone does not make the individual software components, whether in the Trusted or Not Trusted zone, any less vulnerable to attack. The goal of a compartmentalization feature such as TrustZone is to reduce the scope of damage once a software component is exploited by a cyber attack. In TrustZone’s case however, exploits of “Trusted” components are not actually contained, as modules in the Trusted zone have access to resources in the Not Trusted zone. There is ample evidence that microkernels and software stacks such as those typically deployed into the Trusted zone are rife with exploitable vulnerabilities.
How Does TrustZone Compare to Dover CoreGuard™?
TrustZone enforces a simple two-zone compartmentalization policy, which, as noted above, is helpful for some use cases. Dover CoreGuard can implement nearly any security policy you can formally define, including—but not limited to—compartmentalization. Below, I describe how CoreGuard can implement a compartmentalization policy analogous to ARM TrustZone, but first I give a very short overview of the CoreGuard architecture.
Brief Summary of CoreGuard Architecture
The CoreGuard architecture maintains metadata for all words in a computing system, including registers, RAM, and the Program Counter (PC) or “Instruction Pointer.” The metadata is maintained by software-defined policies. Each policy is able to track what instructions are being executed, examine the metadata on every word involved in each instruction, and update metadata as needed. The following sections describe a scenario where the compartmentalization policy is the only policy installed on the machine.
Can We Implement TrustZone Compartmentalization Using Dover CodeGuard?
With CoreGuard, it is straightforward to implement the simple two-compartment policy represented by TrustZone, but CoreGuard can go far beyond that with much more fine-grained policies. Let’s first walk through how CoreGuard can implement a compartmentalization policy.
Tracking Current Compartment Using Policies
The first step is tracking the compartment in which the system is operating. With ARM TrustZone, this is done by a global “secure mode” status bit. Dover CoreGuard can track the current compartment as metadata on the Program Counter. With TrustZone, when the special Secure Monitor Call (SMC) instruction is executed, state transitions from Not Trusted to Trusted mode. With CoreGuard, we do not need to add a new, special instruction. We can instead add metadata to instructions in a distinguished EnterTrustedMode function so that the compartmentalization policy notices when a compartment switch is invoked. The compartmentalization policy, when it sees an instruction in EnterTrustedMode executing, can set the metadata for the Program Counter to indicate that the Trusted compartment is in effect. A corresponding ExitTrustedMode function can then be used to reset the metadata on the Program Counter. The following two rules keep track of which mode the system is in.
If the current instruction is labeled “in EnterTrustedMode function”, then update metadata Compartment(PC) = “Trusted”
If the current instruction is labeled “in ExitTrustedMode function”, then update metadata Compartment(PC) = “Not Trusted”
Access Control for Compartmentalization
At boot time, a designated instruction word at the end of EnterTrustedMode is assigned metadata that will trigger the first rule above; similarly for ExitTrustedMode. The compartmentalization policy will also declare whether the Program Counter starts as Trusted or Not Trusted.
Besides switching between compartments, the other critical element of a compartmentalization policy is to indicate which code and data is accessible to which compartment. ARM TrustZone hardwires a policy in which untrusted mode can only access memory (functions and data) that is labeled “untrusted,” whereas trusted mode can access all memory.
With ARM TrustZone, access to memory is established at boot time. CoreGuard would take this same approach. As part of its secure boot process, CoreGuard consults a metadata database in the boot ROM for tagging of memory (application and data). While it is straightforward to specify an arbitrary number of compartments using Dover policies, let’s consider a case like TrustZone, where there are only two compartments (trusted and not-trusted). The boot ROM will segregate all data and instructions into those two compartments by marking the metadata associated with each word in memory as it is loaded.
Once the metadata for all words of memory is annotated with the compartment in which that memory resides, CoreGuard can implement general rules for the different classes of operation encountered as code executes on the machine. The following two rules check whether an operation is allowed:
If the current instruction is Jump/Branch/Call, allow the instruction if Compartment(PC) == Compartment(TargetInstruction)
If the current instruction is Load (from memory), or Store (to memory), allow the instruction if Compartment(PC) == Compartment(MemoryReferenced)
Having more than two compartments, and specifying how the different compartments are allowed to interact, is a powerful approach towards the goal of “least privilege” system design. With least privilege design—or principle of least privilege (POLP)—each module has only the access/privileges it needs to accomplish its specific function. That way, if one module is compromised, damage is minimized.It is easy to modify this compartmentalization policy to, for example, allow global access if the compartment noted on the Program Counter is Trusted. Also, this compartmentalization policy can be extended to any number of compartments.The first rule states that if we see a control transfer instruction, the compartment of the target instruction should match the current compartment, which is tracked on the Program Counter. For example, to jump into code marked as Trusted, the Program Counter must already be marked as “in Trusted zone.” The second rule checks memory access similarly. For example, to load from or store to memory labeled Trusted, the Program Counter must be labeled as “in Trusted Zone.” Similar rules are straightforward for fall-through control flow, and for allowing Trusted mode to access code and data labeled Not Trusted.
Compartmentalization Is Only One Element of Comprehensive Security
ARM TrustZone, as the primary security feature of ARM architectures, has fixed functionality. It implements a fixed, two-zone compartmentalization scheme that protects trusted software components from being corrupted by untrusted applications that are either malicious or have been compromised by a cyber attack. Compartmentalization guards elements in one component from being disrupted by elements from another compartment, but it does not prevent individual modules from being compromised. In other words, compartmentalization limits the scope of a compromise by a cyber attack, but does not make individual software components any less vulnerable to attack.
Dover CoreGuard allows for more sophisticated, multiple compartment schemes that enable least privilege design. CoreGuard can be used not only for compartmentalization, but also to implement policies that actually block cyber attacks in the first place. For example, by implementing a memory safety policy, CoreGuard can prevent large classes of memory safety violation attacks (e.g., buffer overflow attacks), and by implementing taint tracking policies, CoreGuard can track the integrity and confidentiality of data as it flows through the system to prevent input sanitization attacks (e.g. SQL injection) or exfiltration of confidential data.