systemd-ukify: Unified Kernel Image (UKI) für UEFI Secure Boot mit YubiKey signieren
In einem älteren Beitrag hatte ich bereits beschrieben, wie ich mittels systemd-ukify sogenannte Unified Kernel Images (UKIs) zum Booten meines Arch-Linux-Systems erstelle. Die so generierten UKIs wurden dabei mit meinem eigenen UEFI-Secure-Boot-Schlüssel signiert. Dabei befand sich der private Secure-Boot-Schlüssel jedoch auf meinem System selbst, wobei dieser aber natürlich nur für den Root-Benutzer lesbar ist.
Eine andere Möglichkeit ist es, den privaten Secure-Boot-Schlüssel (konkret geht es um den Signature Database Key) auf einem Hardware-Security-Token, wie z.B. einem YubiKey, zu speichern. Der Vorteil besteht darin, dass der private Schlüssel sich nicht direkt auf dem eigentlichen System befindet und ein Zugriff auf den privaten Schlüssel erschwert wird bzw. ein Auslesen generell beim YubiKey nicht möglich ist. Die Kommunikation zwischen systemd-ukify (intern eigentlich sbsign) und YubiKey findet über die PKCS#11-Schnittstelle statt.
Voraussetzung
Es wird vorausgesetzt, dass ihr bereits euren eigenen Secure-Boot-Schlüssel auf eurem YubiKey generiert bzw. importiert habt. Der verwendete PIV-Slot ist letztendlich egal. Je nachdem welchen Slot ihr verwendet, müsst ihr nur den ukify-Befehl entsprechend anpassen. Ich selbst habe Slot 9c: Digital Signature
verwendet.
Das Ganze funktioniert zudem nur - zumindest bei mir - wenn ihr als PKCS#11-Bibliothek die von Yubico bereitgestellte YKCS11-Bibliothek verwendet. Damit systemd-ukify respektive sbsign diese Bibliothek dann auch verwendet, muss die Umgebungsvariable PKCS11_MODULE_PATH
entsprechend gesetzt sein. Die YKCS11-Bibliothek wird mit dem Paket yubico-piv-tool
unter Arch Linux bereitgestellt.
Zuguterletzt stellt sicher, dass der Service pcscd
läuft. Diesen könnt ihr im Zweifel wie folgt starten:
sudo systemctl start pcscd.service
UKI erstellen & mit YubiKey signieren
Der ukify-Befehl zum Erstellen des UKI und dem Signieren mittels YubiKey sieht wie folgt aus:
sudo PKCS11_MODULE_PATH=/usr/lib/libykcs11.so /usr/lib/systemd/ukify build \
--linux=/boot/vmlinuz-linux \
--initrd=/boot/intel-ucode.img \
--initrd=/boot/initramfs-linux.img \
--cmdline=@/etc/kernel/cmdline \
--splash=/usr/share/systemd/bootctl/splash-arch.bmp \
--signtool=sbsign \
--signing-engine=pkcs11 \
--secureboot-private-key="pkcs11:object=Private key for Digital Signature;type=private" \
--secureboot-certificate=db-yubikey.crt \
--output=/efi/EFI/Linux/arch-linux.efi
Splash image /usr/share/systemd/bootctl/splash-arch.bmp is 566×167 pixels
+ sbverify --list /boot/vmlinuz-linux
No signature table present
Kernel version not specified, starting autodetection 😖.
Found uname version: 6.10.10-arch1-1
+ sbsign --key 'pkcs11:object=Private key for Digital Signature;type=private' --cert db-yubikey.crt --engine pkcs11 /tmp/ukizwn1rsrk --output arch-linux.efi
Enter engine key pass phrase:
Enter PKCS#11 key PIN for Private key for Digital Signature:
Signing Unsigned original image
Wrote signed arch-linux.efi
Befindet sich euer Secure-Boot-Schlüssel nicht im Slot 9c
, dann müsst ihr entsprechend den Alias anpassen (siehe YKCS11-Doku)
Ein Problem für welches ich bisher noch keine Lösung gefunden habe, ist die doppelte Abfrage der YubiKey-PIV-Pin.
Fazit
Wer seine privaten Schlüssel (SSH, GPG, Secure-Boot etc.) nicht direkt auf seinem System, sondern aus Sicherheits- und ggf. Portabilätsgründen lieber auf einem Hardware-Security-Token aufbewahren möchte, kann dieses auch für seinen eigenen Secure-Boot-Schlüssel tun. Das Signieren von Unified Kernel Images in Verbindung mit systemd-ukify und YubiKey funktioniert unter Arch Linux problemlos. Letztendlich ist es aber auch hier wieder ein Abwegen zwischen Sicherheit & Komfort, da bei einem System-Update und dem automatischen Ausführen von systemd-ukify nun immer die YubiKey-PIN doppelt eingegeben werden muss, damit das generierte UKI mittels dem Secure-Boot-Schlüssel auf dem YubiKey signiert werden kann.