[Bug 260138] TPM2 Support in bootloader / kernel in order to retrieve GELI passphrase

From: <bugzilla-noreply_at_freebsd.org>
Date: Tue, 30 Nov 2021 12:29:31 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=260138

            Bug ID: 260138
           Summary: TPM2 Support in bootloader / kernel in order to
                    retrieve GELI passphrase
           Product: Base System
           Version: 13.0-RELEASE
          Hardware: amd64
                OS: Any
            Status: New
          Keywords: feature, loader, patch-ready, security, uefi
          Severity: Affects Many People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: s.adaszewski@gmail.com

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

-- 
You are receiving this mail because:
You are the assignee for the bug.