mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-20 05:28:08 +00:00
5a00bfc035
If we can't mount /boot, show a meaningful error rather than dropping to a recovery shell. Dropping to a recovery shell should be a last resort. Users that know how to use the recovery shell know how to get there. Users that don't know how to use it can be completely stuck and may not know how to get back to the menu or even how to turn off the device. Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
174 lines
5.9 KiB
Bash
Executable File
174 lines
5.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# Retrieve the sealed TOTP secret and initialize a USB Security Dongle with it
|
|
|
|
. /etc/functions
|
|
|
|
HOTP_SECRET="/tmp/secret/hotp.key"
|
|
HOTP_COUNTER="/boot/kexec_hotp_counter"
|
|
HOTP_KEY="/boot/kexec_hotp_key"
|
|
|
|
mount_boot()
|
|
{
|
|
TRACE "Under /bin/seal-hotpkey:mount_boot"
|
|
# Mount local disk if it is not already mounted
|
|
if ! grep -q /boot /proc/mounts; then
|
|
if ! mount -o ro /boot; then
|
|
whiptail $BG_COLOR_ERROR --title 'ERROR' \
|
|
--msgbox "Couldn't mount /boot.\n\nCheck the /boot device in configuration settings, or perform an OEM reset." 0 80
|
|
return 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
TRACE "Under /bin/seal-hotpkey"
|
|
|
|
fatal_error()
|
|
{
|
|
echo -e "\nERROR: ${1}; press Enter to continue."
|
|
read
|
|
die "$1"
|
|
}
|
|
|
|
# Use stored HOTP key branding (this might be useful after OEM reset)
|
|
if [ -r /boot/kexec_hotp_key ]; then
|
|
HOTPKEY_BRANDING="$(cat /boot/kexec_hotp_key)"
|
|
else
|
|
HOTPKEY_BRANDING="HOTP USB Security Dongle"
|
|
fi
|
|
|
|
if [ "$CONFIG_TPM" = "y" ]; then
|
|
DEBUG "Sealing HOTP secret reuses TOTP sealed secret..."
|
|
tpmr unseal 4d47 0,1,2,3,4,7 312 "$HOTP_SECRET" \
|
|
|| fatal_error "Unable to unseal HOTP secret"
|
|
else
|
|
# without a TPM, generate a secret based on the SHA-256 of the ROM
|
|
secret_from_rom_hash > "$HOTP_SECRET" || die "Reading ROM failed"
|
|
fi
|
|
|
|
# Store counter in file instead of TPM for now, as it conflicts with Heads
|
|
# config TPM counter as TPM 1.2 can only increment one counter between reboots
|
|
# get current value of HOTP counter in TPM, create if absent
|
|
mount_boot || exit 1
|
|
|
|
#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 counter"
|
|
#fi
|
|
|
|
#counter_value=$(printf "%d" 0x${counter_value})
|
|
|
|
counter_value=1
|
|
|
|
enable_usb
|
|
# While making sure the key is inserted, capture the status so we can check how
|
|
# many PIN attempts remain
|
|
if ! hotp_token_info="$(hotp_verification info)" ; then
|
|
echo -e "\nInsert your $HOTPKEY_BRANDING and press Enter to configure it"
|
|
read
|
|
if ! hotp_token_info="$(hotp_verification info)" ; then
|
|
# don't leak key on failure
|
|
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null
|
|
fatal_error "Unable to find $HOTPKEY_BRANDING"
|
|
fi
|
|
fi
|
|
|
|
# Set HOTP USB Security Dongle branding based on VID
|
|
if lsusb | grep -q "20a0:" ; then
|
|
HOTPKEY_BRANDING="Nitrokey"
|
|
elif lsusb | grep -q "316d:" ; then
|
|
HOTPKEY_BRANDING="Librem Key"
|
|
else
|
|
HOTPKEY_BRANDING="HOTP USB Security Dongle"
|
|
fi
|
|
|
|
# Truncate the secret if it is longer than the maximum HOTP secret
|
|
truncate_max_bytes 20 "$HOTP_SECRET"
|
|
|
|
# Check when the signing key was created to consider trying the default PIN
|
|
# (Note: we must avoid using gpg --card-status here as the Nitrokey firmware
|
|
# locks up, https://github.com/Nitrokey/nitrokey-pro-firmware/issues/54)
|
|
gpg_key_create_time="$(gpg --list-keys --with-colons | grep -m 1 '^pub:' | cut -d: -f6)"
|
|
gpg_key_create_time="${gpg_key_create_time:-0}"
|
|
DEBUG "Signature key was created at $(date -d "@$gpg_key_create_time")"
|
|
now_date="$(date '+%s')"
|
|
|
|
# Get the number of admin PIN retry attempts remaining
|
|
awk_admin_counter_regex='/^\s*Card counters: Admin (\d),.*$/'
|
|
awk_get_admin_counter="$awk_admin_counter_regex"' { print gensub('"$awk_admin_counter_regex"', "\\1", "") }'
|
|
admin_pin_retries="$(echo "$hotp_token_info" | awk "$awk_get_admin_counter")"
|
|
admin_pin_retries="${admin_pin_retries:-0}"
|
|
DEBUG "Admin PIN retry counter is $admin_pin_retries"
|
|
|
|
# Try using factory default admin PIN for 1 month following OEM reset to ease
|
|
# initial setup. But don't do it forever to encourage changing the PIN and
|
|
# so PIN attempts are not consumed by the default attempt.
|
|
admin_pin="12345678"
|
|
month_secs="$((30*24*60*60))"
|
|
admin_pin_status=1
|
|
if [ "$((now_date - gpg_key_create_time))" -gt "$month_secs" ]; then
|
|
# Remind what the default PIN was in case it still hasn't been changed
|
|
echo "Not trying default PIN ($admin_pin)"
|
|
# Never consume an attempt if there are less than 3 attempts left, otherwise
|
|
# attempting the default PIN could cause an unexpected lockout before getting a
|
|
# chance to enter the correct PIN
|
|
elif [ "$admin_pin_retries" -lt 3 ]; then
|
|
echo "Not trying default PIN ($admin_pin), only $admin_pin_retries attempt(s) left"
|
|
else
|
|
hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" >/dev/null 2>&1
|
|
admin_pin_status="$?"
|
|
fi
|
|
|
|
if [ "$admin_pin_status" -ne 0 ]; then
|
|
# prompt user for PIN and retry
|
|
echo ""
|
|
read -s -p "Enter your $HOTPKEY_BRANDING Admin PIN: " admin_pin
|
|
echo -e "\n"
|
|
|
|
hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING"
|
|
if [ $? -ne 0 ]; then
|
|
echo -e "\n"
|
|
read -s -p "Error setting HOTP secret, re-enter Admin PIN and try again: " admin_pin
|
|
echo -e "\n"
|
|
if ! hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" ; then
|
|
# don't leak key on failure
|
|
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null
|
|
fatal_error "Setting HOTP secret failed"
|
|
fi
|
|
fi
|
|
else
|
|
# remind user to change admin password
|
|
echo -e "\nWARNING: default GPG admin PIN detected: please change this as soon as possible."
|
|
fi
|
|
|
|
# HOTP key no longer needed
|
|
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null
|
|
|
|
# Make sure our counter is incremented ahead of the next check
|
|
#increment_tpm_counter $counter > /dev/null \
|
|
#|| die "Unable to increment tpm counter"
|
|
#increment_tpm_counter $counter > /dev/null \
|
|
#|| die "Unable to increment tpm counter"
|
|
|
|
mount -o remount,rw /boot
|
|
|
|
counter_value=`expr $counter_value + 1`
|
|
echo $counter_value > $HOTP_COUNTER \
|
|
|| fatal_error "Unable to create hotp counter file"
|
|
|
|
# Store/overwrite HOTP USB Security Dongle branding found out beforehand
|
|
echo $HOTPKEY_BRANDING > $HOTP_KEY \
|
|
|| die "Unable to store hotp key file"
|
|
|
|
#sha256sum /tmp/counter-$counter > $HOTP_COUNTER \
|
|
#|| die "Unable to create hotp counter file"
|
|
mount -o remount,ro /boot
|
|
|
|
echo -e "\n$HOTPKEY_BRANDING initialized successfully. Press Enter to continue."
|
|
read
|
|
|
|
exit 0
|