Skip to content

Commit d731e1c

Browse files
committed
Codebase up to TPM DUK: ident, add DEBUG+TRACE_FUNC, fix HOTP resealing only on OS reinstall, clarify TPM increment workflow
Signed-off-by: Thierry Laurion <[email protected]>
1 parent 2ab7d58 commit d731e1c

File tree

12 files changed

+222
-126
lines changed

12 files changed

+222
-126
lines changed

initrd/bin/generic-init

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ while true; do
4848
if [ "$totp_confirm" = "m" ]; then
4949
# Try to select a kernel from the menu
5050
mount_boot
51-
kexec-select-boot -m -b /boot -c "grub.cfg"
51+
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg"
5252
continue
5353
fi
5454

5555
if [ "$totp_confirm" = "y" -o -n "$totp_confirm" ]; then
5656
# Try to boot the default
5757
mount_boot
58-
kexec-select-boot -b /boot -c "grub.cfg" \
58+
DO_WITH_DEBUG kexec-select-boot -b /boot -c "grub.cfg" \
5959
|| recovery "Failed default boot"
6060
fi
6161

initrd/bin/gui-init

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -183,17 +183,6 @@ update_totp() {
183183
TOTP="NO TPM"
184184
else
185185
TOTP=$(unseal-totp)
186-
# On platforms using CONFIG_BOOT_EXTRA_TTYS multiple processes may try to
187-
# access TPM at the same time, failing with EBUSY. The order of execution
188-
# is unpredictable, so the error may appear on main console, secondary one,
189-
# or neither of them if the calls are sufficiently staggered. Try up to
190-
# three times (including previous one) with small delays in case of error,
191-
# instead of immediately scaring users with "you've been pwned" message.
192-
while [ $? -ne 0 ] && [ $tries -lt 2 ]; do
193-
sleep 0.5
194-
((tries++))
195-
TOTP=$(unseal-totp)
196-
done
197186
if [ $? -ne 0 ]; then
198187
BG_COLOR_MAIN_MENU="error"
199188
if [ "$skip_to_menu" = "true" ]; then
@@ -280,7 +269,10 @@ update_hotp() {
280269
HOTP='N/A'
281270
fi
282271

283-
if [[ "$CONFIG_TPM" = n && "$HOTP" = "Invalid code" ]]; then
272+
if [[ "$HOTP" = "Invalid code" ]]; then
273+
#TODO: we shouldn't propose to generate a new secret if there is no /boot/kexec_hotp_counter
274+
# as this passed tpm unseal, so the secret is correct: we should propose to reset TPM instead
275+
# Otherwise, tpm_counter is also inexistent: The OS was most probably reinstalled wihile TPM can still unseal the secret
284276
whiptail_error --title "ERROR: HOTP Validation Failed!" \
285277
--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 \
286278
'g' ' Generate new TOTP/HOTP secret' \
@@ -553,21 +545,30 @@ reset_tpm() {
553545
mount -o rw,remount /boot
554546
#TODO: this is really problematic, we should really remove the primary handle hash
555547

556-
INFO "Removing rollback and primary handle hash under /boot"
548+
INFO "Removing rollback and primary handle hashes under /boot"
549+
550+
DEBUG "Removing /boot/kexec_rollback.txt and /boot/kexec_primhdl_hash.txt"
557551
rm -f /boot/kexec_rollback.txt
558552
rm -f /boot/kexec_primhdl_hash.txt
559553

560554
# create Heads TPM counter before any others
561555
check_tpm_counter /boot/kexec_rollback.txt "" "$tpm_owner_password" ||
562556
die "Unable to find/create tpm counter"
563-
counter="$TPM_COUNTER"
564557

565-
increment_tpm_counter $counter >/dev/null 2>&1 ||
558+
TRACE_FUNC
559+
560+
TPM_COUNTER=$(cut -d: -f1 </tmp/counter)
561+
DEBUG "TPM_COUNTER: $TPM_COUNTER"
562+
#TODO was counter supposed to be empty and that was ok?!?!?!
563+
564+
DO_WITH_DEBUG increment_tpm_counter $TPM_COUNTER>/dev/null 2>&1 ||
566565
die "Unable to increment tpm counter"
567566

568-
sha256sum /tmp/counter-$counter >/boot/kexec_rollback.txt ||
567+
#TODO: should this be here?
568+
DO_WITH_DEBUG sha256sum /tmp/counter-$TPM_COUNTER >/boot/kexec_rollback.txt ||
569569
die "Unable to create rollback file"
570570

571+
TRACE_FUNC
571572
# As a countermeasure for existing primary handle hash, we will now force sign /boot without it
572573
if (whiptail --title 'TPM Reset Successfully' \
573574
--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() {
593594
TRACE_FUNC
594595
mount_boot
595596
if verify_global_hashes; then
596-
kexec-select-boot -m -b /boot -c "grub.cfg" -g
597+
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg" -g
597598
fi
598599
}
599600

@@ -606,11 +607,13 @@ attempt_default_boot() {
606607
fi
607608
DEFAULT_FILE=$(find /boot/kexec_default.*.txt 2>/dev/null | head -1)
608609
if [ -r "$DEFAULT_FILE" ]; then
609-
kexec-select-boot -b /boot -c "grub.cfg" -g ||
610+
TRACE_FUNC
611+
DO_WITH_DEBUG kexec-select-boot -b /boot -c "grub.cfg" -g ||
610612
recovery "Failed default boot"
611613
elif (whiptail_warning --title 'No Default Boot Option Configured' \
612614
--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
613-
kexec-select-boot -m -b /boot -c "grub.cfg" -g
615+
TRACE_FUNC
616+
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg" -g
614617
fi
615618
}
616619

initrd/bin/gui-init-basic

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ select_os_boot_option()
159159
{
160160
TRACE_FUNC
161161
mount_boot
162-
kexec-select-boot -m -b /boot -c "grub.cfg" -g -i
162+
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg" -g -i
163163
}
164164

165165
attempt_default_boot()
@@ -174,11 +174,11 @@ attempt_default_boot()
174174
if [ "$CONFIG_BASIC_NO_AUTOMATIC_DEFAULT" != "y" ]; then
175175
basic-autoboot.sh
176176
elif [ -r "$DEFAULT_FILE" ]; then
177-
kexec-select-boot -b /boot -c "grub.cfg" -g -i -s \
177+
DO_WITH_DEBUG kexec-select-boot -b /boot -c "grub.cfg" -g -i -s \
178178
|| recovery "Failed default boot"
179179
elif (whiptail_warning --title 'No Default Boot Option Configured' \
180180
--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
181-
kexec-select-boot -m -b /boot -c "grub.cfg" -g -i
181+
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg" -g -i
182182
fi
183183
}
184184

initrd/bin/kexec-save-default

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ if [ "$CONFIG_TPM" = "y" ]; then
354354
fi
355355
fi
356356
if [ "$CONFIG_BASIC" != "y" ]; then
357-
kexec-sign-config -p $paramsdir $extparam ||
357+
DO_WITH_DEBUG kexec-sign-config -p $paramsdir $extparam ||
358358
die "Failed to sign default config"
359359
fi
360360
# switch back to ro mode

initrd/bin/kexec-save-key

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,11 @@ kexec-seal-key $paramsdir ||
7777
if [ "$skip_sign" != "y" ]; then
7878
extparam=
7979
if [ "$CONFIG_IGNORE_ROLLBACK" != "y" ]; then
80+
DEBUG "kexec-save-key: CONFIG_IGNORE_ROLLBACK is not set, will sign with -r"
8081
extparam=-r
8182
fi
8283
# sign and auto-roll config counter
83-
kexec-sign-config -p $paramsdir $extparam ||
84+
DO_WITH_DEBUG kexec-sign-config -p $paramsdir $extparam ||
8485
die "Failed to sign updated config"
8586
fi
8687

initrd/bin/kexec-select-boot

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,14 @@ verify_rollback_counter() {
120120
TPM_COUNTER=$(grep counter $TMP_ROLLBACK_FILE | cut -d- -f2)
121121

122122
if [ -z "$TPM_COUNTER" ]; then
123-
die "$TMP_ROLLBACK_FILE: TPM counter not found?"
123+
die "$TMP_ROLLBACK_FILE: TPM counter not found. Please reset TPM through the Heads menu: Options -> TPM/TOTP/HOTP Options -> Reset the TPM"
124124
fi
125125

126126
read_tpm_counter $TPM_COUNTER >/dev/null 2>&1 ||
127-
die "Failed to read TPM counter"
127+
die "Failed to read TPM counter. Please reset TPM through the Heads menu: Options -> TPM/TOTP/HOTP Options -> Reset the TPM"
128128

129129
sha256sum -c $TMP_ROLLBACK_FILE >/dev/null 2>&1 ||
130-
die "Invalid TPM counter state. TPM Reset required"
130+
die "Invalid TPM counter state. Please reset TPM through the Heads menu: Options -> TPM/TOTP/HOTP Options -> Reset the TPM"
131131

132132
valid_rollback="y"
133133
}
@@ -361,9 +361,9 @@ do_boot() {
361361

362362
while true; do
363363
if [ "$force_boot" = "y" -o "$CONFIG_BASIC" = "y" ]; then
364-
check_config $paramsdir force
364+
DO_WITH_DEBUG check_config $paramsdir force
365365
else
366-
check_config $paramsdir
366+
DO_WITH_DEBUG check_config $paramsdir
367367
fi
368368
TMP_DEFAULT_FILE=$(find /tmp/kexec/kexec_default.*.txt 2>/dev/null | head -1) || true
369369
TMP_MENU_FILE="/tmp/kexec/kexec_menu.txt"

initrd/bin/kexec-sign-config

Lines changed: 95 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/bin/bash
2+
# filepath: /home/user/heads/initrd/bin/kexec-sign-config
23
# Sign a valid directory of kexec params
34
set -e -o pipefail
45
. /tmp/config
@@ -9,90 +10,126 @@ TRACE_FUNC
910
rollback="n"
1011
update="n"
1112
while getopts "p:c:ur" arg; do
12-
case $arg in
13-
p) paramsdir="$OPTARG" ;;
14-
c)
15-
counter="$OPTARG"
16-
rollback="y"
17-
;;
18-
u) update="y" ;;
19-
r) rollback="y" ;;
20-
esac
13+
case $arg in
14+
p) paramsdir="$OPTARG" ;;
15+
c)
16+
counter="$OPTARG"
17+
rollback="y"
18+
;;
19+
u) update="y" ;;
20+
r) rollback="y" ;;
21+
esac
2122
done
2223

