Skip to content

Commit

Permalink
TPM Disk Unlock Key fixes for TPM1/TMP2 (fixes #1474)
Browse files Browse the repository at this point in the history
  • Loading branch information
tlaurion committed Aug 30, 2023
1 parent 2655441 commit bca4469
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 26 deletions.
1 change: 0 additions & 1 deletion initrd/bin/gui-init
Expand Up @@ -580,7 +580,6 @@ reset_tpm()
warn "Removing rollback and primary handle hash under /boot"
rm -f /boot/kexec_rollback.txt
rm -f /boot/kexec_primhdl_hash.txt
#TODO: When primhdl_hash is gone but not recreated and signed: fail at TPM Disk Unlock Key for TPM2....

# create Heads TPM counter before any others
check_tpm_counter /boot/kexec_rollback.txt "" "$key_password" \
Expand Down
51 changes: 29 additions & 22 deletions initrd/bin/kexec-insert-key
Expand Up @@ -20,17 +20,17 @@ fi

if [ -r "$TMP_KEY_LVM" ]; then
# Activate the LVM volume group
VOLUME_GROUP=`cat $TMP_KEY_LVM`
VOLUME_GROUP=$(cat $TMP_KEY_LVM)
if [ -z "$TMP_KEY_LVM" ]; then
die "No LVM volume group defined for activation"
fi
lvm vgchange -a y $VOLUME_GROUP \
|| die "$VOLUME_GROUP: unable to activate volume group"
lvm vgchange -a y $VOLUME_GROUP ||
die "$VOLUME_GROUP: unable to activate volume group"
fi

# Measure the LUKS headers before we unseal the disk key
cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \
|| die "LUKS measure failed"
cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks ||
die "LUKS measure failed"

# Unpack the initrd and fixup the crypttab
# this is a hack to split it into two parts since
Expand All @@ -43,14 +43,14 @@ mkdir -p "$INITRD_DIR/etc"
# Attempt to unseal the disk key from the TPM
# should we give this some number of tries?
unseal_failed="n"
if ! kexec-unseal-key "$INITRD_DIR/secret.key" ; then
if ! kexec-unseal-key "$INITRD_DIR/secret.key"; then
unseal_failed="y"
echo "!!! Failed to unseal the TPM LUKS disk key"
fi

# Override PCR 4 so that user can't read the key
tpmr extend -ix 4 -ic generic \
|| die 'Unable to scramble PCR'
tpmr extend -ix 4 -ic generic ||
die 'Unable to scramble PCR'

# Check to continue
if [ "$unseal_failed" = "y" ]; then
Expand All @@ -63,21 +63,21 @@ if [ "$unseal_failed" = "y" ]; then
if [ "$confirm_boot" != 'y' \
-a "$confirm_boot" != 'Y' \
-a -n "$confirm_boot" ] \
; then
; then
die "!!! Aborting boot due to failure to unseal TPM disk key"
fi
fi

echo
echo
echo '+++ Building initrd'
# pad the initramfs (dracut doesn't pad the last gz blob)
# without this the kernel init/initramfs.c fails to read
# the subsequent uncompressed/compressed cpio
dd if="$INITRD" of="$SECRET_CPIO" bs=512 conv=sync \
|| die "Failed to copy initrd to /tmp"
dd if="$INITRD" of="$SECRET_CPIO" bs=512 conv=sync ||
die "Failed to copy initrd to /tmp"

if [ "$unseal_failed" = "n" ]; then
# kexec-save-default might have created crypttab overrides to be injected in initramfs through additional cpio
# kexec-save-default might have created crypttab overrides to be injected in initramfs through additional cpio
if [ -r "$bootdir/kexec_initrd_crypttab_overrides.txt" ]; then
echo "+++ $bootdir/kexec_initrd_crypttab_overrides.txt found..."
echo "+++ Preparing initramfs crypttab overrides as defined under $bootdir/kexec_initrd_crypttab_overrides.txt to be injected through cpio at next kexec call..."
Expand All @@ -87,19 +87,26 @@ if [ "$unseal_failed" = "n" ]; then
crypttab_entry=$(echo "$line" | awk -F ':' {'print $NF'})
# Replace each initrd crypttab file with modified entry containing /secret.key path
mkdir -p "$INITRD_DIR/$(dirname $crypttab_file)"
echo "$crypttab_entry" | tee -a "$INITRD_DIR/$crypttab_file" > /dev/null
echo "$crypttab_entry" | tee -a "$INITRD_DIR/$crypttab_file" >/dev/null
echo "+++ initramfs's $crypttab_file will be overriden with: $crypttab_entry"
done
else
# No crypttab files were found under selected default boot option's initrd file
crypttab_file="etc/crypttab"
mkdir -p "$INITRD_DIR/$(dirname $crypttab_file)"
# overwrite crypttab to mirror behavior of seal-key
echo "+++ The following /etc/crypttab lines will be passed through cpio into kexec call for default boot option:"
for uuid in `cat "$TMP_KEY_DEVICES" | cut -d\ -f2`; do
# NOTE: discard operation (TRIM) is activated by default if no crypptab found in initrd
echo "luks-$uuid UUID=$uuid /secret.key luks,discard" | tee -a "$INITRD_DIR/$crypttab_file"
# TODO: cpio -t is unfit here :( it just extracts early cpio header and not the whole file. Replace with something else
# Meanwhile, force crypttab to be created from scratch on both possible locations: /etc/crypttab and /cryptroot/crypttab
crypttab_files="etc/crypttab cryptroot/crypttab"
for crypttab_file in $crypttab_files; do
mkdir -p "$INITRD_DIR/$(dirname $crypttab_file)"
# overwrite crypttab to mirror behavior of seal-key
echo "+++ The following $crypttab_file overrides will be passed through concatenated secret/initrd.cpio at kexec call:"
for uuid in $(cat "$TMP_KEY_DEVICES" | cut -d\ -f2); do
# NOTE: discard operation (TRIM) is activated by default if no crypptab found in initrd
echo "luks-$uuid UUID=$uuid /secret.key luks,discard" | tee -a "$INITRD_DIR/$crypttab_file"
done
done
fi
( cd "$INITRD_DIR" ; find . -type f | cpio -H newc -o ) >> "$SECRET_CPIO"
(
cd "$INITRD_DIR"
find . -type f | cpio -H newc -o
) >>"$SECRET_CPIO"
fi
7 changes: 4 additions & 3 deletions initrd/bin/kexec-seal-key
Expand Up @@ -47,13 +47,13 @@ DEBUG "$(pcrs)"
# LUKS Key slot 0 is the manual recovery pass phrase
# that they user entered when they installed OS,
# key slot 1 is the one that we've generated.
read -s -p "Enter disk recovery key/passphrase: " disk_password
read -s -p "Enter Disk Recovery Key/passphrase: " disk_password
echo -n "$disk_password" >"$RECOVERY_KEY"
echo

read -s -p "New TPM Disk Unlock Key passphrase for booting: " key_password
echo
read -s -p "Repeat TPM Disk Unlock key passphrase: " key_password2
read -s -p "Repeat TPM Disk Unlock key passphrase for booting: " key_password2
echo

if [ "$key_password" != "$key_password2" ]; then
Expand Down Expand Up @@ -84,7 +84,8 @@ for dev in $(cat "$KEY_DEVICES" | cut -d\ -f1); do
die "Slot 1 should not be the only one existing on $dev. Fix your custom setup"
fi
else
DEBUG "Slot 1 is not the only one existing on $dev. It is safe to use it to store TPM sealed LUKS Disk Unlock Key"
DEBUG "Slot 1 is not the only one existing on $dev"
DEBUG "$dev Slot 1 will be used to store LUKS Disk Unlock Key that will be sealed into TPM next"
fi
done

Expand Down

0 comments on commit bca4469

Please sign in to comment.