Morten Linderud

F/OSS Developer, Arch Linux Developer and security team.

github mastodon twitter email
Simplifying and securing the boot process
Apr 1, 2021
4 minutes read

One of the few things I have been excited about the past year is usable cryptography. We have a lot of neat things these days with hardware tokens, the Trusted Platform Module (TPM) and Secure Boot. But the tooling around these things are bad and hard to use for a while now which is why I got super excited when I saw Lennart Poettering wrote about the upcoming systemd-cryptenroll. It allows one to easily utilize the TPM or FIDO key for unlocking your encrypted partition.

At this point I realized I’m still using a busybox initramfs. mkinitcpio is what Arch Linux uses to create initramfs and it supports two sets of hooks currently which is the “busybox” hooks and the “systemd” hooks. By default the busybox hooks are used and users needs to be over to the systemd ones if they want to.

At this point I also learned that GPT UUIDs, which denotes the partition type, is not only for show. systemd is capable of mounting several partitions solely based on the UUID using the “Discoverable Partitions” specification. Which is pretty neat!

Thus we have the list of goals to modernize my boot process:

  • Use systemd initramfs
  • EFI System Partition with only UEFI stubs (I’ll explain this!)
  • Remove all UUIDs from fstab and kernel parameters
  • Optional:
    • Secure the boot with secure boot
    • Unlock partition hardware key

Current Setup

My current setup is fairly basic I believe. It’s a laptop with two partitions. One is the EFI system partition (ESP), mounted to /boot, and the other is an LUKS encrypted partition formatted with btrfs for /. A few subvolumes for snapper snapshots and the swapfile, but nothing else really.

λ ~ » tree -L 1 /var/btrfs
/var/btrfs
├── @home
├── @home-snapshots
├── @root
├── @root-snapshots
└── @swapfile

λ ~ » tree /boot
/boot
├── EFI
│   ├── arch
│   │   └── fwupdx64.efi
│   ├── BOOT
│   │   └── BOOTX64.EFI
│   └── systemd
│       └── systemd-bootx64.efi
├── loader
│   ├── entries
│   │   └── arch.conf
│   ├── loader.conf
│   └── random-seed
├── intel-ucode.img
├── initramfs-linux.img
├── initramfs-linux-lts.img
├── vmlinuz-linux
└── vmlinuz-linux-lts

λ ~ » cat /boot/loader/entries/arch.conf 
title   Arch Linux
linux   /vmlinuz-linux
initrd  /intel-ucode.img
initrd  /initramfs-linux.img
options root=UUID=67c1a020-ed36-49d5-9e53-f239ee452120 \
        cryptdevice=UUID=a356ac71-8f26-452c-a100-588d4e59bd19:root \
        rootflags=subvol=@root rw quiet
(Note: You probably need to drop the newlines, It’s just easier to read)

The systemd-boot entry is also fairly basic. Point at cryptdevice UUID for unlocking the root partition. The rootflags point at the root subvolme in btrfs. There is not a lot to this setup which is special.

mkinicpio and systemd

First on our agenda is to move from the busybox initramfs to the systemd one. This is the main

Old hooks

HOOKS=(base udev autodetect modconf block keymap encrypt filesystems keyboard btrfs)

New hooks

HOOKS=(systemd autodetect modconf block keyboard sd-encrypt filesystems)

Todo list

  • Use systemd initrd
  • Remove UUIDs from any boot stuff
  • UEFI Executable with sd-boot stub
  • (Optional)
  • Use fido tokens
  • Secure Boot

Change the GPT UUID

$ gdisk /dev/nvme0n1 
GPT fdisk (gdisk) version 1.0.7

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): t
Partition number (1-2): 2
Current type is 8304 (Linux x86-64 root (/))
Hex code or GUID (L to show codes, Enter = 8304): 8304 // <- note the number
Changed type of partition to 'Linux x86-64 root (/)'

Command (? for help): w // write the table
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Command (? for help): i
Partition number (1-2): 2
Partition GUID code: 4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709 (Linux x86-64 root (/))
Partition unique GUID: 44C302FB-1AE1-49B5-9C78-484B7BAFDE6C
First sector: 1050624 (at 513.0 MiB)
Last sector: 1000215182 (at 476.9 GiB)
Partition size: 999164559 sectors (476.4 GiB)
Attribute flags: 0000000000000000
Partition name: 'Linux x86-64 root (/)'
$ cat /etc/fstab
/dev/mapper/root	/					btrfs		rw,noatime,compress=lzo,subvol=@root				0 0

# /dev/mapper/lvm
/dev/mapper/root	/.snapshots			btrfs		rw,noatime,compress=lzo,subvol=@root-snapshots		0 0

# /dev/mapper/lvm
/dev/mapper/root	/home				btrfs		rw,noatime,compress=lzo,subvol=/@home,subvol=@home	0 0

# /dev/mapper/lvm
/dev/mapper/root	/home/.snapshots	btrfs		rw,noatime,compress=lzo,subvol=@home-snapshots		0 0

# /dev/mapper/lvm
/dev/mapper/root  /var/swap  btrfs  rw,noatime,compress=lzo,subvol=@swapfile  0 0
$ cat /etc/kernel/cmdline.systemd 
rw quiet acpi_osi= acpi_backlight=thinkpad_screen nowatchdog bgrt_disable
$ systemd-cryptenroll --fido2-device=auto /dev/nvme0n1p2
🔐 Please enter current passphrase for disk /dev/nvme0n1p2: *****************
Initializing FIDO2 credential on security token.
👆 (Hint: This might require verification of user presence on security token.)
Generating secret key on FIDO2 security token.
👆 In order to allow secret key generation, please verify presence on security token.
New FIDO2 token enrolled as key slot 1.
  • Usecase
  • systemd-crypsetup
  • fido tokens
  • Optional: TPM2
  • UEFI Executables
  • Simplifying boot
    • GPT UUIDs

http://0pointer.net/blog/unlocking-luks2-volumes-with-tpm2-fido2-pkcs11-security-hardware-on-systemd-248.html

The bad :c

No 2FA. Only TPM2 and/or FIDO2. Mention PIN


Back to posts