In March 2021, Arm announced the release of its new Armv9 architecture. The first new architecture in a decade, Armv9 includes new security features—from compartmentalization to memory safety to pointer authentication.
In this blog, we take a deeper look at the security features offered with Armv9, including the pros and cons for each. In addition, we’ll also highlight how Dover’s CoreGuard® solution can fortify these features and provide additional security above and beyond what Armv9 offers, like Information Flow Control.
Feature #1: Confidential Compute Architecture (CCA)
The first security feature we'd like to take a look at is Confidential Computer Architecture. CCA is compartmentalization technology that uses Arm’s existing TrustZone solution as its foundation.
Designed to compete with Intel’s SGX in the cloud-based server market, CCA has “Realms” analogous to SGX’s “Enclaves,” and both CCA and SGX provide attestation, which is particularly important for cloud-based computing. Unlike Intel SGX, Arm CCA also runs on mobile devices, providing compartmentalization between applications.
CCA Provides Coarse-grained Compartmentalization, Protecting One Application From Another
CCA provides what we call “coarse-grained compartmentalization”, protecting one application from another. That is, different applications and runtimes are all given their own “compartments,” or “realms” and there are clear rules for how data can flow from one compartment or realm to another. We use the term “coarse-grained” because each compartment or realm may contain large amounts of software (many millions of instructions) and data (all the data referenced by a single application).
It is certainly a good thing to protect all of the code and data in one application from being extracted or modified by another compromised or malicious application. Coarse-grained compartmentalization, however, does nothing to protect an application from itself.
Everyone thinks that their code is great, and that everyone’s else’s code is flawed and needs to be defended against. In reality, all software is vulnerable to attack because all software is going to have bugs. As documented by Steve McConnell in his book Code Complete, on average, there are 15-50 bugs per 1000 lines of code in all deployed software.
Thus, a buffer overflow attack within an application can still violate the confidentiality and integrity of data within that application and negate the value of compartmentalization. In fact, the entire trusted compartment/realm can be overtaken through a well-crafted buffer overflow attack plus code injection and any control over that device can be lost entirely.
Additionally, coarse-grained compartmentalization mechanisms, like TrustZone, SGX, and (as far as we know) CCA, incur a so-called “context switch” performance penalty when execution switches from one compartment to another. Before switching to a new context, all of the current state of the machine is stored to memory, and the state for the incoming context is loaded from memory. Frequent switching between contexts can add significant overhead to system runtimes, and so there is incentive to avoid context switching by putting more code and data into fewer compartments, which has a performance benefit but adds a serious security (attack surface) risk.
CoreGuard Provides Fine-grained Compartmentalization, Protecting Applications From Themselves
CoreGuard’s Compartmentalization micropolicy provides fine-grained compartmentalization, protecting applications from themselves. By “fine-grained compartmentalization,” we mean that CoreGuard allows you to define as many compartments as is appropriate for the security requirements of your system, even within a single application. Additionally, CoreGuard can provide fine-tuned rules for what data can be passed from one compartment to another.
CoreGuard is also able to solve the problem of context switch overhead, because CoreGuard maintains compartment information as metadata attached to every value in the system, and so context switches are not required to change compartments. This idea of maintaining compartment-related metadata and avoiding context switches is an idea called “Software Fault Isolation (SFI),” dating back at least to Wahbe et al in 1993. However, SFI was originally implemented in software, and the performance overhead was deemed too high. Because CoreGuard maintains metadata using hardware acceleration, there is no performance overhead of maintaining compartment-related metadata and checking access at every instruction.
Dover’s CoreGuard can fortify existing coarse-grained compartmentalization solutions, like CCA, by protecting each application from themselves, as well as monitoring every instruction running on a system—whether the instruction is part of an operating system, a medical data application, or a game app. CoreGuard offers a suite of micropolicies that prevent the exploitation of software vulnerabilities and can be layered together for defense-in-depth. CoreGuard’s base set of micropolicies immunize systems against buffer overflow, code injection, and ROP attacks.
Feature #2: Arm Memory Tagging Extensions (MTE)
The second major security feature offered with Armv9 is Memory Tagging Extension(MTE). First introduced in Armv8.5, MTE can be viewed mostly as a memory safety, debugging tool that allows developers to identify memory safety violations in code. MTE tags each block of allocated memory with one of 16 different “colors,” and also assigns that color to the pointer returned from allocation. At every memory dereference, a check is performed that the pointer and memory colors match. This simple scheme finds many buffer overflow and use-after-free memory safety violations, which, as has been widely documented, account for the majority of successful attacks exploiting software errors.
In addition, Arm MTE adds many instructions to the Arm instruction set, requiring updates to toolchains and runtimes. It is also restricted to 64-bit Arm architectures because they are using the top 4 bits of 64-bit words for the colors. Protection of memory-based MTE metadata (a mapping from physical addresses, at 32-byte granularity, to colors) is the responsibility of the SoC designer and Arm MTE tag granularity is fixed at 16 bytes (i.e., one 4-bit color per 16 bytes of memory).
CoreGuard’s Heap Micropolicy implements a similar approach to memory safety, adding “colors” to pointers and allocated memory. But unlike MTE, CoreGuard is not limited to 16 colors; CoreGuard has a configurable number of colors, which we recommend should always be over 1,000 unless there is little to no dynamic memory allocation. Thus on an Arm MTE system, an attacker has a 1 in 16 chance of “guessing” the correct color for a buffer overflow attack. Those types of odds are fine for debugging, but they are less than ideal for reliable memory safety in the field.
CoreGuard does not add instructions to the host architecture, and CoreGuard also provides color-based memory safety for both 32-bit and 64-bit platforms. CoreGuard tag granularity is programmable and CoreGuard’s default tag granularity for 64-bit systems is 8 bytes, and the default for 32-bit systems is 4 bytes.
Feature #3: Arm Pointer Authentication Codes (PAC)
The third feature is Arm’s Pointer Authentication Codes (PAC) extension. PACs are integrated into the pointers themselves, and are used to authenticate valid pointers. This function protects against increasingly common attacks like Return-Oriented Programming (RoP) attacks, which attempt to overwrite return addresses. Arm’s PAC extension prevents this attack by encrypting the return address and then ensuring that all pointers to the return address are valid by decrypting and validating that pointer.
Unfortunately, PAC requires the addition of instructions to the ISA. as well as cryptologic and key storage to the microarchitecture, to encrypt/sign and decrypt/authenticate pointers. As a result of the additional instructions, there is a negative impact on performance, and thus it’s generally assumed that PAC protection will be limited to only return addresses, as opposed to using PAC on all addresses.
CoreGuard’s Stack micropolicy protects return addresses without adding new instructions to the instruction stream, thus without impacting performance. CoreGuard adds metadata to return addresses indicating that the value is a return address. Only some instructions, function prologues and epilogues, are given permission (by putting metadata on those instructions) to create and use return addresses. Our Code Pointer Integrity (CPI) micropolicy will extend our return address protection to indirect branch pointers, also with no additional performance overhead.
Feature #4: Arm Branch Target Indicator (BTI) Extension
The fourth and final security feature included with Armv9 is the Branch Target Indicator (BTI) extension. BTI adds new "landing" instructions to an instruction stream, immediately preceding instructions that are legitimate targets of branch instructions. At runtime, all indirect jumps (e.g. a function call via a function pointer) must jump to landing instructions. An indirect branch to an instruction that is not a landing instruction will generate a fault. The BTI feature increases control flow integrity, preventing attacks that redirect control flow to unintended locations in the code.
Similar to MTE, BTI is only available on 64-bit Arm platforms. This extension also requires compiler/toolchain support and increases the size of binary images.
CoreGuard’s Control Flow Integrity micropolicy works similarly to BTI by tagging instructions that are known branch targets. However, in CoreGuard’s case, no additional instructions are added to the binary (none of CoreGuard’s capabilities require adding any instructions). Furthermore, CoreGuard is compatible with 32-bit and 64-bit platforms.
Above & Beyond: Dynamic Information Flow Control
Beyond the security protections offered by Armv9, CoreGuard can also provide the critical security feature of dynamic Information Flow Control (IFC).
A central feature of CoreGuard is that metadata, associated with every value in memory and registers, flows along with the values as those values move from memory to registers, are copied and combined, and flow out to memory or I/O. The idea that values have metadata that provides additional context beyond the actual value is an old idea, dating back to tagged architectures. Historically, tagged architectures added a couple of bits to every word in memory. For example, Lisp machines used two bits to track (1) whether memory was in use or could be reclaimed (aka “garbage collection”), and (2) whether a value is a list element (“Lisp” stands for “List processing”). Tracking information flow using hardware bits continues to attract attention, with work at Cornell (Suh et al) and UTexas (Tiwari et al) researching Dynamic Information Flow Tracking (DIFT) architectures.
A novel feature of CoreGuard’s architecture is that CoreGuard maintains metadata without having to add additional bits to every word in memory. Furthermore, rather than limiting to a couple of bits, CoreGuard allows for maintenance and checking of rich, software-defined metadata. The reason that Information Flow Control is so appealing compared to compartmentalization, and even memory safety, is that IFC enables the direct specification and enforcement of confidentiality and integrity requirements of a system.
A compartmentalization scheme is like a gate—access is granted or denied when crossing the gate, but where a value came from or where it is ultimately allowed to flow is not tracked. IFC allows exactly that level of specification and security, namely associating every value with both confidentiality (where a value is allowed to flow), which implements privacy protection and integrity (where a value has come from and if/how it has been modified), which supports integrity as is needed for the protection of things like AI and ML systems.
As Arm Architecture Grows More Complex, Security Becomes More Difficult
Anytime new features are introduced into an architecture, an increased level of complexity is also added, and can make securing the system more difficult. This "complexity creep" is avoided with CoreGuard, since it adds policy-agnostic hardware that will perform software-defined policy checking in parallel with application software processing. Furthermore, CoreGuard does not change the host architecture at all, and is ISA-agnostic. There are no new instructions required of the host ISA, and no changes to the host toolchain needed to support CoreGuard. It can be implemented on an Arm processor (v9 or otherwise), as well as a Tensilica, MIPS, or RISC-V processor.
When it comes to compartmentalization, changes to the level of protection only requires updating the micropolicies on the system—it does not require changing your hardware or your toolchain.
Armv9’s security features like CCA, MTE, and PAC are important and necessary steps taken by Arm to meet the increasing security demands of the market. When considering whether or not to implement some, or all, of these features, it’s important to also consider how additional tools, like Dover’s CoreGuard technology support and fortify those features. Furthermore, if you’re looking to implement security features like those of Armv9 on 32-bit platforms that aren’t currently supported by Armv9, or across other RISC-based architectures outside of Arm, this is made possible by CoreGuard.
To see a side-by-side comparison of the protection level you can expect from both Armv9 security features and CoreGuard, download this infographic today.