This post discusses my personal opinion of Intel’s Trust Domain Extensions (TDX). This instruction set extension is Intel’s latest attempt at implementing a Trusted Execution Environment (TEE).

This post does not make an attempt at trying to explain TDX. I assume that you have a familiarity with Intel TDX at the conceptual level. Intel has a large set of documents about TDX. The introductory overview does a good job of getting you started and should be enough background for this post. Otherwise, I’m assuming general knowledge about how virtualization works.

tl;dr

Instead of increasing the complexity of the hardware, we can have a software-only alternative to TDX with the same security properties and fewer downsides. We can achieve this using a secure microhypervisor that uses existing security features of the CPU, such as TXT and TME-MK. This approach would also be portable to other CPU architectures.

Longer Version

Behind the design of TDX there are some unspoken assumptions:

  1. Existing hypervisors are beyond repair from a security perspective and cannot be trusted.
  2. Intel can write a microhypervisor (the TDX Module) that is secure.

I’m calling the TDX Module a microhypervisor, because it has a large overlap with the functionality commonly found in microhypervisors. It manages vCPU state and nested page tables, while relying on VMMs running in lower privilege levels to do emulation. This is very similar to how microhypervisor-based systems work, such as this one.

Regarding the security of existing hypervisors, there are definitely problems. Linux/KVM on x86 has a lot of emulation code1 that is directly accessible by a malicious guest, is written in C and runs with now guard rails whatsoever. Applying Google’s Rule of 2 this places the system squarely in the DOOM! category.

The conclusion that Intel has drawn out of these assumptions is they introduce a new CPU mode (SEAM mode) where they place their microhypervisor. This microhypervisor comes as an Authenticated Code Module (ACM), which must be cryptograhically signed by Intel. The existing hypervisor then has to use system calls using a new set of instructions (SEAMCALL) to the microhypervisor that is actually in charge. The VMs have to use new instructions (TDCALL) to interact with the outside as well.

TDX Downsides

While this design has more hope of adoption than SGX, the design comes with many downsides.

TDX increases hardware complexity. While adding instructions is not helping, adding a new CPU mode feels an order of magnitude more costly. Intel needs to make sure that everything the CPU already supports works correctly in this new mode. How well Intel can cope with hardware complexity can be seen with Spectre/Meltdown or any errata sheet.

TDX locks out any other provider of the microhypervisor in charge of the system by requiring the TDX module to come with an Intel signature. Everything points to Intel never signing someone else’s code. Especially if you are not a hyperscaler, there is really nothing to hope for here.

TDX gives the end user an extremely poor experience for security issues. You are basically at the mercy of Intel. As long as Intel doesn’t ship an update of the TDX module, there is nothing you can do on your own. Also no one will get advance warning for issues except big players.

On Twitter, I was joking that the TDX module is probably written in shoddy C. Whether it’s shoddy is anyone’s personal opinion, but it turns out that it is actually written in C. Intel has published its source. Would you want the software you base all your security hopes on to be written in the least secure programming language?

A Better Way

If you can write a secure microhypervisor (one of the assumptions of TDX), there is actually no need to go down the road of TDX. Intel already provide all the building blocks of a solution that gives you the benefits of TDX with far fewer downsides.

Boot your secure microhypervisor as a normal baremetal hypervisor. The boot process can be secured via Secure Boot. You can perform remote attestation as well. For this Intel TXT comes in handy. The microhypervisor can defend itself at runtime using an IOMMU and defend VMs using TME-MK.

Your legacy hypervisor can then boot as a sort of Dom0 and take ownership of the platform hardware. Instead of calling into the TDX module, the Dom0 can request services from the secure microhypervisor using regular hypercalls. Instead of patching untrusted guests to use TDCALL to call into the TDX module, they can use existing facilities as well.

This design gives you all the upsides of TDX. The secure microhypervisor will enforce confidentiality protections to the degree that you need them. At the same time, the design eliminates practically all downsides of TDX. The update process of the secure hypervisor does not involve Intel. If you establish your own chain of trust, you can update the hypervisor as you please. Also, Secure Boot (with your own keys) and TXT are usable by anyone.

You are free to implement the secure microhypervisor in any language you want. You can write it in Ada/SPARK or Rust for maximum resiliency. At least not in C. You can do formal verification. You can do fuzzing. Whatever makes you feel comfortable.

You can move the emulation code (Qemu or your favorite alternative) from the Dom0 into host root mode outside of Dom0. The microhypervisor can run it in a sandbox with only clearly defined access to the rest of the system. This removes the need to patch your guest OS or firmware and make it TDX aware, because it will just see a normal emulated system. Even less complexity!

Finally, equivalents of Secure Boot, TXT, TME-MK exist for AMD and other architectures. You can have the same architecture everywhere.

But instead we got TDX. And unfortunately other CPU architectures (RISC-V) have taken it as an example. This makes me sad.

Update 2023-06-09

I misunderstood the FOSDEM talk about the RISC-V confidential computing efforts. Salus, the system for confidential computing developed by Rivos, is actually implementing almost exactly what I outline above. Check out this overview in their README. Way to go! 🎉

  1. KVM on x86 does instruction decoding, instruction emulation and some legacy device emulation. While you can opt out of the legacy device emulation (kernel-irqchip=split), there is no way to opt out of the kernel’s instruction emulation. Also on all platforms you can use VirtIO emulation in the kernel (vhost) and open another large attack surface.