mirror of
https://github.com/linuxboot/heads.git
synced 2025-04-08 03:44:29 +00:00
Codebase up to TPM DUK: ident, add DEBUG+TRACE_FUNC, TRACE_FUNC now gives call hierarchy, fix HOTP resealing only on OS reinstall, clarify TPM increment workflow
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
This commit is contained in:
parent
2ab7d5884b
commit
1f6a975940
@ -5,9 +5,9 @@ find /boot/kexec*.txt | gpg --verify /boot/kexec.sig -
|
||||
#remove invalid kexec_* signed files
|
||||
mount /dev/sda1 /boot && mount -o remount,rw /boot && rm /boot/kexec* && mount -o remount,ro /boot
|
||||
#Generate keys on OpenPGP smartcard:
|
||||
mount-usb && gpg --home=/.gnupg/ --card-edit
|
||||
mount-usb --mode rw && gpg --home=/.gnupg/ --card-edit
|
||||
#Copy generated public key, private_subkey, trustdb and artifacts to external media for backup:
|
||||
mount -o remount,rw /media && mkdir -p /media/gpg_keys; gpg --export-secret-keys --armor email@address.com > /media/gpg_keys/private.key && gpg --export --armor email@address.com > /media/gpg_keys/public.key && gpg --export-ownertrust > /media/gpg_keys/otrust.txt && cp -r ./.gnupg/* /media/gpg_keys/ 2> /dev/null
|
||||
mkdir -p /media/gpg_keys; gpg --export-secret-keys --armor email@address.com > /media/gpg_keys/private.key && gpg --export --armor email@address.com > /media/gpg_keys/public.key && gpg --export-ownertrust > /media/gpg_keys/otrust.txt && cp -r ./.gnupg/* /media/gpg_keys/ 2> /dev/null
|
||||
#Insert public key and trustdb export into reproducible rom:
|
||||
cbfs -o /media/coreboot.rom -a "heads/initrd/.gnupg/keys/public.key" -f /media/gpg_keys/public.key && cbfs -o /media/coreboot.rom -a "heads/initrd/.gnupg/keys/otrust.txt" -f /media/gpg_keys/otrust.txt
|
||||
#Flush changes to external media:
|
||||
|
@ -48,14 +48,14 @@ while true; do
|
||||
if [ "$totp_confirm" = "m" ]; then
|
||||
# Try to select a kernel from the menu
|
||||
mount_boot
|
||||
kexec-select-boot -m -b /boot -c "grub.cfg"
|
||||
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg"
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$totp_confirm" = "y" -o -n "$totp_confirm" ]; then
|
||||
# Try to boot the default
|
||||
mount_boot
|
||||
kexec-select-boot -b /boot -c "grub.cfg" \
|
||||
DO_WITH_DEBUG kexec-select-boot -b /boot -c "grub.cfg" \
|
||||
|| recovery "Failed default boot"
|
||||
fi
|
||||
|
||||
|
@ -183,17 +183,6 @@ update_totp() {
|
||||
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="error"
|
||||
if [ "$skip_to_menu" = "true" ]; then
|
||||
@ -280,7 +269,10 @@ update_hotp() {
|
||||
HOTP='N/A'
|
||||
fi
|
||||
|
||||
if [[ "$CONFIG_TPM" = n && "$HOTP" = "Invalid code" ]]; then
|
||||
if [[ "$HOTP" = "Invalid code" ]]; then
|
||||
#Do not propose to generate a new secret if there is no /boot/kexec_hotp_counter
|
||||
# tpm unseal succeeded: so the sealed secret is correct: we should propose to reset TPM if not already
|
||||
# Here: the OS was most probably reinstalled since TPM can still unseal the secret
|
||||
whiptail_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' \
|
||||
@ -553,21 +545,30 @@ reset_tpm() {
|
||||
mount -o rw,remount /boot
|
||||
#TODO: this is really problematic, we should really remove the primary handle hash
|
||||
|
||||
INFO "Removing rollback and primary handle hash under /boot"
|
||||
INFO "Removing rollback and primary handle hashes under /boot"
|
||||
|
||||
DEBUG "Removing /boot/kexec_rollback.txt and /boot/kexec_primhdl_hash.txt"
|
||||
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 >/dev/null 2>&1 ||
|
||||
TRACE_FUNC
|
||||
|
||||
TPM_COUNTER=$(cut -d: -f1 </tmp/counter)
|
||||
DEBUG "TPM_COUNTER: $TPM_COUNTER"
|
||||
#TODO was counter supposed to be empty and that was ok?!?!?!
|
||||
|
||||
DO_WITH_DEBUG increment_tpm_counter $TPM_COUNTER>/dev/null 2>&1 ||
|
||||
die "Unable to increment tpm counter"
|
||||
|
||||
sha256sum /tmp/counter-$counter >/boot/kexec_rollback.txt ||
|
||||
#TODO: should this be here?
|
||||
DO_WITH_DEBUG sha256sum /tmp/counter-$TPM_COUNTER >/boot/kexec_rollback.txt ||
|
||||
die "Unable to create rollback file"
|
||||
|
||||
TRACE_FUNC
|
||||
# As a countermeasure for existing primary handle hash, we will now force sign /boot without it
|
||||
if (whiptail --title 'TPM Reset Successfully' \
|
||||
--yesno "Would you like to update the checksums and sign all of the files in /boot?\n\nYou will need your GPG key to continue and this will modify your disk.\n\nOtherwise the system will reboot immediately." 0 80); then
|
||||
@ -593,7 +594,7 @@ select_os_boot_option() {
|
||||
TRACE_FUNC
|
||||
mount_boot
|
||||
if verify_global_hashes; then
|
||||
kexec-select-boot -m -b /boot -c "grub.cfg" -g
|
||||
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg" -g
|
||||
fi
|
||||
}
|
||||
|
||||
@ -606,11 +607,13 @@ attempt_default_boot() {
|
||||
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 ||
|
||||
TRACE_FUNC
|
||||
DO_WITH_DEBUG kexec-select-boot -b /boot -c "grub.cfg" -g ||
|
||||
recovery "Failed default boot"
|
||||
elif (whiptail_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
|
||||
TRACE_FUNC
|
||||
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg" -g
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -159,7 +159,7 @@ select_os_boot_option()
|
||||
{
|
||||
TRACE_FUNC
|
||||
mount_boot
|
||||
kexec-select-boot -m -b /boot -c "grub.cfg" -g -i
|
||||
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg" -g -i
|
||||
}
|
||||
|
||||
attempt_default_boot()
|
||||
@ -174,11 +174,11 @@ attempt_default_boot()
|
||||
if [ "$CONFIG_BASIC_NO_AUTOMATIC_DEFAULT" != "y" ]; then
|
||||
basic-autoboot.sh
|
||||
elif [ -r "$DEFAULT_FILE" ]; then
|
||||
kexec-select-boot -b /boot -c "grub.cfg" -g -i -s \
|
||||
DO_WITH_DEBUG kexec-select-boot -b /boot -c "grub.cfg" -g -i -s \
|
||||
|| recovery "Failed default boot"
|
||||
elif (whiptail_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 -i
|
||||
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg" -g -i
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -8,10 +8,10 @@ TRACE_FUNC
|
||||
|
||||
while getopts "b:d:p:i:" arg; do
|
||||
case $arg in
|
||||
b) bootdir="$OPTARG" ;;
|
||||
d) paramsdev="$OPTARG" ;;
|
||||
p) paramsdir="$OPTARG" ;;
|
||||
i) index="$OPTARG" ;;
|
||||
b) bootdir="$OPTARG" ;;
|
||||
d) paramsdev="$OPTARG" ;;
|
||||
p) paramsdir="$OPTARG" ;;
|
||||
i) index="$OPTARG" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
@ -354,7 +354,7 @@ if [ "$CONFIG_TPM" = "y" ]; then
|
||||
fi
|
||||
fi
|
||||
if [ "$CONFIG_BASIC" != "y" ]; then
|
||||
kexec-sign-config -p $paramsdir $extparam ||
|
||||
DO_WITH_DEBUG kexec-sign-config -p $paramsdir $extparam ||
|
||||
die "Failed to sign default config"
|
||||
fi
|
||||
# switch back to ro mode
|
||||
|
@ -77,10 +77,11 @@ kexec-seal-key $paramsdir ||
|
||||
if [ "$skip_sign" != "y" ]; then
|
||||
extparam=
|
||||
if [ "$CONFIG_IGNORE_ROLLBACK" != "y" ]; then
|
||||
DEBUG "kexec-save-key: CONFIG_IGNORE_ROLLBACK is not set, will sign with -r"
|
||||
extparam=-r
|
||||
fi
|
||||
# sign and auto-roll config counter
|
||||
kexec-sign-config -p $paramsdir $extparam ||
|
||||
DO_WITH_DEBUG kexec-sign-config -p $paramsdir $extparam ||
|
||||
die "Failed to sign updated config"
|
||||
fi
|
||||
|
||||
|
@ -20,25 +20,25 @@ force_boot="n"
|
||||
skip_confirm="n"
|
||||
while getopts "b:d:p:a:r:c:uimgfs" arg; do
|
||||
case $arg in
|
||||
b) bootdir="$OPTARG" ;;
|
||||
d) paramsdev="$OPTARG" ;;
|
||||
p) paramsdir="$OPTARG" ;;
|
||||
a) add="$OPTARG" ;;
|
||||
r) remove="$OPTARG" ;;
|
||||
c) config="$OPTARG" ;;
|
||||
u) unique="y" ;;
|
||||
m) force_menu="y" ;;
|
||||
i)
|
||||
valid_hash="y"
|
||||
valid_rollback="y"
|
||||
;;
|
||||
g) gui_menu="y" ;;
|
||||
f)
|
||||
force_boot="y"
|
||||
valid_hash="y"
|
||||
valid_rollback="y"
|
||||
;;
|
||||
s) skip_confirm="y" ;;
|
||||
b) bootdir="$OPTARG" ;;
|
||||
d) paramsdev="$OPTARG" ;;
|
||||
p) paramsdir="$OPTARG" ;;
|
||||
a) add="$OPTARG" ;;
|
||||
r) remove="$OPTARG" ;;
|
||||
c) config="$OPTARG" ;;
|
||||
u) unique="y" ;;
|
||||
m) force_menu="y" ;;
|
||||
i)
|
||||
valid_hash="y"
|
||||
valid_rollback="y"
|
||||
;;
|
||||
g) gui_menu="y" ;;
|
||||
f)
|
||||
force_boot="y"
|
||||
valid_hash="y"
|
||||
valid_rollback="y"
|
||||
;;
|
||||
s) skip_confirm="y" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
@ -120,14 +120,14 @@ verify_rollback_counter() {
|
||||
TPM_COUNTER=$(grep counter $TMP_ROLLBACK_FILE | cut -d- -f2)
|
||||
|
||||
if [ -z "$TPM_COUNTER" ]; then
|
||||
die "$TMP_ROLLBACK_FILE: TPM counter not found?"
|
||||
die "$TMP_ROLLBACK_FILE: TPM counter not found. Please reset TPM through the Heads menu: Options -> TPM/TOTP/HOTP Options -> Reset the TPM"
|
||||
fi
|
||||
|
||||
read_tpm_counter $TPM_COUNTER >/dev/null 2>&1 ||
|
||||
die "Failed to read TPM counter"
|
||||
die "Failed to read TPM counter. Please reset TPM through the Heads menu: Options -> TPM/TOTP/HOTP Options -> Reset the TPM"
|
||||
|
||||
sha256sum -c $TMP_ROLLBACK_FILE >/dev/null 2>&1 ||
|
||||
die "Invalid TPM counter state. TPM Reset required"
|
||||
die "Invalid TPM counter state. Please reset TPM through the Heads menu: Options -> TPM/TOTP/HOTP Options -> Reset the TPM"
|
||||
|
||||
valid_rollback="y"
|
||||
}
|
||||
@ -361,9 +361,9 @@ do_boot() {
|
||||
|
||||
while true; do
|
||||
if [ "$force_boot" = "y" -o "$CONFIG_BASIC" = "y" ]; then
|
||||
check_config $paramsdir force
|
||||
DO_WITH_DEBUG check_config $paramsdir force
|
||||
else
|
||||
check_config $paramsdir
|
||||
DO_WITH_DEBUG check_config $paramsdir
|
||||
fi
|
||||
TMP_DEFAULT_FILE=$(find /tmp/kexec/kexec_default.*.txt 2>/dev/null | head -1) || true
|
||||
TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt"
|
||||
|
@ -27,24 +27,32 @@ fi
|
||||
paramsdir="${paramsdir%%/}"
|
||||
|
||||
assert_signable
|
||||
TRACE_FUNC
|
||||
|
||||
confirm_gpg_card
|
||||
TRACE_FUNC
|
||||
|
||||
# remount /boot as rw
|
||||
mount -o remount,rw /boot
|
||||
|
||||
DEBUG "Signing kexec parameters in $paramsdir, rollback=$rollback, update=$update, counter=$counter"
|
||||
|
||||
# update hashes in /boot before signing
|
||||
if [ "$update" = "y" ]; then
|
||||
(
|
||||
TRACE_FUNC
|
||||
DEBUG "update=y: Updating kexec hashes in /boot"
|
||||
cd /boot
|
||||
find ./ -type f ! -path './kexec*' -print0 | xargs -0 sha256sum >/boot/kexec_hashes.txt
|
||||
if [ -e /boot/kexec_default_hashes.txt ]; then
|
||||
DEBUG "/boot/kexec_default_hashes.txt exists, updating /boot/kexec_default_hashes.txt"
|
||||
DEFAULT_FILES=$(cat /boot/kexec_default_hashes.txt | cut -f3 -d ' ')
|
||||
echo $DEFAULT_FILES | xargs sha256sum >/boot/kexec_default_hashes.txt
|
||||
fi
|
||||
|
||||
#also save the file & directory structure to detect added files
|
||||
print_tree >/boot/kexec_tree.txt
|
||||
TRACE_FUNC
|
||||
)
|
||||
[ $? -eq 0 ] || die "$paramsdir: Failed to update hashes."
|
||||
|
||||
@ -56,31 +64,65 @@ fi
|
||||
if [ "$rollback" = "y" ]; then
|
||||
rollback_file="$paramsdir/kexec_rollback.txt"
|
||||
|
||||
DEBUG "rollback=y, counter=$counter, paramsdir=$paramsdir, rollback_file=$rollback_file"
|
||||
TRACE_FUNC
|
||||
|
||||
if [ -n "$counter" ]; then
|
||||
# use existing counter
|
||||
read_tpm_counter $counter >/dev/null 2>&1 ||
|
||||
DEBUG "rollback=y: provided counter=$counter, will read tpm counter next"
|
||||
TRACE_FUNC
|
||||
|
||||
# use existing tpm counter
|
||||
DO_WITH_DEBUG read_tpm_counter "$counter" >/dev/null 2>&1 ||
|
||||
die "$paramsdir: Unable to read tpm counter '$counter'"
|
||||
else
|
||||
# increment counter
|
||||
check_tpm_counter $rollback_file >/dev/null 2>&1 ||
|
||||
die "$paramsdir: Unable to find/create tpm counter"
|
||||
counter="$TPM_COUNTER"
|
||||
DEBUG "rollback=y: counter was not provided: checking for existing TPM counter from TPM rollback_file=$rollback_file"
|
||||
TRACE_FUNC
|
||||
|
||||
increment_tpm_counter $counter >/dev/null 2>&1 ||
|
||||
die "$paramsdir: Unable to increment tpm counter"
|
||||
if [ -e "$rollback_file" ]; then
|
||||
# Extract TPM_COUNTER from rollback file
|
||||
TPM_COUNTER=$(grep -o 'counter-[0-9a-f]*' "$rollback_file" | cut -d- -f2)
|
||||
DEBUG "rollback=y: Found TPM counter $TPM_COUNTER in rollback file $rollback_file"
|
||||
else
|
||||
DEBUG "Rollback file $rollback_file does not exist. Creating new TPM counter."
|
||||
DO_WITH_DEBUG check_tpm_counter $rollback_file ||
|
||||
die "$paramsdir: Unable to find/create tpm counter"
|
||||
|
||||
TRACE_FUNC
|
||||
TPM_COUNTER=$(cut -d: -f1 </tmp/counter)
|
||||
DEBUG "rollback=y: Created new TPM counter $TPM_COUNTER"
|
||||
fi
|
||||
fi
|
||||
|
||||
sha256sum /tmp/counter-$counter >$rollback_file ||
|
||||
TRACE_FUNC
|
||||
|
||||
# Increment the TPM counter
|
||||
DEBUG "rollback=y: Incrementing counter $TPM_COUNTER."
|
||||
DO_WITH_DEBUG increment_tpm_counter $TPM_COUNTER >/dev/null 2>&1 ||
|
||||
die "$paramsdir: Unable to increment tpm counter"
|
||||
|
||||
# Ensure the incremented counter file exists
|
||||
incremented_counter_file="/tmp/counter-$TPM_COUNTER"
|
||||
if [ ! -e "$incremented_counter_file" ]; then
|
||||
DEBUG "TPM counter file '$incremented_counter_file' not found. Attempting to read it again."
|
||||
DO_WITH_DEBUG read_tpm_counter "$TPM_COUNTER" >/dev/null 2>&1 ||
|
||||
die "$paramsdir: TPM counter file '$incremented_counter_file' not found after incrementing."
|
||||
fi
|
||||
|
||||
DEBUG "TPM counter file '$incremented_counter_file' found."
|
||||
|
||||
# Create the rollback file
|
||||
sha256sum "$incremented_counter_file" >$rollback_file ||
|
||||
die "$paramsdir: Unable to create rollback file"
|
||||
fi
|
||||
|
||||
TRACE_FUNC
|
||||
param_files=$(find $paramsdir/kexec*.txt)
|
||||
if [ -z "$param_files" ]; then
|
||||
die "$paramsdir: No kexec parameter files to sign"
|
||||
fi
|
||||
|
||||
for tries in 1 2 3; do
|
||||
if sha256sum $param_files | gpg \
|
||||
if DO_WITH_DEBUG sha256sum $param_files | gpg \
|
||||
--detach-sign \
|
||||
-a \
|
||||
>$paramsdir/kexec.sig \
|
||||
|
@ -10,19 +10,19 @@ TRACE_FUNC
|
||||
# Good system clock is required for GPG to work properly.
|
||||
# if system year is less then 2024, prompt user to set correct time
|
||||
if [ "$(date +%Y)" -lt 2024 ]; then
|
||||
if whiptail_warning --title "System Time Incorrect" \
|
||||
--yesno "The system time is incorrect. Please set the correct time." \
|
||||
0 80 --yes-button Continue --no-button Skip --clear; then
|
||||
change-time.sh
|
||||
fi
|
||||
if whiptail_warning --title "System Time Incorrect" \
|
||||
--yesno "The system time is incorrect. Please set the correct time." \
|
||||
0 80 --yes-button Continue --no-button Skip --clear; then
|
||||
change-time.sh
|
||||
fi
|
||||
fi
|
||||
|
||||
# Import user's keys if they exist
|
||||
if [ -d /.gnupg/keys ]; then
|
||||
# This is legacy location for user's keys. cbfs-init takes for granted that keyring and trustdb are in /.gnupg
|
||||
# oem-factory-reset generates keyring and trustdb which cbfs-init dumps to /.gnupg
|
||||
# TODO: Remove individual key imports. This is still valid for distro keys only below.
|
||||
gpg --import /.gnupg/keys/*.key /.gnupg/keys/*.asc 2>/dev/null || warn "Importing user's keys failed"
|
||||
# This is legacy location for user's keys. cbfs-init takes for granted that keyring and trustdb are in /.gnupg
|
||||
# oem-factory-reset generates keyring and trustdb which cbfs-init dumps to /.gnupg
|
||||
# TODO: Remove individual key imports. This is still valid for distro keys only below.
|
||||
gpg --import /.gnupg/keys/*.key /.gnupg/keys/*.asc 2>/dev/null || warn "Importing user's keys failed"
|
||||
fi
|
||||
|
||||
# Import trusted distro keys allowed for ISO signing
|
||||
|
@ -731,14 +731,20 @@ generate_checksums() {
|
||||
whiptail_error_die "Unable to create TPM counter"
|
||||
TPM_COUNTER=$(cut -d: -f1 </tmp/counter)
|
||||
|
||||
# increment TPM counter
|
||||
increment_tpm_counter $TPM_COUNTER >/dev/null 2>&1 ||
|
||||
whiptail_error_die "Unable to increment tpm counter"
|
||||
if [ -s /tmp/counter-$TPM_COUNTER ]; then
|
||||
|
||||
# create rollback file
|
||||
sha256sum /tmp/counter-$TPM_COUNTER >/boot/kexec_rollback.txt 2>/dev/null ||
|
||||
whiptail_error_die "Unable to create rollback file"
|
||||
else
|
||||
# increment TPM counter
|
||||
increment_tpm_counter $TPM_COUNTER >/dev/null 2>&1 ||
|
||||
whiptail_error_die "Unable to increment tpm counter"
|
||||
|
||||
# create rollback file
|
||||
sha256sum /tmp/counter-$TPM_COUNTER >/boot/kexec_rollback.txt 2>/dev/null ||
|
||||
whiptail_error_die "Unable to create rollback file"
|
||||
fi
|
||||
fi
|
||||
|
||||
# If HOTP is enabled from board config, create HOTP counter
|
||||
if [ -x /bin/hotp_verification]; then
|
||||
## needs to exist for initial call to unseal-hotp
|
||||
echo "0" >/boot/kexec_hotp_counter
|
||||
fi
|
||||
|
@ -5,7 +5,7 @@ TRACE_FUNC
|
||||
|
||||
if [ "$CONFIG_DEBUG_OUTPUT" = "y" ]; then
|
||||
#Generalize user prompt to continue reboot or go to recovery shell
|
||||
read -r -n 1 -s -p "Press any key to continue reboot or 'r' to go to recovery shell: " REPLY
|
||||
read -r -n 1 -s -p "Press Enter to continue reboot or 'r' to go to recovery shell: " REPLY
|
||||
echo
|
||||
if [ "$REPLY" = "r" ] || [ "$REPLY" = "R" ]; then
|
||||
recovery "Reboot call bypassed to go into recovery shell to debug"
|
||||
|
@ -589,7 +589,7 @@ tpm2_unseal() {
|
||||
# can't do anything without a primary handle.
|
||||
if [ ! -f "$PRIMARY_HANDLE_FILE" ]; then
|
||||
DEBUG "tpm2_unseal: No primary handle, cannot attempt to unseal"
|
||||
warn "No TPM primary handle. You must reset TPM to seal secret to TPM NVRAM"
|
||||
warn "No TPM primary handle. You must reset the TPM to seal secret to TPM NVRAM"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -639,7 +639,7 @@ tpm1_unseal() {
|
||||
|
||||
rm -f "$sealed_file"
|
||||
|
||||
tpm nv_readvalue \
|
||||
DO_WITH_DEBUG tpm nv_readvalue \
|
||||
-in "$index" \
|
||||
-sz "$sealed_size" \
|
||||
-of "$sealed_file" ||
|
||||
@ -719,7 +719,7 @@ tpm1_reset() {
|
||||
DO_WITH_DEBUG tpm physicalsetdeactivated -c &>/dev/null
|
||||
DO_WITH_DEBUG tpm forceclear &>/dev/null
|
||||
DO_WITH_DEBUG tpm physicalenable &>/dev/null
|
||||
DO_WITH_DEBUG tpm takeown -pwdo "$tpm_owner_password" &>/dev/null
|
||||
DO_WITH_DEBUG --mask-position 3 tpm takeown -pwdo "$tpm_owner_password" &>/dev/null
|
||||
|
||||
# And now turn it all back on
|
||||
DO_WITH_DEBUG tpm physicalpresence -s &>/dev/null
|
||||
|
@ -7,12 +7,12 @@ HOTP_SECRET="/tmp/secret/hotp.key"
|
||||
HOTP_COUNTER="/boot/kexec_hotp_counter"
|
||||
|
||||
mount_boot_or_die() {
|
||||
TRACE_FUNC
|
||||
# Mount local disk if it is not already mounted
|
||||
if ! grep -q /boot /proc/mounts; then
|
||||
mount -o ro /boot ||
|
||||
die "Unable to mount /boot"
|
||||
fi
|
||||
TRACE_FUNC
|
||||
# Mount local disk if it is not already mounted
|
||||
if ! grep -q /boot /proc/mounts; then
|
||||
mount -o ro /boot ||
|
||||
die "Unable to mount /boot"
|
||||
fi
|
||||
}
|
||||
|
||||
TRACE_FUNC
|
||||
@ -29,27 +29,33 @@ mount_boot_or_die
|
||||
#counter_value=$(read_tpm_counter $counter | cut -f2 -d ' ' | awk 'gsub("^000e","")')
|
||||
#
|
||||
|
||||
counter_value=$(cat $HOTP_COUNTER)
|
||||
#if HOTP_COUNTER is not present, bail out
|
||||
if [ ! -f $HOTP_COUNTER ]; then
|
||||
die "HOTP counter file not found. If you just reinstalled an OS, you need to reseal the HOTP secret"
|
||||
fi
|
||||
|
||||
# Read the counter from the file
|
||||
counter_value=$(cat $HOTP_COUNTER 2>/dev/null)
|
||||
|
||||
if [ "$counter_value" == "" ]; then
|
||||
die "Unable to read HOTP counter"
|
||||
die "Unable to read HOTP counter"
|
||||
fi
|
||||
|
||||
#counter_value=$(printf "%d" 0x${counter_value})
|
||||
if [ "$CONFIG_TPM" = "y" ]; then
|
||||
DEBUG "Unsealing HOTP secret reuses TOTP sealed secret..."
|
||||
tpmr unseal 4d47 0,1,2,3,4,7 312 "$HOTP_SECRET" || die "Unable to unseal HOTP secret"
|
||||
DEBUG "Unsealing HOTP secret reuses TOTP sealed secret..."
|
||||
tpmr unseal 4d47 0,1,2,3,4,7 312 "$HOTP_SECRET" || die "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"
|
||||
# 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
|
||||
|
||||
# Truncate the secret if it is longer than the maximum HOTP secret
|
||||
truncate_max_bytes 20 "$HOTP_SECRET"
|
||||
|
||||
if ! hotp $counter_value <"$HOTP_SECRET"; then
|
||||
shred -n 10 -z -u "$HOTP_SECRET" 2>/dev/null
|
||||
die 'Unable to compute HOTP hash?'
|
||||
shred -n 10 -z -u "$HOTP_SECRET" 2>/dev/null
|
||||
die 'Unable to compute HOTP hash?'
|
||||
fi
|
||||
|
||||
shred -n 10 -z -u "$HOTP_SECRET" 2>/dev/null
|
||||
@ -65,7 +71,7 @@ mount -o remount,rw /boot
|
||||
DEBUG "Incrementing HOTP counter under $HOTP_COUNTER"
|
||||
counter_value=$(expr $counter_value + 1)
|
||||
echo $counter_value >$HOTP_COUNTER ||
|
||||
die "Unable to create hotp counter file"
|
||||
die "Unable to create hotp counter file"
|
||||
mount -o remount,ro /boot
|
||||
|
||||
exit 0
|
||||
|
@ -8,11 +8,12 @@ TOTP_SECRET="/tmp/secret/totp.key"
|
||||
TRACE_FUNC
|
||||
|
||||
if [ "$CONFIG_TPM" = "y" ]; then
|
||||
tpmr unseal 4d47 0,1,2,3,4,7 312 "$TOTP_SECRET" ||
|
||||
die "Unable to unseal TOTP secret from TPM"
|
||||
DO_WITH_DEBUG --mask-position 5 \
|
||||
tpmr unseal 4d47 0,1,2,3,4,7 312 "$TOTP_SECRET" ||
|
||||
die "Unable to unseal TOTP secret from TPM"
|
||||
fi
|
||||
|
||||
if ! totp -q <"$TOTP_SECRET"; then
|
||||
if ! DO_WITH_DEBUG totp -q <"$TOTP_SECRET"; then
|
||||
shred -n 10 -z -u "$TOTP_SECRET" 2>/dev/null
|
||||
die 'Unable to compute TOTP hash?'
|
||||
fi
|
||||
|
@ -8,7 +8,10 @@ die() {
|
||||
else
|
||||
echo -e "!!! ERROR: $* !!!" >&2
|
||||
fi
|
||||
sleep 2
|
||||
|
||||
# ask user to press any key prior to exit
|
||||
read -n 1 -s -r -p $'Press Enter to continue...\n\n'
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
@ -194,7 +197,7 @@ confirm_gpg_card() {
|
||||
echo "GPG User PIN retry attempts left before becoming locked: $user_pin_retries"
|
||||
echo "GPG Admin PIN retry attempts left before becoming locked: $admin_pin_retries"
|
||||
echo ""
|
||||
warn "Your GPG User PIN, followed by Enter key will be required for input at: 'Please unlock the card' next prompt"
|
||||
warn "Your GPG User PIN, followed by Enter will be required for input at: 'Please unlock the card' next prompt"
|
||||
echo ""
|
||||
}
|
||||
|
||||
@ -512,14 +515,33 @@ DO_WITH_DEBUG() {
|
||||
return "$exit_status"
|
||||
}
|
||||
|
||||
# Trace the current script and function.
|
||||
# TRACE_FUNC outputs the function call stack in a readable format.
|
||||
# It helps debug the execution path leading to the current function.
|
||||
#
|
||||
# The format of the output is:
|
||||
# main(/path/to/script:line) -> function1(/path/to/file:line) -> function2(/path/to/file:line)
|
||||
#
|
||||
# Usage:
|
||||
# Call TRACE_FUNC within any function to print the call hierarchy.
|
||||
TRACE_FUNC() {
|
||||
# Index [1] for BASH_SOURCE and FUNCNAME give us the caller location.
|
||||
# FUNCNAME is 'main' if called from a script outside any function.
|
||||
# BASH_LINENO is offset by 1, it provides the line that the
|
||||
# corresponding FUNCNAME was _called from_, so BASH_LINENO[0] is the
|
||||
# location of the caller.
|
||||
TRACE "${BASH_SOURCE[1]}(${BASH_LINENO[0]}): ${FUNCNAME[1]}"
|
||||
|
||||
local i stack_trace=""
|
||||
|
||||
# Traverse the call stack from the earliest caller to the direct caller of TRACE_FUNC
|
||||
for ((i = ${#FUNCNAME[@]} - 1; i > 1; i--)); do
|
||||
stack_trace+="${FUNCNAME[i]}(${BASH_SOURCE[i]}:${BASH_LINENO[i - 1]}) -> "
|
||||
done
|
||||
|
||||
# Append the direct caller (without extra " -> " at the end)
|
||||
stack_trace+="${FUNCNAME[1]}(${BASH_SOURCE[1]}:${BASH_LINENO[0]})"
|
||||
|
||||
# Print the final trace output
|
||||
TRACE "${stack_trace}"
|
||||
}
|
||||
|
||||
# Show the entire current call stack in debug output - useful if a catastrophic
|
||||
@ -750,7 +772,7 @@ prompt_new_owner_password() {
|
||||
# Cache the password externally to be reused by who needs it
|
||||
DEBUG "Caching TPM Owner Password to /tmp/secret/tpm_owner_password"
|
||||
mkdir -p /tmp/secret || die "Unable to create /tmp/secret"
|
||||
echo -n "$tpm_owner_password" >/tmp/secret/tpm_owner_password || die "Unable to cache TPM password under /tmp/secret"
|
||||
echo -n "$tpm_owner_password" >/tmp/secret/tpm_owner_password || die "Unable to cache TPM password under /tmp/secret/tpm_owner_password"
|
||||
}
|
||||
|
||||
check_tpm_counter() {
|
||||
@ -780,16 +802,21 @@ check_tpm_counter() {
|
||||
# Read the TPM counter value from the TPM.
|
||||
read_tpm_counter() {
|
||||
TRACE_FUNC
|
||||
tpmr counter_read -ix "$1" | tee "/tmp/counter-$1" >/dev/null 2>&1 ||
|
||||
die "Counter read failed"
|
||||
if [ ! -e /tmp/counter-"$1" ]; then
|
||||
DEBUG "Counter file /tmp/counter-$1 not found. Attempting to read from TPM."
|
||||
DO_WITH_DEBUG tpmr counter_read -ix "$1" | tee /tmp/counter-"$1" >/dev/null 2>&1 ||
|
||||
die "Counter read failed for index $1"
|
||||
fi
|
||||
DEBUG "Counter file /tmp/counter-$1 read successfully."
|
||||
}
|
||||
|
||||
# Increment the TPM counter value in the TPM.
|
||||
increment_tpm_counter() {
|
||||
TRACE_FUNC
|
||||
tpmr counter_increment -ix "$1" -pwdc '' |
|
||||
tee /tmp/counter-$1 >/dev/null 2>&1 ||
|
||||
die "TPM counter increment failed for rollback prevention. Please reset the TPM"
|
||||
DO_WITH_DEBUG tpmr counter_increment -ix "$1" -pwdc '' |
|
||||
tee /tmp/counter-"$1" >/dev/null 2>&1 ||
|
||||
die "TPM counter increment failed for rollback prevention. Please reset the TPM."
|
||||
DEBUG "TPM counter incremented successfully for index $1"
|
||||
}
|
||||
|
||||
# Check detached signature on kexec boot params
|
||||
@ -804,14 +831,17 @@ check_config() {
|
||||
fi
|
||||
|
||||
if [ ! -r $1/kexec.sig -a "$CONFIG_BASIC" != "y" ]; then
|
||||
DEBUG "No $1/kexec.sig found"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ $(find $1/kexec*.txt | wc -l) -eq 0 ]; then
|
||||
DEBUG "No $1/kexec*.txt found"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$2" != "force" ]; then
|
||||
DEBUG "second param: $2 != force"
|
||||
# Note that kexec.sig detached signature is solely verifying kexec*.txt files here!
|
||||
if ! sha256sum $(find $1/kexec*.txt) | gpgv $1/kexec.sig -; then
|
||||
die 'Invalid signature on kexec boot params'
|
||||
@ -885,10 +915,11 @@ update_checksums() {
|
||||
extparam=
|
||||
if [ "$CONFIG_TPM" = "y" ]; then
|
||||
if [ "$CONFIG_IGNORE_ROLLBACK" != "y" ]; then
|
||||
DEBUG "add -r to kexec-sign-config since CONFIG_IGNORE_ROLLBACK is not set"
|
||||
extparam=-r
|
||||
fi
|
||||
fi
|
||||
if ! kexec-sign-config -p /boot -u $extparam; then
|
||||
if ! DO_WITH_DEBUG kexec-sign-config -p /boot -u $extparam; then
|
||||
rv=1
|
||||
else
|
||||
rv=0
|
||||
@ -996,12 +1027,12 @@ verify_checksums() {
|
||||
set +e -o pipefail
|
||||
local ret=0
|
||||
cd "$boot_dir" || ret=1
|
||||
sha256sum -c "$TMP_HASH_FILE" >/tmp/hash_output || ret=1
|
||||
sha256sum -c "$TMP_HASH_FILE" >/tmp/hash_output 2>/dev/null || ret=1
|
||||
|
||||
# also make sure that the file & directory structure didn't change
|
||||
# (sha256sum won't detect added files)
|
||||
print_tree >/tmp/tree_output || ret=1
|
||||
if ! cmp -s "$TMP_TREE_FILE" /tmp/tree_output &>/dev/null; then
|
||||
if ! cmp -s "$TMP_TREE_FILE" /tmp/tree_output 2>/dev/null; then
|
||||
ret=1
|
||||
[[ "$gui" != "y" ]] && exit "$ret"
|
||||
# produce a diff that can safely be presented to the user
|
||||
@ -1190,7 +1221,6 @@ scan_boot_options() {
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# truncate a file to a size only if it is longer (busybox truncate lacks '<' and
|
||||
# always sets the file size)
|
||||
truncate_max_bytes() {
|
||||
@ -1220,13 +1250,13 @@ fromhex_plain() {
|
||||
print_battery_charge() {
|
||||
local battery
|
||||
battery="$1"
|
||||
echo "$((100*$(cat "${battery}/charge_now")/$(cat "${battery}/charge_full")))"
|
||||
echo "$((100 * $(cat "${battery}/charge_now") / $(cat "${battery}/charge_full")))"
|
||||
}
|
||||
|
||||
print_battery_health() {
|
||||
local battery
|
||||
battery="$1"
|
||||
echo "$((100*$(cat "${battery}/charge_full")/$(cat "${battery}/charge_full_design")))"
|
||||
echo "$((100 * $(cat "${battery}/charge_full") / $(cat "${battery}/charge_full_design")))"
|
||||
}
|
||||
|
||||
print_battery_name() {
|
||||
|
@ -33,9 +33,9 @@ if lsmod | sed 's/_/-/g' | grep -q "^$module_name\\b"; then
|
||||
fi
|
||||
|
||||
if [ ! -r /sys/class/tpm/tpm0/pcrs -o ! -x /bin/tpm ]; then
|
||||
if [ ! -c /dev/tpmrm0 -o ! -x /bin/tpm2 ]; then
|
||||
tpm_missing=1
|
||||
fi
|
||||
if [ ! -c /dev/tpmrm0 -o ! -x /bin/tpm2 ]; then
|
||||
tpm_missing=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$tpm_missing" ]; then
|
||||
|
Loading…
x
Reference in New Issue
Block a user