Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ivy/sandy/haswell platform locking (SMI finalizing chipset : io386 refresh for maximized boards) #1373

Merged
merged 6 commits into from
Jun 21, 2023

Conversation

tlaurion
Copy link
Collaborator

@tlaurion tlaurion commented Apr 12, 2023

Edit: see #1373 (comment) to deactivate the feature on a single boot session


On chipsets preceding skylake, coreboot can prepare platform locking but let the payload (here Heads) finalize the lockdown (PR0 locked by SMI; also called SMM write Protection) instead of coreboot locking it by itself. This is what this PR is doing for in-tree supported maximized platforms (Haswell, Ivy/Sandy bridge).

Consequently, Heads becomes the only internal programmer (payload) being able to write to SPI (to update whole spi images).

Eventually Heads will also implement authentication prior of permitting to write to SPI. Unsafe boot options or access recovery shell. This is the first step in that direction. And the lowest hanging fruit torward increased security preventing OS to write to firmware.


Based on #326 PR and discussions and adapted to apply chipset locking prior of final kexec call. Also provides coreboot configs and board configs enabling the feature by default for current maximized boards under master.

Also pins io386 module to current latest commit so that firmware image is not impacted by reproducibility issues in the future.

Local build hash and CircleCi hashes matches for io386 (from hashes.txt output in artifacts of CircleCI as well):
949308795c0446fe847bfab5ad67da305c46676a5bc49c170629fcdf5717bb38 ./bin/io386
for io386 module pinned commit 874898af57d86dc057cea39b4a7e0621fc64aa4fb777dfb1eeb11e9134bc9a06 built to be optimized for size and stripped before being injected in tools.cpio (and packed under initrd.cpio.xz and stitched into coreboot as part of its payload).

Also enables to toggle the protection off for single boot (and flash for permanence if really desired), through Change Comfiguration Settings menu, see below for screenshots.

"Finalizing chipset" should always be seen provious of a kexec call.


