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

Documentation fails to explain SRWD issue: hardware write protect is currently (mostly) not possible #985

Open
ln2max opened this issue Mar 3, 2021 · 15 comments

Comments

@ln2max
Copy link

ln2max commented Mar 3, 2021

The Heads documentation suggests:

Finally, once Coreboot has been flashed into the ROM, the write protect pins on the ROMs can be shorted to ground as an extra layer of protection. This prevents any software re-writes of the ROM, even from the Management Engine or other devices on the SPI bus.

However, this is not as easy as it sounds. Most Thinkpad chips require extra SRWD bits to be set when flashing in order for the hardware write protect pins to have any effect. Flashrom doesn't currently support setting these bits, see the linked issue for a more in-depth description of what is needed (and a patch for Flashrom).

@tlaurion
Copy link
Collaborator

@ln2max thanks

@jtf7
Copy link

jtf7 commented Aug 18, 2024

Hardware Write Protection (KGPE-D16)

A number of users have had issues getting this working so here are some tips and using hardware write protection

Hardware write protection is only available on eeprom chips that explicitly support it and typically requires setting specific fuse settings appropriately to enable this function. This information is found in the manufacturer’s documentation for the specific part # of chip you intend to use.

Winbond W25Q128FVAIG

The Winbond W25Q128FVAIG is a 16MB eeprom chip capable of hardware write protection and is compatible with the KGPE-D16. This chip is physically engraved with the abbreviated text 25Q128FVIG.

Fuse Settings
Fuse settings required to activate the hardware write protection feature for this specific part number of Winbond chip are as listed below:

[S18=WPS=0]
[S14=CMP=0]

[S9=QE=0]
[S8=SRP1=0]
[S7=SRP0=1]

[S6=SEC=0]
[S5=TB=0]
[S4=BP2=1]
[S3=BP1=1]
[S2=BP0=1]

Experts can tweak these settings to fine tune the chip’s configuration however, the settings listed above have worked well for me and should work well for most users.

Connecting pin 3 (/WP) and pin 4 (GND) together with these fuse settings will enable hardware write protection. It may be required to power off the system before connecting/disconnecting these pins in order for the correct write state to be recognized.

Many users have a similar version of Winbond chip with part number W25Q128FVAIQ however, it should be noted that this alternate Q version chip is not capable of hardware write protection.

Additional Fuse Settings: Security Register Lock Bits
You may also want to set S11, S12, and S13 as listed below in order to permanently lock the security register as read-only. This is where manufacturer’s info, security related information, and hard coded data for the chip is stored. This is a separate location on the chip from where your ROM image is stored. The vibe I got from reading the Winbond documentation is that this could be a great place for backdoor related shenanigans and it’s probably a good idea to set these fuses in order to lock as read-only. That being said, I’m not entirely sure. I set mine as listed below and it worked for me however, as always, use at your own risk.

[S13=LB3=1]
[S12=LB2=1]
[S11=LB1=1]

@tlaurion
Copy link
Collaborator

tlaurion commented Aug 18, 2024

@ln2max @jtf7 are all those bits set properly with patches having landed to flashrom upstream? Should have landed under 1.3.0 and ones missing there, present in 1.4.0 which was recently released.

Docs at https://docs.dasharo.com/variants/asus_kgpe_d16/spi-wp/#flashrom-write-protection-cli

CC @SergiiDmytruk flashrom/flashrom#185 (comment)

If so, it would be a good time to open an issue under heads-wiki, close flashrom/flashrom#185 and close this issue leaving documentation to be drafted and merged referencing original docs, not redoing them, or, point upstream what is missing for flashrom to be feature complete on SPI WP.

@jtf7
Copy link

jtf7 commented Aug 18, 2024

@ln2max @jtf7 are all those bits set properly with patches having landed to flashrom upstream? Should have landed under 1.3.0 and ones missing there, present in 1.4.0 which was recently released.

