TPM2: add DEBUG and fix path for TPM2 primary key handle hash.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
This commit is contained in:
Thierry Laurion 2023-11-02 14:17:38 -04:00
parent 19c5d16e40
commit 6d7f9be414
No known key found for this signature in database
GPG Key ID: E7B4A71658E36A93
2 changed files with 101 additions and 100 deletions

View File

@ -276,8 +276,9 @@ if [ ! -d $paramsdir ]; then
fi fi
if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
sha256sum /tmp/primary.handle >"$PRIMHASH_FILE" || sha256sum /tmp/secret/primary.handle >"$PRIMHASH_FILE" ||
die "ERROR: Failed to Hash TPM2 primary key handle!" die "ERROR: Failed to Hash TPM2 primary key handle!"
DEBUG "TPM2 primary key handle hash saved to $PRIMHASH_FILE"
fi fi
rm $paramsdir/kexec_default.*.txt 2>/dev/null || true rm $paramsdir/kexec_default.*.txt 2>/dev/null || true

View File

@ -19,18 +19,25 @@ force_boot="n"
skip_confirm="n" skip_confirm="n"
while getopts "b:d:p:a:r:c:uimgfs" arg; do while getopts "b:d:p:a:r:c:uimgfs" arg; do
case $arg in case $arg in
b) bootdir="$OPTARG" ;; b) bootdir="$OPTARG" ;;
d) paramsdev="$OPTARG" ;; d) paramsdev="$OPTARG" ;;
p) paramsdir="$OPTARG" ;; p) paramsdir="$OPTARG" ;;
a) add="$OPTARG" ;; a) add="$OPTARG" ;;
r) remove="$OPTARG" ;; r) remove="$OPTARG" ;;
c) config="$OPTARG" ;; c) config="$OPTARG" ;;
u) unique="y" ;; u) unique="y" ;;
m) force_menu="y" ;; m) force_menu="y" ;;
i) valid_hash="y"; valid_rollback="y" ;; i)
g) gui_menu="y" ;; valid_hash="y"
f) force_boot="y"; valid_hash="y"; valid_rollback="y" ;; valid_rollback="y"
s) skip_confirm="y" ;; ;;
g) gui_menu="y" ;;
f)
force_boot="y"
valid_hash="y"
valid_rollback="y"
;;
s) skip_confirm="y" ;;
esac esac
done done
@ -50,30 +57,28 @@ bootdir="${bootdir%%/}"
paramsdev="${paramsdev%%/}" paramsdev="${paramsdev%%/}"
paramsdir="${paramsdir%%/}" paramsdir="${paramsdir%%/}"
PRIMHASH_FILE="$paramsdir/kexec_primhdl_hash.txt"
if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
if [ -r "$PRIMHASH_FILE" ]; then
sha256sum -c "$PRIMHASH_FILE" ||
{
echo "FATAL: Hash of TPM2 primary key handle mismatch!"
warn "If you have not intentionally regenerated TPM2 primary key,"
warn "your system may have been compromised"
DEBUG "Hash of TPM2 primary key handle mismatched for $PRIMHASH_FILE"
}
else
warn "Hash of TPM2 primary key handle does not exist"
warn "Please rebuild the boot hash tree"
default_failed="y"
DEBUG "Hash of TPM2 primary key handle does not exist under $PRIMHASH_FILE"
fi
fi
#PRIMHASH_FILE="$paramsdir/kexec_primhdl_hash.txt" verify_global_hashes() {
#if [ "$CONFIG_TPM2_TOOLS" = "y" ]; then
# if [ -r "$PRIMHASH_FILE" ]; then
# sha256sum -c "$PRIMHASH_FILE" \
# || {
# echo "FATAL: Hash of TPM2 primary key handle mismatch!";
# warn "If you have not intentionally regenerated TPM2 primary key,";
# warn "your system may have been compromised";
# }
# else
# warn "Hash of TPM2 primary key handle does not exist"
# warn "Please rebuild the boot hash tree"
# default_failed="y"
# fi
#fi
#TODO: Readd when this can work successfully by simply resealing TOTP/HOTP without having to reset TPM2, this is a major pain point for users
#And acutally don't work as intended, even more with TPM DUK
verify_global_hashes()
{
echo "+++ Checking verified boot hash file " echo "+++ Checking verified boot hash file "
# Check the hashes of all the files # Check the hashes of all the files
if verify_checksums "$bootdir" "$gui_menu" ; then if verify_checksums "$bootdir" "$gui_menu"; then
echo "+++ Verified boot hashes " echo "+++ Verified boot hashes "
valid_hash='y' valid_hash='y'
valid_global_hash='y' valid_global_hash='y'
@ -85,44 +90,43 @@ verify_global_hashes()
fi fi
die "$TMP_HASH_FILE: boot hash mismatch" die "$TMP_HASH_FILE: boot hash mismatch"
fi fi
# If user enables it, check root hashes before boot as well # If user enables it, check root hashes before boot as well
if [[ "$CONFIG_ROOT_CHECK_AT_BOOT" = "y" && "$force_menu" == "n" ]]; then if [[ "$CONFIG_ROOT_CHECK_AT_BOOT" = "y" && "$force_menu" == "n" ]]; then
if root-hashes-gui.sh -c; then if root-hashes-gui.sh -c; then
echo "+++ Verified root hashes, continuing boot " echo "+++ Verified root hashes, continuing boot "
# if user re-signs, it wipes out saved options, so scan the boot directory and generate # if user re-signs, it wipes out saved options, so scan the boot directory and generate
if [ ! -r "$TMP_MENU_FILE" ]; then if [ ! -r "$TMP_MENU_FILE" ]; then
scan_options scan_options
fi fi
else else
# root-hashes-gui.sh handles the GUI error menu, just die here # root-hashes-gui.sh handles the GUI error menu, just die here
if [ "$gui_menu" = "y" ]; then if [ "$gui_menu" = "y" ]; then
whiptail $BG_COLOR_ERROR --title 'ERROR: Root Hash Mismatch' \ whiptail $BG_COLOR_ERROR --title 'ERROR: Root Hash Mismatch' \
--msgbox "The root hash check failed!\nExiting to a recovery shell" 0 80 --msgbox "The root hash check failed!\nExiting to a recovery shell" 0 80
fi fi
die "root hash mismatch, see /tmp/hash_output_mismatches for details" die "root hash mismatch, see /tmp/hash_output_mismatches for details"
fi fi
fi fi
} }
verify_rollback_counter() verify_rollback_counter() {
{ TPM_COUNTER=$(grep counter $TMP_ROLLBACK_FILE | cut -d- -f2)
TPM_COUNTER=`grep counter $TMP_ROLLBACK_FILE | cut -d- -f2`
if [ -z "$TPM_COUNTER" ]; then if [ -z "$TPM_COUNTER" ]; then
die "$TMP_ROLLBACK_FILE: TPM counter not found?" die "$TMP_ROLLBACK_FILE: TPM counter not found?"
fi fi
read_tpm_counter $TPM_COUNTER \ read_tpm_counter $TPM_COUNTER ||
|| die "Failed to read TPM counter" die "Failed to read TPM counter"
sha256sum -c $TMP_ROLLBACK_FILE \ sha256sum -c $TMP_ROLLBACK_FILE ||
|| die "Invalid TPM counter state" die "Invalid TPM counter state"
valid_rollback="y" valid_rollback="y"
} }
first_menu="y" first_menu="y"
get_menu_option() { get_menu_option() {
num_options=`cat $TMP_MENU_FILE | wc -l` num_options=$(cat $TMP_MENU_FILE | wc -l)
if [ $num_options -eq 0 ]; then if [ $num_options -eq 0 ]; then
die "No boot options" die "No boot options"
fi fi
@ -132,13 +136,12 @@ get_menu_option() {
elif [ "$gui_menu" = "y" ]; then elif [ "$gui_menu" = "y" ]; then
MENU_OPTIONS="" MENU_OPTIONS=""
n=0 n=0
while read option while read option; do
do
parse_option parse_option
n=`expr $n + 1` n=$(expr $n + 1)
name=$(echo $name | tr " " "_") name=$(echo $name | tr " " "_")
MENU_OPTIONS="$MENU_OPTIONS $n ${name} " MENU_OPTIONS="$MENU_OPTIONS $n ${name} "
done < $TMP_MENU_FILE done <$TMP_MENU_FILE
whiptail --title "Select your boot option" \ whiptail --title "Select your boot option" \
--menu "Choose the boot option [1-$n, a to abort]:" 0 80 8 \ --menu "Choose the boot option [1-$n, a to abort]:" 0 80 8 \
@ -149,12 +152,11 @@ get_menu_option() {
else else
echo "+++ Select your boot option:" echo "+++ Select your boot option:"
n=0 n=0
while read option while read option; do
do
parse_option parse_option
n=`expr $n + 1` n=$(expr $n + 1)
echo "$n. $name [$kernel]" echo "$n. $name [$kernel]"
done < $TMP_MENU_FILE done <$TMP_MENU_FILE
read \ read \
-p "Choose the boot option [1-$n, a to abort]: " \ -p "Choose the boot option [1-$n, a to abort]: " \
@ -166,7 +168,7 @@ get_menu_option() {
fi fi
first_menu="n" first_menu="n"
option=`head -n $option_index $TMP_MENU_FILE | tail -1` option=$(head -n $option_index $TMP_MENU_FILE | tail -1)
parse_option parse_option
} }
@ -175,7 +177,7 @@ confirm_menu_option() {
default_text="Make default" default_text="Make default"
[[ "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" = "y" ]] && default_text="${default_text} and boot" [[ "$CONFIG_TPM_NO_LUKS_DISK_UNLOCK" = "y" ]] && default_text="${default_text} and boot"
whiptail $BG_COLOR_WARNING --title "Confirm boot details" \ whiptail $BG_COLOR_WARNING --title "Confirm boot details" \
--menu "Confirm the boot details for $name:\n\n$(echo $kernel| fold -s -w 80) \n\n" 0 80 8 \ --menu "Confirm the boot details for $name:\n\n$(echo $kernel | fold -s -w 80) \n\n" 0 80 8 \
-- 'd' "${default_text}" 'y' "Boot one time" \ -- 'd' "${default_text}" 'y' "Boot one time" \
2>/tmp/whiptail || die "Aborting boot attempt" 2>/tmp/whiptail || die "Aborting boot attempt"
@ -193,8 +195,8 @@ confirm_menu_option() {
} }
parse_option() { parse_option() {
name=`echo $option | cut -d\| -f1` name=$(echo $option | cut -d\| -f1)
kernel=`echo $option | cut -d\| -f3` kernel=$(echo $option | cut -d\| -f3)
} }
scan_options() { scan_options() {
@ -205,7 +207,7 @@ scan_options() {
die "Failed to parse any boot options" die "Failed to parse any boot options"
fi fi
if [ "$unique" = 'y' ]; then if [ "$unique" = 'y' ]; then
sort -r $option_file | uniq > $TMP_MENU_FILE sort -r $option_file | uniq >$TMP_MENU_FILE
else else
cp $option_file $TMP_MENU_FILE cp $option_file $TMP_MENU_FILE
fi fi
@ -227,7 +229,7 @@ save_default_option() {
-d "$paramsdev" \ -d "$paramsdev" \
-p "$paramsdir" \ -p "$paramsdir" \
-i "$option_index" \ -i "$option_index" \
; then ; then
echo "+++ Saved defaults to device" echo "+++ Saved defaults to device"
sleep 2 sleep 2
default_failed="n" default_failed="n"
@ -245,11 +247,11 @@ default_select() {
# Attempt boot with expected parameters # Attempt boot with expected parameters
# Check that entry matches that which is expected from menu # Check that entry matches that which is expected from menu
default_index=`basename "$TMP_DEFAULT_FILE" | cut -d. -f 2` default_index=$(basename "$TMP_DEFAULT_FILE" | cut -d. -f 2)
# Check to see if entries have changed - useful for detecting grub update # Check to see if entries have changed - useful for detecting grub update
expectedoption=`cat $TMP_DEFAULT_FILE` expectedoption=$(cat $TMP_DEFAULT_FILE)
option=`head -n $default_index $TMP_MENU_FILE | tail -1` option=$(head -n $default_index $TMP_MENU_FILE | tail -1)
if [ "$option" != "$expectedoption" ]; then if [ "$option" != "$expectedoption" ]; then
if [ "$gui_menu" = "y" ]; then if [ "$gui_menu" = "y" ]; then
whiptail $BG_COLOR_ERROR --title 'ERROR: Boot Entry Has Changed' \ whiptail $BG_COLOR_ERROR --title 'ERROR: Boot Entry Has Changed' \
@ -264,7 +266,7 @@ default_select() {
# Enforce that default option hashes are valid # Enforce that default option hashes are valid
echo "+++ Checking verified default boot hash file " echo "+++ Checking verified default boot hash file "
# Check the hashes of all the files # Check the hashes of all the files
if ( cd $bootdir && sha256sum -c "$TMP_DEFAULT_HASH_FILE" > /tmp/hash_output ); then if (cd $bootdir && sha256sum -c "$TMP_DEFAULT_HASH_FILE" >/tmp/hash_output); then
echo "+++ Verified default boot hashes " echo "+++ Verified default boot hashes "
valid_hash='y' valid_hash='y'
else else
@ -285,10 +287,9 @@ user_select() {
# No default expected boot parameters, ask user # No default expected boot parameters, ask user
option_confirm="" option_confirm=""
while [ "$option_confirm" != "y" -a "$option_confirm" != "d" ] while [ "$option_confirm" != "y" -a "$option_confirm" != "d" ]; do
do
get_menu_option get_menu_option
# In force boot mode, no need offer the option to set a default, just boot # In force boot mode, no need offer the option to set a default, just boot
if [[ "$force_boot" = "y" || "$skip_confirm" = "y" ]]; then if [[ "$force_boot" = "y" || "$skip_confirm" = "y" ]]; then
do_boot do_boot
else else
@ -308,8 +309,8 @@ user_select() {
echo "+++ Rebooting to start the new default option" echo "+++ Rebooting to start the new default option"
sleep 2 sleep 2
if [ "$CONFIG_DEBUG_OUTPUT" != "y" ]; then if [ "$CONFIG_DEBUG_OUTPUT" != "y" ]; then
reboot \ reboot ||
|| die "!!! Failed to reboot system" die "!!! Failed to reboot system"
else else
DEBUG "Rebooting is required prior of booting default boot entry" DEBUG "Rebooting is required prior of booting default boot entry"
# Instead of rebooting, drop to a recovery shell # Instead of rebooting, drop to a recovery shell
@ -322,8 +323,7 @@ user_select() {
do_boot do_boot
} }
do_boot() do_boot() {
{
if [ "$CONFIG_BASIC" != y ] && [ "$CONFIG_BOOT_REQ_ROLLBACK" = "y" ] && [ "$valid_rollback" = "n" ]; then if [ "$CONFIG_BASIC" != y ] && [ "$CONFIG_BOOT_REQ_ROLLBACK" = "y" ] && [ "$valid_rollback" = "n" ]; then
die "!!! Missing required rollback counter state" die "!!! Missing required rollback counter state"
fi fi
@ -333,31 +333,31 @@ do_boot()
fi fi
if [ "$CONFIG_BASIC" != y ] && [ "$CONFIG_TPM" = "y" ] && [ -r "$TMP_KEY_DEVICES" ]; then if [ "$CONFIG_BASIC" != y ] && [ "$CONFIG_TPM" = "y" ] && [ -r "$TMP_KEY_DEVICES" ]; then
INITRD=`kexec-boot -b "$bootdir" -e "$option" -i` \ INITRD=$(kexec-boot -b "$bootdir" -e "$option" -i) ||
|| die "!!! Failed to extract the initrd from boot option" die "!!! Failed to extract the initrd from boot option"
if [ -z "$INITRD" ]; then if [ -z "$INITRD" ]; then
die "!!! No initrd file found in boot option" die "!!! No initrd file found in boot option"
fi fi
kexec-insert-key $INITRD \ kexec-insert-key $INITRD ||
|| die "!!! Failed to insert disk key into a new initrd" die "!!! Failed to insert disk key into a new initrd"
kexec-boot -b "$bootdir" -e "$option" \ kexec-boot -b "$bootdir" -e "$option" \
-a "$add" -r "$remove" -o "/tmp/secret/initrd.cpio" \ -a "$add" -r "$remove" -o "/tmp/secret/initrd.cpio" ||
|| die "!!! Failed to boot w/ options: $option" die "!!! Failed to boot w/ options: $option"
else else
kexec-boot -b "$bootdir" -e "$option" -a "$add" -r "$remove" \ kexec-boot -b "$bootdir" -e "$option" -a "$add" -r "$remove" ||
|| die "!!! Failed to boot w/ options: $option" die "!!! Failed to boot w/ options: $option"
fi fi
} }
while true; do while true; do
if [ "$force_boot" = "y" -o "$CONFIG_BASIC" = "y" ]; then if [ "$force_boot" = "y" -o "$CONFIG_BASIC" = "y" ]; then
check_config $paramsdir force check_config $paramsdir force
else else
check_config $paramsdir check_config $paramsdir
fi fi
TMP_DEFAULT_FILE=`find /tmp/kexec/kexec_default.*.txt 2>/dev/null | head -1` || true TMP_DEFAULT_FILE=$(find /tmp/kexec/kexec_default.*.txt 2>/dev/null | head -1) || true
TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt" TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt"
TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt" TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt"
TMP_TREE_FILE="/tmp/kexec/kexec_tree.txt" TMP_TREE_FILE="/tmp/kexec/kexec_tree.txt"
@ -366,8 +366,8 @@ while true; do
TMP_KEY_DEVICES="/tmp/kexec/kexec_key_devices.txt" TMP_KEY_DEVICES="/tmp/kexec/kexec_key_devices.txt"
TMP_KEY_LVM="/tmp/kexec/kexec_key_lvm.txt" TMP_KEY_LVM="/tmp/kexec/kexec_key_lvm.txt"
# Allow a way for users to ignore warnings and boot into their systems # Allow a way for users to ignore warnings and boot into their systems
# even if hashes don't match # even if hashes don't match
if [ "$force_boot" = "y" ]; then if [ "$force_boot" = "y" ]; then
scan_options scan_options
if [ "$CONFIG_BASIC" != "y" ]; then if [ "$CONFIG_BASIC" != "y" ]; then
@ -381,8 +381,8 @@ while true; do
if [ "$CONFIG_TPM" = "y" ]; then if [ "$CONFIG_TPM" = "y" ]; then
if [ ! -r "$TMP_KEY_DEVICES" ]; then if [ ! -r "$TMP_KEY_DEVICES" ]; then
# Extend PCR4 as soon as possible # Extend PCR4 as soon as possible
tpmr extend -ix 4 -ic generic \ tpmr extend -ix 4 -ic generic ||
|| die "Failed to extend PCR 4" die "Failed to extend PCR 4"
fi fi
fi fi
@ -415,7 +415,7 @@ while true; do
-a "$force_menu" = "n" \ -a "$force_menu" = "n" \
-a -r "$TMP_DEFAULT_FILE" \ -a -r "$TMP_DEFAULT_FILE" \
-a -r "$TMP_DEFAULT_HASH_FILE" ] \ -a -r "$TMP_DEFAULT_HASH_FILE" ] \
; then ; then
default_select default_select
default_failed="y" default_failed="y"
else else