Skip to content

Commit c38c13b

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 c38c13b

16 files changed

+216
-121
lines changed

initrd/.bash_history

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ find /boot/kexec*.txt | gpg --verify /boot/kexec.sig -
55
#remove invalid kexec_* signed files
66
mount /dev/sda1 /boot && mount -o remount,rw /boot && rm /boot/kexec* && mount -o remount,ro /boot
77
#Generate keys on OpenPGP smartcard:
8-
mount-usb && gpg --home=/.gnupg/ --card-edit
8+
mount-usb --mode rw && gpg --home=/.gnupg/ --card-edit
99
#Copy generated public key, private_subkey, trustdb and artifacts to external media for backup:
10-
mount -o remount,rw /media && mkdir -p /media/gpg_keys; gpg --export-secret-keys --armor [email protected] > /media/gpg_keys/private.key && gpg --export --armor [email protected] > /media/gpg_keys/public.key && gpg --export-ownertrust > /media/gpg_keys/otrust.txt && cp -r ./.gnupg/* /media/gpg_keys/ 2> /dev/null
10+
mkdir -p /media/gpg_keys; gpg --export-secret-keys --armor [email protected] > /media/gpg_keys/private.key && gpg --export --armor [email protected] > /media/gpg_keys/public.key && gpg --export-ownertrust > /media/gpg_keys/otrust.txt && cp -r ./.gnupg/* /media/gpg_keys/ 2> /dev/null
1111
#Insert public key and trustdb export into reproducible rom:
1212
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
1313
#Flush changes to external media:

initrd/bin/generic-init

+2-2
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

+22-19
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+
#Do not propose to generate a new secret if there is no /boot/kexec_hotp_counter
274+
# tpm unseal succeeded: so the sealed secret is correct: we should propose to reset TPM if not already
275+
# Here: the OS was most probably reinstalled since 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

+3-3
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

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ TRACE_FUNC
88

99
while getopts "b:d:p:i:" arg; do
1010
case $arg in
11-
b) bootdir="$OPTARG" ;;
12-
d) paramsdev="$OPTARG" ;;
13-
p) paramsdir="$OPTARG" ;;
14-
i) index="$OPTARG" ;;
11+
b) bootdir="$OPTARG" ;;
12+
d) paramsdev="$OPTARG" ;;
13+
p) paramsdir="$OPTARG" ;;
14+
i) index="$OPTARG" ;;
1515
esac
1616
done
1717

@@ -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

+2-1
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

+24-24
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,25 @@ force_boot="n"
2020
skip_confirm="n"
2121
while getopts "b:d:p:a:r:c:uimgfs" arg; do
2222
case $arg in
23-
b) bootdir="$OPTARG" ;;
24-
d) paramsdev="$OPTARG" ;;
25-
p) paramsdir="$OPTARG" ;;
26-
a) add="$OPTARG" ;;
27-
r) remove="$OPTARG" ;;
28-
c) config="$OPTARG" ;;
29-
u) unique="y" ;;
30-
m) force_menu="y" ;;
31-
i)
32-
valid_hash="y"
33-
valid_rollback="y"
34-
;;
35-
g) gui_menu="y" ;;
36-
f)
37-
force_boot="y"
38-
valid_hash="y"
39-
valid_rollback="y"
40-
;;
41-
s) skip_confirm="y" ;;
23+
b) bootdir="$OPTARG" ;;
24+
d) paramsdev="$OPTARG" ;;
25+
p) paramsdir="$OPTARG" ;;
26+
a) add="$OPTARG" ;;
27+
r) remove="$OPTARG" ;;
28+
c) config="$OPTARG" ;;
29+
u) unique="y" ;;
30+
m) force_menu="y" ;;
31+
i)
32+
valid_hash="y"
33+
valid_rollback="y"
34+
;;
35+
g) gui_menu="y" ;;
36+
f)
37+
force_boot="y"
38+
valid_hash="y"
39+
valid_rollback="y"
40+
;;
41+
s) skip_confirm="y" ;;
4242
esac
4343
done
4444

@@ -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

+52-10
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,32 @@ fi
2727
paramsdir="${paramsdir%%/}"
2828

2929
assert_signable
30+
TRACE_FUNC
3031

3132
confirm_gpg_card
33+
TRACE_FUNC
3234

3335
# remount /boot as rw
3436
mount -o remount,rw /boot
3537

38+
DEBUG "Signing kexec parameters in $paramsdir, rollback=$rollback, update=$update, counter=$counter"
39+
3640
# update hashes in /boot before signing
3741
if [ "$update" = "y" ]; then
3842
(
43+
TRACE_FUNC
44+
DEBUG "update=y: Updating kexec hashes in /boot"
3945
cd /boot
4046
find ./ -type f ! -path './kexec*' -print0 | xargs -0 sha256sum >/boot/kexec_hashes.txt
4147
if [ -e /boot/kexec_default_hashes.txt ]; then
48+
DEBUG "/boot/kexec_default_hashes.txt exists, updating /boot/kexec_default_hashes.txt"
4249
DEFAULT_FILES=$(cat /boot/kexec_default_hashes.txt | cut -f3 -d ' ')
4350
echo $DEFAULT_FILES | xargs sha256sum >/boot/kexec_default_hashes.txt
4451
fi
4552

4653
#also save the file & directory structure to detect added files
4754
print_tree >/boot/kexec_tree.txt
55+
TRACE_FUNC
4856
)
4957
[ $? -eq 0 ] || die "$paramsdir: Failed to update hashes."
5058

@@ -56,31 +64,65 @@ fi
5664
if [ "$rollback" = "y" ]; then
5765
rollback_file="$paramsdir/kexec_rollback.txt"
5866

67+
DEBUG "rollback=y, counter=$counter, paramsdir=$paramsdir, rollback_file=$rollback_file"
68+
TRACE_FUNC
69+
5970
if [ -n "$counter" ]; then
60-
# use existing counter
61-
read_tpm_counter $counter >/dev/null 2>&1 ||
71+
DEBUG "rollback=y: provided counter=$counter, will read tpm counter next"
72+
TRACE_FUNC
73+
74+
# use existing tpm counter
75+
DO_WITH_DEBUG read_tpm_counter "$counter" >/dev/null 2>&1 ||
6276
die "$paramsdir: Unable to read tpm counter '$counter'"
6377
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"
78+
DEBUG "rollback=y: counter was not provided: checking for existing TPM counter from TPM rollback_file=$rollback_file"
79+
TRACE_FUNC
80+
81+
if [ -e "$rollback_file" ]; then
82+
# Extract TPM_COUNTER from rollback file
83+
TPM_COUNTER=$(grep -o 'counter-[0-9a-f]*' "$rollback_file" | cut -d- -f2)
84+
DEBUG "rollback=y: Found TPM counter $TPM_COUNTER in rollback file $rollback_file"
85+
else
86+
DEBUG "Rollback file $rollback_file does not exist. Creating new TPM counter."
87+
DO_WITH_DEBUG check_tpm_counter $rollback_file ||
88+
die "$paramsdir: Unable to find/create tpm counter"
89+
90+
TRACE_FUNC
91+
TPM_COUNTER=$(cut -d: -f1 </tmp/counter)
92+
DEBUG "rollback=y: Created new TPM counter $TPM_COUNTER"
93+
fi
94+
fi
95+
96+
TRACE_FUNC
97+
98+
# Increment the TPM counter
99+
DEBUG "rollback=y: Incrementing counter $TPM_COUNTER."
100+
DO_WITH_DEBUG increment_tpm_counter $TPM_COUNTER >/dev/null 2>&1 ||
101+
die "$paramsdir: Unable to increment tpm counter"
68102

69-
increment_tpm_counter $counter >/dev/null 2>&1 ||
70-
die "$paramsdir: Unable to increment tpm counter"
103+
# Ensure the incremented counter file exists
104+
incremented_counter_file="/tmp/counter-$TPM_COUNTER"
105+
if [ ! -e "$incremented_counter_file" ]; then
106+
DEBUG "TPM counter file '$incremented_counter_file' not found. Attempting to read it again."
107+
DO_WITH_DEBUG read_tpm_counter "$TPM_COUNTER" >/dev/null 2>&1 ||
108+
die "$paramsdir: TPM counter file '$incremented_counter_file' not found after incrementing."
71109
fi
72110

73-
sha256sum /tmp/counter-$counter >$rollback_file ||
111+
DEBUG "TPM counter file '$incremented_counter_file' found."
112+
113+
# Create the rollback file
114+
sha256sum "$incremented_counter_file" >$rollback_file ||
74115
die "$paramsdir: Unable to create rollback file"
75116
fi
76117

118+
TRACE_FUNC
77119
param_files=$(find $paramsdir/kexec*.txt)
78120
if [ -z "$param_files" ]; then
79121
die "$paramsdir: No kexec parameter files to sign"
80122
fi
81123

82124
for tries in 1 2 3; do
83-
if sha256sum $param_files | gpg \
125+
if DO_WITH_DEBUG sha256sum $param_files | gpg \
84126
--detach-sign \
85127
-a \
86128
>$paramsdir/kexec.sig \

initrd/bin/key-init

+9-9
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ TRACE_FUNC
1010
# Good system clock is required for GPG to work properly.
1111
# if system year is less then 2024, prompt user to set correct time
1212
if [ "$(date +%Y)" -lt 2024 ]; then
13-
if whiptail_warning --title "System Time Incorrect" \
14-
--yesno "The system time is incorrect. Please set the correct time." \
15-
0 80 --yes-button Continue --no-button Skip --clear; then
16-
change-time.sh
17-
fi
13+
if whiptail_warning --title "System Time Incorrect" \
14+
--yesno "The system time is incorrect. Please set the correct time." \
15+
0 80 --yes-button Continue --no-button Skip --clear; then
16+
change-time.sh
17+
fi
1818
fi
1919

2020
# Import user's keys if they exist
2121
if [ -d /.gnupg/keys ]; then
22-
# This is legacy location for user's keys. cbfs-init takes for granted that keyring and trustdb are in /.gnupg
23-
# oem-factory-reset generates keyring and trustdb which cbfs-init dumps to /.gnupg
24-
# TODO: Remove individual key imports. This is still valid for distro keys only below.
25-
gpg --import /.gnupg/keys/*.key /.gnupg/keys/*.asc 2>/dev/null || warn "Importing user's keys failed"
22+
# This is legacy location for user's keys. cbfs-init takes for granted that keyring and trustdb are in /.gnupg
23+
# oem-factory-reset generates keyring and trustdb which cbfs-init dumps to /.gnupg
24+
# TODO: Remove individual key imports. This is still valid for distro keys only below.
25+
gpg --import /.gnupg/keys/*.key /.gnupg/keys/*.asc 2>/dev/null || warn "Importing user's keys failed"
2626
fi
2727

2828
# Import trusted distro keys allowed for ISO signing

0 commit comments

Comments
 (0)