gui-init: Eliminate extra TPM owner password prompts in TPM reset

We just set the TPM owner password, so there's no need to make the user
enter it again.  Eliminates some failure modes if the user mistypes it
or enters the wrong password.

Allow optionally passing in the TPM owner password in tpmr seal,
check_tpm_counter(), seal-totp, and generate_totp_htop().  The user is
still prompted if the password is needed but was not provided, so
existing uses in other contexts continue to work unchanged.

Prompt for the password in reset_tpm() and pass it down to each of the
above.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
This commit is contained in:
Jonathon Hall 2023-03-10 15:36:24 -05:00
parent 48421ada1e
commit 698fc83046
No known key found for this signature in database
GPG Key ID: 1E9C3CA91AE25114
4 changed files with 55 additions and 15 deletions

View File

@ -150,9 +150,10 @@ prompt_update_checksums()
generate_totp_htop()
{
tpm_password="$1" # May be empty, will prompt if needed and empty
TRACE "Under /bin/gui-init:generate_totp_htop"
echo "Scan the QR code to add the new TOTP secret"
if /bin/seal-totp "$BOARD_NAME"; then
if /bin/seal-totp "$BOARD_NAME" "$tpm_password"; then
if [ -x /bin/hotp_verification ]; then
echo "Once you have scanned the QR code, hit Enter to configure your HOTP USB Security Dongle (e.g. Librem Key or Nitrokey)"
read
@ -509,13 +510,39 @@ prompt_totp_mismatch()
fi
}
prompt_new_owner_password() {
read -s -p "New TPM owner password: " key_password
echo
if [ -z "$key_password" ]; then
echo "Empty owner password is not allowed" >&2
return 1
fi
read -s -p "Repeat owner password: " key_password2
echo
if [ "$key_password" != "$key_password2" ]; then
echo "Key passwords do not match" >&2
return 1
fi
}
reset_tpm()
{
TRACE "Under /bin/gui-init:reset_tpm"
if [ "$CONFIG_TPM" = "y" ]; then
if (whiptail $BG_COLOR_WARNING --title 'Reset the TPM' \
--yesno "This will clear the TPM and TPM password, replace them with new ones!\n\nDo you want to proceed?" 0 80) then
/bin/tpm-reset
if ! prompt_new_owner_password; then
echo "Press Enter to return to the menu..."
read
echo
return 1
fi
tpmr reset "$key_password"
# now that the TPM is reset, remove invalid TPM counter files
mount_boot
@ -524,7 +551,7 @@ reset_tpm()
rm -f /boot/kexec_primhdl_hash.txt
# create Heads TPM counter before any others
check_tpm_counter /boot/kexec_rollback.txt \
check_tpm_counter /boot/kexec_rollback.txt "" "$key_password" \
|| die "Unable to find/create tpm counter"
counter="$TPM_COUNTER"
@ -535,7 +562,7 @@ reset_tpm()
|| die "Unable to create rollback file"
mount -o ro,remount /boot
generate_totp_htop
generate_totp_htop "$key_password"
else
echo "Returning to the main menu"
fi

View File

@ -15,6 +15,7 @@ HOST="$1"
if [ -z "$HOST" ]; then
HOST="TPMTOTP"
fi
TPM_PASSWORD="$2"
TOTP_SECRET="/tmp/secret/totp.key"
TOTP_SEALED="/tmp/secret/totp.sealed"
@ -41,7 +42,7 @@ DEBUG "Sealing TOTP neglecting PCR5 involvement (Dynamically loaded kernel modul
DEBUG "Sealing TOTP without PCR6 involvement (LUKS header consistency is not firmware integrity attestation related)"
# pcr 7 is containing measurements of user injected stuff in cbfs
tpmr pcrread -a 7 "$pcrf"
tpmr seal "$TOTP_SECRET" "$TPM_NVRAM_SPACE" 0,1,2,3,4,7 "$pcrf" 312 \
tpmr seal "$TOTP_SECRET" "$TPM_NVRAM_SPACE" 0,1,2,3,4,7 "$pcrf" 312 "" "$TPM_PASSWORD" \
|| die "Unable to write sealed secret to NVRAM"
shred -n 10 -z -u "$TOTP_SEALED" 2> /dev/null

View File

@ -262,7 +262,9 @@ tpm2_seal() {
pcrl="$3" #0,1,2,3,4,5,6,7 (does not include algorithm prefix)
pcrf="$4"
sealed_size="$5" # Not used for TPM2
pass="$6"
pass="$6" # May be empty to seal with no password
tpm_password="$7" # Owner password - will prompt if needed and not empty
# Owner password is always needed for TPM2.
mkdir -p "$SECRET_DIR"
bname="`basename $file`"
@ -313,13 +315,12 @@ tpm2_seal() {
tpm2 load -Q -C "/tmp/$PRIMARY_HANDLE_FILE" \
-u "$SECRET_DIR/$bname.priv" -r "$SECRET_DIR/$bname.pub" \
-c "$SECRET_DIR/$bname.seal.ctx"
read -s -p "TPM owner password: " key_password
echo # new line after password prompt
prompt_tpm_password
# remove possible data occupying this handle
tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$key_password")" \
tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$tpm_password")" \
-c "$handle" 2>/dev/null || true
DO_WITH_DEBUG --mask-position 6 \
tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$key_password")" \
tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$tpm_password")" \
-c "$SECRET_DIR/$bname.seal.ctx" "$handle"
}
tpm1_seal() {
@ -329,7 +330,8 @@ tpm1_seal() {
pcrl="$3" #0,1,2,3,4,5,6,7 (does not include algorithm prefix)
pcrf="$4"
sealed_size="$5"
pass="$6"
pass="$6" # May be empty to seal with no password
tpm_password="$7" # Owner password - will prompt if needed and not empty
sealed_file="$SECRET_DIR/tpm1_seal_sealed.bin"
trap "cleanup_shred '$sealed_file'" EXIT
@ -368,8 +370,7 @@ tpm1_seal() {
tpm physicalpresence -s \
|| warn "Warning: Unable to assert physical presence"
read -s -p "TPM Owner password: " tpm_password
echo
prompt_tpm_password
tpm nv_definespace -in "$index" -sz "$sealed_size" \
-pwdo "$tpm_password" -per 0 \

View File

@ -247,19 +247,30 @@ confirm_gpg_card()
fi
}
# Prompt for an owner password if it is not already set in tpm_password. Sets
# tpm_password. Tools should optionally accept a TPM password on the command
# line, since some flows need it multiple times and only one prompt is ideal.
prompt_tpm_password() {
if [ -n "$tpm_password" ]; then
return 0;
fi
read -s -p "TPM Owner password: " tpm_password
echo # new line after password prompt
}
check_tpm_counter()
{
TRACE "Under /etc/functions:check_tpm_counter"
LABEL=${2:-3135106223}
tpm_password="$3"
# if the /boot.hashes file already exists, read the TPM counter ID
# from it.
if [ -r "$1" ]; then
TPM_COUNTER=`grep counter- "$1" | cut -d- -f2`
else
warn "$1 does not exist; creating new TPM counter"
read -s -p "TPM Owner password: " tpm_password
echo
prompt_tpm_password
tpmr counter_create \
-pwdo "$tpm_password" \
-pwdc '' \