Tested (board owners pinged directly from #692 willing testers) with testcase #1373 (comment)


TODO:
Skylake and newer have been tweaked to be able to do the same but it seems that upstreaming the changes to coreboot has not happened yet but had for older platforms. More info for coreboot devels to jump in from vaultboot fork for their x11 platform patch on unknown coreboot git commit

@tlaurion tlaurion marked this pull request as draft April 12, 2023 20:31
modules/io386 Show resolved Hide resolved
modules/io386 Show resolved Hide resolved
On some newer platforms of intel (confirmed on nehalem, sandy/ivy
bridge), coreboot after commit [2ac149d294af795710eb4bb20f093e9920604abd](https://review.coreboot.org/cgit/coreboot.git/commit/?id=2ac149d294af795710eb4bb20f093e9920604abd)
registers an SMI to lockdown some registers on the chipset, as well
as access to the SPI flash, optionally. The SMI will always be triggered
by coreboot during S3 resume, but can be triggered by either coreboot
or the payload during normal boot path.

Enabling lockdown access to SPI flash will effectly write-protect it,
but there is no runtime option for coreboot to control it, so letting
coreboot to trigger such SMI will leave the owner of the machine lost
any possibility to program the SPI flash with its own OS, and becomes
a nightmare if the machine is uneasy to disassemble, so a scheme could
be implement, in which the SMI to lockdown chipset and SPI flash is left
for a payload to trigger, and temporarily disabling such triggering in
order to program the SPI flash needs authentication.

I have implemented a passcode-protected runtime-disableable lockdown
with grub, described [here](https://github.com/hardenedlinux/Debian-GNU-Linux-Profiles/blob/master/docs/hardened_boot/grub-for-coreboot.md#update-for-coreboot-after-commit-2ac149d294af795710eb4bb20f093e9920604abd). In order to implement a similar scheme for
Heads, I wrote [io386](https://github.com/hardenedlinux/io386).

With this commit, io386 will be called before entering boot routine
to trigger the SMI to finalize the chipset and write protect the SPI
flash at the same time. Entering recovery shell will leave the flash
writable.

(The authentication routine implemented in previous revisions has been
split as an independent commit.)

Originally proposed under PR#326
@tlaurion
Copy link
Collaborator Author

tlaurion commented Jun 12, 2023

Simple testcase from a current flashed maximized rom.

  • Go to recovery shell do not seal secret or do anything else.
  • mount-usb rw to mount usb thumb drive partition in read write mode.
  • flashrom -p internal -r /media/backup.rom to take full backup we will attempt to flash back to later on
  • umount /media to sync write cache to usb thumb drive
  • flash-gui.sh to select downloaded rom with matching commit id above (ga00a8be).
  • reboot when successful
  • from recovery shell, run lock_chip
  • flashrom -p internal -w /media/backup.rom will show flashrom failing to write to SPI, since chipset lockdown has been finalized through io386 call.
    signal-2023-06-12-133002
  • Reboot, go to recovery shell.
  • mount-usb (only read only mode, as default)
  • flashrom -p internal -w /media/backup.rom see it succeeds restoring your backup, since lock_chip has not finalized chipset lockdown

Alternatively, you can boot in unsafe mode and see "Finalize chipset" just before the final kexec call to OS and fiddle around trying to write to SPI with iomem=relaxed present in grub/isolinux config and also see it fail. Only Heads can write to SPI when with io386 finalizing chipset lockdown.

@tlaurion tlaurion marked this pull request as ready for review June 12, 2023 19:17
@tlaurion
Copy link
Collaborator Author

tlaurion commented Jun 12, 2023

Inclusion of io386 binary increased payload footprint compared to master from

FMAP REGION: COREBOOT
Name                           Offset     Type           Size   Comp
cbfs_master_header             0x0        cbfs header        32 none
fallback/romstage              0x80       stage           84776 none
cpu_microcode_blob.bin         0x14c40    microcode       26624 none
fallback/ramstage              0x1b480    stage          105555 LZMA (232580 decompressed)
config                         0x35140    raw              2994 LZMA (9494 decompressed)
revision                       0x35d40    raw               724 none
build_info                     0x36040    raw               101 none
fallback/dsdt.aml              0x36100    raw             14522 none
vbt.bin                        0x39a00    raw              1433 LZMA (4281 decompressed)
cmos_layout.bin                0x3a000    cmos_layout      2012 none
fallback/postcar               0x3a840    stage           29972 none
fallback/payload               0x41dc0    simple elf    7147522 none
(empty)                        0x712e00   null          4941988 none
bootblock                      0xbc96c0   bootblock       26368 none
2023-06-09 17:45:04-04:00 INSTALL   build/x86/coreboot-4.19/x230-hotp-maximized/coreboot.rom => build/x86/x230-hotp-maximized/heads-x230-hotp-maximized-v0.2.0-1564-g3b3c49b.rom

to:

FMAP REGION: COREBOOT
Name                           Offset     Type           Size   Comp
cbfs_master_header             0x0        cbfs header        32 none
fallback/romstage              0x80       stage           84776 none
cpu_microcode_blob.bin         0x14c40    microcode       26624 none
fallback/ramstage              0x1b480    stage          106017 LZMA (233668 decompressed)
config                         0x35300    raw              3013 LZMA (9544 decompressed)
revision                       0x35f00    raw               724 none
build_info                     0x36200    raw               101 none
fallback/dsdt.aml              0x362c0    raw             14522 none
vbt.bin                        0x39bc0    raw              1433 LZMA (4281 decompressed)
cmos_layout.bin                0x3a1c0    cmos_layout      2012 none
fallback/postcar               0x3aa00    stage           29972 none
fallback/payload               0x41f80    simple elf    7148034 none
(empty)                        0x7131c0   null          4941028 none
bootblock                      0xbc96c0   bootblock       26368 none
2023-06-12 14:32:57-04:00 INSTALL   build/x86/coreboot-4.19/x230-hotp-maximized/coreboot.rom => build/x86/x230-hotp-maximized/heads-x230-hotp-maximized-v0.2.0-1568-ga00a8be.rom

For a total increase in payload size of:
7147522-7148034=512 bytes.

@nestire
Copy link
Contributor

nestire commented Jun 14, 2023

tested t430-maximized works as described in the testcase

@tlaurion
Copy link
Collaborator Author

Sorry to ping you again, but those are the ones needing at least on confirmation since other chipset:

  • one sandy bridge supported (x220,t440, etc)
  • one haswell (t440p)
  • p877z-m_pro is an ivy bridge @ThePlexus ? Would be nice that it is documented as such, would need to be tested here.

@alexmaloteaux @natterangell @akfhasodh @doob85 @Thrilleratplay @BlackMaria @srgrint @ThePlexus @srgrint @akunterkontrolle @rbreslow : please test!

@natterangell
Copy link
Contributor

Hi,

Before I test this, I should mention I use an Ivy Bridge CPU in my T420, even though it shipped with Sandy Bridge. Coreboot supports this. Will chipset locking be a problem? I won't be able to refresh externally at the moment, so I'd rather nok bork the machine.

@tlaurion
Copy link
Collaborator Author

tlaurion commented Jun 14, 2023

I should mention I use an Ivy Bridge CPU in my T420, even though it shipped with Sandy Bridge. Coreboot supports this.

Should not be a problem, my understanding is that coreboot platform locking works on Intel chipsets prior of skylake out of the box. This is what we test here.

You will see if flashrom works when its not supposed to. @natterangell please let us know!

@srgrint
Copy link
Contributor

srgrint commented Jun 15, 2023

I have tested with my t440P and it works as expected

@srgrint
Copy link
Contributor

srgrint commented Jun 15, 2023

I have also now tested my x220 which also works fine

@tlaurion
Copy link
Collaborator Author

tlaurion commented Jun 16, 2023

@ThePlexus can you test and report for untested platform? We could then merge, xx20/xx30/haswell having been reported working for this PR.

@3hhh
Copy link
Contributor

3hhh commented Jun 16, 2023

IMO it should be possible for the user to disable this one.

It might be worth thinking about a central configuration store for heads.
E.g. one could verify it from /boot/ in a way similar to the kernel command line and load the config, if it succeeds to verify, use reasonable defaults otherwise.

Alternatively make it possible to disable it at build time via some switch.

@tlaurion
Copy link
Collaborator Author

IMO it should be possible for the user to disable this one.

It might be worth thinking about a central configuration store for heads. E.g. one could verify it from /boot/ in a way similar to the kernel command line and load the config, if it succeeds to verify, use reasonable defaults otherwise.

Alternatively make it possible to disable it at build time via some switch.

I like the idea, which would open the door for runtime switches. While undocumented, here are the current exports that lands currently under /etc/config:

user@heads-tests-deb12:~/heads$ grep -R export boards/ | awk -F ":" {'print $2'}| awk -F "=" {'print $1'}| grep -v "^#" | sort | uniq
export CONFIG_AUTO_BOOT_TIMEOUT
export CONFIG_BOARD_NAME
export CONFIG_BOOT_DEV
export CONFIG_BOOT_EXTRA_TTYS
export CONFIG_BOOT_KERNEL_ADD
export CONFIG_BOOT_KERNEL_REMOVE
export CONFIG_BOOT_RECOVERY_SERIAL
export CONFIG_BOOT_REQ_HASH
export CONFIG_BOOT_REQ_ROLLBACK
export CONFIG_BOOTSCRIPT
export CONFIG_BOOTSCRIPT_NETWORK
export CONFIG_BOOT_STATIC_IP
export CONFIG_COREBOOT
export CONFIG_COREBOOT_VERSION
export CONFIG_DEBUG_OUTPUT
export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT
export CONFIG_FLASHROM_OPTIONS
export CONFIG_LINUXBOOT
export CONFIG_LINUX_USB_COMPANION_CONTROLLER
export CONFIG_LINUX_VERSION
export CONFIG_PRIMARY_KEY_TYPE
export CONFIG_PURISM_BLOBS
export CONFIG_TPM
export CONFIG_TPM2_CAPTURE_PCAP
export CONFIG_TPM2_TOOLS
export CONFIG_TPM_NO_LUKS_DISK_UNLOCK
export CONFIG_USB_BOOT_DEV
export CONFIG_USB_KEYBOARD
export CONFIG_USE_AGETTY
export CONFIG_ZERO_IFD_VSCC

The original PR was looking for CONFIG_IO386, where current check in kexec-boot checks for presence of io386 binary packed under initrd, present at runtime. It would be easy to go into that direction with this PR, and document in a central way where and how to do this somehow maually at first and through a basic UI later on based on documented exports. At the end of the day, this is what the config-gui.sh is doing today: merge /etc/config with runtime /etc/config.user and save them in SPI through cbfs files, and hve them measured as part of measured boot Heads stuff before being used in policies.

I think this would deserve another issue to discuss implementation.

I would be ok introducing CONFIG_FINALIZE_PLATFORM_LOCKING_PRE-SKYLAKE, so that kexec-boot finalize chip if both io386 binary is under initrd and the board config exports CONFIG_FINALIZE_PLATFORM_LOCKING_PRE-SKYLAKE=y.

Nonetheless to say, it could be possible to unset an exported variable at runtime as well. Think of unsafe boot, for example, that could prompt the user in case CONFIG_FINALIZE_PLATFORM_LOCKING_PRE-SKYLAKE=y or whatever else discussed and agreed as being the way forward. Note that unsafe boot option could disable this as well, as long as its clear for the user of the implication, but the safer default should be to lock it and let Heads be the only one tampering with firmware as the safe default where possible.

@3hhh thoughts?

@3hhh
Copy link
Contributor

3hhh commented Jun 18, 2023

this is what the config-gui.sh is doing today: merge /etc/config with runtime /etc/config.user and save them in SPI through cbfs files, and have them measured as part of measured boot Heads stuff before being used in policies.

So runtime configuration options are already implemented via cbfs?
That's good to know and merely makes runtime configuration a documentation issue for now.

I think this would deserve another issue to discuss implementation.

Yes. If there's meant to be a GUI implementation, probably something like $EDITOR /etc/config.user and save to cbfs incl. re-sign afterwards should suffice.

I would be ok introducing CONFIG_FINALIZE_PLATFORM_LOCKING_PRE-SKYLAKE, so that kexec-boot finalize chip if both io386 binary is under initrd and the board config exports CONFIG_FINALIZE_PLATFORM_LOCKING_PRE-SKYLAKE=y.

That would then enable the aforementioned runtime configuration for this PR, yes.

@tlaurion
Copy link
Collaborator Author

tlaurion commented Jun 19, 2023

@3hhh @JonathonHall-Purism not sure how to do first step torward dynamic whiptail menus at 7c379f7#diff-ea606b9946e2de366108a7bea0a76c2b884d7360824975ad7c6e057cd906c120

But @3hhh the last commit permits to go into config manager, and deactivate platform locking for current boot session (meaning no lock_chip would be called on next kexec call), and optionally save the config back to spi, reboot, seal etc as would happen after firmware upgrade.

@JonathonHall-Purism any advice on creating dynamic menus? Have some to point me to in pureboot codebase?

@JonathonHall-Purism
Copy link
Collaborator

@tlaurion Yes, I have examples of exactly this: https://source.puri.sm/firmware/pureboot/-/blob/Release-27/initrd/bin/config-gui.sh#L33

In particular CONFIG_SUPPORT_BLOB_JAIL and CONFIG_SUPPORT_AUTOMATIC_POWERON sound very similar to what you want. CONFIG_SUPPORT_* enables the menu options, which then change the actual config variable.

Bash arrays are wonderful.

…onfig option

kexec-boot: depend on io386 presence and board config option to call lock_chip
…ed at runtime

ash_functions: make sure /tmp/config is sourced before going to recovery shell
TODO: revisit https://source.puri.sm/firmware/pureboot/-/blob/Release-27/initrd/bin/config-gui.sh#L33 to have proper config store later on
@tlaurion
Copy link
Collaborator Author

tlaurion commented Jun 20, 2023

@3hhh you have t530 I see?

995a693 implements a runtime config override, which as all configuration override, can be setuped to be saved into /etc/config.user to override /etc/config that comes from the board configuration.

From a little step back reflexion, I figured it was the best way to implement your request so that people can override default security policy only for one boot, in current case, desiring for example to boot an ISO/USB dongle and be able to override platform locking mecahnism on next kexec call.

Please let me know if that fits your requirement. We could also see another config option override which would permit to add "iomem=relaxed" to KERNEL_ADD arguments passed down to kexec call, defined per board config. Note that an option forward could be to put all configuration options in board configs set to =n since Heads has changed recently to only check for =y in code. That way, the configuration store you are talking about could be implemented.

Also note that Purism has worked a lot on the config-gui.sh on their side, and a lot of things there could be cherry-picked/PR to be merged under Heads as well: https://source.puri.sm/firmware/pureboot/-/blob/Release-27/initrd/bin/config-gui.sh

A config store would definitely be a good idea, and the code there has a nice simple implementation to implement toggles on board config provided options, which can be used at runtime and saved as config.user override of board config runtime options.

@tlaurion
Copy link
Collaborator Author

For prosperity, here is the config option toggle in action:
signal-2023-06-20-135059
signal-2023-06-20-135116
signal-2023-06-20-135128
signal-2023-06-20-135145

On boot, the presence of "Finalizing chipset" disappears, where its present on normal boot path otherwise.

@3hhh
Copy link
Contributor

3hhh commented Jun 20, 2023

Very nice, thank you very much!

I tested it on a T530 and it worked as advertised. :-)

And yes, the Pureboot configuration options look interesting and user-friendly, albeit probably a lot harder to maintain than the simple (but possibly less user-friendly) config file editing I proposed.

@tlaurion
Copy link
Collaborator Author

@ThePlexus your confirmation needed for merging!

@tlaurion
Copy link
Collaborator Author

And yes, the Pureboot configuration options look interesting and user-friendly, albeit probably a lot harder to maintain than the simple (but possibly less user-friendly) config file editing I proposed.

@3hhh you can save the configuration changes from the "Change Configuration Settings" menu. On previous screenshot, that would be "Save the current configuration to the running BIOS" which is basically injecting runtime /tmp/config into what is extracted on boot and sourced at /etc/config.user

@ThePlexus
Copy link
Contributor

@tlaurion I confirm test case works as described on p8z77-m_pro.

@ThePlexus
Copy link
Contributor

thanks for this work!

@tlaurion tlaurion changed the title WiP : io386 refresh Ivy/sandy/haswell platform locking (SMI finalizing chipset : io386 refresh for maximized boards) Jun 21, 2023
@tlaurion
Copy link
Collaborator Author

Merging! Thanks everyone! More testing needed on other PR soon! :)

@tlaurion tlaurion merged commit 6ec0c81 into linuxboot:master Jun 21, 2023
@tlaurion
Copy link
Collaborator Author

tlaurion commented Jun 21, 2023

Once again thanks to @hardenedvault and @persmule for #326 which took way too long to be adapted, tested and merged with boards config to use it.

Hopefully things will get faster from now on.

@tlaurion
Copy link
Collaborator Author

tlaurion commented Apr 8, 2024

Last discussion point on skylake+ under #326 (comment)

@tlaurion
Copy link
Collaborator Author

tlaurion commented Apr 8, 2024

Op refers to x11, post skylake platform, which implements needed change out of coreboot tree and can be used as a base

TODO:

Skylake and newer have been tweaked to be able to do the same but it seems that upstreaming the changes to coreboot has not happened yet but had for older platforms. More info for coreboot devels to jump in from vaultbook fork for their x11 platform patch on unknown coreboot git commit

@tlaurion
Copy link
Collaborator Author

tlaurion commented Apr 29, 2024

Edited OP to point to #1373 (comment) to show how to disable on a single boot session since asked under #1657

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants