Closed osresearch closed 6 years ago
Post to coreboot mailing list: https://mail.coreboot.org/pipermail/coreboot/2017-April/083963.html
Response is that there is no defined way to do this, so dd
or flashrom
might be the best choice: https://mail.coreboot.org/pipermail/coreboot/2017-April/083967.html
I was thinking about taking a shot at closing this issue. Any preference on the approaches below?
1) A patch to coreboot so that on boot it can extend the initrd/ramdisk area and append the contents of an appropriately-named CBFS cpio file right before running the linux payload (inserted with the standard cbfstool prior to flashing). 2) A patch to cbfstool so that the linux payload can be extracted from a pre-built Heads ROM and the initrd extended with the user-specific files before flashing. 3) Using cbfstool to extract files from ROM after Heads payload has started (seems like it would take up quite a lot of valuable space).
If we went with option 2, it would be possible to have cross-platform binaries (maybe in Go) to customize the Heads ROM (adjust config / add keys / verify initial ROM validity) without needing the end user to compile anything prior to flashing. Maybe it's not worth the effort to replicate the CBFS parsing though.
I'm questioning the need to integrate GPG keys inside of the rom. What if we externalized that dependency into /boot? The actual problem is that this is a chicken egg problem, since we want to flash a rom from an external programmer to safe boot a machine. We ask that user to generate his keys from someone else's machine? That should be done on oneself's machine from reproducible build rom.
This is what I thought and would like your comments.
First boot. Call of seal-tpm.
Other boots
What do you think?
@osresearch ? @flammit ?
Ideally the user's public key would live somewhere in the ROM protected by the WP# and BP bits so that there are hopefully no software attacks to modify it. As you point out, this does require a hardware programmer step to install it.
I'm not sure that I understand the concern with generating the key off-machine. The key that is stored in the ROM is only the public key and for users with hardware tokens like yubikeys, the key can be generated in hardware and never live on any machine. In some extreme threat case, it is potentially unsafe for a user to store their key on the same machine that is validating the signatures.
If you're using dm-verity (which we need to document!), then you need GPG to verify the signature on /
or /boot
. If the key lives on /boot
, then an attacker could swap the key and re-sign the merkle root hash. The totp check could potentially reveal this attack. (A separate issue is that I've had problems with clock sync under qubes4 and my x230's hwclock drifts, so the totp is often stale)
re: time drift - There was a qubes4 bug in the qubes-core-agent-linux
where chronyd wasn't starting due to a missing service setting. It's been fixed and is in current-testing right now, but the short term workaround is: qvm-service -e sys-net ntpd
, restart sys-net, then qvm-sync-clock
in dom0 to immediately fix the drift instead of waiting for cron.
As for the keys, I was also thinking that you'd likely be using a hardware-isolated key to start (such as a yubikey 4). If you flash the unmodified version of Heads (w/ the known good reproducible hash), you can use the Heads recovery shell to generate the key on device and retrieve your public key safely. I also find it useful that the key scheme works now without any local persistent storage (i.e. for external verified USB boot only).
That being said, I agree the current UX is a pain and it'd be nice to be able to "add" your public key to the base Heads rom and reflash - all from the recovery shell.
I'm happy to take a shot at this but would like some feedback on which of the approaches above to take - thoughts @osresearch ?
@osresearch The problem comes when trying to train multiple persons at the same time/more massive deployments. The trainee needs to use trainer's laptop to generate his own rom to have his key included in it or have a copy of his key, which comes with some productivity/trust/privacy issues (typing his yubikey password / need to have another computer with old version of GPG to generate the keys / have them copied to the builder's machine who has to build multiple roms...).
It would be ideal that the trainee/user could validate himself that the rom provided on a usb key is a reproducible rom, and that he could add himself his keys from within heads prior to flashing it, on his computer, not the trainer's, prior to installing Qubes.
The workaround I currently use is to have on trainee's computer reproducible rom flashed, make them install Qubes, restore a backup (debian-9-build template and build-x230 vm) and make them build the reproducible rom themselves and check validity, then make them generate the keys under initrd from Nitrokey/Yubikey, put resulting rom on usb key, and make them flash it themselves on their computer.This is time consuming, and error prone. But with that, they can regenerate rom for updates with their own key in the future from provided build-x230 vm.
@osresearch @flammit : Ideally, those keys should be in a different CBFS partition, and that partition known from flashrom's flash map (option from flashrom-x230.sh for initial flash vs updates) and not overwritten from Heads upgrades. That way, the user could boot from heads with osresearch's key present, generate his own key from yubikey/nitrokey from there and add them to the generic rom previously verified and then flash it.
Heads upgrades could then be available online as reproducible binaries (and/or third parties/organizations), and the user could flash it while keeping his keys untouched.
@osresearch what is the use case scenario with Librem 13 having Heads preinstalled?
@flammit: I would go with option 1, since the CBFS partition could be kept intact after inserting the keys once. That would permit to flash reproducible rom upgrades without needing to reflash that partition.
@flammit @osresearch : which direction have you chose? Have you debated?
Right now the user's GPG key has to be baked into the
initrd.cpio
file along with all of the system utilities. It would be easier to update if it could live in a separate CBFS file in the ROM so that users do not need to rebuild all of Heads.