blob: 0b65bf490f6c574709b7b525773027d73fff407e [file] [log] [blame]
/* 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;
}
}