summaryrefslogtreecommitdiff
path: root/firmware/lib/rollback_index.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/lib/rollback_index.c')
-rw-r--r--firmware/lib/rollback_index.c71
1 files changed, 70 insertions, 1 deletions
diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c
index 49b3a84b..4436df54 100644
--- a/firmware/lib/rollback_index.c
+++ b/firmware/lib/rollback_index.c
@@ -481,7 +481,6 @@ uint32_t SetupTPM(int developer_mode, int disable_dev_request,
return TPM_SUCCESS;
}
-
#ifdef DISABLE_ROLLBACK_TPM
/* Dummy implementations which don't support TPM rollback protection */
@@ -680,3 +679,73 @@ uint32_t RollbackKernelLock(int recovery_mode)
}
#endif /* DISABLE_ROLLBACK_TPM */
+
+uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp)
+{
+ uint8_t buf[FWMP_NV_MAX_SIZE];
+ struct RollbackSpaceFwmp *bf = (struct RollbackSpaceFwmp *)buf;
+ uint32_t r;
+ int attempts = 3;
+
+ /* Clear destination in case error or FWMP not present */
+ Memset(fwmp, 0, sizeof(*fwmp));
+
+ while (attempts--) {
+ /* Try to read entire 1.0 struct */
+ r = TlclRead(FWMP_NV_INDEX, buf, sizeof(*bf));
+ if (r == TPM_E_BADINDEX) {
+ /* Missing space is not an error; use defaults */
+ VBDEBUG(("TPM: %s() - no FWMP space\n", __func__));
+ return TPM_SUCCESS;
+ } else if (r != TPM_SUCCESS) {
+ VBDEBUG(("TPM: %s() - read returned 0x%x\n",
+ __func__, r));
+ return r;
+ }
+
+ /*
+ * Struct must be at least big enough for 1.0, but not bigger
+ * than our buffer size.
+ */
+ if (bf->struct_size < sizeof(*bf) ||
+ bf->struct_size > sizeof(buf))
+ return TPM_E_STRUCT_SIZE;
+
+ /*
+ * If space is bigger than we expect, re-read so we properly
+ * compute the CRC.
+ */
+ if (bf->struct_size > sizeof(*bf)) {
+ r = TlclRead(FWMP_NV_INDEX, buf, bf->struct_size);
+ if (r != TPM_SUCCESS)
+ return r;
+ }
+
+ /* Verify CRC */
+ if (bf->crc != Crc8(buf + 2, bf->struct_size - 2)) {
+ VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
+ continue;
+ }
+
+ /* Verify major version is compatible */
+ if ((bf->struct_version >> 4) !=
+ (ROLLBACK_SPACE_FWMP_VERSION >> 4))
+ return TPM_E_STRUCT_VERSION;
+
+ /*
+ * Copy to destination. Note that if the space is bigger than
+ * we expect (due to a minor version change), we only copy the
+ * part of the FWMP that we know what to do with.
+ *
+ * If this were a 1.1+ reader and the source was a 1.0 struct,
+ * we would need to take care of initializing the extra fields
+ * added in 1.1+. But that's not an issue yet.
+ */
+ Memcpy(fwmp, bf, sizeof(*fwmp));
+ return TPM_SUCCESS;
+ }
+
+ VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
+ return TPM_E_CORRUPTED_STATE;
+}
+