2324
if [ -z "$paramsdir" ]; then
24-
die "Usage: $0 -p /boot [ -u | -c counter ]"
25+
die "Usage: $0 -p /boot [ -u | -c counter ]"
2526
fi
2627

2728
paramsdir="${paramsdir%%/}"
2829

2930
assert_signable
31+
TRACE_FUNC
3032

3133
confirm_gpg_card
34+
TRACE_FUNC
3235

3336
# remount /boot as rw
3437
mount -o remount,rw /boot
3538

39+
DEBUG "Signing kexec parameters in $paramsdir, rollback=$rollback, update=$update, counter=$counter"
40+
3641
# update hashes in /boot before signing
3742
if [ "$update" = "y" ]; then
38-
(
39-
cd /boot
40-
find ./ -type f ! -path './kexec*' -print0 | xargs -0 sha256sum >/boot/kexec_hashes.txt
41-
if [ -e /boot/kexec_default_hashes.txt ]; then
42-
DEFAULT_FILES=$(cat /boot/kexec_default_hashes.txt | cut -f3 -d ' ')
43-
echo $DEFAULT_FILES | xargs sha256sum >/boot/kexec_default_hashes.txt
44-
fi
45-
46-
#also save the file & directory structure to detect added files
47-
print_tree >/boot/kexec_tree.txt
48-
)
49-
[ $? -eq 0 ] || die "$paramsdir: Failed to update hashes."
50-
51-
# Remove any package trigger log files
52-
# We don't need them after the user decides to sign
53-
rm -f /boot/kexec_package_trigger*
43+
(
44+
TRACE_FUNC
45+
DEBUG "update=y: Updating kexec hashes in /boot"
46+
cd /boot
47+
find ./ -type f ! -path './kexec*' -print0 | xargs -0 sha256sum >/boot/kexec_hashes.txt
48+
if [ -e /boot/kexec_default_hashes.txt ]; then
49+
DEBUG "/boot/kexec_default_hashes.txt exists, updating /boot/kexec_default_hashes.txt"
50+
DEFAULT_FILES=$(cat /boot/kexec_default_hashes.txt | cut -f3 -d ' ')
51+
echo $DEFAULT_FILES | xargs sha256sum >/boot/kexec_default_hashes.txt
52+
fi
53+
54+
#also save the file & directory structure to detect added files
55+
print_tree >/boot/kexec_tree.txt
56+
TRACE_FUNC
57+
)
58+
[ $? -eq 0 ] || die "$paramsdir: Failed to update hashes."
59+
60+
# Remove any package trigger log files
61+
# We don't need them after the user decides to sign
62+
rm -f /boot/kexec_package_trigger*
5463
fi
5564

