Update 2015-11-25: with "ask-password" caching implemented as of systemd-227
(2015-10-07), better way would be to use that in-kernel caching, though likely
requires systemd running in initramfs (e.g. dracut had that for a while).
Up until now I've used lvm on top of single full-disk dm-crypt partition.
It seems easiest to work with - no need to decrypt individual lv's, no
confusion between what's encrypted (everything but /boot!) and what's not, etc.
Main problem with it though is that it's harder to have non-encrypted parts,
everything is encrypted with the same keys (unless there're several dm-crypt
layers) and it's bad for SSD - dm-crypt still (as of 3.0) doesn't pass any
TRIM requests through, leading to nasty
write amplification effect, even more so with full
disk given to dm-crypt+lvm.
While there's hope that SSD issues
will be kinda-solved
(with an optional security trade-off) in 3.1, it's still much easier to keep
different distros or some decrypted-when-needed partitions with dm-crypt after
lvm, so I've decided to go with the latter for new 120G SSD.
Also, such scheme allows to re-create encrypted lvs, issuing TRIM for the old
ones, thus recycling the blocks even w/o support for this in dm-crypt.
Same as with
previous initramfs,
I've had simple "openct" module (udev there makes it even easier) in
dracut to find inserted smartcard
and use it to obtain encryption key, which is used once to decrypt the only
partition on which everything resides.
Since the only goal of dracut is to find root and get-the-hell-outta-the-way,
it won't even try to decrypt all the /var and /home stuff without serious
ideological changes.
The problem is actually solved in generic distros by
plymouth, which gets the
password(s), caches it, and provides it to dracut and systemd (or whatever
comes as the real "init"). I don't need splash, and actually hate it for
hiding all the info that scrolls in it's place, so plymouth is a no-go for me.
Having a hack to obtain and cache key for dracut by non-conventional means
anyway, I just needed to pass it further to systemd, and since they share common
/run tmpfs these days, it basically means not to rm it in dracut after use.
Luckily, system-wide password handling mechanism in systemd is well-documented and easily
extensible beyond plymouth and default console prompt.
So whole key management in my system goes like this now:
- dracut.cmdline: create udev rule to generate key.
- dracut.udev.openct: find smartcard, run rule to generate and cache
key in /run/initramfs.
- dracut.udev.crypt: check for cached key or prompt for it (caching
result), decrypt root, run systemd.
- systemd: start post-dracut-crypt.path unit to monitor
/run/systemd/ask-password for password prompts, along with default
.path units for fallback prompts via wall/console.
- systemd.udev: discover encrypted devices, create key requests.
- systemd.post-dracut-crypt.path: start post-dracut-crypt.service to
read cached passwords from /run/initramfs and use these to satisfy
requests.
- systemd.post-dracut-crypt-cleanup.service (after local-fs.target is
activated): stop post-dracut-crypt.service, flush caches, generate
new one-time keys for decrypted partitions.
End result is passwordless boot with this new layout, which seem to be only
possible to spoof by getting root during that process somehow, with altering
unencrypted /boot to run some extra code and revert it back being the most
obvious possibility.
It's kinda weird that there doesn't seem to be any caching in place already,
surely not everyone with dm-crypt are using plymouth?
Most complicated piece here is probably the password agent (in python), which
can actually could've been simpler if I haven't followed the proper guidelines and thought
a bit around them.
For example, whole inotify handling thing (I've used it via
ctypes) can be dropped with .path unit
with DirectoryNotEmpty= activation condition - it's there already,
PolicyKit authorization just isn't working
at such an early stage, there doesn't seem to be much need to check request
validity since sending replies to sockets is racy anyway, etc
Still, a good excercise.
Python password agent for systemd.
Unit files to start
and stop it on demand.