mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-19 13:07:58 +00:00
31cf85b707
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.
64 lines
1.4 KiB
Bash
Executable File
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
|