osresearch / safeboot

Scripts to slightly improve the security of the Linux boot process with UEFI Secure Boot and TPM support
https://safeboot.dev/
GNU General Public License v2.0
270 stars 28 forks source link

Seal only on particular(known) PCRs #10

Closed tomoveu closed 4 years ago

tomoveu commented 4 years ago

Hi there,

Just learned about this project from our small TPM developers community and got intrigued to learn more. I came across this FAQ section - "Why does the TPM unsealing fail often?"

It should be possible to seal/unseal based on user-defined set of PCRs and not all of them. Would it not be preferable to target a small set of the PCRs?

Essentially, control what you know.

ps: Kudos for the project! Good set of goals. Can confirm 3 out of the 4 are already used in TPM Enterprise solutions. Unfortunately, TPM adoption is buried under NDAs and closed source. Breaking this is the reason I create tpm.dev So, I like your effort a lot, I'd be happy to try and help.

osresearch commented 4 years ago

Thanks for the pointer to https://tpm.dev/ -- it's always nice to find other communities who care about boot security and attestation.

The list of PCRs can be set in /etc/safeboot/safeboot.conf (current default 0,2,5,7), with an additional PCR extended to log the boot mode parameter so that recovery boots won't unseal the secret, and so that the secret can not be unsealed after exiting the initramfs.

I've patched tpm2_eventlog to be able to parse the Thinkpad logs and that's been helpful for determining where things are going wrong. Sorting by the PCR being update shows that 4 is hashing the entire merged kernel+initrd, so that is likely one of the reasons for things being fragile:

0,EV_S_CRTM_VERSION,'N1MET39W '
0,EV_EFI_PLATFORM_FIRMWARE_BLOB,0xfffe0000-0x100000000
0,EV_EFI_PLATFORM_FIRMWARE_BLOB,0xffea0000-0xfffe0000
0,EV_EFI_PLATFORM_FIRMWARE_BLOB,0xffd30000-0xffde0000
0,EV_EFI_PLATFORM_FIRMWARE_BLOB,0xffde0000-0xffdf0000
0,EV_EFI_PLATFORM_FIRMWARE_BLOB,0xff970000-0xffd30000
0,EV_POST_CODE,'ACPI DATA'
0,EV_POST_CODE,'ACPI DATA'
0,EV_SEPARATOR,0
1,EV_EFI_VARIABLE_DRIVER_CONFIG,LenovoConfig='510530097866692379438757
1,EV_EFI_VARIABLE_DRIVER_CONFIG,LenovoSecurityConfig='1789931603259925
1,EV_EFI_HANDOFF_TABLES,'01000000000000004415fdf294972c4a992ee5bbcf20e
1,EV_SEPARATOR,0
4,EV_SEPARATOR,0
4,EV_EFI_BOOT_SERVICES_APPLICATION,0x429db018/0x05bfe7d0
5,EV_EFI_VARIABLE_BOOT,BootOrder='0200010000001700180019001a001b001c00
5,EV_EFI_VARIABLE_BOOT,Boot0002='010000005c006c0069006e007500780000000
5,EV_EFI_VARIABLE_BOOT,Boot0001='0100000062007200650063006f00760065007
5,EV_EFI_VARIABLE_BOOT,Boot0000='0100000062007500620075006e00740075000
5,EV_EFI_VARIABLE_BOOT,Boot0017='0100000028005500530042002000430044000
5,EV_EFI_VARIABLE_BOOT,Boot0018='0100000028005500530042002000460044004
5,EV_EFI_VARIABLE_BOOT,Boot0019='0100000029004e0056004d006500300000000
5,EV_EFI_VARIABLE_BOOT,Boot001A='0100000029004100540041002000480044004
5,EV_EFI_VARIABLE_BOOT,Boot001B='0100000028005500530042002000480044004
5,EV_EFI_VARIABLE_BOOT,Boot001C='01000000280050004300490020004c0041004
5,EV_EFI_VARIABLE_BOOT,Boot001D='0000000029004f00740068006500720020004
5,EV_EFI_VARIABLE_BOOT,Boot001E='0000000029004f00740068006500720020004
5,EV_EFI_VARIABLE_BOOT,Boot0023='09000000280050004300490020004c0041004
5,EV_EFI_ACTION,'Calling EFI Application from Boot Option'
5,EV_SEPARATOR,0
5,EV_EFI_GPT_EVENT,'4546492050415254000001005c000000b248e0950000000001
7,EV_EFI_VARIABLE_DRIVER_CONFIG,SecureBoot='1'
7,EV_EFI_VARIABLE_DRIVER_CONFIG,PK='a159c0a5e494a74a87b5ab155c2bf0725f
7,EV_EFI_VARIABLE_DRIVER_CONFIG,KEK='a159c0a5e494a74a87b5ab155c2bf0725
7,EV_EFI_VARIABLE_DRIVER_CONFIG,db='a159c0a5e494a74a87b5ab155c2bf0725f
7,EV_EFI_VARIABLE_DRIVER_CONFIG,dbx=''
7,EV_SEPARATOR,0
7,EV_EFI_VARIABLE_AUTHORITY,db='7ac3e2a7903a934f97c426b9a1162289308203
osresearch commented 4 years ago

You might be able to provide some suggestions on #11 - is it possible to ensure that the sealed secret is persistent in a consistent handle so that the initramfs does not need to be regenerated when the disk is resealed?

tomoveu commented 4 years ago

@osresearch happy to, I just responded in issue 11. Essentially, made an observation and then I asked a stupid question :))

Interesting about the Lenovo & PCR4. Do you mean the UEFI Secure Boot is measuring the kernel+initrd together?

Here is something more about PCR fragility from Matthew Garret. He also talked about it in Prague 2017, dual booting Win&Linux is an even bigger hell :/ - https://mjg59.dreamwidth.org/48897.html

osresearch commented 4 years ago

Another option to reduce PCR fragility is to sign the approved PCRs with the PK and bind the sealed data to that public key. This allows an initrd to apply some logic to select the allowed PCR values: https://software.intel.com/content/www/us/en/develop/articles/code-sample-protecting-secret-data-and-keys-using-intel-platform-trust-technology.html#inpage-nav-2-4

osresearch commented 4 years ago

Just committed a fix that hacks in a prediction for PCR4, which allows a new Linux kernel+initrd to be signed with safeboot linux-sign, and then the key to be re-sealed with safeboot luks-seal. It is hardcoded for how the Thinkpad UEFI firmware extends PCR4 with EFI_EV_SEPARATOR and then EFI_BOOT_APPLICATION events.

https://github.com/osresearch/safeboot/commit/bc9fa3992c3977522a3e5dd704aab9cd7563997a https://github.com/osresearch/safeboot/commit/47919284335d33eb1bb09d378f8d2f798456e04a

This depends on the ability to compute the PE hash for the kernel image, which requires a modified version of sbsign: https://github.com/osresearch/sbsigntools/commit/370abb7c49ec2a600f64fcbd441d9297124a5cb7

osresearch commented 4 years ago

Fixed in #58 with pre-computation of PCR4.