<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>sbctl &amp;mdash; Sebastian Wiesner</title>
    <link>https://swsnr.writeas.com/tag:sbctl</link>
    <description>System engineer for satellite mission planning. Gnome. Rust. Arch.  </description>
    <pubDate>Sat, 09 May 2026 12:25:48 +0000</pubDate>
    <image>
      <url>https://i.snap.as/9knB2j11.jpg</url>
      <title>sbctl &amp;mdash; Sebastian Wiesner</title>
      <link>https://swsnr.writeas.com/tag:sbctl</link>
    </image>
    <item>
      <title>Install Arch with Secure boot, TPM2-based LUKS encryption, and systemd-homed</title>
      <link>https://swsnr.writeas.com/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[#archlinux #systemd #secureboot #dracut #sbctl&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed&#34;Discuss.../a &#xA;&#xA;Update: I no longer use dracut, and the corresponding part of this blog&#xA;post no longer reflects my setup.&#xA;&#xA;This article describes my Arch Linux setup which combines Secure Boot with custom keys, TPM2-based full disk encryption and systemd-homed into a fully encrypted and authenticated, yet convenient Linux system.&#xA;&#xA;This setup draws inspiration from Authenticated Boot and Disk Encryption on Linux and Unlocking LUKS2 volumes with TPM2, FIDO2, PKCS#11 Security Hardware on systemd 248 by Lennart Poettering, and combines my previous posts on these topics.&#xA;&#xA;!--more--&#xA;&#xA;What this setup does&#xA;&#xA;Authenticate the boot loader, kernel, initramfs, microcode with Secure Boot, using my own custom keys.  Nothing can boot which wasn’t signed by my keys.&#xA;Everything is either authenticated with my keys (kernel, initramfs, microcode) or encrypted (system partition).&#xA;Encrypt the system partition, and unlock it automatically if the boot process was authenticated, by means of a TPM2 key bound to the secure boot state.&#xA;Give every user their own dedicated encrypted home directory, which gets unlocked at login and locked again at logout.&#xA;&#xA;What it doesn’t&#xA;&#xA;Show an ugly LUKS password prompt at boot (even with Plymouth it’s not really pretty).&#xA;Leave some parts unencrypted and unauthenticated (conventional installations often fail to consider the initramfs).&#xA;Ask me twice for my password, once at boot to unlock the disk and then again at login.&#xA;Encrypt data of all users with a shared key.&#xA;&#xA;Tools used&#xA;&#xA;Archlinux&#xA;systemd   = 250&#xA;systemd-boot as bootloader&#xA;systemd in initramfs to automatically discover and mount the root filesystem&#xA;dracut to generate the initramfs and build signed UEFI binaries&#xA;sbctl to create and enroll Secure Boot keys, and sign binaries&#xA;systemd-homed to manage user accounts with per-user encrypted home directories&#xA;systemd-cryptenroll to add TPM2 and recovery keys tokens to a LUKS partition&#xA;&#xA;The setup&#xA;&#xA;Install the system&#xA;&#xA;We follow the Installation Guide up to and including section “Update the system clock”. Then we partition the disk (/dev/nvme0n1 in our case); we need an EFI system partition of about 500MB and a root partition spanning the rest of the disk. The EFI partition must be unencrypted and have a FAT filesystem; for the root file system we choose btrfs on top of an encrypted partition.&#xA;&#xA;First we partition the disk and reload the partition table; we take care to specify proper partition types (-t option) so that systemd can automatically discover and mount our filesystems without further configuration in /etc/crypttab or /etc/fstab (see Discoverable Partitions Specification (DPS)):&#xA;&#xA;$ targetdevice=/dev/nvme0n1&#xA;$ sgdisk -Z &#34;$targetdevice&#34;&#xA;$ sgdisk -n1:0:+550M -t1:ef00 -c1:EFISYSTEM -N2 -t2:8304 -c2:linux &#34;$targetdevice&#34;&#xA;$ sleep 3&#xA;$ partprobe -s &#34;$targetdevice&#34;&#xA;$ sleep 3&#xA;&#xA;Then we setup the encrypted partition for the root file system. We get asked for an encryption password where we pick a very simple encryption password (even “password” is good enough for now, really) to save some typing during installation, as we’ll later replace the password with TPM2 key and a random recovery key:&#xA;&#xA;$ cryptsetup luksFormat --type luks2 /dev/disk/by-partlabel/linux&#xA;$ cryptsetup luksOpen /dev/disk/by-partlabel/linux root&#xA;$ rootdevice=/dev/mapper/root&#xA;&#xA;Now we create the filesystems:&#xA;&#xA;$ mkfs.fat -F32 -n EFISYSTEM /dev/disk/by-partlabel/EFISYSTEM&#xA;$ mkfs.btrfs -f -L linux &#34;$rootdevice&#34;&#xA;&#xA;Now we can mount the filesystems and create some basic btrfs subvolumes:&#xA;&#xA;$ mount &#34;$rootdevice&#34; /mnt&#xA;$ mkdir /mnt/efi&#xA;$ mount /dev/disk/by-partlabel/EFISYSTEM /mnt/efi&#xA;$ for subvol in var var/log var/cache var/tmp srv home; do btrfs subvolume create &#34;/mnt/$subvol&#34;; done&#xA;&#xA;Now we’re ready to bootstrap Arch Linux: We generate a mirrorlist and install essential packages:&#xA;&#xA;$ reflector --save /etc/pacman.d/mirrorlist --protocol https --latest 5 --sort age&#xA;$ pacstrap /mnt base linux linux-firmware intel-ucode btrfs-progs dracut neovim&#xA;&#xA;This takes a while to download and installation all packages; afterwards we configure some essential settings. Choose locale settings and the $newhostname according to your personal preferences.&#xA;&#xA;$ ln -sf /usr/share/zoneinfo/Europe/Berlin /mnt/etc/localtime&#xA;$ sed -i -e &#39;/^#enGB.UTF-8/s/^#//&#39; /mnt/etc/locale.gen&#xA;$ echo &#39;LANG=enGB.UTF-8&#39;   /mnt/etc/locale.conf&#xA;$ echo &#39;KEYMAP=us&#39;   /mnt/etc/vconsole.conf&#xA;$ echo &#34;$newhostname&#34;   /mnt/etc/hostname&#xA;&#xA;Now we enter the new system and finish configuration by generating locales, enabling a few essential services and setting a root password:&#xA;&#xA;$ arch-chroot /mnt&#xA;$ locale-gen&#xA;$ systemctl enable systemd-homed&#xA;$ systemctl enable systemd-timesyncd&#xA;$ passwd root&#xA;&#xA;Still in chroot we now build unified EFI kernel images (including initrd and kernel) for booting and install the systemd-boot boot loader:&#xA;&#xA;$ pacman -S --noconfirm --asdeps binutils elfutils&#xA;$ dracut -f --uefi --regenerate-all&#xA;$ bootctl install&#xA;&#xA;We do not need to create /etc/fstab or /etc/crypttab; as we assigned the appropriate types to each partition and installed systemd-boot a systemd-based initramfs can automatically determine the disk the system was booted from, and discover all relevant partitions.  It can then use superblock information to automatically open encrypted LUKS devices and mount file systems.&#xA;&#xA;At this point we also need to take care to install everything we need for network configuration after reboot.  For desktop systems I prefer network manager because it integrates well into Gnome:&#xA;&#xA;$ pacman -S networkmanager&#xA;&#xA;We have finished the basic setup from the live disk now; let’s leave chroot and reboot:&#xA;&#xA;$ exit&#xA;$ reboot&#xA;&#xA;After reboot we can complete the system installation, by adding a desktop environment, applications, command line tools, etc.&#xA;&#xA;I like to automate this, and have two bash scripts in my dotfiles, one for boostrapping a new system from a live disk (arch/bootstrap-from-iso.bash) and another one for installing everything after the initial bootstrapping (arch/install.bash).&#xA;&#xA;Create homed user&#xA;&#xA;With the installation finished we create our user account with homectl; let’s name it foo for the purpose of this article. First we should disable copy on write for /home, because this file system feature doesn’t work well with large files frequently updated in place, such as disk images of virtual machines or loopback files as created by systemd-homed:&#xA;&#xA;$ chattr +C /home/&#xA;&#xA;We now create the foo user with an encrypted home directory backed by LUKS and btrfs:&#xA;&#xA;$ homectl create foo --storage luks --fs-type btrfs&#xA;&#xA;By default systemd assigns 85% of the available disk space to the user account, and will balance available space among all user accounts (based on a weight we can configure with —rebalance-weight). On a single user system we may prefer to set an explicit quota for the user account:&#xA;&#xA;$ homectl resize foo 50G&#xA;&#xA;We can also add some additional metadata to the user account:&#xA;&#xA;homectl update foo --real-name &#39;Foo&#39; --email-address foo@example.org --language enGB.UTF-8 --member-of wheel&#xA;&#xA;man homectl provides a complete list of flags; in particular it also offers support for various kinds of security tokens (e.g. FIDO2) for user authentication, provides plenty of means for resource accounting (e.g. memory consumption) for the user account, and supports different kinds of password policies.&#xA;&#xA;Finally we may run into systemd issues with home areas on btrfs (see below); if login fails with a “Operation on home failed: Not enough disk space for home” message we need to enable LUKS discard:&#xA;&#xA;homectl update foo --luks-discard=true&#xA;&#xA;This flag is not safe (heed the warning in man homectl), but until systemd improves its behaviour on btrfs we have no choice unfortunately.&#xA;&#xA;Setup secure boot&#xA;&#xA;First let’s check the secure boot state. We must be in Setup Mode in order to enroll our own keys:&#xA;&#xA;$ sbctl status&#xA;Installed:&#x9;✓ sbctl is installed&#xA;Owner GUID:&#x9;REDACTED&#xA;Setup Mode:&#x9;✗ Enabled&#xA;Secure Boot:&#x9;✗ Disabled&#xA;&#xA;To enable secure boot we need some keys which we generate with sbctl.  For historical reasons sbctl creates these keys in /usr/share/secureboot but plans exists to change this to a more appropriate place (see Github issue 57).&#xA;&#xA;$ sbctl create-keys&#xA;&#xA;Now we tell dracut how to sign the UEFI binaries it builds and rebuild our kernel images to get them signed:&#xA;&#xA;$ cat   /etc/dracut.conf.d/50-secure-boot.conf &lt;&lt;EOF&#xA;uefisecurebootcert=&#34;/usr/share/secureboot/keys/db/db.pem&#34;&#xA;uefisecurebootkey=&#34;/usr/share/secureboot/keys/db/db.key&#34;&#xA;EOF&#xA;$ dracut -f --uefi --regenerate-all&#xA;&#xA;Next we need to sign the bootloader.  With -s we ask sbctl to remember this file in its database which later lets us check signatures with sbctl verify and automatically update all signatures with sbctl sign-all. The sbctl package includes a pacman hook which automatically updates signatures when an EFI binary on /efi or in /usr/lib changed. Note that we do not sign the boot loader on /efi but instead place a signed copy in /usr/lib.  Starting with systemd 250 bootctl will pick up the signed copy when updating the boot loader.  Hence we reinstall the bootloader afterwards to put the signed copy on /efi.&#xA;&#xA;$ sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi&#xA;$ bootctl install&#xA;&#xA;We should also do the same for the firmware update to enable seamless firmware updates under secure boot.  Again we use -s to remember this file in the sbtctl database:&#xA;&#xA;$ sbctl sign -s -o /usr/lib/fwupd/efi/fwupdx64.efi.signed /usr/lib/fwupd/efi/fwupdx64.efi&#xA;&#xA;Now let’s verify that we have all signatures in place and enroll keys if everything’s properly signed:&#xA;&#xA;$ sbctl verify&#xA;Verifying file database and EFI images in /efi...&#xA;✓ /usr/lib/fwupd/efi/fwupdx64.efi.signed is signed&#xA;✓ /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed is signed&#xA;✓ /efi/EFI/BOOT/BOOTX64.EFI is signed&#xA;✓ /efi/EFI/Linux/linux-5.15.12-arch1-1-19ea0ebee1ea4de086128ce1a8e2197b-rolling.efi is signed&#xA;✓ /efi/EFI/systemd/systemd-bootx64.efi is signed&#xA;$ sbctl enroll-keys&#xA;&#xA;After a reboot we can check the secure boot state again; we’ll see that setup mode is now disabled, secure boot is on, and everything was properly enrolled:&#xA;&#xA;$ reboot&#xA;$ sbctl status&#xA;Installed:&#x9;✓ sbctl is installed&#xA;Owner GUID:&#x9;REDACTED&#xA;Setup Mode:&#x9;✓ Disabled&#xA;Secure Boot:&#x9;✓ Enabled&#xA;&#xA;Enroll TPM2 keys&#xA;&#xA;With the boot process secured we can now configure automatic unlocking of the root filesystem, by binding a LUKS key to the TPM.&#xA;&#xA;We enable the tpm2-tss module in the Dracut configuration, install the dependencies of this dracut module, and regenerate our UEFI kernel images (which will again be signed for secure boot):&#xA;&#xA;$ cat   /etc/dracut.conf.d/50-tpm2.conf &lt;&lt;EOF&#xA;adddracutmodules+=&#34; tpm2-tss &#34;&#xA;EOF&#xA;$ pacman -S tpm2-tools&#xA;$ dracut -f --uefi --regenerate-all&#xA;&#xA;Now we can enroll a TPM2 token (bound to the secure boot measurement in PCR 7) and a recovery key to our root filesystem. This prompts for an existing passphrase each time.  Store the recovery key at a safe place outside of this disk, to have it at hand if TPM2 unlocking ever breaks.&#xA;&#xA;$ systemd-cryptenroll /dev/gpt-auto-root-luks --recovery-key&#xA;$ systemd-cryptenroll /dev/gpt-auto-root-luks --tpm2-device=auto&#xA;&#xA;Now reboot and enjoy: The boot process goes straight all the way to the login manager and never shows a LUKS password prompt.  The root filesystem is still reasonably secure: The TPM2 key becomes invalid if the secure boot state changes (e.g. new keys are enrolled, or secure boot is disabled), and cannot be recovered if the disk is removed from the system. Consequently only a kernel signed and authenticated with your own secure boot keys can unlock the root disk automatically.&#xA;&#xA;Finally we can wipe the password slots if you like (make sure to have a recovery key at this point):&#xA;&#xA;$ systemd-cryptenroll /dev/gpt-auto-root-luks --wipe-slot=password&#xA;&#xA;If you cannot use secure boot for some reason you can alternatively bind the TPM2 token to a combination of firmware state and configuration and the exact boot chain (up to and including the specific kernel that was started), by specifing the PCR registers 0-5:&#xA;&#xA;$ systemd-cryptenroll /dev/gpt-auto-root-luks --tpm2-device=auto --tpm2-pcrs 0+1+2+3+4+5&#xA;&#xA;This only permits the current kernel and its specific boot chain (e.g bootloader used) to unlock the root filesystem automatically.  However this means that we need to reboot and then wipe and re-enroll the TPM2 token after every rebuild of the kernel image… which happens quite often in fact: Dracut updates or configuration changes, kernel updates, systemd updates (due to the EFI shim provided by systemd), bootloader updates, bootloader configuration changes, etc.&#xA;&#xA;Hence I generally recommend to use secure boot if possible in any way.&#xA;&#xA;Issues with this setup&#xA;&#xA;While I am happy with this setup it still has a few drawbacks and issues.&#xA;&#xA;Double encryption&#xA;&#xA;In this setup home directories get encrypted twice, once by homed and then again by the underlying LUKS device.  This wastes a bunch of CPU cycles and likely impacts performance a lot, though I haven’t measured the impact and it’s not so bad as to be noticeable in my day-to-day work.&#xA;&#xA;We could optimize this by putting /home/ on a separate partition backed by dm-integrity to authenticate the filesystem (omitting dm-integrity and using a plain file system leaves an attack vector, because linux cannot securely mount untrusted file systems).  This setup requires at least systemd 250 or newer, because earlier versions do not support dm-integrity well.  With systemd 250 we can setup a HMAC-based integrity device, put the HMAC key on the rootfs (e.g. /etc/keys/home.key) and register the home partition in /etc/integritytab with that key, and then mount it via /etc/fstab.&#xA;&#xA;However, this has a few issues on its own, because dm-integrity has a few design issues and is and nowhere near LUKS/dm-crypt:&#xA;&#xA;There’s no key management like LUKS for dm-crypt, meaning we can’t use passphrases or TPM2 keys for dm-integrity devices; instead we need a key file somewhere on disk.&#xA;Unlike LUKS/dm-crypt devices dm-integrity devices aren’t self-describing, because the superblock for dm-integrity doesn’t even contain the algorithm used (see &lt;https://github.com/systemd/systemd/pull/20902). We cannot mount a dm-integrity device without some extra configuration, and worse, getting the configuration wrong can silently corrupt the device.&#xA;For these reasons, DPS cannot and does not support dm-integrity partitions, so we need to configure the whole home partition mount, from dm-integrity up to /etc/fstab.&#xA;&#xA;Tooling issues&#xA;&#xA;There are also multiple issues with current tooling that require some more or less safe workarounds:&#xA;&#xA;At the time of writing systemd-home has issues with resizing LUKS home areas on btrfs filesystems, apparently due to fallocate() idiosyncrasies in btrfs. This issue prevents users from logging in, see systemd issues 19398 and 20960, an Arch forums post, and a mail on the systemd-devel list. A workaround is to enable online discard for the user, but this flag is unsafe because it allows overcommitting disk space, which results in IO errors that the kernel and application are not well prepared to handle (which comes down to potential data loss).  Keep frequent backups if you need this.&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed&#34;Discuss.../a ]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:archlinux" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">archlinux</span></a> <a href="https://swsnr.writeas.com/tag:systemd" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">systemd</span></a> <a href="https://swsnr.writeas.com/tag:secureboot" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">secureboot</span></a> <a href="https://swsnr.writeas.com/tag:dracut" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">dracut</span></a> <a href="https://swsnr.writeas.com/tag:sbctl" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">sbctl</span></a></p>

