#!/bin/sh
# 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 with Qubes.

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
. /etc/config

# Activate the LVM volume group
VOLUME_GROUP=qubes_dom0
lvm vgchange -a y $VOLUME_GROUP \
	|| die "$VOLUME_GROUP: unable to activate volume group"

# Key slot 0 is the manual recovery pass phrase
# that they user entered when they installed Qubes,
# 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

# Remove all the old keys from slot 1
for dev in /dev/$VOLUME_GROUP/*; do
	echo "++++++ $dev: Removing old key slot"
	cryptsetup luksKillSlot \
		--key-file "$RECOVERY_KEY" \
		$dev 1 \
	|| warn "$dev: ignoring problem"
done

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

dd \
	if=/dev/urandom \
	of="$KEY_FILE" \
	bs=1 \
	count=128 \
	2>/dev/null \
|| die "Unable to generate 128 random bytes"

for dev in /dev/$VOLUME_GROUP/*; do
	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
/bin/qubes-measure-luks /dev/$VOLUME_GROUP/* \
	|| die "Unable to measure the LUKS headers"
luks_pcr=`tpm calcfuturepcr -ix 16 -if /tmp/luksDump.txt`

# Note that PCR 4 needs to be set with the "normal-boot"
# path value, which we do not have right now since we are
# in a recovery shell.
# used to be -ix 4 f8fa3b6e32e7c6fe04c366e74636e505b28f3b0d \
# now just all zeros in a normal boot
# PCR 5 must be all zero since no kernel modules should have
# been loaded during a normal boot, but might have been
# loaded in the recovery shell.
# Otherwise use the current values of the PCRs, which will be read
# from the TPM as part of the sealing ("X").
tpm sealfile2 \
	-if "$KEY_FILE" \
	-of "$TPM_SEALED" \
	-pwdd "$key_password" \
	-hk 40000000 \
	-ix 0 X \
	-ix 1 X \
	-ix 2 X \
	-ix 3 X \
	-ix 4 0000000000000000000000000000000000000000 \
	-ix 5 0000000000000000000000000000000000000000 \
	-ix 6 $luks_pcr \
|| die "Unable to seal secret"

rm -f "$KEY_FILE"

# try it without the owner password first
if ! tpm nv_writevalue \
	-in $TPM_INDEX \
	-if "$TPM_SEALED" \
; then
	# to create an nvram space we need the TPM owner password
	# and the TPM physical presence must be asserted.
	#
	# The permissions are 0 since there is nothing special
	# about the sealed file
	tpm physicalpresence -s \
	|| warn "Warning: Unable to assert physical presence"

	read -s -p "TPM Owner password: " tpm_password
	echo

	tpm nv_definespace \
		-in $TPM_INDEX \
		-sz $TPM_SIZE \
		-pwdo "$tpm_password" \
		-per 0 \
	|| warn "Warning: Unable to define NVRAM space; trying anyway"


	tpm nv_writevalue \
		-in $TPM_INDEX \
		-if "$TPM_SEALED" \
	|| die "Unable to write sealed secret to NVRAM"
fi

rm "$TPM_SEALED" \
