diff mbox series

[isar-cip-core] Seal tpm key for disk encryption using PCR11.

Message ID 20241206114443.64042-1-alexander.heinisch@siemens.com (mailing list archive)
State New
Headers show
Series [isar-cip-core] Seal tpm key for disk encryption using PCR11. | expand

Commit Message

Heinisch, Alexander Dec. 6, 2024, 11:44 a.m. UTC
From: Alexander Heinisch <alexander.heinisch@siemens.com>

The recently introduced sealing of the tpm key for disk encryption
was bound to PCR7 only. Since PCR[0-7] are exclusively for use in
platform firmware I switched to seal the key after cryptsetup by
modifying PCR11. PCR11 was chosen because of a similar approach
in systemd where the actual state of the initramfs is reflected.

Signed-off-by: Alexander Heinisch <alexander.heinisch@siemens.com>
---
 .../files/encrypt_partition.clevis.script           | 12 +++++++++++-
 .../files/encrypt_partition.systemd.script          | 13 ++++++++++++-
 .../initramfs-crypt-hook/files/local-top-complete   |  8 ++++----
 3 files changed, 27 insertions(+), 6 deletions(-)

Comments

Jan Kiszka Dec. 8, 2024, 9:16 a.m. UTC | #1
On 06.12.24 12:44, alexander.heinisch@siemens.com wrote:
> From: Alexander Heinisch <alexander.heinisch@siemens.com>
> 
> The recently introduced sealing of the tpm key for disk encryption
> was bound to PCR7 only. Since PCR[0-7] are exclusively for use in
> platform firmware I switched to seal the key after cryptsetup by
> modifying PCR11. PCR11 was chosen because of a similar approach
> in systemd where the actual state of the initramfs is reflected.
> 

As expected, it's not that simple: PCR11 is extended with the kernel
image and more, at least when using system-stub. So, before basing the
disk keys on that, we would have to implement proper measured boot,
including measurement updates for A/B so that we do not "lose" the key
when installing a new UKI.

What would not be a problem are preexisting systems that linked the keys
only to PCR7 on enrollment. Those would indeed still work with the new
crypt hook.

Jan
diff mbox series

Patch

diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.clevis.script b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.clevis.script
index ceeacd1..b63dd94 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.clevis.script
+++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.clevis.script
@@ -27,7 +27,7 @@  enroll_tpm2_token() {
 	tpm_key_algorithm="$4"
 	pcr_bank_hash_type="$5"
 	if [ -x /usr/bin/clevis ]; then
-		TPM2TOOLS_TCTI="device:$tpm_device" clevis luks bind -d "$partition_device" tpm2 '{"key":"'"$tpm_key_algorithm"'", "pcr_bank":"'"$pcr_bank_hash_type"'","pcr_ids":"7"}' < "$passphrase"
+		TPM2TOOLS_TCTI="device:$tpm_device" clevis luks bind -d "$partition_device" tpm2 '{"key":"'"$tpm_key_algorithm"'", "pcr_bank":"'"$pcr_bank_hash_type"'","pcr_ids":"7,11"}' < "$passphrase"
 	else
 		panic "clevis not available cannot enroll tpm2 key!"
 	fi
@@ -44,3 +44,13 @@  finalize_tpm2_encryption() {
 	partition_device="$1"
 	cryptsetup -v luksKillSlot -q  "$partition_device" 0
 }
+
+# invalidate PCR11 to lock access to the disk keys
+invalidate_pcr11() {
+    pcr_bank_hash_type="$1"
+
+    # generate a hash digest based on desired pcr_bank_hash_type
+    hash_digest_extend=$(echo "leaving-initramfs-crypt-hook" | eval "openssl dgst -$pcr_bank_hash_type" | sed "s/.*= //")
+    # invalidate PCR11 to lock access to the disk keys
+    tpm2_pcrextend 11:"$pcr_bank_hash_type"="$hash_digest_extend"
+}
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.systemd.script b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.systemd.script
index 1b7c83b..24b4d69 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.systemd.script
+++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.systemd.script
@@ -36,7 +36,7 @@  enroll_tpm2_token() {
 			PASSWORD=$(cat "$passphrase" )
 			export PASSWORD
 			/usr/bin/systemd-cryptenroll --tpm2-device="$tpm_device" \
-				 --tpm2-pcrs=7 "$partition_device"
+				 --tpm2-pcrs=7+11 "$partition_device"
 			PASSWORD=
 		else
 			panic "Unknown systemd version: '$systemd_version'!"
@@ -55,3 +55,14 @@  finalize_tpm2_encryption() {
 	/usr/bin/systemd-cryptenroll --wipe-slot=0 "$partition_device"
 }
 
+# invalidate PCR11 to lock access to the disk keys
+invalidate_pcr11() {
+    #pcr_bank_hash_type="$1"
+
+    # systemd-cryptenroll in version 252 always uses
+    # sha256 as preferred pcr bank hash type
+    # and sha1 as a fallback if nothing else exists
+
+    # generate a hash digest for sha1 and sha256 (input was "leaving-initramfs-crypt-hook")
+    tpm2_pcrextend 11:sha1=d57309e7907cb50d96b8436eaea074e4204eca86,sha256=12e47e8ce6b0bf565fe88691356de4be41d834c5eb620879d086b9fd9a5b2d6e
+}
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index 4bcb427..4f71b92 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -155,12 +155,12 @@  expand_partition() {
 
 for candidate in /dev/tpm*; do
 	if [ -x /usr/bin/tpm2_pcrread ]; then
-		if ! tpm2_pcrread -T device:"$candidate" "$pcr_bank_hash_type":7 --quiet ; then
+		if ! tpm2_pcrread -T device:"$candidate" "$pcr_bank_hash_type":7,11 --quiet ; then
 			continue
 		fi
 	elif [ -x /usr/bin/tpm2_pcrlist ]; then
 		export TPM2TOOLS_DEVICE_FILE="$candidate"
-		if ! tpm2_pcrlist -L "$pcr_bank_hash_type":7 > /dev/null; then
+		if ! tpm2_pcrlist -L "$pcr_bank_hash_type":7,11 > /dev/null; then
 			continue
 		fi
 	fi
@@ -258,8 +258,8 @@  for partition_set in $partition_sets; do
 	finalize_tpm2_encryption "$part_device"
 done
 
-# invalidate PCR7 to lock access to the disk keys
-tpm2_pcrextend 7:sha1=1111111111111111111111111111111111111111,sha256=1111111111111111111111111111111111111111111111111111111111111111
+# invalidate PCR11 to lock access to the disk keys
+invalidate_pcr11 "$pcr_bank_hash_type"
 
 if [ -n "$watchdog_pid" ]; then
 	kill "$watchdog_pid"