<p><a href="https://remark.as/p/swsnr/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed" rel="nofollow">Discuss...</a></p>

<p><strong>Update:</strong> I no longer use <code>dracut</code>, and the corresponding part of this blog
post no longer reflects my setup.</p>

<p>This article describes my Arch Linux setup which combines Secure Boot with custom keys, TPM2-based full disk encryption and systemd-homed into a fully encrypted and authenticated, yet convenient Linux system.</p>

<p>This setup draws inspiration from <a href="https://0pointer.net/blog/authenticated-boot-and-disk-encryption-on-linux.html" rel="nofollow">Authenticated Boot and Disk Encryption on Linux</a> and <a href="https://0pointer.net/blog/unlocking-luks2-volumes-with-tpm2-fido2-pkcs11-security-hardware-on-systemd-248.html" rel="nofollow">Unlocking LUKS2 volumes with TPM2, FIDO2, PKCS#11 Security Hardware on systemd 248</a> by Lennart Poettering, and combines my previous posts on these topics.</p>



<h2 id="what-this-setup-does" id="what-this-setup-does">What this setup does</h2>
<ul><li>Authenticate the boot loader, kernel, initramfs, microcode with Secure Boot, using my own custom keys.  Nothing can boot which wasn’t signed by my keys.</li>
<li>Everything is either authenticated with my keys (kernel, initramfs, microcode) or encrypted (system partition).</li>
<li>Encrypt the system partition, and unlock it automatically if the boot process was authenticated, by means of a TPM2 key bound to the secure boot state.</li>
<li>Give every user their own dedicated encrypted home directory, which gets unlocked at login and locked again at logout.</li></ul>

