(Hinweis: Dieser Artikel wird evt. etwas spezifisch für Arch Linux).

Wenn ich für mich private Linux-Systeme aufsetze, dann sind diese schon seit einigen Jahren immer verschlüsselt, genauer gesagt, es gibt eine unverschlüsselte Partition, auf die der Bootloader zugreifen kann, und von der dann Kernel und initrd geladen werden, und der Rest der Festplatte ist eine große LUKS-Partition, auf der dann LVM gemacht wird. Eine Beschreibung dazu gibt es im Arch Linux Wiki.

Was mich an dem Setup immer gestört hat ist, dass da eben immer noch Platz für eine Evil Maid-Attacke ist - und da wollte ich den Aufwand für gerne so hoch wie möglich gestalten. Es gibt durchaus eine Technik, welche genau dies tut: Die Rede ist von Secure Boot, welches nur noch Bootloader startet, welche mit im NVRAM hinterlegten Schlüsseln signiert wurden. Ein wichtiges Detail dabei ist, dass Secure Boot fast immer auch eigene Schlüssel unterstützt.

In dem Setup, dass ich umgesetzt habe, werden der Kernel, die initiale RAM-Disk, die CPU-Microcode-Updates und die Kernel-Commandline-Paramter in ein einzelnes EFI-Binary zusammen gepackt, signiert und landen dann auf der EFI System Partition (ESP) unter /boot/efi, während der Kernel sicher auf dem verschlüsselten Filesystem in /boot verbleibt. Damit muss ein Angreifer zwingend Secure Boot aushebeln, wenn er mir ein korruptes Binary unterjubeln will.

Da die Kernel-Kommandozeile Bestandteil des EFI-Binarys wird, ist es nicht notwendig, einen “echten” Bootloader wie grub zu verwenden. Statt dessen setze ich auf systemd-boot (der Link geht wieder zum Arch Linux Wiki).

Vom Prinzip her sind, mehr oder weniger der Reihe nach, die folgenden Schritte auszuführen:

  • Installation des Systems mit LVM auf LUKS
  • Installation des Bootloaders (bootctl install, anlegen der loader.conf)
  • Generieren der eigenen Schlüssel für Secure Boot
  • evt. Herunterladen der Microsoft Secure Boot-Schlüssel (für Dual-Boot-Setups)
  • das Programm KeyTool installieren und in systemd-boot hinterlegen
  • im BIOS den Modus für Secure Boot auf “Setup” ändern
  • Booten in das KeyTool-Programm, löschen der vorhandenen Keys, einpflegen der eigenen Keys
  • Zusammenbau eines EFI-Binarys mit Kernel, initrd etc.
  • Signieren des Binarys
  • Aktivieren von Secure Boot

Die ersten beiden Schritte sind sehr einfach und im Arch Linux Wiki ausreichend beschrieben. Zum Erstellen der eigenen Keys kann man ein Skript von Rod Smith verwenden (man muss unter Arch die Pakete sbsigntools und efitools installieren), das Herunterladen der Microsoft-Keys ist wiederum im Wiki beschrieben.

Um KeyTool zum Laufen zu bringen kopiert man /usr/share/efitools/efi/KeyTool.efi in die ESP und legt einen Eintrag in $ESP/loader/entries/keytool.conf an:

1
2
title KeyTool
efi   /KeyTool.efi

Vor dem Reboot kopiert man noch alle Keys (.cer, .esl, .auth) ebenfalls auf die ESP. Die Reihenfolge, in der man die Schlüssel hinzufügt, ist: eigene DB, evt. Microsoft DB (das .auth-File), KEK, PK.

Das Zusammenbauen des EFI-Binarys ist recht einfach: Man schreibt die Kernel-Kommandozeile z.B. in ein temporäres File, konkateniert den Kernel-Microcode und die initiale RAM-Disk ebenfalls in ein temporäres File und verpackt das dann mitsamt Signatur:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# where to save kernel package
t=$ESP/EFI/Arch/linux-signed.efi
# package kernel and command line
objcopy \
  --add-section .osrel="/etc/os-release"   --change-section-vma .osrel=0x20000    \
  --add-section .cmdline=/tmp/cmdline.tmp  --change-section-vma .cmdline=0x30000  \
  --add-section .linux=/boot/vmlinuz-linux --change-section-vma .linux=0x2000000  \
  --add-section .initrd=/tmp/initrd.tmp    --change-section-vma .initrd=0x3000000 \
  /usr/lib/systemd/boot/efi/linuxx64.efi.stub $t
# sign kernel
sbsign --key DB.key --cert DB.crt --output $t $t
# sign systemd-boot bootloader
sbsign --key DB.key --cert DB.crt --output $ESP/EFI/BOOT/BOOTX64.EFI $ESP/EFI/BOOT/BOOTX64.EFI

Jetzt legt man noch den entsprechenden Eintrag in $ESP/loader/entries/arch.conf an, löscht die Keys, das KeyTool-Binary sowie dessen Bootloader-Eintrag, verifiziert das Ganze nochmal mit bootctl list und kann dann Rebooten und Secure Boot aktivieren.

Es gibt ein AUR-Paket namens sbupate-git, welches dann auch gleich einen Hook für Pacman mitbringt, so dass auch nach Kernel- oder initrd-Updates automatisch neu signiert wird.

Und zu guter Letzt: Es ist natürlich sinnvoll, das BIOS dann auch mit einem Passwort zu sichern. Sonst kann ein Angreifer Secure Boot ja einfach wieder abdrehen…