Docs at https://docs.dasharo.com/variants/asus_kgpe_d16/spi-wp/#flashrom-write-protection-cli

CC @SergiiDmytruk flashrom/flashrom#185 (comment)

If so, it would be a good time to open an issue under heads-wiki, close flashrom/flashrom#185 and close this issue leaving documentation to be drafted and merged referencing original docs, not redoing them, or, point upstream what is missing for flashrom to be feature complete on SPI WP.

The bits I provided should all be correct. When I did this, I went through the Windbond 25Q128FV datasheet (Revision I) extensively and verified multiple times due to the importance I see in having HW write protection working properly. I hired someone to do the custom flashing and so I'm not familiar with the flashrom patches or whats going on there although I'll take a look and try to comprehend.

In the Dasharo link you provided they deliberately only write protect a portion of the chip, the settings I provide HW write protect all the memory blocks. @tlaurion --Can you confirm that it isn't necessary for the boot functionality of Heads to have part of the memory in read-write mode and that keeping it fully locked as read-only the majority of the time is ok? The way they wrote that article leads me to believe they had some legitimate reason for this.

And Windbond doc below for anyone interested
W25Q128FVSIF-TR.PDF
Table 7.1.15 lists Status Register Memory Protection options

@tlaurion
Copy link
Collaborator

tlaurion commented Aug 18, 2024

In the Dasharo link you provided they deliberately only write protect a portion of the chip, the settings I provide HW write protect all the memory blocks.

