#!/bin/bash # This will generate a disk encryption key and seal / ecncrypt # with the current PCRs and then store it in the TPM NVRAM. # It will then need to be bundled into initrd that is booted. set -e -o pipefail . /etc/functions TPM_INDEX=3 TPM_SIZE=312 KEY_FILE="/tmp/secret/secret.key" TPM_SEALED="/tmp/secret/secret.sealed" RECOVERY_KEY="/tmp/secret/recovery.key" . /etc/functions . /tmp/config TRACE "Under kexec-seal-key" paramsdir=$1 if [ -z "$paramsdir" ]; then die "Usage $0 /boot" fi KEY_DEVICES="$paramsdir/kexec_key_devices.txt" KEY_LVM="$paramsdir/kexec_key_lvm.txt" if [ ! -r "$KEY_DEVICES" ]; then die "No devices defined for disk encryption" fi if [ -r "$KEY_LVM" ]; then # Activate the LVM volume group VOLUME_GROUP=`cat $KEY_LVM` if [ -z "$VOLUME_GROUP" ]; 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 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: " disk_password echo -n "$disk_password" > "$RECOVERY_KEY" echo read -s -p "New disk unlock password for booting: " key_password echo read -s -p "Repeat unlock code: " key_password2 echo if [ "$key_password" != "$key_password2" ]; then die "Key passwords do not match" fi # Generate key file dd \ if=/dev/urandom \ of="$KEY_FILE" \ bs=1 \ count=128 \ 2>/dev/null \ || die "Unable to generate 128 random bytes" # Remove all the old keys from slot 1 for dev in `cat "$KEY_DEVICES" | cut -d\ -f1`; do echo "++++++ $dev: Removing old key slot" cryptsetup luksKillSlot \ --key-file "$RECOVERY_KEY" \ $dev 1 \ || warn "$dev: ignoring problem" echo "++++++ $dev: Adding key" cryptsetup luksAddKey \ --key-file "$RECOVERY_KEY" \ --key-slot 1 \ $dev "$KEY_FILE" \ || die "$dev: Unable to add key" done # Now that we have setup the new keys, measure the PCRs # We don't care what ends up in PCR 6; we just want # to get the /tmp/luksDump.txt file. We use PCR16 # since it should still be zero cat "$KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks \ || die "Unable to measure the LUKS headers" pcrf="/tmp/secret/pcrf.bin" tpmr pcrread 0 "$pcrf" tpmr pcrread -a 1 "$pcrf" tpmr pcrread -a 2 "$pcrf" tpmr pcrread -a 3 "$pcrf" # Note that PCR 4 needs to be set with the "normal-boot" path value, which is 0. dd if=/dev/zero bs="$(tpmr pcrsize)" count=1 status=none >> "$pcrf" if [ "$CONFIG_USB_KEYBOARD" = "y" -o -r /lib/modules/libata.ko -o -x /bin/hotp_verification ]; then DEBUG "Sealing TPM disk unlock key with PCR5 involvement (additional kernel modules are loaded per board config)..." # Here, we take pcr 5 into consideration if modules are expected to be measured+loaded tpmr pcrread -a 5 "$pcrf" else DEBUG "Sealing TPM disk unlock key with PCR5=0 (NO additional kernel modules are loaded per board config)..." #no kernel modules are expected to be measured+loaded dd if=/dev/zero bs="$(tpmr pcrsize)" count=1 status=none >> "$pcrf" fi # Precompute the value for pcr 6 DEBUG "Precomputing TPM future value for PCR6 sealing/unsealing of TPM disk unlock key..." tpmr calcfuturepcr -a "/tmp/luksDump.txt" "$pcrf" # We take into consideration user files in cbfs tpmr pcrread -a 7 "$pcrf" DO_WITH_DEBUG --mask-position 7 \ tpmr seal "$KEY_FILE" "$TPM_INDEX" 0,1,2,3,4,5,6,7 "$pcrf" \ "$TPM_SIZE" "$key_password" # should be okay if this fails shred -n 10 -z -u "$pcrf".* 2> /dev/null || true shred -n 10 -z -u "$KEY_FILE" 2> /dev/null \ || warn "Failed to delete key file - continuing" cp /tmp/luksDump.txt "$paramsdir/kexec_lukshdr_hash.txt" \ || warn "Failed to have hashes of LUKS header - continuing"