Skip to content

Draft: Add an ostree secure boot image

Valentin David requested to merge valentindavid/ostree-secure-boot into master

Because OStree needs to pass arguments to the kernel, we have to use PCR 12 on the TPM (as well as PCR 7). But we also need to use a policy OR to be able to allow every command lines in the boot entries (/boot/loader/entries/*.conf).

Note for some weird reason, the command line is in some context logged twice in PCR 7, so we add both expected hashes, one with once logged and one with twice logged. This is normal.

We need to reseal the key every time the boot entries change. This is what reseal.{path,service} do.

That way you cannot change the command line in systemd-boot and expect the root to get decrypted. That is not possible. You need to log as root while secure-booted, add a boot entry and then reboot.

We have to save a blob. For the moment it is saved in /boot/root.key. We could probably embed it in the json of the luks2 header in the future. Because we need /boot in initramfs, we have some udev rules to find it and mount it. Now we use cryptsetup's token API to store the blob in luks header. Now we have a patch for systemd-cryptsetup and systemd-cryptenroll.

We start with a non-encrypted root partition. We leave 32M to be able to convert it to a luks2 volume.

A generator checks if we are booting in secure mode. If so, we change to use the luks filesystem. If a non-encrypted root partition exists, then we encrypt it (encrypt-disk.service).

We need to wait for the TPM to be initialized to start encryption or to open the encrypted device. This is why we tag it with "systemd". Maybe waiting for systemd-udev-settle.service could be enough instead.

systemd-cryptsetup will read socket where we will provide the unsealed key. This is what root-key.{service,socket} do.

OStree does not like not having a separate initrd. It falls back to injecting and init= parameter like if there was no initrd. But we need to have it in the kernel to be signed. For the moment we patch it to disable this fallback.

Note that on the first boot, the root filesystem is not verified with signature. We should do that one day.

/boot uses a detached dm-integrity whose key is stored on the encrypted root disk. That way we can verify no boot entry is ever created offline which could confuse OStree and the resealing.

To build it and run it, you just need to run:

make run-secure-ostree-vm

This needs swtpm and qemu to run. Everything should be needed in builder image since freedesktop-sdk/infrastructure/freedesktop-sdk-docker-images!332 (merged). Just use toolbox.

vm/secure-ostree/image.bst is the image itself.

I have also added vm/keys.bst which creates a simple efi bootable image which registers the boot keys on a machine in setup mode. This is automatically run the VM created by make run-secure-ostree-vm.

This PR also builds OVMF, for 2 reasons. The one provided by QEMU has TPM broken (missing -DTPM2_ENABLE -DTPM1_ENABLE). We also need shell.efi to be bootx64.efi to automatically run the startup.nsh which can poweroff after keys are registered.

Edited by Valentin David

Merge request reports