@jtf7 This is unfortunately needed, otherwise blocking necessary changes on non-static, embedded-systems-not-supposed to-ever-change-and-considered-forever-good.

  • Q: How would RAM init cache be written back to SPI? How would you update Heads? How would Heads config settings, public key or any desired changes (Factory Reset/Re-Ownership be written back into CBFS (Coreboot FileSystem) and then measured + sealed under Heads reporting changes to be accepted at non-tampering but desired config changes?
  • A: It would not be possible, and WP any other region would require you to solder/unsolder prior of changes, then resoldering after changes: to say the least impractical.

@tlaurion: Can you confirm that it isn't necessary for the boot functionality of Heads to have part of the memory in read-write mode and that keeping it fully locked as read-only the majority of the time is ok? The way they wrote that article leads me to believe they had some legitimate reason for this.

Absolutely enforced through explained reasoning there, otherwise that documentation misses the point to your eyes. Measured boot depends on bootblock which is considered RoT for coreboot measured boot. But measured boot alone doesn't enforce anything, security policies need to be applied on top of that coreboot provided feature:

TLDR: only the bootblock should be write protected under Heads use case, so that TPM TCPA/TPM event log (measured boot enforced by coreboot bootblock and next stages) can be meaningful/helpful in providing tamper evidence guarantees.

Setting write protection for any other region would prevent upgrade, which might be useful for your TV or any other device you wish to protect against upgrades and tampering, otherwise you simply prevent the SPI from being effectively writeable, if that is your desire, but this is normally NOT desired, hence why this was pushed forward for joint NlNet application and funded work under #1741.

From those reads, anything missing for documentation?


Note that for KGPE-D16, which was directly targeted for funding and NlNet grant PoW, public direct outcomes were:

@jtf7
Copy link

jtf7 commented Aug 18, 2024

Absolutely enforced through explained reasoning there, otherwise that documentation misses the point to your eyes. Measured boot depends on bootblock which is considered RoT for coreboot measured boot. But measured boot alone doesn't enforce anything, security policies need to be applied on top of that coreboot provided feature:

TLDR: only the bootblock should be write protected under Heads use case, so that TPM TCPA/TPM event log (measured boot enforced by coreboot bootblock and next stages) can be meaningful/helpful in providing tamper evidence guarantees.

I'm not sure I'm following. I will try to comprehend better when I'm a little more refreshed.

I was testing other things awhile back and drifted away from using the Heads TPM and Nitrokey features to boot. Am working on reinstalling and getting everything set up properly now. Then planing to do a Qubes HCL and help document to lower the learning curve for newbies.

For KGPE-D16: My original plan was to leave the pins 3+4 jumpered to keep the Winbond chip HW write-protected for the vast majority of the time and then in those rare times I need to update Dom0 or firmware or change some Heads setting, I would disconnect the jumper in order to allow writes and make changes. After changes are made, I would rejumper pins 3+4 to HW protect the entire chip again.

@tlaurion Are you saying that doing this will prevent Heads from measuring the TPM and operating as intended because it is necessary for Heads to write something to Winbond in order to accomplish this??

@tlaurion
Copy link
Collaborator

I'm not sure I'm following. I will try to comprehend better when I'm a little more refreshed.

I was testing other things awhile back and drifted away from using the Heads TPM and Nitrokey features to boot. Am working on reinstalling and getting everything set up properly now. Then planing to do a Qubes HCL and help document to lower the learning curve for newbies.

Good!

For KGPE-D16: My original plan was to leave the pins 3+4 jumpered to keep the Winbond chip HW write-protected for the vast majority of the time and then in those rare times I need to update Dom0 or firmware or change some Heads setting, I would disconnect the jumper in order to allow writes and make changes. After changes are made, I would rejumper pins 3+4 to HW protect the entire chip again.

@tlaurion Are you saying that doing this will prevent Heads from measuring the TPM and operating as intended because it is necessary for Heads to write something to Winbond in order to accomplish this??

@jtf7 : might have done some shortcuts here. Will clarify.
You could WP whole chip, where soldering/unsoldering unpractical at best which is why adapters have been made with a jumper here as best solution for the moment as retrofit design. But you should WP only after having ran Heads Factory Reset/Re-Ownership wizard. Docs are at https://osresearch.net/Configuring-Keys/

  • TPM extend PCRs through measured boot (Static Root of Trust for Measurement) from bootblock up to the payload and store PCR extend operations in TPM event log where PCR final measurement is the outcome of such extend operations.
  • Heads uses those final measurements and seals them as part of secrets, unsealed on boot. If the measurements are different, unsealing operations will fail
  • Therefore, anything that would change measured sections of the firmware would fail to unseal. Heads documents those PCRs used to seal/unseal secrets at https://osresearch.net/Keys/#tpm-pcrs

So, if you are to WP the whole SPI chip, you will have to do so after OEM Factory Reset/Re-Ownership, that is because additional CBFS files will be injected into firmware which will in turn be sealed into TPM nvram to be unsealed for attestation and TPM Disk Unlock Key passphrase to be released to the OS through kexec call to boot into final OS.

On KGPE-D16, I remember native ram init to modify the MRC cache in SPI under coreboot 4.11, not sure what happens there for Dasharo coreboot fork. If the MRC cache is now static after RAM being trained, you will have to punch exclusion under coreboot config for the MRC region for measured boot.

This is why I have said that bootblock should be partial region write protected per Dasharo docs, since the RoT for measurement in in the bootblock, and Heads ideology is to make firmware tamper evident, not tamper proof; whole SPI WP would implement tamper prevention, which might fit or not in your use case.

As long as you solder WP after sealing TPMTOTP secret into TPM nvram (After having modified SPI content as intended), setting whole SPI WP should not be a problem, unless there is a but under coreboot and some regions, like the ram init cache (MRC cache) changes, you should be good to go.

Updating /boot has nothing to do with the TPM. Heads uses CBFS injected GPG public keyring+trusted db and config.user override as part of additional firmware content measured into TPM PCR7, so once you own the platform secrets, those should not change unless you modify them yourself. If you do so, you will need to unsolder WP, do the changes related to user content needed in CBFS, reseal secret and then solder WP again.

The public key fused inside of CBFS, measured under PCR7, are used to detach sign /boot hashes digest, which is part of Heads /boot verifiecation prior of booting the system. That /boot detached signed digest is verified against public keyring fused into firmware to verify integrity+authenticity prior of each boot of OS, and doesn't require to unsolder/resolder SPI: the pubring/trustdb/config/.user overrides will not change across OS upgrades.

@jtf7 does that clarify my previous post and referenced content?
How would that be summarized to be added into official docs to resolve/close this issue?

@tlaurion
Copy link
Collaborator

tlaurion commented Aug 19, 2024

Hardware Write Protection (KGPE-D16)

A number of users have had issues getting this working so here are some tips and using hardware write protection

Hardware write protection is only available on eeprom chips that explicitly support it and typically requires setting specific fuse settings appropriately to enable this function. This information is found in the manufacturer’s documentation for the specific part # of chip you intend to use.

Winbond W25Q128FVAIG

The Winbond W25Q128FVAIG is a 16MB eeprom chip capable of hardware write protection and is compatible with the KGPE-D16. This chip is physically engraved with the abbreviated text 25Q128FVIG.

Fuse Settings Fuse settings required to activate the hardware write protection feature for this specific part number of Winbond chip are as listed below:

[S18=WPS=0] [S14=CMP=0]

[S9=QE=0] [S8=SRP1=0] [S7=SRP0=1]

[S6=SEC=0] [S5=TB=0] [S4=BP2=1] [S3=BP1=1] [S2=BP0=1]

Experts can tweak these settings to fine tune the chip’s configuration however, the settings listed above have worked well for me and should work well for most users.

Connecting pin 3 (/WP) and pin 4 (GND) together with these fuse settings will enable hardware write protection. It may be required to power off the system before connecting/disconnecting these pins in order for the correct write state to be recognized.

Many users have a similar version of Winbond chip with part number W25Q128FVAIQ however, it should be noted that this alternate Q version chip is not capable of hardware write protection.

Additional Fuse Settings: Security Register Lock Bits You may also want to set S11, S12, and S13 as listed below in order to permanently lock the security register as read-only. This is where manufacturer’s info, security related information, and hard coded data for the chip is stored. This is a separate location on the chip from where your ROM image is stored. The vibe I got from reading the Winbond documentation is that this could be a great place for backdoor related shenanigans and it’s probably a good idea to set these fuses in order to lock as read-only. That being said, I’m not entirely sure. I set mine as listed below and it worked for me however, as always, use at your own risk.

[S13=LB3=1] [S12=LB2=1] [S11=LB1=1]

@jtf7 my question around this was more in the realms of: are those needed if using flashrom and wp whole SPI with flashrom 1.3+?

Do you still need to apply those bits manually or flashrom takes care of it correctly?
CC @ln2max

@SergiiDmytruk
Copy link
Contributor

Do you still need to apply those bits manually or flashrom takes care of it correctly?

This is what those flashrom changes do (except for security/OTP registers which aren't related to WP and I don't know of software that even uses them). I guess @jtf7 just applied the same configuration without flashrom (must be via some other tool).

@tlaurion
Copy link
Collaborator

Do you still need to apply those bits manually or flashrom takes care of it correctly?

This is what those flashrom changes do (except for security/OTP registers which aren't related to WP and I don't know of software that even uses them). I guess @jtf7 just applied the same configuration without flashrom (must be via some other tool).

@SergiiDmytruk OTP in the sense that writing to those registers make the SPI chip WP the regions specified only once and cannot be undone?

@SergiiDmytruk
Copy link
Contributor

@SergiiDmytruk OTP in the sense that writing to those registers make the SPI chip WP the regions specified only once and cannot be undone?

No, it doesn't interact with WP. Security registers exist separately from the main flash memory and provide small (in this case it's 3 registers with 256 bytes in each) amount of memory that can be made read-only with those LB1-LB3 bits which are OTP. So you write something in that register (like a unique ID), set corresponding LB bit and that register can never be changed again.

