Secure Boot: Difference between revisions

From NixOS Wiki
imported>Onny
mNo edit summary
Nicolas-goudry (talk | contribs)
No edit summary
 
(11 intermediate revisions by 6 users not shown)
Line 1: Line 1:
Secure Boot can be enabled on NixOS using the project [https://github.com/nix-community/lanzaboote Lanzaboote]. Secure Boot is a UEFI feature that only allows trusted operating systems to boot. Lanzaboote has two components: <code>lzbt</code> and <code>stub</code>. <code>lzbt</code> signs and installs the boot files on the ESP. <code>stub</code> is a UEFI application that loads the kernel and initrd from the ESP.  
<languages/>
<translate>
<!--T:1-->
Secure Boot usually refers to a platform firmware capability to verify the boot components and ensure that only your own operating system to boot.  


<!--T:2-->
Secure Boot has multiple implementations, the most known one is UEFI Secure Boot, which relies on the UEFI platform firmware, but others implementations can exist on embedded systems.
<!--T:3-->
On NixOS, Secure Boot can be enabled via the project [https://github.com/nix-community/lanzaboote Lanzaboote].
<!--T:4-->
Lanzaboote has two components: <code>lzbt</code> and <code>stub</code>.
<!--T:5-->
<code>lzbt</code> is the command line that signs and installs the boot files on the ESP. 
<!--T:6-->
<code>stub</code> is a UEFI application that loads the kernel and initrd from the ESP, it's different from systemd-stub, see below to see precise differences.
<!--T:7-->
{{warning|Lanzaboote is still in development and requires some prerequisites and precautions. Currently it's only available for nixos-unstable. For more information, please see the GitHub repository or the Quick Start guide.}}
{{warning|Lanzaboote is still in development and requires some prerequisites and precautions. Currently it's only available for nixos-unstable. For more information, please see the GitHub repository or the Quick Start guide.}}


== Requirements ==
== Requirements == <!--T:8-->


<!--T:9-->
The Secure Boot implementation of Lanzaboote requires a system installed in UEFI mode together with systemd-boot enabled.  This can be checked by running <code>bootctl status</code>:
The Secure Boot implementation of Lanzaboote requires a system installed in UEFI mode together with systemd-boot enabled.  This can be checked by running <code>bootctl status</code>:


<syntaxHighlight>
<!--T:10-->
<syntaxHighlight lang=console>
$ bootctl status
$ bootctl status
System:
System:
Line 15: Line 36:
  Boot into FW: supported
  Boot into FW: supported


<!--T:11-->
Current Boot Loader:
Current Boot Loader:
       Product: systemd-boot 251.7
       Product: systemd-boot 251.7
Line 20: Line 42:
</syntaxHighlight>
</syntaxHighlight>


<!--T:12-->
It is recommended to enable a BIOS password and full disc encryption to prevent attacks against UEFI and Secure Boot.
It is recommended to enable a BIOS password and full disc encryption to prevent attacks against UEFI and Secure Boot.


== Setup ==
== Setup == <!--T:13-->
 
First generate Secure Boot keys using <code>sbctl</code>:
 
<syntaxHighlight lang="bash">
sudo nix run nixpkgs#sbctl create-keys
</syntaxHighlight>
 
After that switch from <code>lzbt</code> to <code>bootspec</code> by adding following line to the system configuration:
 
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
boot.bootspec.enable = true;
</nowiki>}}
 
Rebuild the system and reboot. When everything is working, you can garbage collect your old non-bootspec generations:
 
<syntaxHighlight lang="bash">
sudo nix-collect-garbage -d.
</syntaxHighlight>
 
Adjust the following in your flake-enabled system flake.nix configuration by adding the input and adding the lanzaboote nixos module:
 
{{file|/etc/nixos/flake.nix|nix|<nowiki>
[...]
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    lanzaboote.url = "github:nix-community/lanzaboote";
  };
[...]
  outputs = { self, nixpkgs, lanzaboote, ...}: {
    nixosConfigurations = {
      yourHost = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
 
        modules = [
          # This is not a complete NixOS configuration and you need to reference
          # your normal configuration here.
 
          lanzaboote.nixosModules.lanzaboote
[...]
</nowiki>}}
 
In your system configuration explicitly disable <code>systemd-boot</code> and replace it by enabling <code>lanzaboote</code>:
 
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
boot = {
  loader.systemd-boot.enable = lib.mkForce false;
  lanzaboote = {
    enable = true;
    pkiBundle = "/etc/secureboot";
  };
};
</nowiki>}}
 
After you rebuild your system, check <code>sbctl verify</code> output:
 
<syntaxHighlight lang="bash">
$ sudo nix run nixpkgs#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 not signed
✓ /boot/EFI/systemd/systemd-bootx64.efi is signed
</syntaxHighlight>
 
It is expected that the files ending with bzImage.efi are not signed. In case any of the nixos-generation-*.efi files are not signed, you have hit a bug ([https://github.com/nix-community/lanzaboote/issues/39 #39]). This issue will prevent the system from booting successfully when Secure Boot is enabled. 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.
 
For the last step, your UEFI firmware needs to be set to <code>Setup Mode</code> to allow enrolling Secure Boot keys. This varies depending on your vendor and notebookt model.


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:
<!--T:14-->
Follow the instructions in the [https://github.com/nix-community/lanzaboote/blob/master/docs/QUICK_START.md Quick Start guide].


1) Select the "Security" tab.
<!--T:15-->
2) Select the "Secure Boot" entry.
== Key management ==
3) Set "Secure Boot" to enabled.
At the time of writing, Lanzaboote offers only local storage of the keyring, otherwise, it is not possible to rebuild the system and sign the new resulting files.
4) Select "Reset to Setup Mode".
5) Select "Clear All Secure Boot Keys".


When you are done, press F10 to save and exit.
<!--T:16-->
In the future, Lanzaboote will offer two new signature backends: remote signing (an HTTP server which receives signature requests and answers with signatures) and PKCS#11-based signing (that is, bringing an HSM-like device, e.g. YubiKey, NitroKey, etc.).


After reboot enroll your keys to enable Secure Boot. Microsoft keys are used to avoid any booting issues.
<!--T:17-->
{{Warning|Key management is a hard problem which is out of scope for Lanzaboote project, many recipes exist and there is no single perfect solution. Taking the time to learn how to key manage and figure out the right level of threat protection is crucial to achieve an effective boot protection.}}


<syntaxHighlight lang="bash">
<!--T:18-->
$ sudo nix run nixpkgs#sbctl enroll-keys --microsoft
== Differences with `systemd-stub` ==
Enrolling keys to EFI variables...
systemd and distribution upstream have an existing solution called `systemd-stub` but this is not a realistic solution for NixOS as there's too many generations on a system.
With vendor keys from microsoft...
Enrolled keys to the EFI variables!
</syntaxHighlight>


You can now reboot your system. After you've booted, Secure Boot is activated:
<!--T:19-->
Using `systemd-stub`, a kernel and an initrd has to be duplicated for '''each generation''', using Lanzaboote's stub, a kernel and initrd can be '''deduplicated''' without compromising on the security.


<syntaxHighlight lang="bash">
<!--T:20-->
$ bootctl status
Tracking the feature parity with `systemd-stub` can be done in this issue: https://github.com/nix-community/lanzaboote/issues/94.
System:
[[Category:Security]]
      Firmware: UEFI 2.70 (Lenovo 0.4720)
[[Category:Booting]]
Firmware Arch: x64
</translate>
  Secure Boot: enabled (user)
  TPM2 Support: yes
  Boot into FW: supported
</syntaxHighlight>

Latest revision as of 21:28, 12 July 2024

Secure Boot usually refers to a platform firmware capability to verify the boot components and ensure that only your own operating system to boot.

Secure Boot has multiple implementations, the most known one is UEFI Secure Boot, which relies on the UEFI platform firmware, but others implementations can exist on embedded systems.

On NixOS, Secure Boot can be enabled via the project Lanzaboote.

Lanzaboote has two components: lzbt and stub.

lzbt is the command line that signs and installs the boot files on the ESP.

stub is a UEFI application that loads the kernel and initrd from the ESP, it's different from systemd-stub, see below to see precise differences.

Warning: Lanzaboote is still in development and requires some prerequisites and precautions. Currently it's only available for nixos-unstable. For more information, please see the GitHub repository or the Quick Start guide.

Requirements

The Secure Boot implementation of Lanzaboote requires a system installed in UEFI mode together with systemd-boot enabled. This can be checked by running bootctl status:

$ 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 is recommended to enable a BIOS password and full disc encryption to prevent attacks against UEFI and Secure Boot.

Setup

Follow the instructions in the Quick Start guide.

Key management

At the time of writing, Lanzaboote offers only local storage of the keyring, otherwise, it is not possible to rebuild the system and sign the new resulting files.

In the future, Lanzaboote will offer two new signature backends: remote signing (an HTTP server which receives signature requests and answers with signatures) and PKCS#11-based signing (that is, bringing an HSM-like device, e.g. YubiKey, NitroKey, etc.).

Warning: Key management is a hard problem which is out of scope for Lanzaboote project, many recipes exist and there is no single perfect solution. Taking the time to learn how to key manage and figure out the right level of threat protection is crucial to achieve an effective boot protection.

Differences with `systemd-stub`

systemd and distribution upstream have an existing solution called `systemd-stub` but this is not a realistic solution for NixOS as there's too many generations on a system.

Using `systemd-stub`, a kernel and an initrd has to be duplicated for each generation, using Lanzaboote's stub, a kernel and initrd can be deduplicated without compromising on the security.

Tracking the feature parity with `systemd-stub` can be done in this issue: https://github.com/nix-community/lanzaboote/issues/94.