5665
if [ "$rollback" = "y" ]; then
57-
rollback_file="$paramsdir/kexec_rollback.txt"
58-
59-
if [ -n "$counter" ]; then
60-
# use existing counter
61-
read_tpm_counter $counter >/dev/null 2>&1 ||
62-
die "$paramsdir: Unable to read tpm counter '$counter'"
63-
else
64-
# increment counter
65-
check_tpm_counter $rollback_file >/dev/null 2>&1 ||
66-
die "$paramsdir: Unable to find/create tpm counter"
67-
counter="$TPM_COUNTER"
68-
69-
increment_tpm_counter $counter >/dev/null 2>&1 ||
70-
die "$paramsdir: Unable to increment tpm counter"
71-
fi
72-
73-
sha256sum /tmp/counter-$counter >$rollback_file ||
74-
die "$paramsdir: Unable to create rollback file"
66+
67+
# this script was called with -c $OPTARG (counter=$OPTARG) or -r (rollback=y)
68+
DEBUG "rollback=y, counter=$counter, paramsdir=$paramsdir"
69+
TRACE_FUNC
70+
71+
rollback_file="$paramsdir/kexec_rollback.txt"
72+
73+
if [ -n "$counter" ]; then
74+
DEBUG "rollback=y: counter=$counter, will read tpm counter next"
75+
TRACE_FUNC
76+
77+
# use existing tpm counter
78+
DO_WITH_DEBUG read_tpm_counter $counter >/dev/null 2>&1 ||
79+
die "$paramsdir: Unable to read tpm counter '$counter'"
80+
else
81+
DEBUG "rollback=y: counter is empty: checking for existing TPM counter"
82+
TRACE_FUNC
83+
84+
if [ ! -e $rollback_file ]; then
85+
DEBUG "Rollback file $rollback_file does not exist. Creating new TPM counter."
86+
DO_WITH_DEBUG check_tpm_counter $rollback_file ||
87+
die "$paramsdir: Unable to find/create tpm counter"
88+
89+
TRACE_FUNC
90+
DEBUG "rollback=y: checked for existing counter under $rollback_file, found TPM_COUNTER=$TPM_COUNTER"
91+
# we checked for existing counter and didn't die; increment it
92+
DEBUG "rollback=y: Incrementing counter:$TPM_COUNTER."
93+
94+
DO_WITH_DEBUG increment_tpm_counter $counter >/dev/null 2>&1 ||
95+
die "$paramsdir: Unable to increment tpm counter"
96+
TRACE_FUNC
97+
DEBUG "rollback=y: Incremented counter $counter"
98+
else
99+
die "$paramsdir: No rollback file existing. Please reset TPM through the Heads menu: Options -> TPM/TOTP/HOTP Options -> Reset the TPM"
100+
fi
101+
fi
102+
103+
# Ensure the TPM counter file exists
104+
DEBUG "Checking if TPM counter file '/tmp/counter-$counter exists."
105+
if [ ! -e "/tmp/counter-$counter" ]; then
106+
die "$paramsdir: TPM counter file '/tmp/counter-$counter' not found after incrementing."
107+
fi
108+
109+
# Create the rollback file
110+
sha256sum /tmp/counter-$counter >$rollback_file ||
111+
die "$paramsdir: Unable to create rollback file"
75112
fi
76113

77114
param_files=$(find $paramsdir/kexec*.txt)
78115
if [ -z "$param_files" ]; then
79-
die "$paramsdir: No kexec parameter files to sign"
116+
die "$paramsdir: No kexec parameter files to sign"
80117
fi
81118

82119
for tries in 1 2 3; do
83-
if sha256sum $param_files | gpg \
84-
--detach-sign \
85-
-a \
86-
>$paramsdir/kexec.sig \
87-
; then
88-
# successful - update the validated params
89-
check_config $paramsdir
90-
91-
# remount /boot as ro
92-
mount -o remount,ro /boot
93-
94-
exit 0
95-
fi
120+
if DO_WITH_DEBUG sha256sum $param_files | gpg \
121+
--detach-sign \
122+
-a \
123+
>$paramsdir/kexec.sig \
124+
; then
125+
# successful - update the validated params
126+
check_config $paramsdir
127+
128+
# remount /boot as ro
129+
mount -o remount,ro /boot
130+
131+
exit 0
132+
fi
96133
done
97134

98135
# remount /boot as ro

0 commit comments

Comments
 (0)