Measures to protect firmware, bootloader and operating system from tampering have a long history in embedded development (also Smartphones and Tablets). We have been deploying such solutions for many different customers. However, our own development machines, which are x86 most of the time, suffer from very similar issues. Secureboot and similar solutions try to solve at least some associated risks. Nonetheless, a complete chain of trust, including a trustable root of trust, is nearly impossible on conventional x86 architecture.
This blog post introduces an alternative open-source firmware project, addressing these weak points of x86 architecture with different measures. It is the result of some research and experimentation at work with Heads and Qubes OS.
Heads12 was initially presented at “Chaos Communication Congress 33c3 (2016/17)”3, without gaining lots of popularity the following years. In the meanwhile, some (pretty well-known) vendors adopted heads into their mainboards and/or laptops (e.g. Purism Librem4 or NitroKey NitroPad5), which has boosted Heads’ development tremendously.
Summarized, Heads implements a form of measured boot, where the root of trust is moved into the write-protected SPI-flash and the chain of trust is coherent until the operating system takes over. Tampering of firmware, bootloader or the kernel is not impossible, however the user is immediately notified if such a (potentially malicious) action was detected.
Tails is often referred to in this context because it provides the opposite advantages to Heads, however tries to solve similar architectural problems.
The flip side of Tails. Unlike Tails, which aims to be a stateless OS that leaves no trace on the computer of its presence, Heads is intended for the case where you need to store data and state on the computer. 6
On one hand, Tails is a secure stateless operating system, leaving no traces after shutdown. On the other hand, Heads provides the necessary firmware to work with a stateful operating system, but verifies its state on every boot (to prevent tampering).
Before starting to describe how Heads may increase the overall firmware security of your x86 hardware, let’s rethink and question traditional BIOS and UEFI.
From: Linus Torvalds <firstname.lastname@example.org>
The problem with EFI is that it actually superficially
looks much better than the BIOS, but in practice it ends
up being one of those things where it has few real
advantages, and often just a lot of extra complexity
because of the "new and improved" interfaces that were
largely defined by a committee.
Not that I'd ever claim that the BIOS is wonderful either.
Linus Torvalds brings up a valid point: Modern EFI implementations as well as old BIOS consist of a lot of large, unauditable, complex code (even graphical UI including web browser is common in today’s firmwares).
Intel’s edk2 tree (UEFI) would be open-source at core, however different vendors have their own closed-source implementations. (Security) updates, bugfixes, enhancements etc. are all on the behalf of the manufacturer - and take their time to bubble down the firmware supply chains.
Also, the signing keys for Secure Boot are in most cases in absolute control of the vendor, which opens the possibility of leaks to third parties.
Additionally, lots of unverifiable code is in Intel’s Management Engine, a coprocessor which has access to almost all devices of a platform (memory, network, peripherals). It was originally meant to be a management tool for large organizations, but auditing its exact function is impossible. Heads has included an awesome open source project to disable most parts of this potentially dangerous hardware: ME Cleaner7. However, the Intel ME is a very complex topic which would exceed the boundaries of this blog post. Read more about it here.8910
The state of firmware, bootloader, Kernel and operating system is unknown after leaving alone a device for an undefined period (e.g. in a hotel room). That opens a whole range of threats to the overall security of the device. Read more about x86’s state problems in a paper from Joanna Rutkowska.11
Good historical examples for these kinds of attacks are:
Obviously, vendors and manufacturers tried to mitigate the risk of such attacks.
None of these solutions allow us to completely verify the chain of trust from the hardware start to the Kernel / operating system boot without any major flaws. That’s when Heads comes into play.
To improve some issues associated with x86 and its firmware flaws, Heads makes use of well-audited, widely used open source projects. It is based on the coreboot project16 and the Linux kernel, plus a few required libraries and utils. coreboot is an open source x86 firmware with increasing board and Laptop support, only initializing the basic hardware functions and then handing control to any custom payload.
Heads moves the root of trust into the write-protected region of the SPI flash
and allows to completely verify the chain of trust until the measures of the
operating system take over. All signing keys are in total control of the user.
If all signatures match, the Linux kernel
kexec syscall chain-loads the
operating system kernel. If anything went wrong, the user is instantly notified
and the system bootup process stops immediately. Using Linux as a bootloader,
the device drivers are shared among the bootloader and the kernel, which greatly
reduces the attack surface.
To verify the integrity of the firmware, the Trusted Platform Module (TPM), a cryptographic coprocessor in modern mainboards, is used. It signs all parts of the SPI flash: That means tampering is possible, but is noticed on the next boot. The TPM also serves as a hardware key storage to decrypt the fully encrypted operating system installed on the system’s bootup disk. However, at this point it is worth mentioning, that TPMs had various security flaws in the past too: For example some Infinion TPMs17 implemented a broken key generation (RNG), or the communication between the TPM chip and the CPU was not secured by default in old TPM versions18.
Bootloader, hypervisor, kernel, ramdisk etc. are all signed by a user-controlled key: The user’s GPG public key is flashed into the firmware, so that signatures can be verified on boot. Additionally, tampering of the firmware is detected by using a time-based token (TOTP, verified on another device, e.g. Google Authenticator) and a hardware token (HOTP, Nitrokey19) with a boot counter.
To evaluate and test Heads we used an old spare Lenovo ThinkPad T420, because it offers good overall coreboot and Heads support.
Please note: Warranty is void, no guarantee that anything works, proceed at your own risk! That said, let’s continue to the fun part. :-)
First, proceed with building Heads according to the official guide.20
We had to disassemble the whole laptop to access the BIOS SPI flash chip, as its position is just below the magnesium frame under the keyboard. To ease future access, I soldered some wires to the chip and managed to get them out at the maintenance flap at the bottom of the laptop. However, you can also flash only using a SOIC-8 clip if you trust your built image.
Then you can use a Raspberry Pi (or Bus Pirate or similar) to flash the built image over the GPIO SPI interface.
If all went well, Heads initialization screen should show up on next boot. First boot can take a few minutes because of Memory training - don’t panic!
After having passed GPG and TOTP/HOTP verifications, the full-disk-encryption passphrase is asked for. Alternatively, the TPM passes it from the hardware key store.
If all went well, the Linux kernel executes a kexec to jump into the Kernel of the installed operating System - after having verified its integrity and signatures.
In this case, Qubes OS comes up (which you should give a try btw, but that is another blog post).