mirror of
https://github.com/linuxboot/heads.git
synced 2025-03-14 00:06:47 +00:00
Quiet mode introduced output reduction to console to limit technical info provided to end users. Previous informational output (previous default) now outputs this now considered additional information through INFO() calls, which either outputs to console, or debug.log Only DO_WITH_DEBUG should call LOG directly, so that stderr+stdout output is prepended with LOG into debug.log This fixes previous implementation which called LOG in DO_WITH_DEBUG calls and modified expected output to files, which was observed by @3hhh in output of GRUB entries when selecting boot option. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
131 lines
4.9 KiB
Bash
Executable File
131 lines
4.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# Unseal a LUKS Disk Unlock Key from TPM and add to a new initramfs
|
|
set -e -o pipefail
|
|
. /etc/functions
|
|
|
|
TRACE_FUNC
|
|
|
|
TMP_KEY_DEVICES="/tmp/kexec/kexec_key_devices.txt"
|
|
TMP_KEY_LVM="/tmp/kexec/kexec_key_lvm.txt"
|
|
|
|
INITRD="$1"
|
|
|
|
if [ -z "$INITRD" ]; then
|
|
die "Usage: $0 /boot/initramfs... "
|
|
fi
|
|
|
|
if [ ! -r "$TMP_KEY_DEVICES" ]; then
|
|
die "No devices defined for disk encryption"
|
|
fi
|
|
|
|
if [ -r "$TMP_KEY_LVM" ]; then
|
|
# Activate the LVM volume group
|
|
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"
|
|
fi
|
|
|
|
# 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"
|
|
|
|
# Unpack the initrd and fixup the crypttab
|
|
# this is a hack to split it into two parts since
|
|
# we know that the first 0x3400 bytes are the microcode
|
|
INITRD_DIR=/tmp/secret/initrd
|
|
SECRET_CPIO=/tmp/secret/initrd.cpio
|
|
bootdir=$(dirname "$INITRD")
|
|
mkdir -p "$INITRD_DIR/etc"
|
|
|
|
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
|
|
unseal_failed="y"
|
|
echo
|
|
echo "!!! Failed to unseal the TPM LUKS Disk Unlock Key"
|
|
fi
|
|
|
|
# Override PCR 4 so that user can't read the key
|
|
TRACE_FUNC
|
|
INFO "TPM: Extending PCR[4] to prevent any future secret unsealing"
|
|
tpmr extend -ix 4 -ic generic ||
|
|
die 'Unable to scramble PCR'
|
|
|
|
# Check to continue
|
|
if [ "$unseal_failed" = "y" ]; then
|
|
confirm_boot="n"
|
|
read \
|
|
-n 1 \
|
|
-p "Do you wish to boot and use the LUKS Disk Recovery Key? [Y/n] " \
|
|
confirm_boot
|
|
echo
|
|
|
|
if [ "$confirm_boot" != 'y' \
|
|
-a "$confirm_boot" != 'Y' \
|
|
-a -n "$confirm_boot" ] \
|
|
; then
|
|
die "!!! Aborting boot due to failure to unseal TPM Disk Unlock Key"
|
|
fi
|
|
fi
|
|
|
|
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 > /dev/null 2>&1 ||
|
|
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
|
|
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..."
|
|
# kexec-save-default has found crypttab files under initrd and saved them
|
|
cat "$bootdir/kexec_initrd_crypttab_overrides.txt" | while read line; do
|
|
crypttab_file=$(echo "$line" | awk -F ':' {'print $1'})
|
|
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 "+++ 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
|
|
# 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"
|
|
fi
|