@jtf7
Copy link

jtf7 commented Aug 29, 2024

does that clarify my previous post and referenced content?

Yes, thank you for taking the time to elaborate so thoroughly. All of the technical explanations I've read over the years from yourself and others such as the Qubes devs have been very helpful in gaining a better understanding of firmware and software security.

@jtf7
Copy link

jtf7 commented Aug 29, 2024

Security registers exist separately from the main flash memory and provide small (in this case it's 3 registers with 256 bytes in each) amount of memory that can be made read-only with those LB1-LB3 bits which are OTP. So you write something in that register (like a unique ID), set corresponding LB bit and that register can never be changed again.

It's probably best to lock these bits permanently if you are able to, though to be clear this recommendation is more based on my intuition, gut feelings, and street smarts of my experience and knowledge of backdoors, in-general best engineering practices, and technical workings of this Winbond chip as opposed to hard documented rules and facts.

The Winbond SPI firmware and unique identifiers that could potentially tag a chip are stored in this section. We know persistently infected firmware has become more and more of an issue and this section of the SPI chip would be a great place to infect if you were someone looking to infect the device persistently. Permanently locking this section is probably a good idea if practical, especially since its not like the end user will ever have a legitimate need to update this section. And even if there was a reason the end user needed to update in the future, the chips are only a few dollars to replace.

@jtf7
Copy link

jtf7 commented Aug 29, 2024

Additional Fuse Settings: Security Register Lock Bits You may also want to set S11, S12, and S13 as listed below in order to permanently lock the security register as read-only. This is where manufacturer’s info, security related information, and hard coded data for the chip is stored. This is a separate location on the chip from where your ROM image is stored. The vibe I got from reading the Winbond documentation is that this could be a great place for backdoor related shenanigans and it’s probably a good idea to set these fuses in order to lock as read-only. That being said, I’m not entirely sure. I set mine as listed below and it worked for me however, as always, use at your own risk.
[S13=LB3=1] [S12=LB2=1] [S11=LB1=1]

@jtf7 my question around this was more in the realms of: are those needed if using flashrom and wp whole SPI with flashrom 1.3+?

This is a separate section of the chip. It's geared more toward the SPI chips admin and operation than user data. I would consider this section to be critical to security despite not necessarily being used by the end user.

I've added this below, does this explanation help?

Security registers exist separately from the main flash memory and provide small (in this case it's 3 registers with 256 bytes in each) amount of memory that can be made read-only with those LB1-LB3 bits which are OTP. So you write something in that register (like a unique ID), set corresponding LB bit and that register can never be changed again.

It's probably best to lock these bits permanently if you are able to, though to be clear this recommendation is more based on my intuition, gut feelings, and street smarts of my experience and knowledge of backdoors, in-general best engineering practices, and technical workings of this Winbond chip as opposed to hard documented rules and facts.

The Winbond SPI firmware and unique identifiers that could potentially tag a chip are stored in this section. We know persistently infected firmware has become more and more of an issue and this section of the SPI chip would be a great place to infect if you were someone looking to infect the device persistently. Permanently locking this section is probably a good idea if practical, especially since its not like the end user will ever have a legitimate need to update this section. And even if there was a reason the end user needed to update in the future, the chips are only a few dollars to replace.

@jtf7
Copy link

jtf7 commented Aug 29, 2024

my question around this was more in the realms of: are those needed if using flashrom and wp whole SPI with flashrom 1.3+?

A couple of the fuse settings I specified are listed as "x" in the documentation and could technically be set to either 1 or 0. Despite this, I decided to explicitly define the fuses for simplicity and since it's possible there may be some "gotchas" that could apply when using alternate settings. (Using alternate settings for these pins could possibly change other settings, you'd need to read through the documents in full if for some reason you wanted to do this.)

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

No branches or pull requests

4 participants