From 27c457f04b566891bd8468d929e1dafd04585ba6 Mon Sep 17 00:00:00 2001
From: Thierry Laurion <insurgo@riseup.net>
Date: Tue, 24 Oct 2023 11:19:49 -0400
Subject: [PATCH] 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>
---
 .../qemu-coreboot-whiptail-tpm1.config        |  5 ++-
 initrd/bin/gui-init                           | 12 ++---
 initrd/bin/kexec-seal-key                     |  4 +-
 initrd/bin/oem-factory-reset                  |  8 ++--
 initrd/bin/seal-totp                          |  2 +-
 initrd/bin/tpm-reset                          |  2 +-
 initrd/bin/tpmr                               | 35 ++++++++-------
 initrd/etc/functions                          | 44 +++++++++----------
 8 files changed, 58 insertions(+), 54 deletions(-)

diff --git a/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config b/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config
index bc485944..0b05dfaa 100644
--- a/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config
+++ b/boards/qemu-coreboot-whiptail-tpm1/qemu-coreboot-whiptail-tpm1.config
@@ -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
diff --git a/initrd/bin/gui-init b/initrd/bin/gui-init
index a9bfc417..1434f570 100755
--- a/initrd/bin/gui-init
+++ b/initrd/bin/gui-init
@@ -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
diff --git a/initrd/bin/kexec-seal-key b/initrd/bin/kexec-seal-key
index 4e0cb321..70985d1c 100755
--- a/initrd/bin/kexec-seal-key
+++ b/initrd/bin/kexec-seal-key
@@ -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"
 }
diff --git a/initrd/bin/oem-factory-reset b/initrd/bin/oem-factory-reset
index b9e7ce4b..1f44cc46 100755
--- a/initrd/bin/oem-factory-reset
+++ b/initrd/bin/oem-factory-reset
@@ -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
diff --git a/initrd/bin/seal-totp b/initrd/bin/seal-totp
index d3953ce4..9df8e85a 100755
--- a/initrd/bin/seal-totp
+++ b/initrd/bin/seal-totp
@@ -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"
 	}
diff --git a/initrd/bin/tpm-reset b/initrd/bin/tpm-reset
index f8b0c6a8..5049bea0 100755
--- a/initrd/bin/tpm-reset
+++ b/initrd/bin/tpm-reset
@@ -7,4 +7,4 @@ echo '*****'
 
 prompt_new_owner_password
 
-tpmr reset "$key_password"
+tpmr reset "$tpm_owner_password"
diff --git a/initrd/bin/tpmr b/initrd/bin/tpmr
index ddcf5e88..e64ec2bf 100755
--- a/initrd/bin/tpmr
+++ b/initrd/bin/tpmr
@@ -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
diff --git a/initrd/etc/functions b/initrd/etc/functions
index 1227c66c..5bea478d 100755
--- a/initrd/etc/functions
+++ b/initrd/etc/functions
@@ -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 '' \