#!/bin/sh # Unseal a disk key from TPM and add to a new initramfs set -e -o pipefail . /etc/functions 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 disk key cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \ || die "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 ! kexec-unseal-key "$INITRD_DIR/secret.key" ; then die 'Unseal disk key failed' fi # Override PCR 4 so that user can't read the key tpm extend -ix 4 -ic generic \ || die 'Unable to scramble PCR' 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" # overwrite /etc/crypttab to mirror the behavior for in seal-key for uuid in `cat "$TMP_KEY_DEVICES" | cut -d\ -f2`; do echo "luks-$uuid UUID=$uuid /secret.key" >> "$INITRD_DIR/etc/crypttab" done ( cd "$INITRD_DIR" ; find . -type f | cpio -H newc -o ) >> "$SECRET_CPIO"