<h2 id="what-it-doesn-t" id="what-it-doesn-t">What it doesn’t</h2>
<ul><li>Show an ugly LUKS password prompt at boot (even with Plymouth it’s not really pretty).</li>
<li>Leave some parts unencrypted and unauthenticated (conventional installations often fail to consider the initramfs).</li>
<li>Ask me twice for my password, once at boot to unlock the disk and then again at login.</li>
<li>Encrypt data of all users with a shared key.</li></ul>

<h2 id="tools-used" id="tools-used">Tools used</h2>
<ul><li><strong>Archlinux</strong></li>
<li><strong>systemd</strong> &gt;= 250</li>
<li><strong>systemd-boot</strong> as bootloader</li>
<li><strong>systemd</strong> in initramfs to automatically discover and mount the root filesystem</li>
<li><strong>dracut</strong> to generate the initramfs and build signed UEFI binaries</li>
<li><strong>sbctl</strong> to create and enroll Secure Boot keys, and sign binaries</li>
<li><strong>systemd-homed</strong> to manage user accounts with per-user encrypted home directories</li>
<li><strong>systemd-cryptenroll</strong> to add TPM2 and recovery keys tokens to a LUKS partition</li></ul>

<h2 id="the-setup" id="the-setup">The setup</h2>

<h3 id="install-the-system" id="install-the-system">Install the system</h3>

<p>We follow the <a href="https://wiki.archlinux.org/title/installation_guide" rel="nofollow">Installation Guide</a> up to and including section <a href="https://wiki.archlinux.org/title/installation_guide#Update_the_system_clock" rel="nofollow">“Update the system clock”</a>. Then we partition the disk (<code>/dev/nvme0n1</code> in our case); we need an EFI system partition of about 500MB and a root partition spanning the rest of the disk. The EFI partition must be unencrypted and have a FAT filesystem; for the root file system we choose btrfs on top of an encrypted partition.</p>

<p>First we partition the disk and reload the partition table; we take care to specify proper partition types (-t option) so that systemd can automatically discover and mount our filesystems without further configuration in <code>/etc/crypttab</code> or <code>/etc/fstab</code> (see <a href="https://systemd.io/DISCOVERABLE_PARTITIONS/" rel="nofollow">Discoverable Partitions Specification (DPS)</a>):</p>

<pre><code class="language-console">$ target_device=/dev/nvme0n1
$ sgdisk -Z &#34;$target_device&#34;
$ sgdisk -n1:0:+550M -t1:ef00 -c1:EFISYSTEM -N2 -t2:8304 -c2:linux &#34;$target_device&#34;
$ sleep 3
$ partprobe -s &#34;$target_device&#34;
$ sleep 3
</code></pre>

<p>Then we setup the encrypted partition for the root file system. We get asked for an encryption password where we pick a very simple encryption password (even “password” is good enough for now, really) to save some typing during installation, as we’ll later replace the password with TPM2 key and a random recovery key:</p>

<pre><code class="language-console">$ cryptsetup luksFormat --type luks2 /dev/disk/by-partlabel/linux
$ cryptsetup luksOpen /dev/disk/by-partlabel/linux root
$ root_device=/dev/mapper/root
</code></pre>

<p>Now we create the filesystems:</p>

<pre><code class="language-console">$ mkfs.fat -F32 -n EFISYSTEM /dev/disk/by-partlabel/EFISYSTEM
$ mkfs.btrfs -f -L linux &#34;$root_device&#34;
</code></pre>

<p>Now we can mount the filesystems and create some basic btrfs subvolumes:</p>

<pre><code class="language-console">$ mount &#34;$root_device&#34; /mnt
$ mkdir /mnt/efi
$ mount /dev/disk/by-partlabel/EFISYSTEM /mnt/efi
$ for subvol in var var/log var/cache var/tmp srv home; do btrfs subvolume create &#34;/mnt/$subvol&#34;; done
</code></pre>

<p>Now we’re ready to bootstrap Arch Linux: We generate a mirrorlist and install essential packages:</p>

<pre><code class="language-console">$ reflector --save /etc/pacman.d/mirrorlist --protocol https --latest 5 --sort age
$ pacstrap /mnt base linux linux-firmware intel-ucode btrfs-progs dracut neovim
</code></pre>

<p>This takes a while to download and installation all packages; afterwards we configure some essential settings. Choose locale settings and the <code>$new_hostname</code> according to your personal preferences.</p>

<pre><code class="language-console">$ ln -sf /usr/share/zoneinfo/Europe/Berlin /mnt/etc/localtime
$ sed -i -e &#39;/^#en_GB.UTF-8/s/^#//&#39; /mnt/etc/locale.gen
$ echo &#39;LANG=en_GB.UTF-8&#39; &gt;/mnt/etc/locale.conf
$ echo &#39;KEYMAP=us&#39; &gt;/mnt/etc/vconsole.conf
$ echo &#34;$new_hostname&#34; &gt;/mnt/etc/hostname
</code></pre>

<p>Now we enter the new system and finish configuration by generating locales, enabling a few essential services and setting a root password:</p>

<pre><code class="language-console">$ arch-chroot /mnt
$ locale-gen
$ systemctl enable systemd-homed
$ systemctl enable systemd-timesyncd
$ passwd root
</code></pre>

<p>Still in chroot we now build unified EFI kernel images (including initrd and kernel) for booting and install the systemd-boot boot loader:</p>

<pre><code class="language-console">$ pacman -S --noconfirm --asdeps binutils elfutils
$ dracut -f --uefi --regenerate-all
$ bootctl install
</code></pre>

<p>We do <em>not</em> need to create <code>/etc/fstab</code> or <code>/etc/crypttab</code>; as we assigned the appropriate types to each partition and installed systemd-boot a systemd-based initramfs can automatically determine the disk the system was booted from, and discover all relevant partitions.  It can then use superblock information to automatically open encrypted LUKS devices and mount file systems.</p>

<p>At this point we also need to take care to install everything we need for network configuration after reboot.  For desktop systems I prefer network manager because it integrates well into Gnome:</p>

<pre><code class="language-console">$ pacman -S networkmanager
</code></pre>

<p>We have finished the basic setup from the live disk now; let’s leave chroot and reboot:</p>

<pre><code class="language-console">$ exit
$ reboot
</code></pre>

<p>After reboot we can complete the system installation, by adding a desktop environment, applications, command line tools, etc.</p>

<p>I like to automate this, and have two bash scripts in my <a href="https://github.com/swsnr/dotfiles" rel="nofollow">dotfiles</a>, one for boostrapping a new system from a live disk (<a href="https://github.com/swsnr/dotfiles/blob/6a25c4e0620068ecc6360fcbe1587eb14b622ac2/arch/bootstrap-from-iso.bash" rel="nofollow"><code>arch/bootstrap-from-iso.bash</code></a>) and another one for installing everything after the initial bootstrapping (<a href="https://github.com/swsnr/dotfiles/blob/6a25c4e0620068ecc6360fcbe1587eb14b622ac2/arch/install.bash" rel="nofollow"><code>arch/install.bash</code></a>).</p>

<h3 id="create-homed-user" id="create-homed-user">Create homed user</h3>

<p>With the installation finished we create our user account with <code>homectl</code>; let’s name it <code>foo</code> for the purpose of this article. First we should disable copy on write for <code>/home</code>, because this file system feature doesn’t work well with large files frequently updated in place, such as disk images of virtual machines or loopback files as created by systemd-homed:</p>

