#!/bin/sh
# This will unseal and unecncrypt the drive encryption key from the TPM
# The TOTP secret will be shown to the user on each encryption attempt.
# It will then need to be bundled into initrd that is booted with Qubes.

TPM_INDEX=3
TPM_SIZE=312

. /etc/functions
mkdir -p /tmp/secret

sealed_file="/tmp/secret/sealed.key"
key_file="$1"

if [ -z "$key_file" ]; then
	key_file="/tmp/secret/secret.key"
fi

tpm nv_readvalue \
	-in "$TPM_INDEX" \
	-sz "$TPM_SIZE" \
	-of "$sealed_file" \
|| die "Unable to read key from TPM NVRAM"


get_password()
{
	last_half=X

	while true; do

		# update the TOTP code every thirty seconds
		date=`date "+%Y-%m-%d %H:%M:%S"`
		seconds=`date "+%s"`
		half=`expr \( $seconds % 60 \) / 30`
		if [ "$half" != "$last_half" ]; then
			last_half=$half;
			TOTP=`unseal-totp` \
			|| die "TOTP code generation failed"
		fi

		echo -n "$date $TOTP: "

		# read the first character, non-blocking
		read \
			-t 1 \
			-n 1 \
			-s \
			-p "Enter unlock password: " \
			tpm_password_1 \
		&& break

		# nothing typed, redraw the line
		echo -ne '\r'
	done

	# they have started typing, read the rest, blocking
	if [ -z "$tpm_password_1" ]; then
		# they hit enter; we should exit gracefully
		tpm_password=""
	else
		# they hit something else, read the rest of the line
		read \
			-s \
			-p '' \
			tpm_password_2
		tpm_password="$tpm_password_1$tpm_password_2"
	fi

	# clean up with a newline
	echo

}

for tries in 1 2 3; do
	get_password

	if tpm unsealfile \
		-if "$sealed_file" \
		-of "$key_file" \
		-pwdd "$tpm_password" \
		-hk 40000000 \
	; then
		rm -f /tmp/secret/sealed
		exit 0
	fi

	pcrs
	warn "Unable to unseal disk encryption key"
done

die "Retry count exceeded..."
