Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WiP: Improve checksum verification upon totp unseal errors #1508

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 11 additions & 78 deletions initrd/bin/gui-init
Original file line number Diff line number Diff line change
Expand Up @@ -62,81 +62,6 @@ mount_boot()
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"
Expand Down Expand Up @@ -210,6 +135,10 @@ update_totp()
DEBUG "Show PCRs"
DEBUG "$(pcrs)"

#In all cases where TPM is involved in TOTP/HOTP secret unsealing errors
# Show global integrity report first to show also /boot integrity reports
report_integrity_measurements

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
Expand All @@ -225,7 +154,7 @@ update_totp()
2>/tmp/whiptail || recovery "GUI menu failed"

option=$(cat /tmp/whiptail)
case "$option" in
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
Expand Down Expand Up @@ -431,6 +360,7 @@ show_options_menu()
'b' ' Boot Options -->' \
't' ' TPM/TOTP/HOTP Options -->' \
'u' ' Update checksums and sign all files in /boot' \
'v' ' Verify checksums and signed /boot files' \
'c' ' Change configuration settings -->' \
'f' ' Flash/Update the BIOS -->' \
'g' ' GPG Options -->' \
Expand All @@ -453,6 +383,9 @@ show_options_menu()
u )
prompt_update_checksums
;;
v )
verify_global_hashes update
;;
c )
config-gui.sh
;;
Expand Down Expand Up @@ -606,7 +539,7 @@ select_os_boot_option()
{
TRACE "Under /bin/gui-init:select_os_boot_option"
mount_boot
if verify_global_hashes ; then
if verify_global_hashes update ; then
kexec-select-boot -m -b /boot -c "grub.cfg" -g
fi
}
Expand All @@ -616,7 +549,7 @@ attempt_default_boot()
TRACE "Under /bin/gui-init:attempt_default_boot"
mount_boot

if ! verify_global_hashes; then
if ! verify_global_hashes update; then
return
fi
DEFAULT_FILE=`find /boot/kexec_default.*.txt 2>/dev/null | head -1`
Expand Down
4 changes: 2 additions & 2 deletions initrd/bin/kexec-seal-key
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ done

# Remove all the old keys from slot 1
for dev in $(cat "$KEY_DEVICES" | cut -d\ -f1); do
echo "++++++ $dev: Removing old key slot 1"
echo "++++++ $dev: Removing $dev LUKS' old key slot 1 with provided passphrase"
cryptsetup luksKillSlot \
--key-file "$RECOVERY_KEY" \
$dev 1 ||
Expand All @@ -102,7 +102,7 @@ for dev in $(cat "$KEY_DEVICES" | cut -d\ -f1); do
--key-file "$RECOVERY_KEY" \
--key-slot 1 \
$dev "$KEY_FILE" ||
die "$dev: Unable to add key to slot 1"
die "$dev: Unable to add key to $dev LUKS's slot 1 with provided passphrase"
done

# Now that we have setup the new keys, measure the PCRs
Expand Down
35 changes: 0 additions & 35 deletions initrd/bin/kexec-select-boot
Original file line number Diff line number Diff line change
Expand Up @@ -66,41 +66,6 @@ if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
fi
fi

verify_global_hashes()
{
echo "+++ Checking verified boot hash file "
# Check the hashes of all the files
if verify_checksums "$bootdir" "$gui_menu" ; then
echo "+++ Verified boot hashes "
valid_hash='y'
valid_global_hash='y'
else
if [ "$gui_menu" = "y" ]; then
CHANGED_FILES=$(grep -v 'OK$' /tmp/hash_output | cut -f1 -d ':')
whiptail $BG_COLOR_ERROR --title 'ERROR: Boot Hash Mismatch' \
--msgbox "The following files failed the verification process:\n${CHANGED_FILES}\nExiting to a recovery shell" 0 80
fi
die "$TMP_HASH_FILE: boot hash mismatch"
fi
# If user enables it, check root hashes before boot as well
if [[ "$CONFIG_ROOT_CHECK_AT_BOOT" = "y" && "$force_menu" == "n" ]]; then
if root-hashes-gui.sh -c; then
echo "+++ Verified root hashes, continuing boot "
# if user re-signs, it wipes out saved options, so scan the boot directory and generate
if [ ! -r "$TMP_MENU_FILE" ]; then
scan_options
fi
else
# root-hashes-gui.sh handles the GUI error menu, just die here
if [ "$gui_menu" = "y" ]; then
whiptail $BG_COLOR_ERROR --title 'ERROR: Root Hash Mismatch' \
--msgbox "The root hash check failed!\nExiting to a recovery shell" 0 80
fi
die "root hash mismatch, see /tmp/hash_output_mismatches for details"
fi
fi
}

verify_rollback_counter()
{
TPM_COUNTER=`grep counter $TMP_ROLLBACK_FILE | cut -d- -f2`
Expand Down
57 changes: 0 additions & 57 deletions initrd/bin/oem-factory-reset
Original file line number Diff line number Diff line change
Expand Up @@ -321,63 +321,6 @@ set_default_boot_option()
|| whiptail_error_die "Failed to create hashes of boot files"
}

report_integrity_measurements()
{
#check for GPG key in keyring
GPG_KEY_COUNT=`gpg -k 2>/dev/null | wc -l`
if [ $GPG_KEY_COUNT -ne 0 ]; then
# Check and report TOTP
# update the TOTP code every thirty seconds
date=`date "+%Y-%m-%d %H:%M:%S %Z"`
seconds=`date "+%s"`
half=`expr \( $seconds % 60 \) / 30`
if [ "$CONFIG_TPM" != "y" ]; then
TOTP="NO TPM"
elif [ "$half" != "$last_half" ]; then
last_half=$half;
TOTP=`unseal-totp` > /dev/null 2>&1
fi

# Check and report on HOTP status
if [ -x /bin/hotp_verification ]; then
HOTP=`unseal-hotp` > /dev/null 2>&1
enable_usb
if ! hotp_verification info > /dev/null 2>&1 ; then
whiptail $CONFIG_WARNING_BG_COLOR --title 'WARNING: Please insert your HOTP enabled USB Security dongle' --msgbox "Your HOTP enabled USB Security dongle was not detected.\n\nPlease remove it and insert it again." 0 80
fi
# Don't output HOTP codes to screen, so as to make replay attacks harder
hotp_verification check $HOTP
case "$?" in
0 )
HOTP="Success"
;;
4 )
HOTP="Invalid code"
MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR
;;
* )
HOTP="Error checking code, Insert USB Security dongle and retry"
MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR
;;
esac
else
HOTP='N/A'
fi
# Check for detached signed digest and report on /boot integrity status
check_config /boot force
TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt"

if ( cd /boot && sha256sum -c "$TMP_HASH_FILE" > /tmp/hash_output ); then
HASH="OK"
else
HASH="ALTERED"
fi

#Show results
whiptail $MAIN_MENU_BG_COLOR --title "Measured Integrity Report" --msgbox "$date\nTOTP: $TOTP | HOTP: $HOTP\n/BOOT INTEGRITY: $HASH\n\nPress OK to continue or Ctrl+Alt+Delete to reboot" 0 80
fi
}

usb_security_token_capabilities_check()
{
TRACE "Under /bin/oem-factory-reset:usb_security_token_capabilities_check"
Expand Down
Loading