<pre><code class="language-console">$ chattr +C /home/
</code></pre>

<p>We now create the <code>foo</code> user with an encrypted home directory backed by LUKS and btrfs:</p>

<pre><code class="language-console">$ homectl create foo --storage luks --fs-type btrfs
</code></pre>

<p>By default systemd assigns 85% of the available disk space to the user account, and will balance available space among all user accounts (based on a weight we can configure with <code>—rebalance-weight</code>). On a single user system we may prefer to set an explicit quota for the user account:</p>

<pre><code class="language-console">$ homectl resize foo 50G
</code></pre>

<p>We can also add some additional metadata to the user account:</p>

<pre><code class="language-console">homectl update foo --real-name &#39;Foo&#39; --email-address foo@example.org --language en_GB.UTF-8 --member-of wheel
</code></pre>

<p><code>man homectl</code> provides a complete list of flags; in particular it also offers support for various kinds of security tokens (e.g. FIDO2) for user authentication, provides plenty of means for resource accounting (e.g. memory consumption) for the user account, and supports different kinds of password policies.</p>

<p>Finally we may run into systemd issues with home areas on btrfs (see below); if login fails with a “Operation on home failed: Not enough disk space for home” message we need to enable LUKS discard:</p>

<pre><code class="language-console">homectl update foo --luks-discard=true
</code></pre>

<p>This flag is not safe (heed the warning in <code>man homectl</code>), but until systemd improves its behaviour on btrfs we have no choice unfortunately.</p>

<h3 id="setup-secure-boot" id="setup-secure-boot">Setup secure boot</h3>

<p>First let’s check the secure boot state. We must be in Setup Mode in order to enroll our own keys:</p>

<pre><code class="language-console">$ sbctl status
Installed:	✓ sbctl is installed
Owner GUID:	REDACTED
Setup Mode:	✗ Enabled
Secure Boot:	✗ Disabled
</code></pre>

<p>To enable secure boot we need some keys which we generate with <code>sbctl</code>.  For historical reasons sbctl creates these keys in <code>/usr/share/secureboot</code> but plans exists to change this to a more appropriate place (see <a href="https://github.com/Foxboron/sbctl/issues/57" rel="nofollow">Github issue 57</a>).</p>

<pre><code class="language-console">$ sbctl create-keys
</code></pre>

<p>Now we tell dracut how to sign the UEFI binaries it builds and rebuild our kernel images to get them signed:</p>

<pre><code class="language-console">$ cat &gt; /etc/dracut.conf.d/50-secure-boot.conf &lt;&lt;EOF
uefi_secureboot_cert=&#34;/usr/share/secureboot/keys/db/db.pem&#34;
uefi_secureboot_key=&#34;/usr/share/secureboot/keys/db/db.key&#34;
EOF
$ dracut -f --uefi --regenerate-all
</code></pre>

<p>Next we need to sign the bootloader.  With <code>-s</code> we ask <code>sbctl</code> to remember this file in its database which later lets us check signatures with <code>sbctl verify</code> and automatically update all signatures with <code>sbctl sign-all</code>. The <code>sbctl</code> package includes a pacman hook which automatically updates signatures when an EFI binary on <code>/efi</code> or in <code>/usr/lib</code> changed. Note that we do not sign the boot loader on <code>/efi</code> but instead place a signed copy in <code>/usr/lib</code>.  Starting with systemd 250 <code>bootctl</code> will pick up the signed copy when updating the boot loader.  Hence we reinstall the bootloader afterwards to put the signed copy on <code>/efi</code>.</p>

<pre><code class="language-console">$ sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi
$ bootctl install
</code></pre>

<p>We should also do the same for the firmware update to enable seamless firmware updates under secure boot.  Again we use <code>-s</code> to remember this file in the <code>sbtctl</code> database:</p>

<pre><code class="language-console">$ sbctl sign -s -o /usr/lib/fwupd/efi/fwupdx64.efi.signed /usr/lib/fwupd/efi/fwupdx64.efi
</code></pre>

<p>Now let’s verify that we have all signatures in place and enroll keys if everything’s properly signed:</p>

<pre><code class="language-console">$ sbctl verify
Verifying file database and EFI images in /efi...
✓ /usr/lib/fwupd/efi/fwupdx64.efi.signed is signed
✓ /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed is signed
✓ /efi/EFI/BOOT/BOOTX64.EFI is signed
✓ /efi/EFI/Linux/linux-5.15.12-arch1-1-19ea0ebee1ea4de086128ce1a8e2197b-rolling.efi is signed
✓ /efi/EFI/systemd/systemd-bootx64.efi is signed
$ sbctl enroll-keys
</code></pre>

<p>After a reboot we can check the secure boot state again; we’ll see that setup mode is now disabled, secure boot is on, and everything was properly enrolled:</p>

<pre><code class="language-console">$ reboot
$ sbctl status
Installed:	✓ sbctl is installed
Owner GUID:	REDACTED
Setup Mode:	✓ Disabled
Secure Boot:	✓ Enabled
</code></pre>

<h3 id="enroll-tpm2-keys" id="enroll-tpm2-keys">Enroll TPM2 keys</h3>

<p>With the boot process secured we can now configure automatic unlocking of the root filesystem, by binding a LUKS key to the TPM.</p>

<p>We enable the tpm2-tss module in the Dracut configuration, install the dependencies of this dracut module, and regenerate our UEFI kernel images (which will again be signed for secure boot):</p>

<pre><code class="language-console">$ cat &gt; /etc/dracut.conf.d/50-tpm2.conf &lt;&lt;EOF
add_dracutmodules+=&#34; tpm2-tss &#34;
EOF
$ pacman -S tpm2-tools
$ dracut -f --uefi --regenerate-all
</code></pre>

<p>Now we can enroll a TPM2 token (bound to the secure boot measurement in PCR 7) and a recovery key to our root filesystem. This prompts for an existing passphrase each time.  Store the recovery key at a safe place <em>outside</em> of this disk, to have it at hand if TPM2 unlocking ever breaks.</p>

<pre><code class="language-console">$ systemd-cryptenroll /dev/gpt-auto-root-luks --recovery-key
$ systemd-cryptenroll /dev/gpt-auto-root-luks --tpm2-device=auto
</code></pre>

<p>Now reboot and enjoy: The boot process goes straight all the way to the login manager and never shows a LUKS password prompt.  The root filesystem is still reasonably secure: The TPM2 key becomes invalid if the secure boot state changes (e.g. new keys are enrolled, or secure boot is disabled), and cannot be recovered if the disk is removed from the system. Consequently only a kernel signed and authenticated with your own secure boot keys can unlock the root disk automatically.</p>

<p>Finally we can wipe the password slots if you like (<strong>make sure to have a recovery key at this point</strong>):</p>

<pre><code class="language-console">$ systemd-cryptenroll /dev/gpt-auto-root-luks --wipe-slot=password
</code></pre>

<p>If you cannot use secure boot for some reason you can alternatively bind the TPM2 token to a combination of firmware state and configuration and the exact boot chain (up to and including the specific kernel that was started), by specifing the PCR registers 0-5:</p>

<pre><code class="language-console">$ systemd-cryptenroll /dev/gpt-auto-root-luks --tpm2-device=auto --tpm2-pcrs 0+1+2+3+4+5
</code></pre>

<p>This only permits the current kernel and its specific boot chain (e.g bootloader used) to unlock the root filesystem automatically.  However this means that we need to reboot and then wipe and re-enroll the TPM2 token after every rebuild of the kernel image… which happens quite often in fact: Dracut updates or configuration changes, kernel updates, systemd updates (due to the EFI shim provided by systemd), bootloader updates, bootloader configuration changes, etc.</p>

<p>Hence I generally recommend to use secure boot if possible in any way.</p>

<h2 id="issues-with-this-setup" id="issues-with-this-setup">Issues with this setup</h2>

<p>While I am happy with this setup it still has a few drawbacks and issues.</p>

<h3 id="double-encryption" id="double-encryption">Double encryption</h3>

<p>In this setup home directories get encrypted twice, once by homed and then again by the underlying LUKS device.  This wastes a bunch of CPU cycles and likely impacts performance a lot, though I haven’t measured the impact and it’s not so bad as to be noticeable in my day-to-day work.</p>

<p>We could optimize this by putting <code>/home/</code> on a separate partition backed by dm-integrity to authenticate the filesystem (omitting dm-integrity and using a plain file system leaves an attack vector, because linux cannot securely mount untrusted file systems).  This setup requires at least systemd 250 or newer, because earlier versions do not support dm-integrity well.  With systemd 250 we can setup a HMAC-based integrity device, put the HMAC key on the rootfs (e.g. <code>/etc/keys/home.key</code>) and register the home partition in <code>/etc/integritytab</code> with that key, and then mount it via <code>/etc/fstab</code>.</p>

