Rohde-Schwarz / TrustedGRUB2

DEPRECATED TPM enabled GRUB2 Bootloader
GNU General Public License v3.0
191 stars 78 forks source link

Calculating PCR 10 and 11 #39

Closed johnwallace123 closed 8 years ago

johnwallace123 commented 8 years ago

I'd like to use TrustedGRUB2 to seal a key that I can then use to decrypt the root partition automatically. However, in order to properly seal the data, I need to be able to compute the expected PCRs (See Issue #2 for a similar approach), because if I update the kernel, I'll need to be able to seal the data to the expected values of the PCRs so that it will unseal at boot. Because the kernel changes, PCR10 will certainly change, and PCR11 will likely change because the name of the kernel in the command line will change.

When I attempt to calculate PCR10, I follow along with the debugging output and I do the following: PCR10=00000000000000000000 PCR10=sha1sum($PCR10 || sha1sum(/boot/vmlinuz...)) PCR10=sha1sum($PCR10 || sha1sum(/boot/initrd...))

My hashes match what I see in the debug output, but the actual value in PCR10 differs when I get to a command prompt. Is there anything else that is measured after loading the initrd image?

As for PCR11, is there a way to invoke the GRUB command line from the shell in a way that will evaluate the conditionals and print out the commands that would be executed? Alternatively, is there a way to log all of the commands that were executed at the last boot? I could probably use that log and pair things up with the current grub.cfg file to determine what commands will be executed on the next bootup.

