Subject: bug#45512: Feature Request: keyfile support for LUKS volume opening

From: raid5atemyhomework <[email-masked]>
Date: Mon, 28 Dec 2020 17:12:59 +0000

Consider the following use-case:

* I have a boot device including a partition backing `/`.
* My `/home` is on a separate RAID array, because my homework is important and I would like to not lose it.
* Each disk in the RAID array is *separately* LUKS-encrypted.
  * This allows me to decommission any disk in the array by destroying its LUKS header with `cryptsetup erase` on the decommissioned disk.
  * While I could instead encrypt the RAID block device, if I decommission one of the members of the array, it might contain the LUKS header for the encrypted device, and I am not confident that my passphrase "RAID5 is not a good dog" is not known by anyone else.
    I also cannot `cryptsetup erase` the RAID block device as that would destroy all the data in the entire array.
  * For example, my classmates want to copy my homework, so if for example one of the disks starts having trouble and I decide to send it back to the seller for a replacement, my classmates might intercept the disk in the hope of copying my homework.

Unfortunately, if I have several disks in my RAID array, then boot would be painful as I would need to enter my passphrase for each disk in the array.

In this case, I would appreciate instead using a keyfile.

* I *also* encrypt my `/` root partition.
  * I use my passphrase "RAID5 is not a good dog" for this partition.
* In the `/root` directory, I generate a keyfile by `dd if=/dev/random bs=32 of=/root/keyfile`.
* I individually LUKS-encrypt each disk in the array using the keyfile `/root/keyfile`.

Then, on boot:

* I `cryptsetup` my `/` root partition and enter my passphrase.
* I mount `/`.
* Each of my RAID disks is then opened by `cryptsetup` but specifying a `--key-file` as `/root/keyfile`.
* I assemble my array and open the LVM container on top and mount my `/home`.

This means that at boot, I just input a passphrase once, and this decrypts a keyfile that can be used to open all the other LUKS devies on my system.

This is a important use-case:

* If I LUKS-encrypted my `/home` only, I run the risk that the LUKS header is on a disk that I am decommissioning.
  Then, a classmate with possession of my passphrase "RAID5 is not a good dog" and who intercepts the decommissioned disk may be able to recover part of my precious homework and submit it to my professor and get good grades.
* If instead I have a keyfile on my encrypted partition, my classmate not only needs to know my passphrase "RAID5 is not a good dog" and have intercepted the decommissioned disk, they *also* have to gain access to my boot disk, which is safely inside my computer tower.
* Because the keyfile is stored only on the `/root` directory, I can easily destroy all my data (in case my classmates try to get at my actual computer tower) by doing a `cryptsetup erase` on the root partition.

It also allows other use-cases:

* If I am using HDDs in the RAID array, I might get tired of the low speed, so I might decide to use a `bcache` or `dm-cache` with an SSD cache to speed up my array.
  * The cache SSD must also be encrypted, otherwise if I decommission my SSD cache device then it might contain my precious homework in unencrypted form.
    With a keyfile stored on an encrypted root partition, I can encrypt my SSD cache without adding yet another passphrase to enter during boot.

It seems to me that this model where the only device with a LUKS keyslot containing a pasphrase would be the root partition, and all other encrypted devices use a keyfile on the root partition, is generally a good basis for ensuring that my data is difficult for somebody else to access even as I upgrade my system.

There is of course the risk that the device with the root partition fails and thus accidentally destroy all my data, thus reducing my reliability, but I could `xxd /root/keyfile`, write down the hexdump on a piece of paper, then store that piece of paper in the same facility where I store all my gold bullion.
Similarly I could instead use a keyfile generated from a dozen words from `/etc/dictionaries-common/words`, which would be easier to store on paper.

To implement this, there is some overlap with https://issues.guix.gnu.org/45497
Basically, we need as well an `arguments` field in `mapped-device` records, where we can add `#:key-file` for LUKS mapped devices.

Another is that we also need to have `dependencies` for `mapped-device`s, not just for `file-system`s.
Crucially, a `mapped-device` might depend on a `file-system` --- in this case, a LUKS-encrypted container that uses a keyfile must wait for the filesystem that contains the keyfile to get mounted.
In particular, I notice that existing `mapped-device-kind`s have ad hoc "wait for sources to come online" waitloops, when we should instead be using proper Shepherd `requirement` specifications.

A complication here is that I am uncertain how Guix handles the root filesystem from the `initrd`.