From the beginning we have had big plans for the Librem Key. When we first announced our partnership with Nitrokey to produce the Librem Key all we could talk about publicly was the standard USB security token features it would have and some of the integration possibilities between the Librem laptop and Librem Key that would make security easier for the average person. What we couldn’t say at the time was that we were also working toward making the Librem Key do something that doesn’t exist anywhere else–integrate it with the tamper-evident Heads BIOS to make it incredibly easy to tell whether your BIOS has been tampered with. In this post I’m going to talk about why we wanted to add this feature, some of the work that went into it, and dive into some of the technologies that are working behind the scenes to help you understand how it works.
Making Heads User Friendly
Heads is an incredibly powerful and cutting edge project that takes the boot-time security protections you get with products like Secure Boot but using free software, reproducible builds, and keys that are fully under your control. We are working toward our goal of having Heads on all of our laptops by default, but when we started working on that effort we realized that the default user interface was definitely aimed more toward security experts. At the time, when you booted into Heads you got a console screen with a text menu. If Heads detected any issues, typically it would dump you to a recovery shell with some technical error output.
Since we think every user would benefit from the protections Heads provides, we have done a lot of work to bring more user-friendly GUI menus to Heads. We started with a console-based GUI and later added our own custom tool fbwhiptail which uses the same syntax as the standard whiptail console menu tool used by Debian but outputs an even more user-friendly GUI on a framebuffer.
As we continued to work toward making Heads more user-friendly, we realized we had an opportunity with the Librem Key to add an incredibly powerful, secure, yet easy to use way to detect tampering that was much better than the default. Before we talk about where the Librem Key fits in, though, it’s important to understand how Heads detects tampering by default.
How Heads Detects BIOS Tampering
Heads uses the TPM in a computer as a standalone, trusted, tamper-proof chip it can use to store BIOS measurements and secrets. In my post Demonstrating Tamper Detection with Heads I walk through the full process but I will highlight some of the relevant points here.
The way Heads protects the BIOS from tampering is that when you first set up Heads, you store the current BIOS’s measurements into special registers in the TPM called PCRs (Platform Configuration Registers). At this time Heads also generates a random string and using the TPMTOTP tool originally created by Matthew Garrett it stores this secret in a special encrypted register in the TPM–this process is called sealing. The TPMTOTP tool also takes this secret and converts it into a QR code it displays on the screen. Then you can use a multi-factor authentication application on your phone to take a picture of this QR code and add this to any other multi-factor authentication secrets you manage.
The next time the system boots, measurements from every executable part of the boot process is sent by Heads to the TPM and stored in PCRs. Then Heads requests for the TPM to unseal the TPMTOTP secret it added previously. The TPM will only unseal that secret if all of the measurements in its PCRs match what it has stored from the valid, un-tampered-with BIOS. Once the secret is unsealed, Heads uses TPMTOTP to combine that secret with the current time and convert it into a 6-digit code. You then open up your multi-factor authentication application on your phone and compare the 6-digit code on your laptop screen with the 6-digit code on your phone. If both codes match, the BIOS hasn’t been tampered with. If the codes don’t match, either the time is off on either device, or someone has tampered with the BIOS or the TPM and generated and stored a new secret to replace the old one.
Improving on TOTP Codes
It’s important to note that Heads does not require you to verify the TOTP (Time-based One Time Password) code on the screen each time you boot. In fact it has no way of knowing whether you have or not–the whole point is that the laptop is authenticating itself to you, not the other way around. So there’s a good chance that your average user may not feel like going to the trouble of getting out their phone, launching an app, and inspecting the code each time they boot. Plus, this process requires that a user must have a smart phone that can run one of these apps. Users might test the code every so often but I imagine many would just hit Enter and boot their system more often than not.
We realized we could make the process more convenient and easier to use by taking the phone out of the equation or at least adding a Librem Key to the equation. While the Librem Key doesn’t have a screen like a phone, it does have a green and red LED. What could be easier than plugging in a USB device, booting the computer, and then inspecting the LED to see whether you are safe? By making it easy, users would be more likely to test their BIOS at each boot.
HOTP to Trot
Since we were working with Nitrokey to produce the Librem Key, we started collaborating with them on this feature. The first step was to think through how this authentication would work. Because the Librem Key doesn’t have a clock of its own, and we don’t want it to trust the clock on the laptop, we decided to use HOTP (HMAC-based One Time Password) instead of TOTP as our authentication protocol.
HOTP and TOTP are very similar to each other. In fact, you can argue that TOTP is just a specific implementation of HOTP. With HOTP both sides have a shared secret and initialize an always-incrementing counter. Each side combines its secret with the current counter value and generates an HMAC (hashed message authentication code) that in this case is converted into a 6-digit code. If the codes match, then one side has proven to the other that it has a copy of the shared secret and both sides will then increment their counter. With TOTP, you just exchange the always-incrementing counter with the current timestamp, typically rounded to 30-second increments.
For this to work we needed not only to change the firmware we were going to use for the Librem Key so that it could accept this special HOTP-over-USB authentication, we also needed a userspace tool that knew how to talk to the Librem Key. The end result after working with Nitrokey was a couple of changes to the firmware and a completely new userspace program called nitrokey-hotp-verification that contains two command-line tools we needed to include in Heads, libremkey_hotp_initialize and libremkey_hotp_verification. The former tool will initialize the a Librem Key with the current HOTP secret and counter value and the latter performs various HOTP functions with the Librem Key including testing a 6-digit HOTP code.
Heads, Meet Librem Key
The next step was to add Librem Key support to Heads. This required quite a few UI changes, modifications to the default tools it used when generating new TOTP secrets, and adding libremkey_hotp_initialize and libremkey_hotp_verification command line tools within Heads itself. Instead of doing away with the TOTP code we are actually using the same exact TPM secret, just in addition to converting it into a TOTP code, we are also combining it with the incrementing counter to generate an HOTP code too. So when you tell Heads that you want to seal a new TOTP secret, if your version of Heads has Librem Key support enabled, in addition to showing you a QR code, it will also prompt you to insert your Librem Key and set up the secret there as well using the libremkey_hotp_initialize program.
The next time you boot, in addition to displaying the TOTP code in the menu as always, it also attempts to communicate with your Librem Key using the libremkey_hotp_verification tool. If the Librem Key isn’t inserted, it gets a specific error and warns the user that the key isn’t plugged in, but it doesn’t stop the user from booting. If the user then plugs in the key and tells Heads to regenerate the code, it can do a second test from the GUI. If you lose your Librem Key or leave it behind somewhere, you can always just fall back to the standard TOTP code + phone approach until you have a new Librem Key to enroll.
After Heads sends the Librem Key an HOTP code, if the code matches what the Librem Key itself generates, it will flash a green LED and return a success code to Heads to display on the laptop screen. If the HOTP codes don’t match, the Librem Key will flash a red LED indefinitely and also send a specific error back to Heads which will cause it to show a red background and error dialog. Note that you shouldn’t trust the Heads UI to display this error, it’s only for convenience. A modified UI could lie to you so you should only trust the Librem Key LED at this phase of the boot process.
Here’s a short demo video of the Librem Key testing a valid BIOS and then one that detects tampering with Heads.
To simulate tampering, I just generate a brand new TOTP/HOTP secret in the TPM with the Librem Key unplugged. Since the Librem Key has the old secret, it will generate a completely different 6-digit HOTP code and take that as an error.
Anti-Interdiction Protection and The Future of Librem Key and Heads Integration
As I mentioned in the Introducing the Librem Key post, having the Librem Key vouch for the integrity of the BIOS opens up a lot of opportunities for more advanced anti-interdiction protection for those customers who are concerned about that risk. The way this would work, we would configure a Librem Key and Librem laptop running Heads before shipping and then ship the two packages separately. The idea here is that it would be more difficult for an attacker to interdict both packages than just one.
Then when you unbox everything, you can immediately test the integrity of your machine before you do anything else. At that point you could also generate completely new secrets between Heads and the Librem Key so there’s not even a chance we could have a copy of your secrets–the keys are under your control. For customers willing to wait, we could even ship the Librem Key first and only ship the laptop after they acknowledge receipt of the Librem Key. With delayed shipping you would have even more assurance that someone wouldn’t be able to modify both the Librem Key and laptop in transit.
If you can’t tell, we are very excited about all of the possibilities the Librem Key opens up to us to better protect you and your secrets, while still keeping security convenient and your keys in your own control. Stay tuned: as we unlock even more features in the Librem Key we’ll be sure to post about it here.