mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-23 14:52:27 +00:00
c064b78ef6
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
682 lines
23 KiB
Bash
Executable File
682 lines
23 KiB
Bash
Executable File
#!/bin/bash
|
|
# Boot from a local disk installation
|
|
|
|
BOARD_NAME=${CONFIG_BOARD_NAME:-${CONFIG_BOARD}}
|
|
MAIN_MENU_TITLE="${BOARD_NAME} | $CONFIG_BRAND_NAME Boot Menu"
|
|
export BG_COLOR_MAIN_MENU=""
|
|
|
|
. /etc/functions
|
|
. /etc/gui_functions
|
|
. /etc/luks-functions
|
|
. /tmp/config
|
|
|
|
# skip_to_menu is set if the user selects "continue to the main menu" from any
|
|
# error, so we will indeed go to the main menu even if other errors occur. It's
|
|
# reset when we reach the main menu so the user can retry from the main menu and
|
|
# # see errors again.
|
|
skip_to_menu="false"
|
|
|
|
mount_boot()
|
|
{
|
|
TRACE "Under /bin/gui-init:mount_boot"
|
|
# Mount local disk if it is not already mounted
|
|
while ! grep -q /boot /proc/mounts ; do
|
|
# try to mount if CONFIG_BOOT_DEV exists
|
|
if [ -e "$CONFIG_BOOT_DEV" ]; then
|
|
mount -o ro $CONFIG_BOOT_DEV /boot
|
|
[[ $? -eq 0 ]] && continue
|
|
fi
|
|
|
|
# CONFIG_BOOT_DEV doesn't exist or couldn't be mounted, so give user options
|
|
BG_COLOR_MAIN_MENU=$BG_COLOR_ERROR
|
|
whiptail $BG_COLOR_ERROR --title "ERROR: No Bootable OS Found!" \
|
|
--menu " No bootable OS was found on the default boot device $CONFIG_BOOT_DEV.
|
|
How would you like to proceed?" 0 80 4 \
|
|
'b' ' Select a new boot device' \
|
|
'u' ' Boot from USB' \
|
|
'm' ' Continue to the main menu' \
|
|
'x' ' Exit to recovery shell' \
|
|
2>/tmp/whiptail || recovery "GUI menu failed"
|
|
|
|
option=$(cat /tmp/whiptail)
|
|
case "$option" in
|
|
b )
|
|
config-gui.sh boot_device_select
|
|
if [ $? -eq 0 ]; then
|
|
# update CONFIG_BOOT_DEV
|
|
. /tmp/config
|
|
BG_COLOR_MAIN_MENU=""
|
|
fi
|
|
;;
|
|
u )
|
|
exec /bin/usb-init
|
|
;;
|
|
m )
|
|
skip_to_menu="true"
|
|
break
|
|
;;
|
|
* )
|
|
recovery "User requested recovery shell"
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
verify_global_hashes()
|
|
{
|
|
TRACE "Under /bin/gui-init:verify_global_hashes"
|
|
# Check the hashes of all the files, ignoring signatures for now
|
|
check_config /boot force
|
|
TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt"
|
|
TMP_TREE_FILE="/tmp/kexec/kexec_tree.txt"
|
|
TMP_PACKAGE_TRIGGER_PRE="/tmp/kexec/kexec_package_trigger_pre.txt"
|
|
TMP_PACKAGE_TRIGGER_POST="/tmp/kexec/kexec_package_trigger_post.txt"
|
|
|
|
if verify_checksums /boot ; then
|
|
return 0
|
|
elif [[ ! -f "$TMP_HASH_FILE" || ! -f "$TMP_TREE_FILE" ]] ; then
|
|
if (whiptail $BG_COLOR_ERROR --title 'ERROR: Missing File!' \
|
|
--yesno "One of the files containing integrity information for /boot is missing!\n\nIf you are setting up heads for the first time or upgrading from an\nolder version, select Yes to create the missing files.\n\nOtherwise this could indicate a compromise and you should select No to\nreturn to the main menu.\n\nWould you like to create the missing files now?" 0 80) then
|
|
if update_checksums ; then
|
|
BG_COLOR_MAIN_MENU=""
|
|
return 0;
|
|
else
|
|
whiptail $BG_COLOR_ERROR --title 'ERROR' \
|
|
--msgbox "Failed to update checksums / sign default config" 0 80
|
|
fi
|
|
fi
|
|
BG_COLOR_MAIN_MENU=$BG_COLOR_ERROR
|
|
return 1
|
|
else
|
|
CHANGED_FILES=$(grep -v 'OK$' /tmp/hash_output | cut -f1 -d ':' | tee -a /tmp/hash_output_mismatches)
|
|
CHANGED_FILES_COUNT=$(wc -l /tmp/hash_output_mismatches | cut -f1 -d ' ')
|
|
|
|
# if files changed before package manager started, show stern warning
|
|
if [ -f "$TMP_PACKAGE_TRIGGER_PRE" ]; then
|
|
PRE_CHANGED_FILES=$(grep '^CHANGED_FILES' $TMP_PACKAGE_TRIGGER_POST | cut -f 2 -d '=' | tr -d '"')
|
|
TEXT="The following files failed the verification process BEFORE package updates ran:\n${PRE_CHANGED_FILES}\n\nCompare against the files $CONFIG_BRAND_NAME has detected have changed:\n${CHANGED_FILES}\n\nThis could indicate a compromise!\n\nWould you like to update your checksums anyway?"
|
|
|
|
# if files changed after package manager started, probably caused by package manager
|
|
elif [ -f "$TMP_PACKAGE_TRIGGER_POST" ]; then
|
|
LAST_PACKAGE_LIST=$(grep -E "^(Install|Remove|Upgrade|Reinstall):" $TMP_PACKAGE_TRIGGER_POST)
|
|
UPDATE_INITRAMFS_PACKAGE=$(grep '^UPDATE_INITRAMFS_PACKAGE' $TMP_PACKAGE_TRIGGER_POST | cut -f 2 -d '=' | tr -d '"')
|
|
|
|
if [ "$UPDATE_INITRAMFS_PACKAGE" != "" ]; then
|
|
TEXT="The following files failed the verification process AFTER package updates ran:\n${CHANGED_FILES}\n\nThis is likely due to package triggers in$UPDATE_INITRAMFS_PACKAGE.\n\nYou will need to update your checksums for all files in /boot.\n\nWould you like to update your checksums now?"
|
|
else
|
|
TEXT="The following files failed the verification process AFTER package updates ran:\n${CHANGED_FILES}\n\nThis might be due to the following package updates:\n$LAST_PACKAGE_LIST.\n\nYou will need to update your checksums for all files in /boot.\n\nWould you like to update your checksums now?"
|
|
fi
|
|
|
|
else
|
|
if [ $CHANGED_FILES_COUNT -gt 10 ]; then
|
|
# drop to console to show full file list
|
|
whiptail $ERROR_BG_COLOR --title 'ERROR: Boot Hash Mismatch' \
|
|
--msgbox "${CHANGED_FILES_COUNT} files failed the verification process!\\n\nThis could indicate a compromise!\n\nHit OK to review the list of files.\n\nType \"q\" to exit the list and return." 0 80
|
|
|
|
echo "Type \"q\" to exit the list and return." >> /tmp/hash_output_mismatches
|
|
less /tmp/hash_output_mismatches
|
|
#move outdated hash mismatch list
|
|
mv /tmp/hash_output_mismatches /tmp/hash_output_mismatch_old
|
|
TEXT="Would you like to update your checksums now?"
|
|
else
|
|
TEXT="The following files failed the verification process:\n\n${CHANGED_FILES}\n\nThis could indicate a compromise!\n\nWould you like to update your checksums now?"
|
|
fi
|
|
fi
|
|
|
|
if (whiptail $BG_COLOR_ERROR --title 'ERROR: Boot Hash Mismatch' --yesno "$TEXT" 0 80) then
|
|
if update_checksums ; then
|
|
BG_COLOR_MAIN_MENU=""
|
|
return 0;
|
|
else
|
|
whiptail $BG_COLOR_ERROR --title 'ERROR' \
|
|
--msgbox "Failed to update checksums / sign default config" 0 80
|
|
fi
|
|
fi
|
|
BG_COLOR_MAIN_MENU=$BG_COLOR_ERROR
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
prompt_update_checksums()
|
|
{
|
|
TRACE "Under /bin/gui-init:prompt_update_checksums"
|
|
if (whiptail $BG_COLOR_WARNING --title 'Update Checksums and sign all files in /boot' \
|
|
--yesno "You have chosen to update the checksums and sign all of the files in /boot.\n\nThis means that you trust that these files have not been tampered with.\n\nYou will need your GPG key available, and this change will modify your disk.\n\nDo you want to continue?" 0 80) then
|
|
if ! update_checksums ; then
|
|
whiptail $BG_COLOR_ERROR --title 'ERROR' \
|
|
--msgbox "Failed to update checksums / sign default config" 0 80
|
|
fi
|
|
fi
|
|
}
|
|
|
|
generate_totp_hotp()
|
|
{
|
|
TRACE "Under /bin/gui-init:generate_totp_hotp"
|
|
tpm_owner_password="$1" # May be empty, will prompt if needed and empty
|
|
if [ "$CONFIG_TPM" != "y" ] && [ -x /bin/hotp_verification ]; then
|
|
echo "Generating new HOTP secret"
|
|
/bin/seal-hotpkey
|
|
elif echo -e "Generating new TOTP secret...\n\n" && /bin/seal-totp "$BOARD_NAME" "$tpm_owner_password"; then
|
|
echo
|
|
if [ -x /bin/hotp_verification ]; then
|
|
if [ "$CONFIG_TOTP_SKIP_QRCODE" != y ]; then
|
|
echo "Once you have scanned the QR code, hit Enter to configure your HOTP USB Security Dongle (e.g. Librem Key or Nitrokey)"
|
|
read
|
|
fi
|
|
/bin/seal-hotpkey
|
|
else
|
|
if [ "$CONFIG_TOTP_SKIP_QRCODE" != y ]; then
|
|
echo "Once you have scanned the QR code, hit Enter to continue"
|
|
read
|
|
fi
|
|
fi
|
|
# clear screen
|
|
printf "\033c"
|
|
else
|
|
warn "Unsealing TOTP/HOTP secret from previous sealed measurements failed"
|
|
warn 'Try "Generate new HOTP/TOTP secret" option if you updated firmware content'
|
|
fi
|
|
}
|
|
|
|
update_totp()
|
|
{
|
|
TRACE "Under /bin/gui-init:update_totp"
|
|
# update the TOTP code
|
|
date=`date "+%Y-%m-%d %H:%M:%S %Z"`
|
|
tries=0
|
|
if [ "$CONFIG_TPM" != "y" ]; then
|
|
TOTP="NO TPM"
|
|
else
|
|
TOTP=`unseal-totp`
|
|
# On platforms using CONFIG_BOOT_EXTRA_TTYS multiple processes may try to
|
|
# access TPM at the same time, failing with EBUSY. The order of execution
|
|
# is unpredictable, so the error may appear on main console, secondary one,
|
|
# or neither of them if the calls are sufficiently staggered. Try up to
|
|
# three times (including previous one) with small delays in case of error,
|
|
# instead of immediately scaring users with "you've been pwned" message.
|
|
while [ $? -ne 0 ] && [ $tries -lt 2 ]; do
|
|
sleep 0.5
|
|
((tries++))
|
|
TOTP=`unseal-totp`
|
|
done
|
|
if [ $? -ne 0 ]; then
|
|
BG_COLOR_MAIN_MENU=$BG_COLOR_ERROR
|
|
if [ "$skip_to_menu" = "true" ]; then
|
|
return 1 # Already asked to skip to menu from a prior error
|
|
fi
|
|
|
|
DEBUG "CONFIG_TPM: $CONFIG_TPM"
|
|
DEBUG "CONFIG_TPM2_TOOLS: $CONFIG_TPM2_TOOLS"
|
|
DEBUG "Show PCRs"
|
|
DEBUG "$(pcrs)"
|
|
|
|
whiptail $BG_COLOR_ERROR --title "ERROR: TOTP Generation Failed!" \
|
|
--menu " ERROR: $CONFIG_BRAND_NAME couldn't generate the TOTP code.\n
|
|
If you have just completed a Factory Reset, or just reflashed
|
|
your BIOS, you should generate a new HOTP/TOTP secret.\n
|
|
If this is the first time the system has booted, you should
|
|
reset the TPM and set your own password.\n
|
|
If you have not just reflashed your BIOS, THIS COULD INDICATE TAMPERING!\n
|
|
How would you like to proceed?" 0 80 4 \
|
|
'g' ' Generate new HOTP/TOTP secret' \
|
|
'i' ' Ignore error and continue to main menu' \
|
|
'p' ' Reset the TPM' \
|
|
'x' ' Exit to recovery shell' \
|
|
2>/tmp/whiptail || recovery "GUI menu failed"
|
|
|
|
option=$(cat /tmp/whiptail)
|
|
case "$option" in
|
|
g )
|
|
if (whiptail $BG_COLOR_WARNING --title 'Generate new TOTP/HOTP secret' \
|
|
--yesno "This will erase your old secret and replace it with a new one!\n\nDo you want to proceed?" 0 80) then
|
|
generate_totp_hotp && update_totp && BG_COLOR_MAIN_MENU="" && reseal_tpm_disk_decryption_key
|
|
fi
|
|
;;
|
|
i )
|
|
skip_to_menu="true"
|
|
return 1
|
|
;;
|
|
p )
|
|
reset_tpm && update_totp && BG_COLOR_MAIN_MENU="" && reseal_tpm_disk_decryption_key
|
|
;;
|
|
x )
|
|
recovery "User requested recovery shell"
|
|
;;
|
|
esac
|
|
fi
|
|
fi
|
|
}
|
|
|
|
update_hotp()
|
|
{
|
|
TRACE "Under /bin/gui-init:update_hotp"
|
|
if [ -x /bin/hotp_verification ]; then
|
|
HOTP=`unseal-hotp`
|
|
if ! hotp_verification info ; then
|
|
if [ "$skip_to_menu" = "true" ]; then
|
|
return 1 # Already asked to skip to menu from a prior error
|
|
fi
|
|
if ! whiptail $BG_COLOR_WARNING \
|
|
--title "WARNING: Please Insert Your $HOTPKEY_BRANDING" \
|
|
--yes-button "Retry" --no-button "Skip" \
|
|
--yesno "Your $HOTPKEY_BRANDING was not detected.\n\nPlease insert your $HOTPKEY_BRANDING" 0 80 ; then
|
|
HOTP="Error checking code, Insert $HOTPKEY_BRANDING and retry"
|
|
BG_COLOR_MAIN_MENU=$BG_COLOR_WARNING
|
|
return
|
|
fi
|
|
fi
|
|
# Don't output HOTP codes to screen, so as to make replay attacks harder
|
|
hotp_verification check "$HOTP"
|
|
case "$?" in
|
|
0 )
|
|
HOTP="Success"
|
|
BG_COLOR_MAIN_MENU=""
|
|
;;
|
|
4|7 ) # 4: code was incorrect, 7: code was not a valid HOTP code at all
|
|
HOTP="Invalid code"
|
|
BG_COLOR_MAIN_MENU=$BG_COLOR_ERROR
|
|
;;
|
|
* )
|
|
HOTP="Error checking code, Insert $HOTPKEY_BRANDING and retry"
|
|
BG_COLOR_MAIN_MENU=$BG_COLOR_WARNING
|
|
;;
|
|
esac
|
|
else
|
|
HOTP='N/A'
|
|
fi
|
|
|
|
if [[ "$CONFIG_TPM" = n && "$HOTP" = "Invalid code" ]]; then
|
|
whiptail $BG_COLOR_ERROR --title "ERROR: HOTP Validation Failed!" \
|
|
--menu "ERROR: $CONFIG_BRAND_NAME couldn't validate the HOTP code.\n\nIf you just reflashed your BIOS, you should generate a new TOTP/HOTP secret.\n\nIf you have not just reflashed your BIOS, THIS COULD INDICATE TAMPERING!\n\nHow would you like to proceed?" 0 80 4 \
|
|
'g' ' Generate new TOTP/HOTP secret' \
|
|
'i' ' Ignore error and continue to main menu' \
|
|
'x' ' Exit to recovery shell' \
|
|
2>/tmp/whiptail || recovery "GUI menu failed"
|
|
|
|
option=$(cat /tmp/whiptail)
|
|
case "$option" in
|
|
g )
|
|
if (whiptail $BG_COLOR_WARNING --title 'Generate new TOTP/HOTP secret' \
|
|
--yesno "This will erase your old secret and replace it with a new one!\n\nDo you want to proceed?" 0 80) then
|
|
generate_totp_hotp && BG_COLOR_MAIN_MENU="" && reseal_tpm_disk_decryption_key
|
|
fi
|
|
;;
|
|
i )
|
|
return 1
|
|
;;
|
|
x )
|
|
recovery "User requested recovery shell"
|
|
;;
|
|
esac
|
|
fi
|
|
}
|
|
|
|
clean_boot_check()
|
|
{
|
|
TRACE "Under /bin/gui-init:clean_boot_check"
|
|
# assume /boot mounted
|
|
if ! grep -q /boot /proc/mounts ; then
|
|
return
|
|
fi
|
|
|
|
# check for any kexec files in /boot
|
|
kexec_files=`find /boot -name kexec*.txt`
|
|
[ ! -z "$kexec_files" ] && return
|
|
|
|
#check for GPG key in keyring
|
|
GPG_KEY_COUNT=`gpg -k 2>/dev/null | wc -l`
|
|
[ $GPG_KEY_COUNT -ne 0 ] && return
|
|
|
|
# check for USB security token
|
|
if [ -x /bin/hotp_verification ]; then
|
|
if ! gpg --card-status > /dev/null ; then
|
|
return
|
|
fi
|
|
fi
|
|
|
|
# OS is installed, no kexec files present, no GPG keys in keyring, security token present
|
|
# prompt user to run OEM factory reset
|
|
oem-factory-reset \
|
|
"Clean Boot Detected - Perform OEM Factory Reset / Re-Ownership?" "$BG_COLOR_WARNING"
|
|
}
|
|
|
|
check_gpg_key()
|
|
{
|
|
TRACE "Under /bin/gui-init:check_gpg_key"
|
|
GPG_KEY_COUNT=`gpg -k 2>/dev/null | wc -l`
|
|
if [ $GPG_KEY_COUNT -eq 0 ]; then
|
|
BG_COLOR_MAIN_MENU=$BG_COLOR_ERROR
|
|
if [ "$skip_to_menu" = "true" ]; then
|
|
return 1 # Already asked to skip to menu from a prior error
|
|
fi
|
|
whiptail $BG_COLOR_ERROR --title "ERROR: GPG keyring empty!" \
|
|
--menu "ERROR: $CONFIG_BRAND_NAME couldn't find any GPG keys in your keyring.\n\nIf this is the first time the system has booted,\nyou should add a public GPG key to the BIOS now.\n\nIf you just reflashed a new BIOS, you'll need to add at least one\npublic key to the keyring.\n\nIf you have not just reflashed your BIOS, THIS COULD INDICATE TAMPERING!\n\nHow would you like to proceed?" 0 80 4 \
|
|
'g' ' Add a GPG key to the running BIOS' \
|
|
'F' ' OEM Factory Reset / Re-Ownership' \
|
|
'i' ' Ignore error and continue to main menu' \
|
|
'x' ' Exit to recovery shell' \
|
|
2>/tmp/whiptail || recovery "GUI menu failed"
|
|
|
|
option=$(cat /tmp/whiptail)
|
|
case "$option" in
|
|
g )
|
|
gpg-gui.sh && BG_COLOR_MAIN_MENU=""
|
|
;;
|
|
i )
|
|
skip_to_menu="true"
|
|
return 1
|
|
;;
|
|
F )
|
|
oem-factory-reset
|
|
;;
|
|
|
|
x )
|
|
recovery "User requested recovery shell"
|
|
;;
|
|
esac
|
|
fi
|
|
}
|
|
|
|
prompt_auto_default_boot()
|
|
{
|
|
TRACE "Under /bin/gui-init:prompt_auto_default_boot"
|
|
echo -e "\nHOTP verification success\n\n"
|
|
if pause_automatic_boot; then
|
|
echo -e "\n\nAttempting default boot...\n\n"
|
|
attempt_default_boot
|
|
fi
|
|
}
|
|
|
|
show_main_menu()
|
|
{
|
|
TRACE "Under /bin/gui-init:show_main_menu"
|
|
date=`date "+%Y-%m-%d %H:%M:%S %Z"`
|
|
whiptail $BG_COLOR_MAIN_MENU --title "$MAIN_MENU_TITLE" \
|
|
--menu "$date\nTOTP: $TOTP | HOTP: $HOTP" 0 80 10 \
|
|
'd' ' Default boot' \
|
|
'r' ' Refresh TOTP/HOTP' \
|
|
'o' ' Options -->' \
|
|
's' ' System Info' \
|
|
'p' ' Power Off' \
|
|
2>/tmp/whiptail || recovery "GUI menu failed"
|
|
|
|
option=$(cat /tmp/whiptail)
|
|
case "$option" in
|
|
d )
|
|
attempt_default_boot
|
|
;;
|
|
r )
|
|
update_totp && update_hotp
|
|
;;
|
|
o )
|
|
show_options_menu
|
|
;;
|
|
s )
|
|
show_system_info
|
|
;;
|
|
p )
|
|
poweroff
|
|
;;
|
|
esac
|
|
}
|
|
|
|
show_options_menu()
|
|
{
|
|
TRACE "Under /bin/gui-init:show_options_menu"
|
|
whiptail $BG_COLOR_MAIN_MENU --title "$CONFIG_BRAND_NAME Options" \
|
|
--menu "" 0 80 10 \
|
|
'b' ' Boot Options -->' \
|
|
't' ' TPM/TOTP/HOTP Options -->' \
|
|
'u' ' Update checksums and sign all files in /boot' \
|
|
'c' ' Change configuration settings -->' \
|
|
'f' ' Flash/Update the BIOS -->' \
|
|
'g' ' GPG Options -->' \
|
|
'F' ' OEM Factory Reset / Re-Ownership -->' \
|
|
'C' ' Reencrypt LUKS container -->' \
|
|
'P' ' Change LUKS Disk Recovery Key passphrase ->' \
|
|
'R' ' Check/Update file hashes on root disk -->' \
|
|
'x' ' Exit to recovery shell' \
|
|
'r' ' <-- Return to main menu' \
|
|
2>/tmp/whiptail || recovery "GUI menu failed"
|
|
|
|
option=$(cat /tmp/whiptail)
|
|
case "$option" in
|
|
b )
|
|
show_boot_options_menu
|
|
;;
|
|
t )
|
|
show_tpm_totp_hotp_options_menu
|
|
;;
|
|
u )
|
|
prompt_update_checksums
|
|
;;
|
|
c )
|
|
config-gui.sh
|
|
;;
|
|
f )
|
|
flash-gui.sh
|
|
;;
|
|
g )
|
|
gpg-gui.sh
|
|
;;
|
|
F )
|
|
oem-factory-reset
|
|
;;
|
|
C )
|
|
luks_reencrypt
|
|
luks_secrets_cleanup
|
|
;;
|
|
P )
|
|
luks_change_passphrase
|
|
luks_secrets_cleanup
|
|
;;
|
|
R )
|
|
root-hashes-gui.sh
|
|
;;
|
|
x )
|
|
recovery "User requested recovery shell"
|
|
;;
|
|
r )
|
|
;;
|
|
esac
|
|
}
|
|
|
|
show_boot_options_menu()
|
|
{
|
|
TRACE "Under /bin/gui-init:show_boot_options_menu"
|
|
whiptail $BG_COLOR_MAIN_MENU --title "Boot Options" \
|
|
--menu "Select A Boot Option" 0 80 10 \
|
|
'm' ' Show OS boot menu' \
|
|
'u' ' USB boot' \
|
|
'i' ' Ignore tampering and force a boot (Unsafe!)' \
|
|
'r' ' <-- Return to main menu' \
|
|
2>/tmp/whiptail || recovery "GUI menu failed"
|
|
|
|
option=$(cat /tmp/whiptail)
|
|
case "$option" in
|
|
m )
|
|
# select a kernel from the menu
|
|
select_os_boot_option
|
|
;;
|
|
u )
|
|
exec /bin/usb-init
|
|
;;
|
|
i )
|
|
force_unsafe_boot
|
|
;;
|
|
r )
|
|
;;
|
|
esac
|
|
}
|
|
|
|
show_tpm_totp_hotp_options_menu()
|
|
{
|
|
TRACE "Under /bin/gui-init:show_tpm_totp_hotp_options_menu"
|
|
whiptail $BG_COLOR_MAIN_MENU --title "TPM/TOTP/HOTP Options" \
|
|
--menu "Select An Option" 0 80 10 \
|
|
'g' ' Generate new TOTP/HOTP secret' \
|
|
'r' ' Reset the TPM' \
|
|
't' ' TOTP/HOTP does not match after refresh, troubleshoot' \
|
|
'm' ' <-- Return to main menu' \
|
|
2>/tmp/whiptail || recovery "GUI menu failed"
|
|
|
|
option=$(cat /tmp/whiptail)
|
|
case "$option" in
|
|
g )
|
|
generate_totp_hotp && reseal_tpm_disk_decryption_key
|
|
;;
|
|
r )
|
|
reset_tpm && reseal_tpm_disk_decryption_key
|
|
;;
|
|
t )
|
|
prompt_totp_mismatch
|
|
;;
|
|
m )
|
|
;;
|
|
esac
|
|
}
|
|
|
|
prompt_totp_mismatch()
|
|
{
|
|
TRACE "Under /bin/gui-init:prompt_totp_mismatch"
|
|
if (whiptail $BG_COLOR_WARNING --title "TOTP/HOTP code mismatched" \
|
|
--yesno "TOTP/HOTP code mismatches could indicate either TPM tampering or clock drift:\n\nTo correct clock drift: 'date -s yyyy-MM-DD hh:mm:ss' in UTC timezone\nand save it to the RTC: 'hwclock -w'\nthen reboot and try again.\n\nWould you like to exit to a recovery console?" 0 80) then
|
|
echo ""
|
|
echo "To correct clock drift: 'date -s yyyy-MM-DD hh:mm:ss' in UTC timezone"
|
|
echo "and save it to the RTC: 'hwclock -w'"
|
|
echo ""
|
|
echo "Alternatively you could do this automatically with an Ethernet cable connected to a functional network: 'network-init-recovery'"
|
|
echo ""
|
|
echo "Then reboot and try again"
|
|
echo ""
|
|
recovery "TOTP/HOTP mismatch"
|
|
fi
|
|
}
|
|
|
|
reset_tpm()
|
|
{
|
|
TRACE "Under /bin/gui-init:reset_tpm"
|
|
if [ "$CONFIG_TPM" = "y" ]; then
|
|
if (whiptail $BG_COLOR_WARNING --title 'Reset the TPM' \
|
|
--yesno "This will clear the TPM and TPM password, replace them with new ones!\n\nDo you want to proceed?" 0 80) then
|
|
|
|
if ! prompt_new_owner_password; then
|
|
echo "Press Enter to return to the menu..."
|
|
read
|
|
echo
|
|
return 1
|
|
fi
|
|
|
|
tpmr reset "$tpm_owner_password"
|
|
|
|
# now that the TPM is reset, remove invalid TPM counter files
|
|
mount_boot
|
|
mount -o rw,remount /boot
|
|
warn "Removing rollback and primary handle hash under /boot"
|
|
rm -f /boot/kexec_rollback.txt
|
|
rm -f /boot/kexec_primhdl_hash.txt
|
|
|
|
# create Heads TPM counter before any others
|
|
check_tpm_counter /boot/kexec_rollback.txt "" "$tpm_owner_password" \
|
|
|| die "Unable to find/create tpm counter"
|
|
counter="$TPM_COUNTER"
|
|
|
|
increment_tpm_counter $counter \
|
|
|| die "Unable to increment tpm counter"
|
|
|
|
sha256sum /tmp/counter-$counter > /boot/kexec_rollback.txt \
|
|
|| die "Unable to create rollback file"
|
|
mount -o ro,remount /boot
|
|
|
|
generate_totp_hotp "$tpm_owner_password"
|
|
else
|
|
echo "Returning to the main menu"
|
|
fi
|
|
else
|
|
whiptail $BG_COLOR_ERROR --title 'ERROR: No TPM Detected' --msgbox "This device does not have a TPM.\n\nPress OK to return to the Main Menu" 0 80
|
|
fi
|
|
}
|
|
|
|
select_os_boot_option()
|
|
{
|
|
TRACE "Under /bin/gui-init:select_os_boot_option"
|
|
mount_boot
|
|
if verify_global_hashes ; then
|
|
kexec-select-boot -m -b /boot -c "grub.cfg" -g
|
|
fi
|
|
}
|
|
|
|
attempt_default_boot()
|
|
{
|
|
TRACE "Under /bin/gui-init:attempt_default_boot"
|
|
mount_boot
|
|
|
|
if ! verify_global_hashes; then
|
|
return
|
|
fi
|
|
DEFAULT_FILE=`find /boot/kexec_default.*.txt 2>/dev/null | head -1`
|
|
if [ -r "$DEFAULT_FILE" ]; then
|
|
kexec-select-boot -b /boot -c "grub.cfg" -g \
|
|
|| recovery "Failed default boot"
|
|
elif (whiptail $BG_COLOR_WARNING --title 'No Default Boot Option Configured' \
|
|
--yesno "There is no default boot option configured yet.\nWould you like to load a menu of boot options?\nOtherwise you will return to the main menu." 0 80) then
|
|
kexec-select-boot -m -b /boot -c "grub.cfg" -g
|
|
fi
|
|
}
|
|
|
|
force_unsafe_boot()
|
|
{
|
|
TRACE "Under /bin/gui-init:force_unsafe_boot"
|
|
if [ "$CONFIG_RESTRICTED_BOOT" = y ]; then
|
|
whiptail $BG_COLOR_ERROR --title 'ERROR: Restricted Boot Enabled' --msgbox "Restricted Boot is Enabled, forced boot not allowed.\n\nPress OK to return to the Main Menu" 0 80
|
|
return
|
|
fi
|
|
# Run the menu selection in "force" mode, bypassing hash checks
|
|
if (whiptail $BG_COLOR_WARNING --title 'Unsafe Forced Boot Selected!' \
|
|
--yesno "WARNING: You have chosen to skip all tamper checks and boot anyway.\n\nThis is an unsafe option!\n\nDo you want to proceed?" 0 80) then
|
|
mount_boot && kexec-select-boot -m -b /boot -c "grub.cfg" -g -f
|
|
fi
|
|
}
|
|
|
|
# gui-init start
|
|
TRACE "Under /bin/gui-init, start"
|
|
|
|
# Use stored HOTP key branding
|
|
if [ -r /boot/kexec_hotp_key ]; then
|
|
HOTPKEY_BRANDING="$(cat /boot/kexec_hotp_key)"
|
|
else
|
|
HOTPKEY_BRANDING="HOTP USB Security Dongle"
|
|
fi
|
|
|
|
if [ -x /bin/hotp_verification ]; then
|
|
enable_usb
|
|
fi
|
|
|
|
if detect_boot_device ; then
|
|
# /boot device with installed OS found
|
|
clean_boot_check
|
|
else
|
|
# can't determine /boot device or no OS installed,
|
|
# so fall back to interactive selection
|
|
mount_boot
|
|
fi
|
|
|
|
# detect whether any GPG keys exist in the keyring, if not, initialize that first
|
|
check_gpg_key
|
|
# Even if GPG init fails, still try to update TOTP/HOTP so the main menu can
|
|
# show the correct status.
|
|
update_totp
|
|
update_hotp
|
|
|
|
if [ "$HOTP" = "Success" -a -n "$CONFIG_AUTO_BOOT_TIMEOUT" ]; then
|
|
prompt_auto_default_boot
|
|
fi
|
|
|
|
while true; do
|
|
TRACE "Under gui-init:while true loop"
|
|
skip_to_menu="false"
|
|
show_main_menu
|
|
done
|
|
|
|
recovery "Something failed during boot"
|