commit
30d6c92583
|
@ -1,124 +1,236 @@
|
||||||
# How to get started with Lanzaboote-based SecureBoot?
|
# Quick Start: NixOS Secure Boot
|
||||||
|
|
||||||
**Requirements** :
|
This document attempts to guide users into setting up UEFI Secure Boot
|
||||||
|
for their NixOS system using a custom key chain. The audience are
|
||||||
|
experienced NixOS users.
|
||||||
|
|
||||||
- Using `systemd-boot`
|
This guide has been tested on a Lenovo Thinkpad and is expected to
|
||||||
- Either the private certificate to sign files or control over your SecureBoot keys to insert your own, read the section on how to enroll your keys
|
work on other Thinkpads without change. On other systems, certain
|
||||||
|
steps may be different.
|
||||||
|
|
||||||
**Disclaimer** : This project bring its own UEFI stub to circumvent the difficulty introduced by UKI model where everything has to baked in.
|
## ⚠ Disclaimers ⚠
|
||||||
The authors are aware of the concept of "extending" initrds through <https://github.com/systemd/systemd/blob/main/src/boot/efi/stub.c#L23>.
|
|
||||||
We are exploring this avenue to minimize our dependency on this custom stub, but, we want to explore the full needs of the NixOS usecases first.
|
|
||||||
|
|
||||||
## Enrolling your own keys
|
Secure Boot for NixOS is still in development and has some sharp
|
||||||
|
edges. There may be cases where you end up with a system that does not
|
||||||
|
boot.
|
||||||
|
|
||||||
**Disclaimer** : Some device firmware, e.g. GPU (so-called [OpROMs](https://en.wikipedia.org/wiki/Option_ROM)) get executed at boot, replacing your platform keys
|
**We only recommend this to NixOS users that are comfortable using
|
||||||
with your own, can cause them to not run anymore under SecureBoot, as they are signed using [Microsoft Corporation UEFI CA 2011 certificate], aka the Microsoft 3rd Party UEFI CA certificate.
|
recovery tools to restore their system or have a backup ready.**
|
||||||
To know about *limited* mitigations regarding this, **read** the "keeping Microsoft keys" subsection.
|
|
||||||
|
|
||||||
**Disclaimer** : TPMs interaction are out of scope for this project, please read more about TPM eventlog, but note that Lanzastub do not implement any TPM event logging for now.
|
## Requirements
|
||||||
|
|
||||||
### Entering into Setup Mode
|
To be able to setup Secure Boot on your device, NixOS needs to be
|
||||||
|
installed in UEFI mode and
|
||||||
|
[`systemd-boot`](https://www.freedesktop.org/wiki/Software/systemd/systemd-boot/)
|
||||||
|
must be used as a boot loader.
|
||||||
|
|
||||||
Depending on your machine, you need:
|
These prerequisites can be checked via `bootctl status`:
|
||||||
|
|
||||||
- either, to reset your keys to enter into Setup Mode (removing your Microsoft keys!)
|
|
||||||
- either, to allow changes to your keys from your running system (**possibly**, keeping your Microsoft keys)
|
|
||||||
|
|
||||||
These instructions varies on your BIOS, see <https://www.rodsbooks.com/efi-bootloaders/controlling-sb.html#setuputil> for an example.
|
|
||||||
|
|
||||||
You can confirm to be in Setup Mode using `bootctl status`, reading `Secure Boot` line, which should show a line similar to: `Secure Boot: no (setup mode)`.
|
|
||||||
|
|
||||||
In this context, **note that** `/sys/firmware/efi/efivars/` becomes writeable from your Linux system.
|
|
||||||
|
|
||||||
**Bricking your machine in a bad way can happen if this location gets overwritten by a strange command / program.** ^[I already `rm'd -rf` this location once, it was very not funny.]
|
|
||||||
|
|
||||||
### Installing your keys
|
|
||||||
|
|
||||||
#### Easy way: `sbctl`
|
|
||||||
|
|
||||||
`sbctl` has static locations for keys, in nixpkgs, `sbctl` writes to `/etc/secureboot`, so prepare a directory for this location with the **right permissions**.
|
|
||||||
|
|
||||||
- Creating keys is: `sbctl create-keys`
|
|
||||||
- Rotating keys is: `sbctl rotate-keys` (with `sbctl` ≥ 0.10)
|
|
||||||
|
|
||||||
For enrollment, first, read the next subsection:
|
|
||||||
|
|
||||||
##### Keeping Microsoft keys
|
|
||||||
|
|
||||||
If you want to keep Microsoft keys, run:
|
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ sbctl enroll-keys --microsoft
|
$ bootctl status
|
||||||
|
System:
|
||||||
|
Firmware: UEFI 2.70 (Lenovo 0.4720)
|
||||||
|
Secure Boot: disabled (disabled)
|
||||||
|
TPM2 Support: yes
|
||||||
|
Boot into FW: supported
|
||||||
|
|
||||||
|
Current Boot Loader:
|
||||||
|
Product: systemd-boot 251.7
|
||||||
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
It will include Microsoft Corporation UEFI CA 2011 certificate.
|
In the `bootctl` output, the firmware needs to be `UEFI` and the
|
||||||
|
current boot loader needs to be `systemd-boot`. If this is the case,
|
||||||
|
you are all set to continue.
|
||||||
|
|
||||||
It does not guarantee that everything will work out of the box, it may be the case you have other certificates that should be included from your OEM which are not distributed in `sbctl`.
|
## Part 1: Preparing Your System
|
||||||
|
|
||||||
Therefore, please double check everything until this project can provide better guarantees.
|
In the first part, we will prepare everything on the software side of
|
||||||
|
things. At the end of this part, you will have your own Secure Boot
|
||||||
|
keys and a NixOS that has signed boot binaries.
|
||||||
|
|
||||||
##### Ignoring Microsoft keys
|
### Finding the UEFI System Partition (ESP)
|
||||||
|
|
||||||
If you want to **remove** Microsoft keys, you have very good reasons to do so (i.e. not trusting Microsoft to not give a valid certificate to OEM which could pose risk to your threat model), run:
|
The UEFI boot process revolves around a special partition on the
|
||||||
|
disk. This partition is called _ESP_, the (U)EFI System
|
||||||
|
Partition. This partition is by convention mounted at `/boot` on NixOS
|
||||||
|
and the rest of this document assumes this.
|
||||||
|
|
||||||
```
|
You can verify that `/boot` is the ESP by looking for `ESP:` in
|
||||||
$ sbctl enroll-keys --yes-this-might-brick-my-machine
|
`bootctl status` output.
|
||||||
|
|
||||||
|
### Creating Your Keys
|
||||||
|
|
||||||
|
To create Secure Boot keys, we use `sbctl`, a popular Secure Boot Key
|
||||||
|
Manager. `sbctl` is available in
|
||||||
|
[Nixpkgs](https://github.com/NixOS/nixpkgs) as `pkgs.sbctl`.
|
||||||
|
|
||||||
|
Once you have installed sbctl (or entered a Nix shell), creating your
|
||||||
|
Secure Boot keys requires this command:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ sudo sbctl create-keys
|
||||||
|
[sudo] password for julian:
|
||||||
|
Created Owner UUID 8ec4b2c3-dc7f-4362-b9a3-0cc17e5a34cd
|
||||||
|
Creating secure boot keys...✓
|
||||||
|
Secure boot keys created!
|
||||||
```
|
```
|
||||||
|
|
||||||
The authors of this project declines all responsibility for running this command and bricking your machine, this is **experimental** SecureBoot.
|
This takes a couple of seconds. When it is done, your Secure Boot keys
|
||||||
|
are located in `/etc/secureboot`. `sbctl` sets the permissions of the
|
||||||
|
secret key so that only root can read it.
|
||||||
|
|
||||||
#### Harder ways: follow the Archlinux Wiki
|
### Switching to bootspec
|
||||||
|
|
||||||
Read about this on <https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot#Enrolling_keys_in_firmware>.
|
Lanzatool currently doesn't handle
|
||||||
|
non-[bootspec](https://github.com/grahamc/rfcs/blob/bootspec/rfcs/0125-bootspec.md)
|
||||||
|
generations well
|
||||||
|
([#55](https://github.com/nix-community/lanzaboote/issues/55)). As
|
||||||
|
such, we need to switch to bootspec and get rid of all previous
|
||||||
|
generations before we can continue.
|
||||||
|
|
||||||
## Using the `Lanzaboote` project in your NixOS configuration
|
Bootspec is currently available as preview in nixpkgs unstable. To
|
||||||
|
enable bootspec, set `boot.bootspec.enable = true;` in your system
|
||||||
|
configuration, rebuild and reboot.
|
||||||
|
|
||||||
**Disclaimer** : `Lanzaboote` requires [RFC-0125 aka bootspec](https://github.com/NixOS/rfcs/pull/125) on your system, this is automatically enabled on your behalf.
|
When everything is working, you can garbage collect your old
|
||||||
|
non-bootspec generations: `nix-collect-garbage -d`.
|
||||||
|
|
||||||
**Warning** : `Lanzaboote` is compatible only with `systemd-boot` for now, also, it replaces `boot.loader.systemd-boot` and has no feature parity with this NixOS module.
|
🔪 **Sharp edge:** 🔪 This will leave old boot entries lying around in
|
||||||
|
the ESP. `systemd-boot` will display these during boot. This can be
|
||||||
|
confusing during boot. **After you made a backup of your ESP**, you
|
||||||
|
may delete these entries in `/boot/loader/entries`.
|
||||||
|
|
||||||
Use your favorite way to import this project in your configuration, i.e. Flakes or [niv](https://github.com/nmattia/niv) or `fetchFromGitHub`:
|
### Configuring NixOS (with Flakes)
|
||||||
|
|
||||||
### `fetchFromGitHub`
|
Below is a fragment of a NixOS configuration that enables the Secure
|
||||||
|
Boot stack.
|
||||||
|
|
||||||
```
|
```nix
|
||||||
{ pkgs, config, lib, ... }:
|
nixosConfigurations = {
|
||||||
{
|
yourHost = nixpkgs.lib.nixosSystem {
|
||||||
imports = [
|
system = "x86_64-linux";
|
||||||
(pkgs.fetchFromGitHub {
|
|
||||||
owner = "nix-community";
|
modules = [
|
||||||
repo = "lanzaboote";
|
# ... other modules ...
|
||||||
rev = "relevant-revision";
|
|
||||||
sha256 = lib.fakeHash;
|
lanzaboote.nixosModules.lanzaboote
|
||||||
})
|
|
||||||
|
({ config, pkgs, lib, ... }: {
|
||||||
|
# This should already be here from switching to bootspec earlier.
|
||||||
|
# It's not required anymore, but also doesn't do any harm.
|
||||||
|
boot.bootspec.enable = true;
|
||||||
|
|
||||||
|
environment.systemPackages = [
|
||||||
|
# For debugging and troubleshooting Secure Boot.
|
||||||
|
pkgs.sbctl
|
||||||
];
|
];
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
# Lanzaboote currently replaces the sytemd-boot module.
|
||||||
|
# This setting is usually set to true in configuration.nix
|
||||||
|
# generated at installation time. So we force it to false
|
||||||
|
# for now.
|
||||||
|
boot.loader.systemd-boot.enable = lib.mkForce false;
|
||||||
|
|
||||||
Now, assuming the NixOS module is imported, you only need to have:
|
|
||||||
|
|
||||||
```
|
|
||||||
{ pkgs, config, lib, ... }: {
|
|
||||||
boot.lanzaboote = {
|
boot.lanzaboote = {
|
||||||
enable = true;
|
enable = true;
|
||||||
publicKeyFile = "/etc/secureboot/keys/db/db.pem"; # DB public key
|
pkiBundle = "/etc/secureboot";
|
||||||
privateKeyFile = "/etc/secureboot/keys/db/db.key"; # DB private key
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
};
|
};
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Different options can be added:
|
After you rebuild your system, check `sbctl verify` output:
|
||||||
|
|
||||||
- `boot.lanzaboote.pkiBundle`: provide the whole PKI bundle generated by `sbctl create-keys`, useful when you want to automate key enrollment, **security warning**: those will be copied at system activation in `/tmp/pki` to perform the enrollment because `sbctl` do not support dynamic arbitrary paths for now.
|
```console
|
||||||
- `boot.lanzaboote.enrollKeys`: perform automatic enrollment key, if needed, at each rebuild
|
$ sudo sbctl verify
|
||||||
|
Verifying file database and EFI images in /boot...
|
||||||
|
✓ /boot/EFI/BOOT/BOOTX64.EFI is signed
|
||||||
|
✓ /boot/EFI/Linux/nixos-generation-355.efi is signed
|
||||||
|
✓ /boot/EFI/Linux/nixos-generation-356.efi is signed
|
||||||
|
✓ /boot/EFI/nixos/0n01vj3mq06pc31i2yhxndvhv4kwl2vp-linux-6.1.3-bzImage.efi is signed
|
||||||
|
✓ /boot/EFI/systemd/systemd-bootx64.efi is signed
|
||||||
|
```
|
||||||
|
|
||||||
## Known limitations
|
🔪 **Sharp edge:** 🔪 In case something is **not** signed in the
|
||||||
|
`sbctl verify` output, you have hit a bug
|
||||||
|
([#39](https://github.com/nix-community/lanzaboote/issues/39)). You
|
||||||
|
**have to fix this** to avoid ending up with an unbootable system
|
||||||
|
([#58](https://github.com/nix-community/lanzaboote/issues/58)). The
|
||||||
|
way to solve this is **deleting** the unsigned files indicated by
|
||||||
|
`sbctl` and switching to the configuration again. This will copy and
|
||||||
|
sign the missing files.
|
||||||
|
|
||||||
- Generations are shown improperly because `/etc/os-release` induces the wrong name in the `systemd-boot` menu according to this algorithm: <>
|
## Part 2: Enabling Secure Boot
|
||||||
- `$esp/nixos` is a hardcoded path to store initrds & kernels
|
|
||||||
- The lifecycle between disabling Lanzaboote and getting back into Lanzaboote is not clear
|
Now that NixOS is ready for Secure Boot, we will setup the
|
||||||
- No TPM event logging & measurements is taking place
|
firmware. At the end of this section, Secure Boot will be enabled on
|
||||||
- Alternative Nix store locations are not supported
|
your system and your firmware will only boot binaries that are signed
|
||||||
- PKCS#11 engine support is not available
|
with your keys.
|
||||||
|
|
||||||
|
These instructions are specific to Thinkpads and may need to be
|
||||||
|
adapted on other systems.
|
||||||
|
|
||||||
|
### Entering Secure Boot Setup Mode
|
||||||
|
|
||||||
|
The UEFI firmware allows enrolling Secure Boot keys when it is in
|
||||||
|
_Setup Mode_.
|
||||||
|
|
||||||
|
On a Thinkpad enter the BIOS menu using the "Reboot into Firmware"
|
||||||
|
entry in the systemd-boot boot menu. Once you are in the BIOS menu:
|
||||||
|
|
||||||
|
1. Select the "Security" tab.
|
||||||
|
2. Select the "Secure Boot" entry.
|
||||||
|
3. Set "Secure Boot" to enabled.
|
||||||
|
4. Select "Reset to Setup Mode".
|
||||||
|
5. Select "Clear All Secure Boot Keys".
|
||||||
|
|
||||||
|
When you are done, press F10 to save and exit.
|
||||||
|
|
||||||
|
You can see these steps as a video [here](https://www.youtube.com/watch?v=aLuCAh7UzzQ).
|
||||||
|
|
||||||
|
### Enrolling Keys
|
||||||
|
|
||||||
|
Once you've booted your system into NixOS again, you have to enroll
|
||||||
|
your keys to activate Secure Boot. We include Microsoft keys here to
|
||||||
|
avoid boot issues.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ sudo sbctl enroll-keys --microsoft
|
||||||
|
Enrolling keys to EFI variables...
|
||||||
|
With vendor keys from microsoft...✓
|
||||||
|
Enrolled keys to the EFI variables!
|
||||||
|
```
|
||||||
|
|
||||||
|
You can now reboot your system. After you've booted, Secure Boot is
|
||||||
|
activated:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ bootctl status
|
||||||
|
System:
|
||||||
|
Firmware: UEFI 2.70 (Lenovo 0.4720)
|
||||||
|
Firmware Arch: x64
|
||||||
|
Secure Boot: enabled (user)
|
||||||
|
TPM2 Support: yes
|
||||||
|
Boot into FW: supported
|
||||||
|
```
|
||||||
|
|
||||||
|
That's all! 🥳
|
||||||
|
|
||||||
|
## Disabling Secure Boot and Lanzaboote
|
||||||
|
|
||||||
|
When you want to get back to a system without the Secure Boot stack,
|
||||||
|
**first** disable Secure Boot in your firmware settings. Then you can
|
||||||
|
disable the Lanzaboote related settings in the NixOS configuration and
|
||||||
|
rebuild.
|
||||||
|
|
||||||
|
You may need to clean up the `EFI/Linux` directory in the ESP manually
|
||||||
|
to get rid of stale boot entries. **Please backup your ESP, before you
|
||||||
|
delete any files** in case something goes wrong.
|
||||||
|
|
||||||
|
## Alternatives
|
||||||
|
|
||||||
|
The [ArchLinux wiki](https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot)
|
||||||
|
contains alternatives to handling your keys, in case `sbctl` is not
|
||||||
|
flexible enough.
|
||||||
|
|
Loading…
Reference in New Issue