mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-20 21:43:11 +00:00
353a0efe6f
This adds support for seamless booting of Qubes with a TPM disk key, as well as signing of qubes files in /boot with a Yubikey. The signed hashes also includes a TPM counter, which is incremented when new hashes are signed. This prevents rollback attacks against the /boot filesystem. The TPMTOTP value is presented to the user at the time of entering the disk encryption keys. Hitting enter will generate a new code. The LUKS headers are included in the TPM sealing of the disk encryption keys.
84 lines
2.6 KiB
Bash
Executable File
84 lines
2.6 KiB
Bash
Executable File
#!/bin/sh
|
|
# Boot a Qubes installation that has already been setup.
|
|
# This depends on the PCR 4 being "normal-boot":
|
|
# f8fa3b6e32e7c6fe04c366e74636e505b28f3b0d
|
|
# which is only set if the top level /init script has started
|
|
# without user intervention or dropping into a recovery shell.
|
|
|
|
. /etc/functions
|
|
. /etc/config
|
|
|
|
if [ "$1" = "recovery" ]; then
|
|
warn "Recovery mode boot; ignoring key failures"
|
|
RECOVERY=1
|
|
fi
|
|
|
|
# TODO: Allow /boot to be encrypted?
|
|
# This would require a different TPM key, a user passphrase to decrypt it,
|
|
# or loading the USB modules to talk to a Yubikey to get the thing.
|
|
if ! grep -q /boot /proc/mounts ; then
|
|
mount -o ro "$CONFIG_QUBES_BOOT_DEV" /boot \
|
|
|| recovery '$CONFIG_BOOT_DEV: Unable to mount /boot'
|
|
fi
|
|
|
|
BOOT_HASHES=/boot/boot.hashes
|
|
if [ ! -r "$BOOT_HASHES" ]; then
|
|
recovery "$BOOT_HASHES does not exist; re-run qubes-update"
|
|
fi
|
|
|
|
# Verify the signature on the hashes
|
|
gpgv "$BOOT_HASHES.asc" "$BOOT_HASHES" \
|
|
|| recovery 'boot hashes signature failed'
|
|
|
|
# Retrieve the TPM counter ID and generate its current value
|
|
TPM_COUNTER=`grep counter $BOOT_HASHES | cut -d- -f2`
|
|
if [ -z "$TPM_COUNTER" ]; then
|
|
recovery "$BOOT_HASHES: TPM counter not found?"
|
|
fi
|
|
|
|
tpm counter_read -ix "$TPM_COUNTER" | tee "/tmp/counter-$TPM_COUNTER"
|
|
|
|
# Check the hashes of all the files
|
|
sha256sum -c "$BOOT_HASHES" \
|
|
|| recovery "$BOOT_HASHES: hash mismatch"
|
|
|
|
XEN=`grep /boot/xen $BOOT_HASHES | cut -d\ -f3 | tail -1`
|
|
KERNEL=`grep /boot/vmlin $BOOT_HASHES | cut -d\ -f3 | tail -1`
|
|
INITRD=`grep /boot/initram $BOOT_HASHES | cut -d\ -f3 | tail -1`
|
|
|
|
# Activate the dom0 group
|
|
lvm vgchange -a y "$CONFIG_QUBES_VG" \
|
|
|| recovery "$CONFIG_QUBES_VG: LVM volume group activate failed"
|
|
|
|
# Measure the LUKS headers before we unseal the disk key
|
|
qubes-measure-luks /dev/$CONFIG_QUBES_VG/* \
|
|
|| recovery "LUKS measure failed"
|
|
|
|
# Unpack the initrd and fixup the /etc/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
|
|
mkdir -p "$INITRD_DIR/etc"
|
|
|
|
# Attempt to unseal the disk key from the TPM
|
|
# should we give this some number of tries?
|
|
if ! unseal-key "$INITRD_DIR/secret.key" ; then
|
|
warn 'Unseal disk key failed'
|
|
if [ -z "$RECOVERY" ]; then
|
|
recovery 'Starting recovery shell'
|
|
fi
|
|
fi
|
|
|
|
# Override PCR 4 so that user can't read the key
|
|
tpm extend -ix 4 -ic qubes \
|
|
|| recovery 'Unable to scramble PCR'
|
|
|
|
echo '+++ Building initrd'
|
|
( cd "$INITRD_DIR" ; find . | cpio -H newc -o ) > "$SECRET_CPIO"
|
|
cat "$INITRD" >> "$SECRET_CPIO"
|
|
|
|
/bin/qubes-boot "$XEN" "$KERNEL" "$SECRET_CPIO"
|
|
|
|
recovery "Something failed..."
|