Index: src/platform/vboot_reference/utils/rollback_index.c |
diff --git a/src/platform/vboot_reference/utils/rollback_index.c b/src/platform/vboot_reference/utils/rollback_index.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0b65bf490f6c574709b7b525773027d73fff407e |
--- /dev/null |
+++ b/src/platform/vboot_reference/utils/rollback_index.c |
@@ -0,0 +1,148 @@ |
+/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ * |
+ * Functions for querying, manipulating and locking rollback indices |
+ * stored in the TPM NVRAM. |
+ */ |
+ |
+#include "rollback_index.h" |
+ |
+#include <stdint.h> |
+#include <tss/tcs.h> |
+ |
+#include "tlcl.h" |
+ |
+uint16_t g_firmware_key_version = 0; |
+uint16_t g_firmware_version = 0; |
+uint16_t g_kernel_key_version = 0; |
+uint16_t g_kernel_version = 0; |
+ |
+static void InitializeSpaces(void) { |
+ uint16_t zero = 0; |
+ uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE; |
+ |
+ printf("Initializing spaces\n"); |
+ TlclSetNvLocked(); /* useful only the first time */ |
+ |
+ TlclDefineSpace(FIRMWARE_KEY_VERSION_NV_INDEX, perm, sizeof(uint16_t)); |
+ TlclWrite(FIRMWARE_KEY_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t)); |
+ |
+ TlclDefineSpace(FIRMWARE_VERSION_NV_INDEX, perm, sizeof(uint16_t)); |
+ TlclWrite(FIRMWARE_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t)); |
+ |
+ TlclDefineSpace(KERNEL_KEY_VERSION_NV_INDEX, perm, sizeof(uint16_t)); |
+ TlclWrite(KERNEL_KEY_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t)); |
+ |
+ TlclDefineSpace(KERNEL_VERSION_NV_INDEX, perm, sizeof(uint16_t)); |
+ TlclWrite(KERNEL_VERSION_NV_INDEX, (uint8_t*) &zero, sizeof(uint16_t)); |
+} |
+ |
+static void EnterRecovery(void) { |
+ /* Temporary recovery stub. Currently just initalizes spaces. */ |
+ InitializeSpaces(); |
+} |
+ |
+static int GetTPMRollbackIndices(void) { |
+ /* We just perform the reads, making sure they succeed. A failure means that |
+ * the rollback index locations are some how messed up and we must jump to |
+ * recovery */ |
+ if (TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX, |
+ (uint8_t*) &g_firmware_key_version, |
+ sizeof(g_firmware_key_version)) || |
+ TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX, |
+ (uint8_t*) &g_firmware_key_version, |
+ sizeof(g_firmware_key_version)) || |
+ TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX, |
+ (uint8_t*) &g_firmware_key_version, |
+ sizeof(g_firmware_key_version)) || |
+ TPM_SUCCESS != TlclRead(FIRMWARE_KEY_VERSION_NV_INDEX, |
+ (uint8_t*) &g_firmware_key_version, |
+ sizeof(g_firmware_key_version))) |
+ return 0; |
+ return 1; |
+} |
+ |
+ |
+void SetupTPM(void) { |
+ TlclLibinit(); |
+ TlclStartup(); |
+ /* TODO(gauravsh): The call to self test should probably be deferred. |
+ * As per semenzato@chromium.org - |
+ * TlclStartup should be called before the firmware initializes the memory |
+ * controller, so the selftest can run in parallel with that. Here we should |
+ * just call TlclSelftestFull to make sure the self test has |
+ * completed---unless we want to rely on the NVRAM operations being available |
+ * before the selftest completes. */ |
+ TlclSelftestfull(); |
+ TlclAssertPhysicalPresence(); |
+ if (!GetTPMRollbackIndices()) { |
+ fprintf(stderr, "Ho Ho Ho! We must jump to recovery."); |
+ EnterRecovery(); |
+ } |
+} |
+ |
+ |
+uint16_t GetStoredVersion(int type) { |
+ switch (type) { |
+ case FIRMWARE_KEY_VERSION: |
+ return g_firmware_key_version; |
+ break; |
+ case FIRMWARE_VERSION: |
+ return g_firmware_version; |
+ break; |
+ case KERNEL_KEY_VERSION: |
+ return g_kernel_key_version; |
+ break; |
+ case KERNEL_VERSION: |
+ return g_kernel_version; |
+ break; |
+ } |
+ return 0; |
+} |
+ |
+int WriteStoredVersion(int type, uint16_t version) { |
+ switch (type) { |
+ case FIRMWARE_KEY_VERSION: |
+ return (TPM_SUCCESS == TlclWrite(FIRMWARE_KEY_VERSION_NV_INDEX, |
+ (uint8_t*) &version, |
+ sizeof(uint16_t))); |
+ break; |
+ case FIRMWARE_VERSION: |
+ return (TPM_SUCCESS == TlclWrite(FIRMWARE_VERSION_NV_INDEX, |
+ (uint8_t*) &version, |
+ sizeof(uint16_t))); |
+ break; |
+ case KERNEL_KEY_VERSION: |
+ return (TPM_SUCCESS == TlclWrite(KERNEL_KEY_VERSION_NV_INDEX, |
+ (uint8_t*) &version, |
+ sizeof(uint16_t))); |
+ break; |
+ case KERNEL_VERSION: |
+ return (TPM_SUCCESS == TlclWrite(KERNEL_VERSION_NV_INDEX, |
+ (uint8_t*) &version, |
+ sizeof(uint16_t))); |
+ break; |
+ } |
+ return 0; |
+} |
+ |
+void LockStoredVersion(int type) { |
+ /* TODO(gauravsh): Add error checking here to make sure TlclWriteLock |
+ * did not fail. We must jump to recovery in that case. |
+ */ |
+ switch (type) { |
+ case FIRMWARE_KEY_VERSION: |
+ TlclWriteLock(FIRMWARE_KEY_VERSION_NV_INDEX); |
+ break; |
+ case FIRMWARE_VERSION: |
+ TlclWriteLock(FIRMWARE_VERSION_NV_INDEX); |
+ break; |
+ case KERNEL_KEY_VERSION: |
+ TlclWriteLock(KERNEL_KEY_VERSION_NV_INDEX); |
+ break; |
+ case KERNEL_VERSION: |
+ TlclWriteLock(KERNEL_VERSION_NV_INDEX); |
+ break; |
+ } |
+} |