crossystem: support clear_tpm_owner_request on TPM2.0 simulator

This CL would give VM boards the ability to hard reset TPM.

When clearing TPM ownership on real devices, there are two things
would happen:
1. TPM reset all of its NVRAM data.
2. mount-encrypted can't decrypt old encrypted partition.

The TPM2.0 simulator put its NV space at "/var/lib/trunks/NVChip".
And "/var/lib" is under encrypted partition.
Remove the mount-encrypted key would cause mount-encrypted lost the
encrypted partition on next boot, and it would simply achieve those
two targets.

BUG=b:170785530
BRANCH=none
TEST=crossystem clear_tpm_owner_request=1

Cq-Depend: chromium:2501904
Signed-off-by: Yi Chou <yich@google.com>
Change-Id: Ifeff0cf03bf76706849905816d22024f3d1b952f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2470577
Reviewed-by: Joel Kitching <kitching@chromium.org>
diff --git a/Makefile b/Makefile
index 8f1bd14..f508a38 100644
--- a/Makefile
+++ b/Makefile
@@ -191,6 +191,13 @@
 CFLAGS += -DMOCK_TPM
 endif
 
+# TPM2_SIMULATOR indicates whether the TPM2 simulator feature is enable or not.
+ifneq ($(filter-out 0,${TPM2_SIMULATOR}),)
+CFLAGS += -DTPM2_SIMULATOR=1
+else
+CFLAGS += -DTPM2_SIMULATOR=0
+endif
+
 # DETACHABLE indicates whether the device is a detachable or not.
 ifneq ($(filter-out 0,${DETACHABLE}),)
 CFLAGS += -DDETACHABLE=1
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index 6d72dc0..25a55d8 100644
--- a/host/lib/crossystem.c
+++ b/host/lib/crossystem.c
@@ -3,10 +3,11 @@
  * found in the LICENSE file.
  */
 
+#include <ctype.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <string.h>
-#include <ctype.h>
+#include <unistd.h>
 
 #include "2api.h"
 #include "2common.h"
@@ -23,6 +24,9 @@
 /* Filename for kernel command line */
 #define KERNEL_CMDLINE_PATH "/proc/cmdline"
 
+/* Filename for the mount-encrypted key */
+#define MOUNT_ENCRYPTED_KEY_PATH "/mnt/stateful_partition/encrypted.key"
+
 /* Fields that GetVdatString() can get */
 typedef enum VdatStringField {
 	VDAT_STRING_DEPRECATED_TIMERS = 0,  /* Timer values */
@@ -370,7 +374,12 @@
 	} else if (!strcasecmp(name,"disable_dev_request")) {
 		value = vb2_get_nv_storage(VB2_NV_DISABLE_DEV_REQUEST);
 	} else if (!strcasecmp(name,"clear_tpm_owner_request")) {
-		value = vb2_get_nv_storage(VB2_NV_CLEAR_TPM_OWNER_REQUEST);
+		if (TPM2_SIMULATOR)
+			/* Check mount-encrypted key status */
+			value = access(MOUNT_ENCRYPTED_KEY_PATH, F_OK) != 0;
+		else
+			value = vb2_get_nv_storage(
+				VB2_NV_CLEAR_TPM_OWNER_REQUEST);
 	} else if (!strcasecmp(name,"clear_tpm_owner_done")) {
 		value = vb2_get_nv_storage(VB2_NV_CLEAR_TPM_OWNER_DONE);
 	} else if (!strcasecmp(name,"tpm_rebooted")) {
@@ -542,7 +551,26 @@
 	} else if (!strcasecmp(name,"disable_dev_request")) {
 		return vb2_set_nv_storage(VB2_NV_DISABLE_DEV_REQUEST, value);
 	} else if (!strcasecmp(name,"clear_tpm_owner_request")) {
-		return vb2_set_nv_storage(VB2_NV_CLEAR_TPM_OWNER_REQUEST, value);
+		if (TPM2_SIMULATOR) {
+			/* We don't support to set clear_tpm_owner_request to 0
+			 * on simulator */
+			if (value == 0)
+				return -1;
+			/* Check mount-encrypted key status */
+			if (!access(MOUNT_ENCRYPTED_KEY_PATH, F_OK)) {
+				/* Remove the mount_encrypted key, and it would
+				 * also clear the TPM2.0 simulator NV space on
+				 * it. */
+				return remove(MOUNT_ENCRYPTED_KEY_PATH);
+			} else {
+				/* Return success when the file is already
+				 * removed */
+				return 0;
+			}
+		} else {
+			return vb2_set_nv_storage(
+				VB2_NV_CLEAR_TPM_OWNER_REQUEST, value);
+		}
 	} else if (!strcasecmp(name,"clear_tpm_owner_done")) {
 		/* Can only clear this flag; it's set by firmware. */
 		return vb2_set_nv_storage(VB2_NV_CLEAR_TPM_OWNER_DONE, 0);