Skip to content

Commit 112998e

Browse files
committed
Merge remote-tracking branch 'origin/master' into HEAD
2 parents 13642fa + 81dbf23 commit 112998e

21 files changed

+467
-241
lines changed

initrd/.bash_history

Lines changed: 2 additions & 2 deletions
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@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
10+
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
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

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: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -150,16 +150,21 @@ generate_totp_hotp() {
150150
TRACE_FUNC
151151
tpm_owner_password="$1" # May be empty, will prompt if needed and empty
152152
if [ "$CONFIG_TPM" != "y" ] && [ -x /bin/hotp_verification ]; then
153+
# If we don't have a TPM, but we have a HOTP USB Security dongle
154+
TRACE_FUNC
153155
echo "Generating new HOTP secret"
154-
/bin/seal-hotpkey
156+
/bin/seal-hotpkey ||
157+
die "Failed to generate HOTP secret"
155158
elif echo -e "Generating new TOTP secret...\n\n" && /bin/seal-totp "$BOARD_NAME" "$tpm_owner_password"; then
156159
echo
157160
if [ -x /bin/hotp_verification ]; then
161+
# If we have a TPM and a HOTP USB Security dongle
158162
if [ "$CONFIG_TOTP_SKIP_QRCODE" != y ]; then
159163
echo "Once you have scanned the QR code, hit Enter to configure your HOTP USB Security dongle (e.g. Librem Key or Nitrokey)"
160164
read
161165
fi
162-
/bin/seal-hotpkey
166+
TRACE_FUNC
167+
/bin/seal-hotpkey || die "Failed to generate HOTP secret"
163168
else
164169
if [ "$CONFIG_TOTP_SKIP_QRCODE" != y ]; then
165170
echo "Once you have scanned the QR code, hit Enter to continue"
@@ -183,17 +188,6 @@ update_totp() {
183188
TOTP="NO TPM"
184189
else
185190
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
197191
if [ $? -ne 0 ]; then
198192
BG_COLOR_MAIN_MENU="error"
199193
if [ "$skip_to_menu" = "true" ]; then
@@ -280,7 +274,10 @@ update_hotp() {
280274
HOTP='N/A'
281275
fi
282276

283-
if [[ "$CONFIG_TPM" = n && "$HOTP" = "Invalid code" ]]; then
277+
if [[ "$HOTP" = "Invalid code" ]]; then
278+
#Do not propose to generate a new secret if there is no /boot/kexec_hotp_counter
279+
# tpm unseal succeeded: so the sealed secret is correct: we should propose to reset TPM if not already
280+
# Here: the OS was most probably reinstalled since TPM can still unseal the secret
284281
whiptail_error --title "ERROR: HOTP Validation Failed!" \
285282
--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 \
286283
'g' ' Generate new TOTP/HOTP secret' \
@@ -553,21 +550,29 @@ reset_tpm() {
553550
mount -o rw,remount /boot
554551
#TODO: this is really problematic, we should really remove the primary handle hash
555552

556-
INFO "Removing rollback and primary handle hash under /boot"
553+
INFO "Removing rollback and primary handle hashes under /boot"
554+
555+
DEBUG "Removing /boot/kexec_rollback.txt and /boot/kexec_primhdl_hash.txt"
557556
rm -f /boot/kexec_rollback.txt
558557
rm -f /boot/kexec_primhdl_hash.txt
559558

560559
# create Heads TPM counter before any others
561560
check_tpm_counter /boot/kexec_rollback.txt "" "$tpm_owner_password" ||
562561
die "Unable to find/create tpm counter"
563-
counter="$TPM_COUNTER"
564562

565-
increment_tpm_counter $counter >/dev/null 2>&1 ||
563+
TRACE_FUNC
564+
565+
TPM_COUNTER=$(cut -d: -f1 </tmp/counter)
566+
DEBUG "TPM_COUNTER: $TPM_COUNTER"
567+
#TPM_COUNTER can be empty
568+
569+
DO_WITH_DEBUG increment_tpm_counter $TPM_COUNTER>/dev/null 2>&1 ||
566570
die "Unable to increment tpm counter"
567571

568-
sha256sum /tmp/counter-$counter >/boot/kexec_rollback.txt ||
572+
DO_WITH_DEBUG sha256sum /tmp/counter-$TPM_COUNTER >/boot/kexec_rollback.txt ||
569573
die "Unable to create rollback file"
570574

575+
TRACE_FUNC
571576
# As a countermeasure for existing primary handle hash, we will now force sign /boot without it
572577
if (whiptail --title 'TPM Reset Successfully' \
573578
--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
@@ -576,7 +581,8 @@ reset_tpm() {
576581
--msgbox "Failed to update checksums / sign default config" 0 80
577582
fi
578583
else
579-
die "TPM reset successful, but user chose not to update checksums"
584+
warn "TPM reset successful, but user chose not to update+sign /boot checksums. Rebooting"
585+
reboot
580586
fi
581587
mount -o ro,remount /boot
582588

@@ -593,7 +599,7 @@ select_os_boot_option() {
593599
TRACE_FUNC
594600
mount_boot
595601
if verify_global_hashes; then
596-
kexec-select-boot -m -b /boot -c "grub.cfg" -g
602+
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg" -g
597603
fi
598604
}
599605

@@ -606,11 +612,13 @@ attempt_default_boot() {
606612
fi
607613
DEFAULT_FILE=$(find /boot/kexec_default.*.txt 2>/dev/null | head -1)
608614
if [ -r "$DEFAULT_FILE" ]; then
609-
kexec-select-boot -b /boot -c "grub.cfg" -g ||
615+
TRACE_FUNC
616+
DO_WITH_DEBUG kexec-select-boot -b /boot -c "grub.cfg" -g ||
610617
recovery "Failed default boot"
611618
elif (whiptail_warning --title 'No Default Boot Option Configured' \
612619
--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
620+
TRACE_FUNC
621+
DO_WITH_DEBUG kexec-select-boot -m -b /boot -c "grub.cfg" -g
614622
fi
615623
}
616624

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: 5 additions & 5 deletions
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

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-seal-key

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -63,57 +63,70 @@ fi
6363

6464
DEBUG "$(pcrs)"
6565

66-
66+
# First, collect all the LUKS devices that need to be tested
6767
luks_drk_passphrase_valid=0
68-
for dev in $key_devices ; do
69-
attempts=0
70-
while [ $attempts -lt 3 ]; do
71-
if [ "$luks_drk_passphrase_valid" == "0" ]; then
72-
# Ask for the passphrase only once
73-
read -s -p "Enter LUKS Disk Recovery Key (DRK) passphrase that can unlock $key_devices: " disk_recovery_key_passphrase
74-
#Using he provided passphrase as the DRK "keyfile" for unattended operations
75-
echo -n "$disk_recovery_key_passphrase" >"$DISK_RECOVERY_KEY_FILE"
76-
echo
77-
fi
68+
attempts=0
7869

79-
DEBUG "Testing $DISK_RECOVERY_KEY_FILE keyfile created from provided passphrase against $dev individual key slots"
80-
if cryptsetup open $dev --test-passphrase --key-file "$DISK_RECOVERY_KEY_FILE" >/dev/null 2>&1; then
81-
echo "++++++ $dev: LUKS device unlocked successfully with the DRK passphrase"
82-
luks_drk_passphrase_valid=1
70+
# Ask for the DRK passphrase first, before testing any devices
71+
while [ $attempts -lt 3 ] && [ $luks_drk_passphrase_valid -eq 0 ]; do
72+
read -r -s -p $'\nEnter LUKS Disk Recovery Key (DRK) passphrase that can unlock '"$key_devices"': ' disk_recovery_key_passphrase
73+
echo
74+
echo -n "$disk_recovery_key_passphrase" >"$DISK_RECOVERY_KEY_FILE"
75+
76+
# Test the passphrase against ALL devices before deciding if it's valid
77+
all_devices_unlocked=1
78+
79+
for dev in $key_devices; do
80+
DEBUG "Testing $DISK_RECOVERY_KEY_FILE keyfile against $dev"
81+
if ! cryptsetup open $dev --test-passphrase --key-file "$DISK_RECOVERY_KEY_FILE" >/dev/null 2>&1; then
82+
warn "Failed to unlock LUKS device $dev with the provided passphrase."
83+
all_devices_unlocked=0
8384
break
8485
else
85-
attempts=$((attempts + 1))
86-
if [ "$attempts" == "3" ] && [ "$luks_drk_passphrase_valid" == "0" ]; then
87-
die "Failed to unlock LUKS device $dev with the provided passphrase. Exiting..."
88-
elif [ "$attempts" != "3" ] && [ "$luks_drk_passphrase_valid" == "1" ]; then
89-
#We failed unlocking with DRK passphrase another LUKS container
90-
die "LUKS device $key_devices cannot all be unlocked with same passphrase. Please make $key_devices devices unlockable with the same passphrase. Exiting"
91-
else
92-
warn "Failed to unlock LUKS device $dev with the provided passphrase. Please try again."
93-
fi
86+
echo "++++++ $dev: LUKS device unlocked successfully with the DRK passphrase"
9487
fi
9588
done
89+
90+
if [ $all_devices_unlocked -eq 1 ]; then
91+
luks_drk_passphrase_valid=1
92+
else
93+
attempts=$((attempts + 1))
94+
if [ $attempts -eq 3 ]; then
95+
die "Failed to unlock all LUKS devices with the provided passphrase after 3 attempts. Exiting..."
96+
else
97+
warn "Please try again."
98+
fi
99+
fi
96100
done
97101

102+
# Now that all devices are verified with the DRK passphrase, proceed with DUK setup
103+
MIN_PASSPHRASE_LENGTH=12
98104
attempts=0
99105
while [ $attempts -lt 3 ]; do
100-
read -s -p "New LUKS TPM Disk Unlock Key (DUK) passphrase for booting: " key_password
106+
read -r -s -p $'\nNew LUKS TPM Disk Unlock Key (DUK) passphrase for booting (minimum '"$MIN_PASSPHRASE_LENGTH"' characters): ' key_password
101107
echo
102-
read -s -p "Repeat LUKS TPM Disk Unlock Key (DUK) passphrase for booting: " key_password2
108+
if [ ${#key_password} -lt $MIN_PASSPHRASE_LENGTH ]; then
109+
attempts=$((attempts + 1))
110+
warn "Disk Unlock Key (DUK) passphrase is too short. Please try again."
111+
continue
112+
fi
113+
114+
read -r -s -p $'\nRepeat LUKS TPM Disk Unlock Key (DUK) passphrase for booting: ' key_password2
103115
echo
104116
if [ "$key_password" != "$key_password2" ]; then
105117
attempts=$((attempts + 1))
106-
if [ "$attempts" == "3" ]; then
107-
die "Disk Unlock Key (DUK) passphrases do not match. Exiting..."
108-
else
109-
warn "Disk Unlock Key (DUK) passphrases do not match. Please try again."
110-
fi
118+
warn "Disk Unlock Key (DUK) passphrases do not match. Please try again."
111119
else
112120
break
113121
fi
114122
done
115123

124+
if [ $attempts -ge 3 ]; then
125+
die "Failed to set a valid Disk Unlock Key (DUK) passphrase after 3 attempts. Exiting..."
126+
fi
127+
116128
# Generate key file
129+
echo
117130
echo "++++++ Generating new randomized 128 bytes key file that will be sealed/unsealed by LUKS TPM Disk Unlock Key passphrase"
118131
dd \
119132
if=/dev/urandom \
@@ -159,7 +172,7 @@ for dev in $key_devices; do
159172
# Get all the key slots that are used on $dev
160173
luks_used_keyslots=($(cryptsetup luksDump "$dev" | grep -E "$regex" | sed "$sed_command"))
161174
DEBUG "$dev LUKS key slots: ${luks_used_keyslots[*]}"
162-
175+
163176
#Find the key slot that can be unlocked with the provided passphrase
164177
drk_key_slot=$(find_drk_key_slot)
165178

@@ -181,8 +194,8 @@ for dev in $key_devices; do
181194
# Heads expects key slot LUKSv1:7 or LUKSv2:31 to be used for TPM DUK setup.
182195
# Ask user to confirm otherwise
183196
warn "LUKS key slot $keyslot is not typical ($duk_keyslot expected) for TPM Disk Unlock Key setup"
184-
read -p "Are you sure you want to wipe it? [y/N] " -n 1 -r
185-
echo
197+
read -p $'Are you sure you want to wipe it? [y/N]\n' -n 1 -r
198+
echo ""
186199
# If user does not confirm, skip this slot
187200
if [[ $REPLY =~ ^[Yy]$ ]]; then
188201
wipe_desired="yes"
@@ -203,7 +216,6 @@ for dev in $key_devices; do
203216
fi
204217
done
205218

206-
207219
echo "++++++ $dev: Adding LUKS TPM Disk Unlock Key to LUKS key slot $duk_keyslot"
208220
DO_WITH_DEBUG cryptsetup luksAddKey \
209221
--key-file "$DISK_RECOVERY_KEY_FILE" \

0 commit comments

Comments
 (0)