<p>However, this has a few issues on its own, because dm-integrity has a few design issues and is and nowhere near LUKS/dm-crypt:</p>
<ul><li>There’s no key management like LUKS for dm-crypt, meaning we can’t use passphrases or TPM2 keys for dm-integrity devices; instead we need a key file somewhere on disk.</li>
<li>Unlike LUKS/dm-crypt devices dm-integrity devices aren’t self-describing, because the superblock for dm-integrity doesn’t even contain the algorithm used (see &lt;<a href="https://github.com/systemd/systemd/pull/20902" rel="nofollow">https://github.com/systemd/systemd/pull/20902</a>). We cannot mount a dm-integrity device without some extra configuration, and worse, getting the configuration wrong can silently corrupt the device.</li>
<li>For these reasons, <a href="https://systemd.io/DISCOVERABLE_PARTITIONS/" rel="nofollow">DPS</a> cannot and does not support dm-integrity partitions, so we need to configure the whole home partition mount, from dm-integrity up to <code>/etc/fstab</code>.</li></ul>

<h2 id="tooling-issues" id="tooling-issues">Tooling issues</h2>

<p>There are also multiple issues with current tooling that require some more or less safe workarounds:</p>
<ul><li>At the time of writing systemd-home has issues with resizing LUKS home areas on btrfs filesystems, apparently due to <code>fallocate()</code> idiosyncrasies in btrfs. This issue prevents users from logging in, see systemd issues <a href="https://github.com/systemd/systemd/issues/19398" rel="nofollow">19398</a> and <a href="https://github.com/systemd/systemd/issues/20960" rel="nofollow">20960</a>, an <a href="https://bbs.archlinux.org/viewtopic.php?id=258382" rel="nofollow">Arch forums post</a>, and a <a href="https://lists.freedesktop.org/archives/systemd-devel/2020-August/045092.html" rel="nofollow">mail on the systemd-devel list</a>. A workaround is to enable online discard for the user, but this flag is unsafe because it allows overcommitting disk space, which results in IO errors that the kernel and application are not well prepared to handle (which comes down to potential data loss).  Keep frequent backups if you need this.</li></ul>

<p><a href="https://remark.as/p/swsnr/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed" rel="nofollow">Discuss...</a></p>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/install-arch-with-secure-boot-tpm2-based-luks-encryption-and-systemd-homed</guid>
      <pubDate>Wed, 05 Jan 2022 23:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Unlock LUKS rootfs with TPM2 key</title>
      <link>https://swsnr.writeas.com/unlock-luks-rootfs-with-tpm2-key?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[#dracut #luks #sbctl #archlinux #systemd #secureboot&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/unlock-luks-rootfs-with-tpm2-key&#34;Discuss.../a &#xA;&#xA;Historically cryptsetup and LUKS only supported good old passwords; however recent systemd versions extend cryptsetup with additional key types such as FIDO tokens and TPM devices.&#xA;&#xA;I like the idea of encrypting the rootfs with a TPM2 key; it allows booting without ugly LUKS password prompts but still it keeps data encrypted at rest, and when combined with secure boot also still protects the running system against unauthorized access.&#xA;&#xA;Secure boot will prevent others from placing custom kernels on the unencrypted EFI system partition and booting these, or changing the kernel cmdline, in order to obtain root access to the unlocked rootfs.  LUKS encryption with a TPM-based key bound to secure boot state protects the data if someone removes the hard disk and attempts to access it offline, or tries to disable secure boot in order to boot a custom kernel.&#xA;&#xA;I’ve covered secure boot setup in a past article; this article talks about the TPM2-based encryption.&#xA;&#xA;!--more--&#xA;&#xA;Enroll TPM key&#xA;&#xA;Check that the system supports TPM2:&#xA;&#xA;$ systemd-cryptenroll --tpm2-device=list&#xA;PATH        DEVICE      DRIVER &#xA;/dev/tpmrm0 MSFT0101:00 tpmcrb&#xA;&#xA;Then enroll a new TPM2 key (use the appropriate block device path of course):&#xA;&#xA;$ systemd-cryptenroll --tpm2-device=auto /dev/disk/by-partlabel/linux &#xA;New TPM2 token enrolled as key slot 1.&#xA;&#xA;Then add recovery key:&#xA;&#xA;$ systemd-cryptenroll --recovery-key  /dev/disk/by-partlabel/linux&#xA;🔐 Please enter current passphrase for disk /dev/disk/by-partlabel/linux: &#xA;A secret recovery key has been generated for this volume:&#xA;&#xA;    🔐 efcfbdlt-rhkdjjul-inbhbvhi-nfkvbbbv-didjbjel-butkrrig-ugbrivdd-evnkkkgn&#xA;&#xA;Please save this secret recovery key at a secure location. It may be used to&#xA;regain access to the volume if the other configured access credentials have&#xA;been lost or forgotten. The recovery key may be entered in place of a password&#xA;whenever authentication is requested.&#xA;New recovery key enrolled as key slot 2.&#xA;&#xA;As suggested save this key in a secure location outside of the system. If TPM2 unlocking fails systemd will prompt for a password where you can enter this key.  This lets us access the data even if the TPM2 key became invalid (e.g. when the secure boot configuration changes).&#xA;&#xA;Configure dracut&#xA;&#xA;Force dracut to include the TPM2 software stack, by adding /etc/dracut.conf.d/tpm.conf:&#xA;&#xA;adddracutmodules+=&#34; tpm2-tss &#34;&#xA;And add files dracut currently fails to add, see&#xA;https://github.com/dracutdevs/dracut/issues/1676&#xA;install_items+=&#34; /usr/lib/cryptsetup/libcryptsetup-token-systemd-tpm2.so &#34;&#xA;&#xA;The last line adds necessary cryptsetup plugins which dracut doesn’t yet add (see https://github.com/dracutdevs/dracut/issues/1676).&#xA;&#xA;Make sure to use dracut newer than 055-106-g813577e2; dracut 55 has a typo in the tpm2-tss module dependencies which breaks the module (see https://github.com/dracutdevs/dracut/pull/1526), and another issue with systemd-sysusers which interferes with TPM2 support in early boot (see https://github.com/dracutdevs/dracut/pull/1658).  As of Dec 2021 you’ll need to install dracut-git from AUR.&#xA;&#xA;Reboot and cleanup&#xA;&#xA;Reboot to verify that the system now boots without a LUKS prompt.  Afterwards remove the password key from the rootfs:&#xA;&#xA;$ systemd-cryptenroll --wipe-slot=password /dev/disk/by-partlabel/linux&#xA;&#xA;Now the system only unlocks with the TPM2 key or the recovery key.&#xA;&#xA;Tighten security&#xA;&#xA;Check that&#xA;&#xA;secure boot is enabled (bootctl status or sbctl status),&#xA;secure boot uses custom keys,&#xA;all kernels are signed (sbctl verify; also check the firmware updater and other relevant EFI binaries), and&#xA;no unsigned initramfs or microcode image is used (at best use bundled UEFI executables).&#xA;&#xA;For users consider to use systemd-homed which offers per-user encrypted home “areas”, backed by LUKS encrypted loopback files.&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/unlock-luks-rootfs-with-tpm2-key&#34;Discuss.../a ]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:dracut" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">dracut</span></a> <a href="https://swsnr.writeas.com/tag:luks" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">luks</span></a> <a href="https://swsnr.writeas.com/tag:sbctl" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">sbctl</span></a> <a href="https://swsnr.writeas.com/tag:archlinux" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">archlinux</span></a> <a href="https://swsnr.writeas.com/tag:systemd" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">systemd</span></a> <a href="https://swsnr.writeas.com/tag:secureboot" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">secureboot</span></a></p>

<p><a href="https://remark.as/p/swsnr/unlock-luks-rootfs-with-tpm2-key" rel="nofollow">Discuss...</a></p>

<p>Historically cryptsetup and LUKS only supported good old passwords; however recent systemd versions extend cryptsetup with <a href="https://0pointer.net/blog/unlocking-luks2-volumes-with-tpm2-fido2-pkcs11-security-hardware-on-systemd-248.html" rel="nofollow">additional key types</a> such as FIDO tokens and TPM devices.</p>

<p>I like the idea of encrypting the rootfs with a TPM2 key; it allows booting without ugly LUKS password prompts but still it keeps data encrypted at rest, and when combined with secure boot also still protects the running system against unauthorized access.</p>

<p>Secure boot will prevent others from placing custom kernels on the unencrypted EFI system partition and booting these, or changing the kernel cmdline, in order to obtain root access to the unlocked rootfs.  LUKS encryption with a TPM-based key bound to secure boot state protects the data if someone removes the hard disk and attempts to access it offline, or tries to disable secure boot in order to boot a custom kernel.</p>

<p>I’ve covered <a href="2021-04-01-secure-boot-on-arch-linux-with-sbctl-and-dracut.md" rel="nofollow">secure boot setup in a past article</a>; this article talks about the TPM2-based encryption.</p>



<h2 id="enroll-tpm-key" id="enroll-tpm-key">Enroll TPM key</h2>

<p>Check that the system supports TPM2:</p>

<pre><code class="language-console">$ systemd-cryptenroll --tpm2-device=list
PATH        DEVICE      DRIVER 
/dev/tpmrm0 MSFT0101:00 tpm_crb
</code></pre>

<p>Then enroll a new TPM2 key (use the appropriate block device path of course):</p>

<pre><code class="language-console">$ systemd-cryptenroll --tpm2-device=auto /dev/disk/by-partlabel/linux 
New TPM2 token enrolled as key slot 1.
</code></pre>

<p>Then add recovery key:</p>

<pre><code class="language-console">$ systemd-cryptenroll --recovery-key  /dev/disk/by-partlabel/linux
🔐 Please enter current passphrase for disk /dev/disk/by-partlabel/linux: 
A secret recovery key has been generated for this volume:

    🔐 efcfbdlt-rhkdjjul-inbhbvhi-nfkvbbbv-didjbjel-butkrrig-ugbrivdd-evnkkkgn

Please save this secret recovery key at a secure location. It may be used to
regain access to the volume if the other configured access credentials have
been lost or forgotten. The recovery key may be entered in place of a password
whenever authentication is requested.
New recovery key enrolled as key slot 2.
</code></pre>

<p>As suggested save this key in a secure location outside of the system. If TPM2 unlocking fails systemd will prompt for a password where you can enter this key.  This lets us access the data even if the TPM2 key became invalid (e.g. when the secure boot configuration changes).</p>

<h2 id="configure-dracut" id="configure-dracut">Configure dracut</h2>

<p>Force dracut to include the TPM2 software stack, by adding /etc/dracut.conf.d/tpm.conf:</p>

<pre><code class="language-console">add_dracutmodules+=&#34; tpm2-tss &#34;
# And add files dracut currently fails to add, see
# https://github.com/dracutdevs/dracut/issues/1676
install_items+=&#34; /usr/lib/cryptsetup/libcryptsetup-token-systemd-tpm2.so &#34;
</code></pre>

<p>The last line adds necessary cryptsetup plugins which dracut doesn’t yet add (see <a href="https://github.com/dracutdevs/dracut/issues/1676" rel="nofollow">https://github.com/dracutdevs/dracut/issues/1676</a>).</p>

<p>Make sure to use dracut newer than 055-106-g813577e2; dracut 55 has a typo in the tpm2-tss module dependencies which breaks the module (see <a href="https://github.com/dracutdevs/dracut/pull/1526" rel="nofollow">https://github.com/dracutdevs/dracut/pull/1526</a>), and another issue with systemd-sysusers which interferes with TPM2 support in early boot (see <a href="https://github.com/dracutdevs/dracut/pull/1658" rel="nofollow">https://github.com/dracutdevs/dracut/pull/1658</a>).  As of Dec 2021 you’ll need to install <a href="https://aur.archlinux.org/packages/dracut-git" rel="nofollow">dracut-git from AUR</a>.</p>

<h3 id="reboot-and-cleanup" id="reboot-and-cleanup">Reboot and cleanup</h3>

<p>Reboot to verify that the system now boots without a LUKS prompt.  Afterwards remove the password key from the rootfs:</p>

<pre><code class="language-console">$ systemd-cryptenroll --wipe-slot=password /dev/disk/by-partlabel/linux
</code></pre>

<p>Now the system only unlocks with the TPM2 key or the recovery key.</p>

<h3 id="tighten-security" id="tighten-security">Tighten security</h3>

<p>Check that</p>
<ul><li>secure boot is enabled (<code>bootctl status</code> or <code>sbctl status</code>),</li>
<li>secure boot uses custom keys,</li>
<li>all kernels are signed (<code>sbctl verify</code>; also check the firmware updater and other relevant EFI binaries), and</li>
<li>no unsigned initramfs or microcode image is used (at best use bundled UEFI executables).</li></ul>

<p>For users consider to use systemd-homed which offers per-user encrypted home “areas”, backed by LUKS encrypted loopback files.</p>

<p><a href="https://remark.as/p/swsnr/unlock-luks-rootfs-with-tpm2-key" rel="nofollow">Discuss...</a></p>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/unlock-luks-rootfs-with-tpm2-key</guid>
      <pubDate>Sun, 26 Dec 2021 23:00:00 +0000</pubDate>
    </item>
    <item>
      <title> Secure boot on Arch Linux with sbctl and dracut</title>
      <link>https://swsnr.writeas.com/secure-boot-on-arch-linux-with-sbctl-and-dracut?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[#archlinux #secureboot #dracut #sbctl&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/secure-boot-on-arch-linux-with-sbctl-and-dracut&#34;Discuss.../a &#xA;&#xA;I started playing around with secure boot, with the ultimately goal of setting it up on my laptop. I experimented in a libvirt/qemu VM and to my surprise a custom secure boot setup is rather easy (the Secure Boot page on the Arch Wiki suggests quite the contrary), thanks to dracut and a fairly recent tool named sbctl which just recently had it’s first release.&#xA;&#xA;!--more--&#xA;&#xA;VM Setup&#xA;&#xA;We start with a fresh libvirt VM (you’ll qemu, libvirt, and edk2-ovmf) of a recent Arch Linux ISO using the EFI secure boot firmware provided by the edk2-ovmf package at /usr/share/edk2-ovmf/x64/OVMFCODE.secboot.fd; when using virt-manager be sure to edit the configuration before starting the installation and make sure to select this firmware (otherwise you’ll end up in a BIOS-based VM which doesn’t really get far in terms of secure boot). Go through the standard installation process (I have a custom bootstrap script for a quick fresh Arch install with some standard settings); do make sure to install dracut for initrd and kernel image generation and setup systemd-boot as the EFI bootloader. Install the linux-lts kernel in addition to the standard linux kernel; this allows to leave one kernel unsigned after enabling secure boot to verify that booting the unsigned kernel is really forbidden.&#xA;&#xA;Also build unified images right away with dracut --uefi --kver; together with systemd partition auto-discovery this avoids the need for dedicated boot loader configuration and already prepares for secure boot (which requires unified EFI binaries).&#xA;&#xA;Prerequisites&#xA;&#xA;After rebooting check the secure boot state with bootctl first to make sure that the firmware supports secure boot:&#xA;&#xA;bootctl | head&#xA;System:&#xA;     Firmware: UEFI 2.70 (EDK II 1.00)&#xA;  Secure Boot: disabled&#xA;   Setup Mode: setup&#xA; Boot into FW: supported&#xA;&#xA;Current Boot Loader:&#xA;      Product: systemd-boot 247.4-2-arch&#xA;     Features: ✓ Boot counting&#xA;               ✓ Menu timeout control&#xA;&#xA;Now install sbctl to generate and enroll secure boot keys and sign EFI binaries (pacman -S sbctl); then check how sbctl sees the secure boot state:&#xA;&#xA;sbctl  status&#xA;  WARNING: Setup Mode: Enabled&#xA;  WARNING: Secure Boot: Disabled&#xA;&#xA;Key generation&#xA;&#xA;Now we can generate our set of secure boot keys with sbctl:&#xA;&#xA;sbctl create-keys&#xA;  Creating secure boot keys...&#xA;  -  Created UUID bb88de62-623a-4450-b256-7c9ffc924f64...&#xA;  Create EFI signature list /usr/share/secureboot/keys/PK/PK.der.esl...&#xA;  Signing /usr/share/secureboot/keys/PK/PK.der.esl with /usr/share/secureboot/keys/PK/PK.key...&#xA;  Create EFI signature list /usr/share/secureboot/keys/KEK/KEK.der.esl...&#xA;  Signing /usr/share/secureboot/keys/KEK/KEK.der.esl with /usr/share/secureboot/keys/PK/PK.key...&#xA;  Create EFI signature list /usr/share/secureboot/keys/db/db.der.esl...&#xA;  Signing /usr/share/secureboot/keys/db/db.der.esl with /usr/share/secureboot/keys/KEK/KEK.key...&#xA;&#xA;This command creates all required keys in /usr/share/secureboot; on a physical installation it’s probably very advisable to copy the entire contents of the directory to a secure off-site location for backup.&#xA;&#xA;sbctl verify now lists all EFI binaries as unsigned:&#xA;&#xA;sbctl verify&#xA;  Verifying file database and EFI images in /efi...&#xA;  -  WARNING: /efi/EFI/BOOT/BOOTX64.EFI is not signed&#xA;  -  WARNING: /efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed&#xA;  -  WARNING: /efi/EFI/Linux/linux-5.11.11-arch1-1-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed&#xA;  -  WARNING: /efi/EFI/systemd/systemd-bootx64.efi is not signed&#xA;&#xA;Boot loader signatures&#xA;&#xA;Sign the boot loader first:&#xA;&#xA;sbctl sign -s /efi/EFI/BOOT/BOOTX64.EFI&#xA;  -  Signing /efi/EFI/BOOT/BOOTX64.EFI...&#xA;sbctl sign -s /efi/EFI/systemd/systemd-bootx64.efi&#xA;  -  Signing /efi/EFI/systemd/systemd-bootx64.efi...&#xA;&#xA;Now the boot loader is properly signed:&#xA;&#xA;sbctl verify&#xA;  Verifying file database and EFI images in /efi...&#xA;  -  /efi/EFI/systemd/systemd-bootx64.efi is signed&#xA;  -  /efi/EFI/BOOT/BOOTX64.EFI is signed&#xA;  -  WARNING: /efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed&#xA;  -  WARNING: /efi/EFI/Linux/linux-5.11.11-arch1-1-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed&#xA;&#xA;The -s flag stores these paths in an internal sbctl database which keeps track of files sbsign signed; sbctl uses this database in sbctl sign-all to refresh the signatures of all files it ever signed. This helps with boot loader updates:&#xA;&#xA;bootctl update&#xA;Copied &#34;/usr/lib/systemd/boot/efi/systemd-bootx64.efi&#34; to &#34;/efi/EFI/systemd/systemd-bootx64.efi&#34;.&#xA;Copied &#34;/usr/lib/systemd/boot/efi/systemd-bootx64.efi&#34; to &#34;/efi/EFI/BOOT/BOOTX64.EFI&#34;.&#xA;sbctl verify&#xA;  Verifying file database and EFI images in /efi...&#xA;  -  WARNING: /efi/EFI/BOOT/BOOTX64.EFI is not signed&#xA;  -  WARNING: /efi/EFI/systemd/systemd-bootx64.efi is not signed&#xA;  -  WARNING: /efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed&#xA;  -  WARNING: /efi/EFI/Linux/linux-5.11.11-arch1-1-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed&#xA;sbctl sign-all&#xA;  -  Signing /efi/EFI/systemd/systemd-bootx64.efi...&#xA;  -  Signing /efi/EFI/BOOT/BOOTX64.EFI...&#xA;sbctl verify&#xA;  Verifying file database and EFI images in /efi...&#xA;  -  /efi/EFI/BOOT/BOOTX64.EFI is signed&#xA;  -  /efi/EFI/systemd/systemd-bootx64.efi is signed&#xA;  -  WARNING: /efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed&#xA;  -  WARNING: /efi/EFI/Linux/linux-5.11.11-arch1-1-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed&#xA;&#xA;Signed unified kernel images&#xA;&#xA;To sign the kernel tell dracut about the secure boot keys:&#xA;&#xA;cat   /etc/dracut.conf.d/50-secure-boot.conf &lt;&lt;EOF&#xA;uefisecurebootcert=&#34;/usr/share/secureboot/keys/db/db.pem&#34;&#xA;uefisecurebootkey=&#34;/usr/share/secureboot/keys/db/db.key&#34;&#xA;EOF&#xA;&#xA;While at it also configure a few other non-essential but still very useful dracut options, to silence the boot process and reduce the size of the images:&#xA;&#xA;cat   /etc/dracut.conf.d/40-options.conf &lt;&lt;EOF&#xA;kernelcmdline=&#34;quiet&#34;&#xA;compress=&#34;zstd&#34;&#xA;hostonly=&#34;yes&#34;&#xA;EOF&#xA;&#xA;With secure boot systemd-boot can no longer set a kernel command line: In this mode systemd-boot uses EFI interfaces to start binaries, to avoid bypassing the signature requirement; this interface does not support for kernel command line arguments. For this reason the desired command line as well as all required initrds must be embedded into a single signed EFI binary, and any command line flags like &#34;quiet&#34; must be set through dracut with the kernelcmdline setting.&#xA;&#xA;Now generate a unified UEFI binary for the LTS kernel:&#xA;&#xA;dracut --force --uefi --kver 5.10.27-1-lts&#xA;dracut: Executing: /usr/bin/dracut --force --uefi --kver 5.10.27-1-lts&#xA;…&#xA;dracut:  Creating image file &#39;/efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi&#39; &#xA;dracut: Using UEFI kernel cmdline:&#xA;dracut: quiet&#xA;warning: data remaining[25025536 vs 25035138]: gaps between PE/COFF sections?&#xA;warning: data remaining[25025536 vs 25035144]: gaps between PE/COFF sections?&#xA;Signing Unsigned original image&#xA;dracut:  Creating signed UEFI image file &#39;/efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi&#39; done &#xA;&#xA;Note the last line: dracut bundled everything into a single EFI file and signed it. sbctl verify confirms the new signature:&#xA;&#xA;sbctl verify&#xA;  Verifying file database and EFI images in /efi...&#xA;  -  /efi/EFI/BOOT/BOOTX64.EFI is signed&#xA;  -  /efi/EFI/systemd/systemd-bootx64.efi is signed&#xA;  -  /efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is signed&#xA;&#xA;Secure boot activation&#xA;&#xA;Now enroll the new secure boot keys into the EFI firmware, check that the firmware left secure boot setup mode:&#xA;&#xA;sbctl enroll-keys&#xA;  Syncing /usr/share/secureboot/keys to EFI variables...&#xA;  Synced keys!&#xA;sbctl status&#xA;  Setup Mode: Disabled&#xA;  WARNING: Secure Boot: Disabled&#xA;&#xA;Now enable the boot loader menu to be able to select a kernel at boot and reboot:&#xA;&#xA;echo &#39;timeout 10&#39;     /efi/loader/loader.conf&#xA;reboot&#xA;&#xA;The firmware now prohibits booting the unsigned kernel, but allows the signed kernel:&#xA;&#xA;secureboot with prohibited and permitted binary&#xA;&#xA;Open points&#xA;&#xA;Dracut automates signing kernel images (dracut-hook-uefi automatically invokes dracut when installing or updating kernel images through pacman), but ensuring proper signatures on the bootloader itself even across updates presents an open issue; ideally there should be some way to call sbctl sign-all automatically after bootctl.&#xA;&#xA;sbctl is also a rather new project, which published a first 0.1 only recently; it remains to be seen how sustainable the project is (I dearly hope it is since it provides a huge improvement over the state of the art secure-boot tooling).&#xA;&#xA;a href=&#34;https://remark.as/p/swsnr/secure-boot-on-arch-linux-with-sbctl-and-dracut&#34;Discuss.../a ]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://swsnr.writeas.com/tag:archlinux" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">archlinux</span></a> <a href="https://swsnr.writeas.com/tag:secureboot" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">secureboot</span></a> <a href="https://swsnr.writeas.com/tag:dracut" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">dracut</span></a> <a href="https://swsnr.writeas.com/tag:sbctl" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">sbctl</span></a></p>

<p><a href="https://remark.as/p/swsnr/secure-boot-on-arch-linux-with-sbctl-and-dracut" rel="nofollow">Discuss...</a></p>

<p>I started playing around with secure boot, with the ultimately goal of setting it up on my laptop. I experimented in a libvirt/qemu VM and to my surprise a custom secure boot setup is rather easy (the <a href="https://wiki.archlinux.org/index.php/Unified_Extensible_Firmware_Interface/Secure_Boot#Manual_process" rel="nofollow">Secure Boot</a> page on the Arch Wiki suggests quite the contrary), thanks to dracut and a fairly recent tool named <code>sbctl</code> which just recently had it’s first release.</p>



<h2 id="vm-setup" id="vm-setup">VM Setup</h2>

<p>We start with a fresh libvirt VM (you’ll <code>qemu</code>, <code>libvirt</code>, and <code>edk2-ovmf</code>) of a recent Arch Linux ISO using the EFI secure boot firmware provided by the <code>edk2-ovmf</code> package at <code>/usr/share/edk2-ovmf/x64/OVMF_CODE.secboot.fd</code>; when using virt-manager be sure to edit the configuration before starting the installation and make sure to select this firmware (otherwise you’ll end up in a BIOS-based VM which doesn’t really get far in terms of secure boot). Go through the standard installation process (I have a <a href="https://github.com/lunaryorn/dotfiles/blob/61826f1240901368f9f2432c9a6d892f64bf0099/arch/bootstrap-from-iso.bash" rel="nofollow">custom bootstrap script</a> for a quick fresh Arch install with some standard settings); do make sure to install <code>dracut</code> for initrd and kernel image generation and setup systemd-boot as the EFI bootloader. Install the <code>linux-lts</code> kernel in addition to the standard <code>linux</code> kernel; this allows to leave one kernel unsigned after enabling secure boot to verify that booting the unsigned kernel is really forbidden.</p>

<p>Also build unified images right away with <code>dracut --uefi --kver</code>; together with systemd partition auto-discovery this avoids the need for dedicated boot loader configuration and already prepares for secure boot (which requires unified EFI binaries).</p>

<h2 id="prerequisites" id="prerequisites">Prerequisites</h2>

<p>After rebooting check the secure boot state with <code>bootctl</code> first to make sure that the firmware supports secure boot:</p>

<pre><code class="language-console"># bootctl | head
System:
     Firmware: UEFI 2.70 (EDK II 1.00)
  Secure Boot: disabled
   Setup Mode: setup
 Boot into FW: supported

Current Boot Loader:
      Product: systemd-boot 247.4-2-arch
     Features: ✓ Boot counting
               ✓ Menu timeout control
</code></pre>

<p>Now install <code>sbctl</code> to generate and enroll secure boot keys and sign EFI binaries (<code>pacman -S sbctl</code>); then check how sbctl sees the secure boot state:</p>

<pre><code class="language-console"># sbctl  status
==&gt; WARNING: Setup Mode: Enabled
==&gt; WARNING: Secure Boot: Disabled
</code></pre>

<h2 id="key-generation" id="key-generation">Key generation</h2>

<p>Now we can generate our set of secure boot keys with <code>sbctl</code>:</p>

<pre><code class="language-console"># sbctl create-keys
==&gt; Creating secure boot keys...
  -&gt; Created UUID bb88de62-623a-4450-b256-7c9ffc924f64...
==&gt; Create EFI signature list /usr/share/secureboot/keys/PK/PK.der.esl...
==&gt; Signing /usr/share/secureboot/keys/PK/PK.der.esl with /usr/share/secureboot/keys/PK/PK.key...
==&gt; Create EFI signature list /usr/share/secureboot/keys/KEK/KEK.der.esl...
==&gt; Signing /usr/share/secureboot/keys/KEK/KEK.der.esl with /usr/share/secureboot/keys/PK/PK.key...
==&gt; Create EFI signature list /usr/share/secureboot/keys/db/db.der.esl...
==&gt; Signing /usr/share/secureboot/keys/db/db.der.esl with /usr/share/secureboot/keys/KEK/KEK.key...
</code></pre>

<p>This command creates all required keys in <code>/usr/share/secureboot</code>; on a physical installation it’s probably very advisable to copy the entire contents of the directory to a secure off-site location for backup.</p>

<p><code>sbctl verify</code> now lists all EFI binaries as unsigned:</p>

<pre><code class="language-console"># sbctl verify
==&gt; Verifying file database and EFI images in /efi...
  -&gt; WARNING: /efi/EFI/BOOT/BOOTX64.EFI is not signed
  -&gt; WARNING: /efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed
  -&gt; WARNING: /efi/EFI/Linux/linux-5.11.11-arch1-1-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed
  -&gt; WARNING: /efi/EFI/systemd/systemd-bootx64.efi is not signed
</code></pre>

<h2 id="boot-loader-signatures" id="boot-loader-signatures">Boot loader signatures</h2>

<p>Sign the boot loader first:</p>

<pre><code class="language-console"># sbctl sign -s /efi/EFI/BOOT/BOOTX64.EFI
  -&gt; Signing /efi/EFI/BOOT/BOOTX64.EFI...
# sbctl sign -s /efi/EFI/systemd/systemd-bootx64.efi
  -&gt; Signing /efi/EFI/systemd/systemd-bootx64.efi...
</code></pre>

<p>Now the boot loader is properly signed:</p>

<pre><code class="language-console"># sbctl verify
==&gt; Verifying file database and EFI images in /efi...
  -&gt; /efi/EFI/systemd/systemd-bootx64.efi is signed
  -&gt; /efi/EFI/BOOT/BOOTX64.EFI is signed
  -&gt; WARNING: /efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed
  -&gt; WARNING: /efi/EFI/Linux/linux-5.11.11-arch1-1-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed
</code></pre>

<p>The <code>-s</code> flag stores these paths in an internal <code>sbctl</code> database which keeps track of files <code>sbsign</code> signed; <code>sbctl</code> uses this database in <code>sbctl sign-all</code> to refresh the signatures of all files it ever signed. This helps with boot loader updates:</p>

<pre><code class="language-console"># bootctl update
Copied &#34;/usr/lib/systemd/boot/efi/systemd-bootx64.efi&#34; to &#34;/efi/EFI/systemd/systemd-bootx64.efi&#34;.
Copied &#34;/usr/lib/systemd/boot/efi/systemd-bootx64.efi&#34; to &#34;/efi/EFI/BOOT/BOOTX64.EFI&#34;.
# sbctl verify
==&gt; Verifying file database and EFI images in /efi...
  -&gt; WARNING: /efi/EFI/BOOT/BOOTX64.EFI is not signed
  -&gt; WARNING: /efi/EFI/systemd/systemd-bootx64.efi is not signed
  -&gt; WARNING: /efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed
  -&gt; WARNING: /efi/EFI/Linux/linux-5.11.11-arch1-1-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed
# sbctl sign-all
  -&gt; Signing /efi/EFI/systemd/systemd-bootx64.efi...
  -&gt; Signing /efi/EFI/BOOT/BOOTX64.EFI...
# sbctl verify
==&gt; Verifying file database and EFI images in /efi...
  -&gt; /efi/EFI/BOOT/BOOTX64.EFI is signed
  -&gt; /efi/EFI/systemd/systemd-bootx64.efi is signed
  -&gt; WARNING: /efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed
  -&gt; WARNING: /efi/EFI/Linux/linux-5.11.11-arch1-1-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is not signed
</code></pre>

<h2 id="signed-unified-kernel-images" id="signed-unified-kernel-images">Signed unified kernel images</h2>

<p>To sign the kernel tell dracut about the secure boot keys:</p>

<pre><code class="language-console"># cat &gt; /etc/dracut.conf.d/50-secure-boot.conf &lt;&lt;EOF
uefi_secureboot_cert=&#34;/usr/share/secureboot/keys/db/db.pem&#34;
uefi_secureboot_key=&#34;/usr/share/secureboot/keys/db/db.key&#34;
EOF
</code></pre>

<p>While at it also configure a few other non-essential but still very useful dracut options, to silence the boot process and reduce the size of the images:</p>

<pre><code class="language-console"># cat &gt; /etc/dracut.conf.d/40-options.conf &lt;&lt;EOF
kernel_cmdline=&#34;quiet&#34;
compress=&#34;zstd&#34;
hostonly=&#34;yes&#34;
EOF
</code></pre>

<p>With secure boot systemd-boot can no longer set a kernel command line: In this mode systemd-boot uses EFI interfaces to start binaries, to avoid bypassing the signature requirement; this interface does not support for kernel command line arguments. For this reason the desired command line as well as all required initrds must be embedded into a single signed EFI binary, and any command line flags like “quiet” must be set through dracut with the <code>kernel_cmdline</code> setting.</p>

<p>Now generate a unified UEFI binary for the LTS kernel:</p>

<pre><code class="language-console"># dracut --force --uefi --kver 5.10.27-1-lts
dracut: Executing: /usr/bin/dracut --force --uefi --kver 5.10.27-1-lts
…
dracut: *** Creating image file &#39;/efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi&#39; ***
dracut: Using UEFI kernel cmdline:
dracut: quiet
warning: data remaining[25025536 vs 25035138]: gaps between PE/COFF sections?
warning: data remaining[25025536 vs 25035144]: gaps between PE/COFF sections?
Signing Unsigned original image
dracut: *** Creating signed UEFI image file &#39;/efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi&#39; done ***
</code></pre>

<p>Note the last line: dracut bundled everything into a single EFI file <em>and</em> signed it. <code>sbctl verify</code> confirms the new signature:</p>

<pre><code class="language-console"># sbctl verify
==&gt; Verifying file database and EFI images in /efi...
  -&gt; /efi/EFI/BOOT/BOOTX64.EFI is signed
  -&gt; /efi/EFI/systemd/systemd-bootx64.efi is signed
  -&gt; /efi/EFI/Linux/linux-5.10.27-1-lts-b2f521553ef8449289122ae8d4c2cffe-rolling.efi is signed
</code></pre>

<h2 id="secure-boot-activation" id="secure-boot-activation">Secure boot activation</h2>

<p>Now enroll the new secure boot keys into the EFI firmware, check that the firmware left secure boot setup mode:</p>

<pre><code class="language-console"># sbctl enroll-keys
==&gt; Syncing /usr/share/secureboot/keys to EFI variables...
==&gt; Synced keys!
# sbctl status
==&gt; Setup Mode: Disabled
==&gt; WARNING: Secure Boot: Disabled
</code></pre>

<p>Now enable the boot loader menu to be able to select a kernel at boot and reboot:</p>

<pre><code class="language-console"># echo &#39;timeout 10&#39; &gt;&gt; /efi/loader/loader.conf
# reboot
</code></pre>

<p>The firmware now prohibits booting the unsigned kernel, but allows the signed kernel:</p>

<p><img src="https://i.snap.as/N2JKKj36.webp" alt="secureboot with prohibited and permitted binary"/></p>

<h2 id="open-points" id="open-points">Open points</h2>

<p>Dracut automates signing kernel images (<a href="https://aur.archlinux.org/packages/dracut-hook-uefi" rel="nofollow">dracut-hook-uefi</a> automatically invokes dracut when installing or updating kernel images through pacman), but ensuring proper signatures on the bootloader itself even across updates presents an open issue; ideally there should be some way to call <code>sbctl sign-all</code> automatically after <code>bootctl</code>.</p>

<p><code>sbctl</code> is also a rather new project, which published a first 0.1 only recently; it remains to be seen how sustainable the project is (I dearly hope it is since it provides a huge improvement over the state of the art secure-boot tooling).</p>

<p><a href="https://remark.as/p/swsnr/secure-boot-on-arch-linux-with-sbctl-and-dracut" rel="nofollow">Discuss...</a></p>
]]></content:encoded>
      <guid>https://swsnr.writeas.com/secure-boot-on-arch-linux-with-sbctl-and-dracut</guid>
      <pubDate>Wed, 31 Mar 2021 22:00:00 +0000</pubDate>
    </item>
  </channel>
</rss>