From fd6a947cb35ff970b6d04230e31e4e597add289f Mon Sep 17 00:00:00 2001
From: Jonathon Hall <jonathon.hall@puri.sm>
Date: Mon, 6 Nov 2023 10:31:50 -0500
Subject: [PATCH] tpmr: Move last TPM owner password prompt/shred into tpmr

Prompt for TPM owner password internally within tpm2_counter_create.
Add tpm1_counter_create to prompt for password internally.  Wipe the
cache in either if the operation fails, in case the password was
incorrect.

Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
---
 initrd/bin/oem-factory-reset |  1 -
 initrd/bin/tpmr              | 38 +++++++++++++++++++++++-------------
 initrd/etc/functions         | 11 -----------
 3 files changed, 24 insertions(+), 26 deletions(-)

diff --git a/initrd/bin/oem-factory-reset b/initrd/bin/oem-factory-reset
index a2db035a..fe0936d8 100755
--- a/initrd/bin/oem-factory-reset
+++ b/initrd/bin/oem-factory-reset
@@ -603,7 +603,6 @@ generate_checksums() {
     if [ "$CONFIG_TPM" = "y" ]; then
         if [ "$CONFIG_IGNORE_ROLLBACK" != "y" ]; then
             tpmr counter_create \
-                -pwdo "$TPM_PASS" \
                 -pwdc '' \
                 -la -3135106223 |
                 tee /tmp/counter ||
diff --git a/initrd/bin/tpmr b/initrd/bin/tpmr
index 933bd103..c530deb7 100755
--- a/initrd/bin/tpmr
+++ b/initrd/bin/tpmr
@@ -290,18 +290,23 @@ tpm2_counter_inc() {
 	echo "$index: $(tpm2 nvread 0x$index | xxd -pc8)"
 }
 
-tpm2_counter_cre() {
-	TRACE "Under /bin/tpmr:tpm2_counter_cre"
+tpm1_counter_create() {
+	TRACE "Under /bin/tpmr:tpm1_counter_create"
+	# tpmr handles the TPM owner password (from cache or prompt), but all
+	# other parameters for TPM1 are passed directly, and TPM2 mimics the
+	# TPM1 interface.
+	prompt_tpm_owner_password
+	if ! tpm counter_create -pwdo "$(cat "/tmp/secret/tpm_owner_password")" "$@"; then
+		DEBUG "Failed to create counter from tpm1_counter_create. Wiping /tmp/secret/tpm_owner_password"
+		shred -n 10 -z -u /tmp/secret/tpm_owner_password
+		die "Unable to create counter from tpm1_counter_create"
+	fi
+}
+
+tpm2_counter_create() {
+	TRACE "Under /bin/tpmr:tpm2_counter_create"
 	while true; do
 		case "$1" in
-		-pwdo)
-			pwdo="$2"
-			shift 2
-			;;
-		-pwdof)
-			pwdo="file:$2"
-			shift 2
-			;;
 		-pwdc)
 			pwd="$2"
 			shift 2
@@ -315,13 +320,14 @@ tpm2_counter_cre() {
 			;;
 		esac
 	done
+	prompt_tpm_owner_password
 	rand_index="1$(dd if=/dev/urandom bs=1 count=3 | xxd -pc3)"
 	tpm2 nvdefine -C o -s 8 -a "ownerread|authread|authwrite|nt=1" \
-		-P "$(tpm2_password_hex "$pwdo")" "0x$rand_index" >/dev/console ||
+		-P "$(tpm2_password_hex "$(cat "/tmp/secret/tpm_owner_password")")" "0x$rand_index" >/dev/console ||
 		{
-			DEBUG "Failed to create counter from tpm2_counter_cre. Wiping /tmp/secret/tpm_owner_password"
+			DEBUG "Failed to create counter from tpm2_counter_create. Wiping /tmp/secret/tpm_owner_password"
 			shred -n 10 -z -u /tmp/secret/tpm_owner_password
-			die "Unable to create counter from tpm2_counter_cre"
+			die "Unable to create counter from tpm2_counter_create"
 		}
 	echo "$rand_index: (valid after an increment)"
 }
@@ -742,6 +748,10 @@ if [ "$CONFIG_TPM2_TOOLS" != "y" ]; then
 		shift
 		replay_pcr "sha1" "$@"
 		;;
+	counter_create)
+		shift
+		tpm1_counter_create "$@"
+		;;
 	destroy)
 		shift
 		tpm1_destroy "$@"
@@ -793,7 +803,7 @@ counter_increment)
 	tpm2_counter_inc "$@"
 	;;
 counter_create)
-	tpm2_counter_cre "$@"
+	tpm2_counter_create "$@"
 	;;
 destroy)
 	tpm2_destroy "$@"
diff --git a/initrd/etc/functions b/initrd/etc/functions
index 0a3ffd1a..7e6a6351 100755
--- a/initrd/etc/functions
+++ b/initrd/etc/functions
@@ -250,22 +250,11 @@ check_tpm_counter() {
 		TPM_COUNTER=$(grep counter- "$1" | cut -d- -f2)
 	else
 		warn "$1 does not exist; creating new TPM counter"
-		prompt_tpm_owner_password
 		tpmr counter_create \
-			-pwdo "$tpm_password" \
 			-pwdc '' \
 			-la $LABEL |
 			tee /tmp/counter ||
-			{
-				DEBUG "Failed to create TPM counter. Shredding TPM Owner Password"
-				#tpm2 counter_cre wipes the cached tpm owner password if invalid.
-				#tpm1 calls counter_create directly and does not wipe the cached password.
-				# This is a workaround to make the two calls behave the same in case we need to create a new counter.
-				# I am not able to get here in my tests: the cached password should be able to create a counter at this point.
-				#TODO: unify the two calls further and delete the next shred call.
-				shred -n 10 -z -u /tmp/secret/tpm_owner_password
 				die "Unable to create TPM counter"
-			}
 		TPM_COUNTER=$(cut -d: -f1 </tmp/counter)
 	fi