altfw: add the ability to disable rollback APIs

Adds a flag to VbSelectAndLoadKernelParams that will disable TPM
rollback APIs. This is necessary for altfw depthcharge because the real
depthcharge locks the rollback area of the TPM before handing off to
altfw, so any attempt to access these values will fail.

BUG=fuchsia:80827
TEST=successfully booted depthcharge -> altfw -> ChromeOS
BRANCH=fuchsia/atlas

Change-Id: Ib7e042f9894058a23efe553546868b0711112aaa
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/vboot_reference/+/560321
Reviewed-by: Simon Shields <simonshields@google.com>
diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg
index 55b4b57..4df2965 100644
--- a/PRESUBMIT.cfg
+++ b/PRESUBMIT.cfg
@@ -5,3 +5,6 @@
 # The indentation is checked by checkpatch not the python script
 tab_check: false
 
+# Upload checks don't accept any Fuchsia bug format yet, disable for now.
+bug_field_check: false
+
diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h
index 860a5fc..fa9cbd3 100644
--- a/firmware/include/vboot_api.h
+++ b/firmware/include/vboot_api.h
@@ -313,6 +313,12 @@
  */
 #define VB_SALK_INFLAGS_VENDOR_DATA_SETTABLE (1 << 1)
 
+/* Flag to indicate that we are running from altfw and cannot use the
+ * kernel anti-rollback APIs. All anti-rollback versions will be reported
+ * as 0 and updates will be a no-op.
+ */
+#define VB_SALK_INFLAGS_ALTFW_NO_ROLLBACKS (1 << 2)
+
 /**
  * Select and loads the kernel.
  *
diff --git a/firmware/lib/include/rollback_index.h b/firmware/lib/include/rollback_index.h
index ff36911..a4783ed 100644
--- a/firmware/lib/include/rollback_index.h
+++ b/firmware/lib/include/rollback_index.h
@@ -141,6 +141,15 @@
  */
 uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp);
 
+/**
+ * Disable rollback APIs.
+ *
+ * After calling this, all Rollback*() functions will return success but will
+ * be a no-op. The purpose of this is to run depthcharge as an altfw image,
+ * which runs after RollbackKernelLock() has already been called.
+ */
+void RollbackDisable(void);
+
 /****************************************************************************/
 
 /*
diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c
index f52c8b5..f46e28a 100644
--- a/firmware/lib/rollback_index.c
+++ b/firmware/lib/rollback_index.c
@@ -242,6 +242,8 @@
 #ifdef DISABLE_ROLLBACK_TPM
 /* Dummy implementations which don't support TPM rollback protection */
 
+void RollbackDisable(void) { /* Already disabled here. */ }
+
 uint32_t RollbackKernelRead(uint32_t* version)
 {
 	*version = 0;
@@ -266,8 +268,22 @@
 
 #else
 
+static int disable_rollback_apis = 0;
+
+void RollbackDisable(void) { disable_rollback_apis = 1; }
+
+#define RETURN_IF_ROLLBACK_DISABLED()                                          \
+	do {                                                                   \
+		if (disable_rollback_apis) {                                   \
+			VB2_DEBUG("Rollback APIs have been disabled\n");       \
+			return TPM_SUCCESS;                                    \
+		}                                                              \
+	} while (0)
+
 uint32_t RollbackKernelRead(uint32_t* version)
 {
+	RETURN_IF_ROLLBACK_DISABLED();
+
 	RollbackSpaceKernel rsk;
 
 	/*
@@ -301,6 +317,8 @@
 
 uint32_t RollbackKernelWrite(uint32_t version)
 {
+	RETURN_IF_ROLLBACK_DISABLED();
+
 	RollbackSpaceKernel rsk;
 	uint32_t old_version;
 	RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
@@ -313,6 +331,8 @@
 
 uint32_t RollbackKernelLock(int recovery_mode)
 {
+	RETURN_IF_ROLLBACK_DISABLED();
+
 	static int kernel_locked = 0;
 	uint32_t r;
 
@@ -327,6 +347,8 @@
 
 uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp)
 {
+	RETURN_IF_ROLLBACK_DISABLED();
+
 	union {
 		/*
 		 * Use a union for buf and bf, rather than making bf a pointer
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 17b3b7b..02c23bb 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -327,6 +327,21 @@
 	sd->gbb_size = cparams->gbb_size;
 	sd->gbb_flags = sd->gbb->flags;
 
+	/* Disable rollback TPM calls if necessary. */
+	if (kparams->inflags & VB_SALK_INFLAGS_ALTFW_NO_ROLLBACKS) {
+		/* Double-check that we're in developer mode. There shouldn't be any
+		   way to run the custom Fuchsia firmware outside of developer mode,
+		   but add this just to be safe. If we ever upstream Fuchsia support
+		   into the real depthcharge build, disabling rollbacks won't be
+		   necessary as we won't need altfw anymore. */
+		if (ctx.flags & VB2_CONTEXT_DEVELOPER_MODE) {
+			RollbackDisable();
+		} else {
+			VB2_DEBUG("Must be in dev mode to disable rollbacks\n");
+			return VBERROR_DEV_FIRMWARE_SWITCH_MISMATCH;
+		}
+	}
+
 	/* Read kernel version from the TPM.  Ignore errors in recovery mode. */
 	if (RollbackKernelRead(&shared->kernel_version_tpm)) {
 		VB2_DEBUG("Unable to get kernel versions from TPM\n");