TPM2 DUK and TOTP/HOTP reseal fix, refactoring and ifferenciating tpm_password into tpm_owner_password and reusing correctly

i
TODO: fix all TODO in PR prior of review + squash

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
This commit is contained in:
Thierry Laurion 2023-10-24 11:19:49 -04:00
parent 729f2b17b8
commit 27c457f04b
No known key found for this signature in database
GPG Key ID: E7B4A71658E36A93
8 changed files with 58 additions and 54 deletions

View File

@ -11,11 +11,12 @@ export CONFIG_LINUX_VERSION=5.10.5
#export CONFIG_BASIC=y
#Enable HAVE_GPG_KEY_BACKUP to test GPG key backup drive (we cannot inject config under QEMU (no internal flashing))
#TODO: comment following line prior of pushing final version
export CONFIG_HAVE_GPG_KEY_BACKUP=y
#Enable DEBUG output
#export CONFIG_DEBUG_OUTPUT=y
#export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y
export CONFIG_DEBUG_OUTPUT=y
export CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT=y
CONFIG_COREBOOT_CONFIG=config/coreboot-qemu-tpm1.config
CONFIG_LINUX_CONFIG=config/linux-qemu.config

View File

@ -151,12 +151,12 @@ prompt_update_checksums()
generate_totp_hotp()
{
tpm_password="$1" # May be empty, will prompt if needed and empty
TRACE "Under /bin/gui-init:generate_totp_hotp"
TRACE "Under /bin/gui-init:generate_totp_hotp"
tpm_owner_password="$1" # May be empty, will prompt if needed and empty
if [ "$CONFIG_TPM" != "y" ] && [ -x /bin/hotp_verification ]; then
echo "Generating new HOTP secret"
/bin/seal-hotpkey
elif echo -e "Generating new TOTP secret...\n\n" && /bin/seal-totp "$BOARD_NAME" "$tpm_password"; then
elif echo -e "Generating new TOTP secret...\n\n" && /bin/seal-totp "$BOARD_NAME" "$tpm_owner_password"; then
echo
if [ -x /bin/hotp_verification ]; then
if [ "$CONFIG_TOTP_SKIP_QRCODE" != y ]; then
@ -567,7 +567,7 @@ reset_tpm()
return 1
fi
tpmr reset "$key_password"
tpmr reset "$tpm_owner_password"
# now that the TPM is reset, remove invalid TPM counter files
mount_boot
@ -577,7 +577,7 @@ reset_tpm()
rm -f /boot/kexec_primhdl_hash.txt
# create Heads TPM counter before any others
check_tpm_counter /boot/kexec_rollback.txt "" "$key_password" \
check_tpm_counter /boot/kexec_rollback.txt "" "$tpm_owner_password" \
|| die "Unable to find/create tpm counter"
counter="$TPM_COUNTER"
@ -588,7 +588,7 @@ reset_tpm()
|| die "Unable to create rollback file"
mount -o ro,remount /boot
generate_totp_hotp "$key_password"
generate_totp_hotp "$tpm_owner_password"
else
echo "Returning to the main menu"
fi

View File

@ -136,13 +136,13 @@ tpmr calcfuturepcr 6 "/tmp/luksDump.txt" >>"$pcrf"
tpmr pcrread -a 7 "$pcrf"
DEBUG "TODO: REMOVE THIS: key_password=$key_password here"
DEBUG "TODO: REMOVE THIS: content of /tmp/secret/tpm_password: $(cat /tmp/secret/tpm_password) here"
DEBUG "TODO: REMOVE THIS: content of /tmp/secret/tpm_owner_password: $(cat /tmp/secret/tpm_owner_password) here"
DO_WITH_DEBUG --mask-position 7 \
tpmr seal "$KEY_FILE" "$TPM_INDEX" 0,1,2,3,4,5,6,7 "$pcrf" \
"$TPM_SIZE" "$key_password" || {
shred -n 10 -z -u /tmp/secret/tpm_password 2>/dev/null
shred -n 10 -z -u /tmp/secret/tpm_owner_password 2>/dev/null
:
die "Unable to write TPM Disk Unlock Key to NVRAM"
}

View File

@ -1114,16 +1114,16 @@ else
fi
if [ "$CONFIG_TPM" = "y" ]; then
tpm_password_changed="
tpm_owner_password_changed="
TPM Owner Password: $TPM_PASS\n"
else
tpm_password_changed=""
tpm_owner_password_changed=""
fi
## Show to user current provisioned secrets prior of rebooting
whiptail --msgbox "
$luks_passphrase_changed
$tpm_password_changed
$tpm_owner_password_changed
GPG Admin PIN: $ADMIN_PIN\n
GPG User PIN: $USER_PIN\n\n" \
$HEIGHT $WIDTH --title "Provisioned secrets"
@ -1139,6 +1139,6 @@ whiptail --msgbox "
# Clean LUKS secrets
luks_secrets_cleanup
unset luks_passphrase_changed
unset tpm_password_changed
unset tpm_owner_password_changed
reboot

View File

@ -50,7 +50,7 @@ tpmr pcrread -a 7 "$pcrf"
#Make sure we clear the TPM Owner Password from memory in case it failed to be used to seal TOTP
tpmr seal "$TOTP_SECRET" "$TPM_NVRAM_SPACE" 0,1,2,3,4,7 "$pcrf" 312 "" "$TPM_PASSWORD" ||
{
shred -n 10 -z -u /tmp/secret/tpm_password 2>/dev/null
shred -n 10 -z -u /tmp/secret/tpm_owner_password 2>/dev/null
:
die "Unable to write sealed secret to NVRAM"
}

View File

@ -7,4 +7,4 @@ echo '*****'
prompt_new_owner_password
tpmr reset "$key_password"
tpmr reset "$tpm_owner_password"

View File

@ -393,6 +393,7 @@ tpm2_seal() {
tpm_password="$7" # Owner password - will prompt if needed and not empty
# TPM Owner Password is always needed for TPM2.
DEBUG "TODO REMOVE THIS. tpm2_seal: pass=$pass tpm_password=$tpm_password"
mkdir -p "$SECRET_DIR"
bname="`basename $file`"
@ -442,12 +443,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"
prompt_tpm_password
prompt_tpm_owner_password
# remove possible data occupying this handle
tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$tpm_password")" \
tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$tpm_owner_password")" \
-c "$handle" 2>/dev/null || true
DO_WITH_DEBUG --mask-position 6 \
tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$tpm_password")" \
tpm2 evictcontrol -Q -C o -P "$(tpm2_password_hex "$tpm_owner_password")" \
-c "$SECRET_DIR/$bname.seal.ctx" "$handle"
}
tpm1_seal() {
@ -497,7 +498,7 @@ tpm1_seal() {
tpm physicalpresence -s \
|| warn "Unable to assert physical presence"
prompt_tpm_password
prompt_tpm_owner_password
tpm nv_definespace -in "$index" -sz "$sealed_size" \
-pwdo "$tpm_password" -per 0 \
@ -554,6 +555,8 @@ tpm2_unseal() {
UNSEAL_PASS_SUFFIX="+$(tpm2_password_hex "$pass")"
fi
DEBUG "TODO REMOVE THIS. tpm2_unseal: pass=$pass UNSEAL_PASS_SUFFIX=$UNSEAL_PASS_SUFFIX"
tpm2 unseal -Q -c "$handle" -p "session:$POLICY_SESSION$UNSEAL_PASS_SUFFIX" \
-S "/tmp/$ENC_SESSION_FILE" > "$file"
}
@ -594,18 +597,18 @@ tpm1_unseal() {
tpm2_reset() {
TRACE "Under /bin/tpmr:tpm2_reset"
key_password="$1"
tpm_owner_password="$1"
mkdir -p "$SECRET_DIR"
# output TPM Owner Password key_password to a file to be reused in this boot session until recovery shell/reboot
DEBUG "Caching TPM Owner Password to $SECRET_DIR/tpm_password"
echo "$key_password" > "$SECRET_DIR/tpm_password"
DEBUG "Caching TPM Owner Password to $SECRET_DIR/tpm_owner_password"
echo -n "$tpm_owner_password" > "$SECRET_DIR/tpm_owner_password"
tpm2 clear -c platform || warn "Unable to clear TPM on platform hierarchy"
tpm2 changeauth -c owner "$(tpm2_password_hex "$key_password")"
tpm2 changeauth -c endorsement "$(tpm2_password_hex "$key_password")"
tpm2 changeauth -c owner "$(tpm2_password_hex "$tpm_owner_password")"
tpm2 changeauth -c endorsement "$(tpm2_password_hex "$tpm_owner_password")"
tpm2 createprimary -C owner -g sha256 -G "${CONFIG_PRIMARY_KEY_TYPE:-rsa}" \
-c "$SECRET_DIR/primary.ctx" -P "$(tpm2_password_hex "$key_password")"
-c "$SECRET_DIR/primary.ctx" -P "$(tpm2_password_hex "$tpm_owner_password")"
tpm2 evictcontrol -C owner -c "$SECRET_DIR/primary.ctx" "$PRIMARY_HANDLE" \
-P "$(tpm2_password_hex "$key_password")"
-P "$(tpm2_password_hex "$tpm_owner_password")"
shred -u "$SECRET_DIR/primary.ctx"
tpm2_startsession
@ -643,18 +646,18 @@ tpm2_reset() {
}
tpm1_reset() {
TRACE "Under /bin/tpmr:tpm1_reset"
key_password="$1"
tpm_owner_password="$1"
mkdir -p "$SECRET_DIR"
# output key_password to a file to be reused in this boot session until recovery shell/reboot
DEBUG "Caching TPM Owner Password to $SECRET_DIR/tpm_password"
echo "$key_password" > "$SECRET_DIR/tpm_password"
# output tpm_owner_password to a file to be reused in this boot session until recovery shell/reboot
DEBUG "Caching TPM Owner Password to $SECRET_DIR/tpm_owner_password"
echo -n "$tpm_owner_password" > "$SECRET_DIR/tpm_owner_password"
# Make sure the TPM is ready to be reset
tpm physicalpresence -s
tpm physicalenable
tpm physicalsetdeactivated -c
tpm forceclear
tpm physicalenable
tpm takeown -pwdo "$key_password"
tpm takeown -pwdo "$tpm_owner_password"
# And now turn it all back on
tpm physicalpresence -s

View File

@ -192,28 +192,28 @@ list_usb_storage() {
# 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() {
TRACE "Under /etc/functions:prompt_tpm_password"
prompt_tpm_owner_password() {
TRACE "Under /etc/functions:prompt_tpm_owner_password"
#Caller might already have cached the password in tpm_password. If not, prompt for it and cache it externally
if [ -n "$tpm_password" ]; then
DEBUG "tpm_password variable already set by caller. Reusing"
DEBUG "TODO REMOVE THIS! tpm_password is $tpm_password here."
if [ -n "$tpm_owner_password" ]; then
DEBUG "tpm_owner_password variable already set by caller. Reusing"
DEBUG "TODO REMOVE THIS! tpm_owner_password is $tpm_owner_password here."
return 0
elif [ -s /tmp/secret/tpm_password ]; then
DEBUG "/tmp/secret/tpm_password already cached in file. Reusing"
tpm_password=$(cat /tmp/secret/tpm_password)
DEBUG "TODO REMOVE THIS! tpm_password is $tpm_password here."
elif [ -s /tmp/secret/tpm_owner_password ]; then
DEBUG "/tmp/secret/tpm_owner_password already cached in file. Reusing"
tpm_owner_password=$(cat /tmp/secret/tpm_owner_password)
DEBUG "TODO REMOVE THIS! tpm_owner_password is $tpm_owner_password here."
return 0
fi
read -s -p "TPM Owner Password: " tpm_password
read -s -p "TPM Owner Password: " tpm_owner_password
#TODO: This function is called for both owner and TPM sealing calls. We should probably have a different prompt for each
echo # new line after password prompt
# Cache the password externally to be reused by who needs it
DEBUG "Caching TPM Owner Password to /tmp/secret/tpm_password"
DEBUG "Caching TPM Owner Password to /tmp/secret/tpm_owner_password"
mkdir -p /tmp/secret || die "Unable to create /tmp/secret"
echo "$key_password" >/tmp/secret/tpm_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 owner_password under /tmp/secret/tpm_owner_password"
}
# Prompt for a new owner password when resetting the TPM. Returned in
@ -221,26 +221,26 @@ prompt_tpm_password() {
# the script will loop until this is met.
prompt_new_owner_password() {
TRACE "Under /etc/functions:prompt_new_owner_password"
local key_password2
key_password=1
key_password2=2
while [ "$key_password" != "$key_password2" ] || [ "${#key_password}" -gt 32 ] || [ -z "$key_password" ]; do
read -s -p "New TPM Owner Password (2 words suggested, 1-32 characters max): " key_password
local tpm_owner_password2
tpm_owner_password=1
tpm_owner_password2=2
while [ "$tpm_owner_password" != "$tpm_owner_password2" ] || [ "${#tpm_owner_password}" -gt 32 ] || [ -z "$tpm_owner_password" ]; do
read -s -p "New TPM Owner Password (2 words suggested, 1-32 characters max): " tpm_owner_password
echo
read -s -p "Repeat chosen TPM Owner Password: " key_password2
read -s -p "Repeat chosen TPM Owner Password: " tpm_owner_password2
echo
if [ "$key_password" != "$key_password2" ]; then
if [ "$tpm_owner_password" != "$tpm_owner_password2" ]; then
echo "Passphrases entered do not match. Try again!"
echo
fi
done
# Cache the password externally to be reused by who needs it
DEBUG "Caching TPM Owner Password to /tmp/secret/tpm_password"
DEBUG "Caching TPM Owner Password to /tmp/secret/tpm_owner_password"
mkdir -p /tmp/secret || die "Unable to create /tmp/secret"
echo "$key_password" >/tmp/secret/tpm_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"
}
check_tpm_counter() {
@ -253,7 +253,7 @@ check_tpm_counter() {
TPM_COUNTER=$(grep counter- "$1" | cut -d- -f2)
else
warn "$1 does not exist; creating new TPM counter"
prompt_tpm_password
prompt_tpm_owner_password
tpmr counter_create \
-pwdo "$tpm_password" \
-pwdc '' \