random-archer / mkinitcpio-systemd-tool

Provisioning tool for systemd in initramfs (systemd-tool)
https://www.archlinux.org/packages/community/any/mkinitcpio-systemd-tool/
Other
112 stars 27 forks source link

Unlocking SED drives #88

Closed Tronic closed 2 years ago

Tronic commented 2 years ago

Self-encrypting SSDs can be unlocked by sedutil or by sed-opal-unlocker programs within initramfs, avoiding an extra reboot after unlocking the system drive.

I am trying the adapt the existing initrd-shell and cryptsetup scripts for this but they are HEAVY. A lot of unit files and shell scripts, so I cannot quite grasp how all that works together yet.

I need a password prompt and then I will run a few commands using the password given to unlock the drives, a partprobe to rescan them and then systemd should resume with normal mounting of rootfs, finding swap partitions and all that. So far I have ssh working and it offers the option "secret agent" but that appears to be doing nothing (presumably because I don't have cryptsetup drives). I can enter my commands on the shell to unlock manually.

Ideally this would also work on local console with or without Plymouth but currently I get no login session or password prompt locally, not until rootfs mount timeouts and systemd offers an emergency shell.

How should I approach the problem of implementing this, with minimal extra work required?

Andrei-Pozolotin commented 2 years ago

1) you can start by inserting a new menu entry https://github.com/random-archer/mkinitcpio-systemd-tool/blob/master/src/initrd-shell.sh#L291 which would call your sedutil specific function, which, upon success, should transfer control to secret agent to continue unlocking cryptsetup drives inside the now open ssd

2) you would also need to create a resource systemd unit file similar to https://github.com/random-archer/mkinitcpio-systemd-tool/blob/master/src/initrd-shell.service which brings files, folders, binaries into initrd image build

Tronic commented 2 years ago

Thanks for your pointers. I will see about adding that menu entry.

Point 2 I already implemented, the module also uses ExecStart=unlock.sh like this to handle the local console, and the same script can be run over ssh too of course:

#!/bin/sh
PASSWORD=$(systemd-ask-password)
sedutil-cli --setLockingRange 1 RW $PASSWORD /dev/nvme0
sedutil-cli --setLockingRange 1 RW $PASSWORD /dev/nvme1
mdadm --assemble RootRaid /dev/nvme0n1p2 /dev/nvme1n1p2

LockingRange 1 covers everything of the drives, except for the GPTs and the EFI system partition, so prior to unlocking the kernel gets I/O errors when it tries to probe other partitions.

Ideally partprobe would be used instead of manually assembling the RAID, but for some reason running it within initramfs does not cause arrays to be redetected (and presumably doesn't trigger a re-read of filesystem UUIDs of any unlocked partitions). Perhaps this is because I don't have udev (on initramfs), because a plain partprobe works if I boot into a Linux live distro to do the unlocking.

This script gets the job done but it is ugly, I would prefer something reusable worth of releasing. Right after the array is started systemd figures it out and continues normal boot, shutting down any initrd shells (either local or ssh) that were open and perhaps waiting for password input.

I see some complex logic for choosing the right password agent in initrd-shell. Perhaps a better one is available than the plain systemd-ask-password (the output of this gets overrun by other systemd messages). I should look into secret agent.

Tronic commented 2 years ago

initrd-cryptsetup works smarter, because systemd somehow triggers it when needed and it cannot be enabled manually. Something like this would be good but I have no idea of how that works.

Andrei-Pozolotin commented 2 years ago

it seems eventually systemd will support sedutil https://github.com/systemd/systemd/issues/16089

meanwhile you could ask sedutil people for better ideas https://gitter.im/sedutil/sedutil?source=orgpage