This is a PULL REQUEST for: https://github.com/sadaszewski/freebsd-src/compare/main...main-cherry-pick-tpm-support-in-stand See https://lists.freebsd.org/archives/freebsd-hackers/2021-November/000504.html for the discussion. The referenced patch implements the support for TPM2 in the EFI bootloader and in the kernel in order to allow for storage and retrievel of a GELI passphrase in a TPM2 module, protected with a PCR policy, and boot into (and only into) the corresponding "safe" boot filesystem and root filesystem, identified by means of a secret marker. The way the bootloader behavior is modified is the following: 1) before calling efipart_inithandles(), an attempt to retrieve the passphrase from a TPM2 module might be performed - how this is achieved is described later on. 2) if a passphrase is indeed retrieved, then after determining currdev, the currdev is checked for the presence of a /.passphrase_marker file which must contain the sha256 of the passphrase as retrieved from the TPM (and an optional salt). This is supposed to ensure that we do not end up booting an environment not on the device we just unlocked with the passphrase. 3a) If all is go, the autoboot_delay is set to -1 in order to prevent any interaction and continue the boot process of the "safe" environment. A 'kern.geom.eli.passphrase.from_tpm2.passphrase' variable is set to the passphrase from TPM in order for kernel use later, as well as a kern.geom.eli.passphrase.from_tpm2.was_retrieved'='1' variable. 3b) If the passphrase marker does not match, the bootloader cleans up GELI keys, the TPM passphrase and kern.geom.eli.passphrase and exits. The way the kernel behavior is modified is the following: 1) In init_main.c, after vfs_mountroot() a check is performed (by means of EVENTHANDLER_REGISTER). 2a) If kern.geom.eli.passphrase.from_tpm2.was_retrieved is not set to 1, then we do nothing and continue the boot process 2b) If the was_retrieved variable is set to '1' then we check for the same passphrase marker as the bootloader, its content compared against the 'kern.geom.eli.passphrase.from_tpm2.passphrase' variable. 3a) If all is go, the passphrase variable is unset and the boot process continues, 3c) If the passphrase marker does not match, we panic. The configuration of the bootloader for this procedure looks the following: 1) We set an efivar KernGeomEliPassphraseFromTpm2NvIndex to contain the TPM2 NV Index we store our passphrase in, e.g. 0x1000001 2) We set an efivar KernGeomEfiPassphraseFromTpm2PolicyPcr to contain the PCR policy used to secure the passphrase, e.g. sha256:0,2,4,7 3a) If both are set, the bootloader will attempt to retrieve the passphrase and behave in the modified way described above 3b) Otherwise, it behaves as the vanilla version and will ask for GELI passphrases if necessary The configuration of the TPM and the passphrase marker looks the following: 1) echo -n "passphrase" | sha256 >/.passphrase_marker 2) chmod 600 /.passphrase_marker 3) tpm2_createpolicy -L policy.digest --policy-pcr -l sha256:0,2,4,7 4) tpm2_nvdefine -Q 0x1000001 -s `wc -c /.passphrase_marker` -L policy.digest -A "policyread|policywrite" 5) tpm2_nvwrite -Q 0x1000001 -i /.passphrase_marker -P pcr:sha256:0,2,4,7
Added hard-coded PCR Extend on PCR8 to secure the case when the passphrase is stored in the TPM but not retrieved. Bootloader permits the boot of an arbitrary environment if the passphrase is not retrieved (i.e. no /.passphrase_marker check), therefore it needs to be ensured that the policy protecting the passphrase NVIndex includes PCR8 and therefore denies future access in such a case.
Hello, it's been a while since this has been hanging in here. Is there anything I can do to improve the chances of having this request taken under consideration? This feature has a critical role in a FreeBSD-based product I am developing and it would clearly be very helpful and much appreciated if it was integrated upstream. Thank you in advance, looking forward to hearing from you.
Since for the moment there does not seem to be that much traction for integrating it upstream, I have created a separate Git repository: https://github.com/sadaszewski/freebsd-patch-geli-password-from-tpm2 which can somewhat intelligently patch any FreeBSD source tree and allows to build the TPM2-passphrase-aware bootloader and kernel. I hope this will facilitate use by people who actually want/need it. I will also start putting some unit tests in there, in particular for the TPM code using swtpm + libtss2-tcti-swtpm - hopefully in the future all of it can be mostly test-covered. Soon, I will also throw in some scripts that automate the TPM2 setup. I also think about making a slight rewrite in a separate branch that would indeed use TPM2 encrypting facilities rather than NV store, as suggested in the mailing list thread. I can now see how this would be a much better solution overall - with the config and encrypted passphrase that could reside simply in a file on the EFI partition.
(In reply to s.adaszewski from comment #3) I am very grateful for the work that you have done on this and for uploading the code to github. I stopped building custom kernels a couple of years ago but, I will start again to test this code. I have a use for this code today. I was hoping to find a 'HowTo' and was suprised that after two years, this still isn't in RELEASE. I work in an organisation that is predominantly staffed by volunteers. Many of us have contributed good ideas for improvements but ideas often get shelved usually because of insufficient practical support from the rest of the organisation. This is usually because others don't understand the idea well enough, or don't see why they should put in the extra work to see it completed. They simply don't appreciate the benefit. In FreeBSD terms, I think this could mean that for this code to get pulled into a release, the following is likely to be needed, and those people willing and able to do the work required to achieve it. The FreeBSD installer will need to be modified to: - Test for the presence of a suitable TPM chip or fTPM - To offer the option of using the TPM and initialising it with required keys - To offer the option of using the TPM for full disk encryption The FreeBSD handbook will need additional content for: - Describing the benefits of using a TPM with some example use cases - How to retro-install an existing TPM equipped machine for new encrypted filesystems - Document the supporting packages that are required Eg. tpm2-tools and example use cases - Document the changes to /boot/loader.conf , /etc/rc.conf The bigger picture is doing the same for: - Using the TPM's RNG - Configuring VPNs to use TPM - Configuring SSH to use TPM - Using the TPM with finger print readers and smartcards for authentication - Using a TPM in a certificate authority Useful links to help appreciate the inadequate documentation in the FreeBSD Handbook concerning using a TPM with FreeBSD: https://reviews.freebsd.org/D19620?id= https://github.com/tpm2-software/tpm2-pkcs11 https://linderud.dev/blog/store-ssh-keys-inside-the-tpm-ssh-tpm-agent/ https://www.evolware.org/2020/05/20/notes-on-using-a-tpm2-module-on-linux/ https://www.hardill.me.uk/wordpress/2021/02/07/adding-a-tpm-to-my-offline-certificate-authority/ I will try to do some of this work if I can get it running. -Vince-