From 8fcf1ddba8d1dd56332a5b156591574e69b6d3ab Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 2 Apr 2024 17:06:12 -0400 Subject: [PATCH 1/4] Makefile: add real.gitclean target which calls 'git clean -fxd' Ease cleaning up everything. IMOH better then real.clean target Signed-off-by: Thierry Laurion --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index a64d4b09f..4f113d9c9 100644 --- a/Makefile +++ b/Makefile @@ -793,3 +793,5 @@ real.clean: fi; \ done cd install && rm -rf -- * +real.gitclean: + git clean -fxd From adda59c6752719bb4cbbbfcd5268bff00df5bbdf Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Tue, 26 Mar 2024 14:20:48 -0400 Subject: [PATCH 2/4] LUKS header change validation at both sealing and unsealing of TPM Disk Unlock Key. Fixes linuxboot#1092. Supersedes linuxboot#1093 - Cherry-picks ed1c23a (credit to @hardened-vault) thank you!) - Addresses and correct self-review under linuxboot#1093 (@hardened-vault: you don't answer often here!) - kexec-unseal-key: Warn a user who attempts to default boot while his Disk Unlock Key passphrase fails to unseal because LUKS headers changed. (linuxboot#1093 (comment)) - kexec-seal-key: Identical as in ed1c23a - kexec-add-key: Tell the user that the Headers did not change when changing TPM released Disk Unlock Key (Through changing default boot at Options->Boot Options -> Show OS boot options: select a new boot option and set a Disk Unlock Key in TPM, accept to modify disk and sign /boot options) - Here, we cancel the diff output shown on screen linuxboot#1093 (comment) - And we change the warning given to the user to past tense "Headers of LUKS containers to be unlocked via TPM Disk Unlock Key passphrase did not change." Signed-off-by: Thierry Laurion --- initrd/bin/kexec-insert-key | 3 +++ initrd/bin/kexec-unseal-key | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/initrd/bin/kexec-insert-key b/initrd/bin/kexec-insert-key index f06c54833..674aab4e6 100755 --- a/initrd/bin/kexec-insert-key +++ b/initrd/bin/kexec-insert-key @@ -57,6 +57,9 @@ tpmr extend -ix 4 -ic generic || # Check to continue if [ "$unseal_failed" = "y" ]; then confirm_boot="n" + if diff "$(dirname $INITRD)/kexec_lukshdr_hash.txt" /tmp/luksDump.txt > /dev/null 2>&1; then + echo "Headers of LUKS containers to be unlocked via TPM Disk Unlock Key passphrase did not change." + fi read \ -n 1 \ -p "Do you wish to boot and use the LUKS Disk Recovery Key? [Y/n] " \ diff --git a/initrd/bin/kexec-unseal-key b/initrd/bin/kexec-unseal-key index 3f18c4358..6f5cbd9f2 100755 --- a/initrd/bin/kexec-unseal-key +++ b/initrd/bin/kexec-unseal-key @@ -40,6 +40,14 @@ for tries in 1 2 3; do DEBUG $(pcrs) warn "Unable to unseal disk encryption key" + if [ -e /boot/kexec_lukshdr_hash.txt -a -e /tmp/luksDump.txt ]; then + if ! diff /boot/kexec_lukshdr_hash.txt /tmp/luksDump.txt > /dev/null 2>&1; then + warn "Encrypted LUKS(es) container(s) headers changed since they were measured and sealed in TPM for Disk Unlock key. You might want to investigate." + fi + else + warn "No encrypted LUKS container(s) headers were found/comparable under /boot/kexec_lukshdr_hash.txt" + warn "You might need to setup a new boot default and Disk Unlock Key from Options->Boot Options->Show OS boot menu." + fi done die "Retry count exceeded..." From f6232aa70f7d16fd637e8974228451b61b2cd45e Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 27 Mar 2024 10:04:10 -0400 Subject: [PATCH 3/4] Change disk encryption -> LUKS Disk Key and other relative/relative verbiage, remove irrelevant DEBUG trace under kexec-unseal-key TODO: - $(pcrs) call sometimes fail in DEBUG call, outputting too many chars to be inserted in kmesg. Call removed here since redundant (PCR6 already extended with LUKS header) - Notes added for TPM2 simplification over TPM1 in code as TODO Signed-off-by: Thierry Laurion --- FAQ.md | 4 ++-- initrd/bin/kexec-insert-key | 14 +++++++------- initrd/bin/kexec-save-default | 2 +- initrd/bin/kexec-select-boot | 4 +++- initrd/bin/kexec-unseal-key | 13 ++++++------- initrd/bin/oem-factory-reset | 2 +- initrd/init | 2 +- 7 files changed, 21 insertions(+), 20 deletions(-) diff --git a/FAQ.md b/FAQ.md index e3909b1d6..1e2c1c609 100644 --- a/FAQ.md +++ b/FAQ.md @@ -112,8 +112,8 @@ your disk password, which is perhaps an improvement. Disk key in TPM (LUKS TPM Disk Unlock Key) or user passphrase? --- -Depends on your threat model. With the disk key in the TPM an attacker -would need to have the entire machine (or a backdoor in the TPM) +Depends on your threat model. With the Disk Unlock Key in the TPM an +attacker would need to have the entire machine (or a backdoor in the TPM) to get the key and their attempts to unlock it can be rate limited by the TPM hardware. diff --git a/initrd/bin/kexec-insert-key b/initrd/bin/kexec-insert-key index 674aab4e6..9a48c2584 100755 --- a/initrd/bin/kexec-insert-key +++ b/initrd/bin/kexec-insert-key @@ -1,5 +1,5 @@ #!/bin/bash -# Unseal a disk key from TPM and add to a new initramfs +# Unseal a LUKS Disk Unlock Key from TPM and add to a new initramfs set -e -o pipefail . /etc/functions @@ -28,7 +28,7 @@ if [ -r "$TMP_KEY_LVM" ]; then die "$VOLUME_GROUP: unable to activate volume group" fi -# Measure the LUKS headers before we unseal the disk key +# Measure the LUKS headers before we unseal the LUKS Disk Unlock Key from TPM cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks || die "LUKS measure failed" @@ -40,13 +40,13 @@ SECRET_CPIO=/tmp/secret/initrd.cpio bootdir=$(dirname "$INITRD") mkdir -p "$INITRD_DIR/etc" -# Attempt to unseal the disk key from the TPM +# Attempt to unseal the Disk Unlok Key from the TPM # should we give this some number of tries? unseal_failed="n" if ! kexec-unseal-key "$INITRD_DIR/secret.key"; then unseal_failed="y" echo - echo "!!! Failed to unseal the TPM LUKS disk key" + echo "!!! Failed to unseal the TPM LUKS Disk Unlock Key" fi # Override PCR 4 so that user can't read the key @@ -57,8 +57,8 @@ tpmr extend -ix 4 -ic generic || # Check to continue if [ "$unseal_failed" = "y" ]; then confirm_boot="n" - if diff "$(dirname $INITRD)/kexec_lukshdr_hash.txt" /tmp/luksDump.txt > /dev/null 2>&1; then - echo "Headers of LUKS containers to be unlocked via TPM Disk Unlock Key passphrase did not change." + if cmp -s "$bootdir/kexec_lukshdr_hash.txt" /tmp/luksDump.txt > /dev/null 2>&1; then + echo "Encrypted disk keys(s) have not been changed since sealed in TPM Disk Unlock Key" fi read \ -n 1 \ @@ -69,7 +69,7 @@ if [ "$unseal_failed" = "y" ]; then -a "$confirm_boot" != 'Y' \ -a -n "$confirm_boot" ] \ ; then - die "!!! Aborting boot due to failure to unseal TPM disk key" + die "!!! Aborting boot due to failure to unseal TPM Disk Unlock Key" fi fi diff --git a/initrd/bin/kexec-save-default b/initrd/bin/kexec-save-default index 1e5fcd810..c7a4f04fa 100755 --- a/initrd/bin/kexec-save-default +++ b/initrd/bin/kexec-save-default @@ -195,7 +195,7 @@ if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" != "y" ] && [ DEBUG "LUKS TPM Disk Unlock Key was previously set up from $KEY_DEVICES" read \ -n 1 \ - -p "Do you want to reseal a disk key to the TPM [y/N]: " \ + -p "Do you want to reseal a Disk Unlock Key in the TPM [y/N]: " \ change_key_confirm echo diff --git a/initrd/bin/kexec-select-boot b/initrd/bin/kexec-select-boot index 4161af4ae..54ce4064b 100755 --- a/initrd/bin/kexec-select-boot +++ b/initrd/bin/kexec-select-boot @@ -70,6 +70,8 @@ if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then else warn "Hash of TPM2 primary key handle does not exist" warn "Please rebuild the boot hash tree" + warn "Select Options-> Update checksums and sign all files in /boot" + #TODO: Simplify/Automatize TPM2 firmware upgrade process. Today: upgrade, reboot, reseal(type TPM owner pass), resign, boot default_failed="y" DEBUG "Hash of TPM2 primary key handle does not exist under $PRIMHASH_FILE" fi @@ -340,7 +342,7 @@ do_boot() { fi kexec-insert-key $INITRD || - die "!!! Failed to insert disk key into a new initrd" + die "!!! Failed to prepare TPM Disk Unlock Key for boot" kexec-boot -b "$bootdir" -e "$option" \ -a "$add" -r "$remove" -o "/tmp/secret/initrd.cpio" || diff --git a/initrd/bin/kexec-unseal-key b/initrd/bin/kexec-unseal-key index 6f5cbd9f2..77597b4ea 100755 --- a/initrd/bin/kexec-unseal-key +++ b/initrd/bin/kexec-unseal-key @@ -38,15 +38,14 @@ for tries in 1 2 3; do exit 0 fi - DEBUG $(pcrs) - warn "Unable to unseal disk encryption key" - if [ -e /boot/kexec_lukshdr_hash.txt -a -e /tmp/luksDump.txt ]; then - if ! diff /boot/kexec_lukshdr_hash.txt /tmp/luksDump.txt > /dev/null 2>&1; then - warn "Encrypted LUKS(es) container(s) headers changed since they were measured and sealed in TPM for Disk Unlock key. You might want to investigate." + warn "Unable to unseal LUKS Disk Unlock Key from TPM" + if [ -e /boot/kexec_lukshdr_hash.txt ] && [ -e /tmp/luksDump.txt ]; then + if ! cmp -s /boot/kexec_lukshdr_hash.txt /tmp/luksDump.txt > /dev/null 2>&1; then + warn "Encrypted disk keys(s) have changed since sealed in TPM Disk Unlock Key. You might want to investigate." fi else - warn "No encrypted LUKS container(s) headers were found/comparable under /boot/kexec_lukshdr_hash.txt" - warn "You might need to setup a new boot default and Disk Unlock Key from Options->Boot Options->Show OS boot menu." + warn "Could not check for tampering of Encrypted disk keys(s)" + warn "Re-seal the TPM Disk Unlock Key by re-selecting your default boot option to enable this check (Options -> Boot Options -> Show OS boot menu)." fi done diff --git a/initrd/bin/oem-factory-reset b/initrd/bin/oem-factory-reset index ff0889f66..2380bf763 100755 --- a/initrd/bin/oem-factory-reset +++ b/initrd/bin/oem-factory-reset @@ -893,7 +893,7 @@ if [ "$use_defaults" == "n" -o "$use_defaults" == "N" ]; then echo "Each prompt requires a single letter answer: eg. (Y/n)." echo -e "If you don't know what to answer, pressing Enter will select the default answer for that prompt: eg. Y, above.\n" - # Re-ownership of encrypted disk key, content and passphrase + # Re-ownership of LUKS encrypted Disk: key, content and passphrase echo -e -n "\n\nWould you like to change the current LUKS Disk Recovery Key passphrase?\n (Highly recommended if you didn't install the Operating System yourself, so that past configured passphrase would not permit to access content.\n Note that without re-encrypting disk, a backed up header could be restored to access encrypted content with old passphrase) [y/N]: " read -n 1 prompt_output echo diff --git a/initrd/init b/initrd/init index 67a179b76..cea537b8d 100755 --- a/initrd/init +++ b/initrd/init @@ -12,7 +12,7 @@ export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin # running out of the ram disk. There are no fileysstems mounted. # It is important to have a way to invoke a recovery shell in case # the boot scripts are messed up, but also important to modify the -# PCRs if this happens to prevent the TPM disk keys from being revealed. +# PCRs if this happens to prevent the TPM Disk Unlock Keys from being revealed. # First thing it is vital to mount the /dev and other system directories mkdir /proc /sys /dev /tmp /boot /media 2>&- 1>&- From fb5cbf41a13c900072e88e9c7a9f24842c8d5fde Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Mon, 8 Apr 2024 16:22:57 -0400 Subject: [PATCH 4/4] kexec-insert-key: refactor tampering check for encrypted disk keys prior of TPM unsealing ops move code from kexec-unseal-key to kexec-insert-key, address code review and apply verbiage suggestion changes Signed-off-by: Thierry Laurion --- initrd/bin/kexec-insert-key | 20 ++++++++++++++++---- initrd/bin/kexec-unseal-key | 8 -------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/initrd/bin/kexec-insert-key b/initrd/bin/kexec-insert-key index 9a48c2584..4d52f73a6 100755 --- a/initrd/bin/kexec-insert-key +++ b/initrd/bin/kexec-insert-key @@ -40,7 +40,22 @@ SECRET_CPIO=/tmp/secret/initrd.cpio bootdir=$(dirname "$INITRD") mkdir -p "$INITRD_DIR/etc" -# Attempt to unseal the Disk Unlok Key from the TPM +if [ -e /boot/kexec_lukshdr_hash.txt ] && [ -e /tmp/luksDump.txt ]; then + if ! cmp -s /boot/kexec_lukshdr_hash.txt /tmp/luksDump.txt >/dev/null 2>&1; then + #LUKS header hash part of detached signed hash digest under boot doesn't match qubes-measure-luks tmp file + warn "Encrypted disk keys have changed since the TPM Disk Unlock Key was sealed. If you did not make this change, the disk may be compromised" + exit 1 + else + #LUKS header hash part of detached signed hash digest matches + echo "+++ Encrypted disk keys have not been changed since sealed in TPM Disk Unlock Key" + #TODO: remove "+++" with boot info helper when added, same with "!!!" currently for info. + fi +else + warn "Could not check for tampering of Encrypted disk keys" + warn "Re-seal the TPM Disk Unlock Key by re-selecting your default boot option to enable this check (Options -> Boot Options -> Show OS boot menu)." +fi + +# Attempt to unseal the Disk Unlock Key from the TPM # should we give this some number of tries? unseal_failed="n" if ! kexec-unseal-key "$INITRD_DIR/secret.key"; then @@ -57,9 +72,6 @@ tpmr extend -ix 4 -ic generic || # Check to continue if [ "$unseal_failed" = "y" ]; then confirm_boot="n" - if cmp -s "$bootdir/kexec_lukshdr_hash.txt" /tmp/luksDump.txt > /dev/null 2>&1; then - echo "Encrypted disk keys(s) have not been changed since sealed in TPM Disk Unlock Key" - fi read \ -n 1 \ -p "Do you wish to boot and use the LUKS Disk Recovery Key? [Y/n] " \ diff --git a/initrd/bin/kexec-unseal-key b/initrd/bin/kexec-unseal-key index 77597b4ea..346eda9b8 100755 --- a/initrd/bin/kexec-unseal-key +++ b/initrd/bin/kexec-unseal-key @@ -39,14 +39,6 @@ for tries in 1 2 3; do fi warn "Unable to unseal LUKS Disk Unlock Key from TPM" - if [ -e /boot/kexec_lukshdr_hash.txt ] && [ -e /tmp/luksDump.txt ]; then - if ! cmp -s /boot/kexec_lukshdr_hash.txt /tmp/luksDump.txt > /dev/null 2>&1; then - warn "Encrypted disk keys(s) have changed since sealed in TPM Disk Unlock Key. You might want to investigate." - fi - else - warn "Could not check for tampering of Encrypted disk keys(s)" - warn "Re-seal the TPM Disk Unlock Key by re-selecting your default boot option to enable this check (Options -> Boot Options -> Show OS boot menu)." - fi done die "Retry count exceeded..."