Securely booting x86 using Heads
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.
What about Tails?
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).
The flaws of x86 BIOS and UEFI
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> Newsgroups: fa.linux.kernel Message-ID: <fa.K4M0mC9bP4Gr24fvdHc+zatz61M@ifi.uio.no> 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
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.
The problem with Intel’s Management Engine
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
Exploiting and protecting x86 firmware
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:
- HackingTeam malware installed through UEFI (2015)12
- CIA backdoor exploited through UEFI (uncovered by WikiLeaks, 2017)13
- Vulnerabilities like Thunderstrike (2014)14
- Exploits like LightEater (2015)15
Attempts of protection
Obviously, vendors and manufacturers tried to mitigate the risk of such attacks.
- Intel: One attempt was Intel’s Boot Guard/Verified Boot. However, it silently fails upon mismatching signatures, which renders it completely useless.
- Google: Google’s attempt is vboot2 used on Chromebooks, which really addresses some of the present issues. Unfortunately, it is too specialized and unflexible to support a broad range of devices.
- GNU GRUB: That’s why GNU GRUB has been forked to Trusted GRUB, which has support for TPM and signed kernels. The problem with it is, that it duplicates all device/ filesystem driver functionality from Linux kernel and thus becomes bloated too. Additionally, the code is not professionally audited nor widely adopted or tested.
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.
Heads, the little brother/sister of Tails
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.
How Heads works
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.
Trying out Heads on an old Thinkpad
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.
Show me what you got
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!
Configure your Heads installation according to official documentation by setting up GPG keys, TOTP or HOTP etc.2122
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).