My current setup is using a minimal CentOS 7.2 image with stock trousers and a custom tpm-tools (solution from https://bugzilla.redhat.com/show_bug.cgi?id=1126097), and TrustedGRUB2 1.3.0 compiled in debug mode (-DTGRUB_DEBUG).

Thanks for your help and amazing software!

neusdan commented 8 years ago

Regarding PCR 10: that's really strange. As you can see here PCR 10 is only used for kernel and initrd measurements if you only use linux and initrd commands.

The TrustedGRUB 2 measurements are currently not extended to the event log (#11), but maybe you can see something else in /sys/kernel/security/tpm0/ascii_bios_measurements ?

PCR 11: Precomputation is really uncomfortable at the moment. If you have compiled with TGRUB_DEBUG you can see what strings are measured

Alternatively, is there a way to log all of the commands that were executed at the last boot

Not yet, but it's a good idea. I'll create an issue for that.

johnwallace123 commented 8 years ago

After further examination, it looks like something else is also using PCR-10. I changed the TPM_LOADER_MEASUREMENT_PCR to 15 and manually measured the files in question to PCR14. Both registers matched each other and matched my manual calculations. Furthermore, PCR10 was nonzero after the change.

There was nothing in the BIOS event log (/sys/kernel/security/tpm0/ascii_bios_measurements), but I did find a PCR10 measurement in the IMA event log (/sys/kernel/security/ima/ascii_runtime_measurements). It looked like:

10 <sha1> ima <sha1> boot_aggregate

My suspicion is that when I tried to install iml2text (from #13), that package measures something into PCR10, but I'd need to rebuild the test machine to confirm. You can consider my PCR10 confusion resolved.

As for PCR11, is there a way to redirect the TGRUB_DEBUG output to somewhere it can be read after boot? That would completely solve #40, at least for my purposes. My initial reading is that grub by default can't write to the /boot partition, and of course, the / partition is encrypted and unreadable at boot time.

Thanks again for the help, and sorry for adding any confusion. If I find any solutions to any open issues, I'll submit a PR, but it looks like you're much more capable than I!

neusdan commented 8 years ago

I've implemented the logging for the measurements. But unfortunately it's not that helpful. On my machine the output of /sys/kernel/security/tpm0/ascii_bios_measurements looks like this:

13 9d14ee6a6fe29193db75d1b6348709e07f2bd38f 0d [IPL]
13 88eb95db48817de416481ebaf488f986fb83f603 0d [IPL]
13 263c771ac7fc42fbaade86298964643f371aed71 0d [IPL]
13 31a1ec609fc56c2f9124dd880d746731dc90ecce 0d [IPL]
13 724cd8c9cf8b99d396ba078d0b319d88279874e7 0d [IPL]
13 0fd1c86fbcddbd0eb609f2e965a79d3bb80f35c0 0d [IPL]
13 426f5a84bfd08c8bf4455a04208052fcf7a42087 0d [IPL]
13 78d0fae38e065e4ff4a6d8668fc34a227e08a68b 0d [IPL]
13 7c132d4f8c78e56d6f802c88584bd9e24712cd97 0d [IPL]
11 a4e1c6f50579b47c964111d1ea2170e6f923c941 0d [IPL]
11 610a881e824bb6fd57bea1c994805116171e3c9f 0d [IPL]
13 c8c2e9a0b5722742a684a3b78125cdad15f4b051 0d [IPL]
13 c181f75f220ec2adc8940cc1637f8d7dcf750bea 0d [IPL]
13 b77536c3b213c46c365d300af00df2d8451c94d5 0d [IPL]
11 453dee6ce82bd80ea89bd8085724ae9784ff0f1b 0d [IPL]
11 75409120452bbbee30abe289af973ecdd7e0ef6b 0d [IPL]

I set a description on each TPM_Extend but it does not find it's way to the log (only "IPL").

I'll look into the "redirect TGRUB_DEBUG to file log thing"

neusdan commented 8 years ago

Ok, bad news. It's not possible to write to a file from GRUB2. They only way i could find is described here It's possible to write to the grubenv file but that's not really convenient.

With this you have to do something like this for every command:

set command1="linux /vmlinuz"
export command1
save_env command1

Then you could read out the file from the booted OS. There is also the limitation of only 1024 characters.

Maybe another solution would be to write the executed commands to the NVRAM of the TPM. But i have no experience with this.

For now i'm not aware of a good solution for your problem. So it's maybe best to keep the grub.cfg small and without branches.

johnwallace123 commented 8 years ago

Your research matches what I've also seen. Unfortunately, the issue with using the grubenv file is that the "export" and "save_env" commands would also be measured, leading to an infinite death spiral of logging and measuring! Additionally, the NVRAM isn't a great option, as it's only guranteed to be 1280 bytes, and it has a very limited number of writes (O(10K), though if you're rebooting a Linux machine thousands of times, you're Doing It Wrong).

It is interesting that the event description doesn't propagate. However, I think by adding to the event log, this should solve both this issue and #40.

My solution to logging all of the commands read would be to hash each line of the grub.cfg (stripping leading whitespace) and attempt to match it with the hashes in the event log, preserving order. If the grub.cfg doesn't change, you should be able to match the commands uniquely. If the grub.cfg doesn't change dramatically, you can still infer what the expected control flow should be based on the commands that you can match up. If you completely rewrite the grub.cfg, all bets are off, but in that case, you probably know what you're doing anyway!

The nice part (for you) of this solution is that it can't be implemented in the actual grub code, but needs to be implemented in a higher level. Once I get a workable script, I'd be happy to share it here, but I think both this issue and #40 can be closed. Thanks for the help and patience.

johnwallace123 commented 8 years ago

I won't reopen the issue, but as an FYI, I have made progress on precomputing PCR 11 given a grub configuration and a list of hashes at last boot, which can be seen here: https://github.com/johnwallace123/tpm-luks/blob/master/tpm-luks/tpm-luks-command-hash.py. If this is helpful to anyone else, I'm happy to share.

I'm sure that there are a number of ways this can go wrong; it assumes that the saved environment variables will always be loaded, when that should only happen at "load_env". However, this script does work for a stock CentOS7 load and will accurately compute the PCR upon a kernel upgrade.

Additionally, it looks like the "standard" security settings for CentOS7 involve enabling the Linux INtegrity Management Architecture (see http://linux-ima.sourceforge.net/) which extends PCR 10, confounding the kernel + initramfs measurments made by TrustedGRUB. I've resolved by moving the kernel measurements to PCR 14. In addition to this, in my fork, I've made a few updates that allow for a RPM to be build relatively easily, thanks in large part to @momiji.

Thanks again for all of your help and effort integrating the TPM into grub2.