linuxboot / heads

A minimal Linux that runs as a coreboot or LinuxBoot ROM payload to provide a secure, flexible boot environment for laptops, workstations and servers.
https://osresearch.net/
GNU General Public License v2.0
1.43k stars 187 forks source link

Have qemu boards support writeable pflash and internal flashing #1203

Open tlaurion opened 2 years ago

tlaurion commented 2 years ago

Seems like both qemu and flashrom will need to be patched. Meanwhile, injecting key is made from separate qemu board build statement, and "reflashing" is rebooting qemu/kvm with newer built rom.


Current limitations stated under OP under #1188, where the following traces are what needs to be resolved:

@JonathonHall-Purism : would like to know what is the issue with nvram you were talking about earlier, and also what avenues possible with pflash since from what I've read from libvirt XML and qemu doc, the flash is not writable. Any input you have there would be useful in other open issues

Looks like the size limit is just a matter of changing this default for max_fw_size: https://gitlab.com/qemu-project/qemu/-/blob/master/hw/i386/pc.c#L1833

Re: writable flash, it seems to exist but the only discussion I can find is about people using it incorrectly: https://bugs.launchpad.net/qemu/+bug/1818367/comments/4

The element, with @type='pflash', no other attributes, and then no sibling element either, happens to be valid, but it is an extremely niche use case. It is used when you have a unified, writeable, OVMF.fd file that contains both the firmware executable and the live variable store.

This does sound like what we want, I have no idea right now how this works with plain qemu, whether flashrom supports it, or what it would take to add.

Originally posted by @JonathonHall-Purism in https://github.com/osresearch/heads/issues/1188#issuecomment-1218004671

tlaurion commented 2 years ago

Leaving traces of pertinent mailing list sub threads

tlaurion commented 6 months ago

Track https://github.com/Dasharo/dasharo-issues/issues/828

tlaurion commented 6 months ago

Specifically

As referred by https://github.com/Dasharo/dasharo-issues/issues/828

tlaurion commented 5 months ago
tlaurion commented 1 week ago

Question asked under Dasharo OSFV matrix channel at https://matrix.to/#/!MwWOJhMJzlxIdAQxae:matrix.3mdeb.com/$-G0q4GBkLoQwCk7d1geSf-U74XuqTNwtSb6HT072K-s?via=matrix.org&via=nitro.chat&via=matrix.3mdeb.com:

@krystian-hebel @miczyg1 @macpijan @pietrushnic : as of today, Heads only missing feature for unattended testing, simulating real hardware workflow, is SPI/pflash RW to passed rom image: being able to flashrom/flashprog read/write referred rom image passed to qemu/kvm to get persistence of firmware changes made to cbfs for config store for persistence between reboot and measured boot/part of sealed secrets (TPMTOTP, TPM DUK, config setting changes, boot device etc etc etc).

Can omebody ELI5/TLDR if it would be possible/how complicated it would be to provide qemu R/W access to passed rom image so there is no differences between real hardware operations vs emulated ops?

Ie, from master's

  • ./docker_repro.sh make BOARD=qemu-coreboot-whiptail-tpm2-hotp USB_TOKEN=Nitrokey3NFC
  • ./docker_repro.sh make BOARD=qemu-coreboot-whiptail-tpm2-hotp USB_TOKEN=Nitrokey3NFC run

commands, expending to

!!!!!! Build starts !!!!!!
Makefile:270: warning: overriding recipe for target 'all'
Makefile:251: warning: ignoring old recipe for target 'all'
swtpm socket \
  --tpm2 \
  --tpmstate dir="/home/user/heads/build/x86/qemu-coreboot-whiptail-tpm2-hotp/vtpm" \
  --flags "startup-clear" \
  --terminate \
  --ctrl type=unixio,path="/home/user/heads/build/x86/qemu-coreboot-whiptail-tpm2-hotp/vtpm/sock" &
sleep 0.5
qemu-system-x86_64 -drive file="/home/user/heads/build/x86/qemu-coreboot-whiptail-tpm2-hotp/root.qcow2",if=virtio \
  --machine q35,accel=kvm:tcg \
  -rtc base=utc \
  -smp 1 \
  -vga std \
  -m "$(cat "/home/user/heads/build/x86/qemu-coreboot-whiptail-tpm2-hotp/memory")" \
  -serial stdio \
  --bios "/home/user/heads/build/x86/qemu-coreboot-whiptail-tpm2-hotp/heads-qemu-coreboot-whiptail-tpm2-hotp-v0.2.0-2440-gff307d4.rom" \
  -object rng-random,filename=/dev/urandom,id=rng0 \
  -device virtio-rng-pci,rng=rng0 \
  -netdev user,id=u1 -device e1000,netdev=u1 \
  -chardev socket,id=chrtpm,path="/home/user/heads/build/x86/qemu-coreboot-whiptail-tpm2-hotp/vtpm/sock" \
  -tpmdev emulator,id=tpm0,chardev=chrtpm \
  -device tpm-tis,tpmdev=tpm0 \
  -device qemu-xhci,id=usb \
  -device usb-tablet \
  -drive file="/home/user/heads/build/x86/qemu-coreboot-whiptail-tpm2-hotp/usb_fd.raw",if=none,id=usb-fd-drive,format=raw \
  -device usb-storage,bus=usb.0,drive=usb-fd-drive \
  -device usb-host,vendorid=8352,productid=17074 \

automated testing still requires following targets/qemu.md workarounds because no SPI flash from within Heads to inject generated keyring, trustdb and config.user which normally would be injected into cbfs. Therefore, qemu.md instructs to

  • mount qemu's emulated thumb drive usb_fd.raw to get pubkey, and as opposed to real hardware which keeps trustdb/keyring persistently, asks dev/automated testing to inject the key manually (which injection creates unique trustdb/keyring per pubkey injection)
  • asks dev to ./docker_repro.sh make BOARD=qemu-coreboot-whiptail-tpm2-hotp PUBKEY_ASC=exported_emulated_thumbdrive_pubkey.asc inject_gpg which creates a rom with host created trustdb/keyring (and no config.user persistence of config)
  • asks dev to finally run ./docker_repro.sh make BOARD=qemu-coreboot-whiptail-tpm2-hotp PUBKEY_ASC=exported_emulated_thumbdrive_pubkey.asc run

To simulate a whole real hardware workflow... If there was support for pflash rw, then emulated vs real hardware workflow would be exactly the same.

Thoughts? That would resolve https://github.com/linuxboot/heads/issues/1203

tlaurion commented 1 week ago

Of course, changes to qemu would need to be merged inside of nix, and then flake.lock under Heads using this new built qemu, included under nix based created docker images under Heads.

When Heads needed canokey support built it under nix by default:

Leading to PR merging collaboration work, changing flake.lock and flake.nix to point to new qemu_full on which Heads docker image build atop of nix under https://github.com/linuxboot/heads/pull/1687