| 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;
|
| + }
|
| +}
|
|
|