heads/initrd/bin/unseal-hotp
Kyle Rankin 31cf85b707
Add Librem Key support to Heads
The Librem Key is a custom device USB-based security token Nitrokey is
producing for Purism and among other things it has custom firmware
created for use with Heads. In particular, when a board is configured
with CONFIG_LIBREMKEY, this custom firmware allows Heads to use the
sealed TOTP secret to also send an HOTP authentication to the Librem
Key. If the HOTP code is successful, the Librem Key will blink a green
LED, if unsuccessful it will blink red, thereby informing the user that
Heads has been tampered with without requiring them to use a phone to
validate the TOTP secret.

Heads will still use and show the TOTP secret, in case the user wants to
validate both codes (in case the Librem Key was lost or is no longer
trusted). It will also show the result of the HOTP verification (but not
the code itself), even though the user should trust only what the Librem
Key displays, so the user can confirm that both the device and Heads are
in sync. If HOTP is enabled, Heads will maintain a new TPM counter
separate from the Heads TPM counter that will increment each time HOTP
codes are checked.

This change also modifies the routines that update TOTP so that if
the Librem Key executables are present it will also update HOTP codes
and synchronize them with a Librem Key.
2018-06-19 12:27:27 -07:00

64 lines
1.4 KiB
Bash
Executable File

#!/bin/sh
# Retrieve the sealed file and counter from the NVRAM, unseal it and compute the hotp
. /etc/functions
HOTP_SEALED="/tmp/secret/hotp.sealed"
HOTP_SECRET="/tmp/secret/hotp.key"
HOTP_COUNTER="/boot/kexec_hotp_counter"
mount_boot()
{
# Mount local disk if it is not already mounted
if ! grep -q /boot /proc/mounts ; then
mount -o ro /boot \
|| recovery "Unable to mount /boot"
fi
}
tpm nv_readvalue \
-in 4d47 \
-sz 312 \
-of "$HOTP_SEALED" \
|| die "Unable to retrieve sealed file from TPM NV"
tpm unsealfile \
-hk 40000000 \
-if "$HOTP_SEALED" \
-of "$HOTP_SECRET" \
|| die "Unable to unseal HOTP secret"
rm -f "$HOTP_SEALED"
# get current value of HOTP counter in TPM, create if absent
mount_boot
check_tpm_counter $HOTP_COUNTER hotp \
|| die "Unable to find/create TPM counter"
counter="$TPM_COUNTER"
counter_value=$(read_tpm_counter $counter | cut -f2 -d ' ' | awk 'gsub("^000e","")')
if [ "$counter_value" == "" ]; then
die "Unable to read HOTP TPM counter"
fi
counter_value=$(printf "%d" 0x${counter_value})
if ! hotp $counter_value < "$HOTP_SECRET"; then
rm -f "$HOTP_SECRET"
die 'Unable to compute HOTP hash?'
fi
rm -f "$HOTP_SECRET"
increment_tpm_counter $counter > /dev/null \
|| die "Unable to increment tpm counter"
mount -o remount,rw /boot
sha256sum /tmp/counter-$counter > $HOTP_COUNTER \
|| die "Unable to create hotp counter file"
mount -o remount,ro /boot
exit 0