Add checksum to TPM RollbackSpace regions for FW and kernel.

BUG=chrome-os-partner:9707
TEST=manual

  make
  make runtests

You can also test it by clearing the TPM, then manually looking at the TPM
regions. In dev-mode, clear the regions and you'll see something like this:

  localhost ~ # tpmc read 1007 a
  1 0 0 0 0 0 0 0 0 0
  localhost ~ # tpmc read 1008 d
  1 4c 57 52 47 0 0 0 0 0 0 0 0
  localhost ~ #

Go back to normal mode and reboot, and you'll see something like this:

  localhost ~ # tpmc read 1007 a
  2 0 1 0 1 0 0 0 0 4f
  localhost ~ # tpmc read 1008 d
  2 4c 57 52 47 1 0 1 0 0 0 0 55
  localhost ~ #

The important things are that the first number is now 2, instead of 1, and
the last number is not zero (it's a checksum, so it'll vary depending on the
other numbers, which will themselves vary according to the firmware and
kernel versions).

Change-Id: Ia4040311c2a4b2819792549b883377c8b6b89d48
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/22856
Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
Bill Richardson
2012-05-16 10:04:38 -07:00
committed by Gerrit
parent f63ab219c5
commit feac077c1d
9 changed files with 417 additions and 47 deletions

View File

@@ -6,12 +6,17 @@
* stored in the TPM NVRAM.
*/
#include "crc8.h"
#include "rollback_index.h"
#include "tlcl.h"
#include "tss_constants.h"
#include "utility.h"
#include "vboot_api.h"
#ifndef offsetof
#define offsetof(A,B) __builtin_offsetof(A,B)
#endif
#ifdef ROLLBACK_UNITTEST
/* Compiling for unit test, so we need the real implementations of
* rollback functions. The unit test mocks the underlying tlcl
@@ -67,31 +72,134 @@ uint32_t SafeDefineSpace(uint32_t index, uint32_t perm, uint32_t size) {
/* Functions to read and write firmware and kernel spaces. */
static uint32_t ReadSpaceFirmware(RollbackSpaceFirmware* rsf) {
return TlclRead(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware));
uint32_t ReadSpaceFirmware(RollbackSpaceFirmware* rsf) {
uint32_t r;
int attempts = 3;
while (attempts--) {
r = TlclRead(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware));
if (r != TPM_SUCCESS)
return r;
/* No CRC in this version, so we'll create one when we write it. Note that
* we're marking this as version 2, not ROLLBACK_SPACE_FIRMWARE_VERSION,
* because version 2 just added the CRC. Later versions will need to
* set default values for any extra fields explicitly (probably here). */
if (rsf->struct_version < 2) {
rsf->struct_version = 2; /* Danger Will Robinson! Danger! */
return TPM_SUCCESS;
}
/* If the CRC is good, we're done. If it's bad, try a couple more times to
* see if it gets better before we give up. It could just be noise. */
if (rsf->crc8 == Crc8(rsf, offsetof(RollbackSpaceFirmware, crc8)))
return TPM_SUCCESS;
VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
}
VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
return TPM_E_CORRUPTED_STATE;
}
static uint32_t WriteSpaceFirmware(const RollbackSpaceFirmware* rsf) {
return SafeWrite(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware));
uint32_t WriteSpaceFirmware(RollbackSpaceFirmware* rsf) {
RollbackSpaceFirmware rsf2;
uint32_t r;
int attempts = 3;
/* All writes should use struct_version 2 or greater. */
if (rsf->struct_version < 2)
rsf->struct_version = 2;
rsf->crc8 = Crc8(rsf, offsetof(RollbackSpaceFirmware, crc8));
while (attempts--) {
r = SafeWrite(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware));
/* Can't write, not gonna try again */
if (r != TPM_SUCCESS)
return r;
/* Read it back to be sure it got the right values. */
r = ReadSpaceFirmware(&rsf2); /* This checks the CRC */
if (r == TPM_SUCCESS)
return r;
VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
/* Try writing it again. Maybe it was garbled on the way out. */
}
VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
return TPM_E_CORRUPTED_STATE;
}
#ifndef DISABLE_ROLLBACK_TPM
static uint32_t ReadSpaceKernel(RollbackSpaceKernel* rsk) {
return TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
}
#endif
uint32_t ReadSpaceKernel(RollbackSpaceKernel* rsk) {
uint32_t r;
int attempts = 3;
static uint32_t WriteSpaceKernel(const RollbackSpaceKernel* rsk) {
return SafeWrite(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
while (attempts--) {
r = TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
if (r != TPM_SUCCESS)
return r;
/* No CRC in this version, so we'll create one when we write it. Note that
* we're marking this as version 2, not ROLLBACK_SPACE_KERNEL_VERSION,
* because version 2 just added the CRC. Later versions will need to
* set default values for any extra fields explicitly (probably here). */
if (rsk->struct_version < 2) {
rsk->struct_version = 2; /* Danger Will Robinson! Danger! */
return TPM_SUCCESS;
}
/* If the CRC is good, we're done. If it's bad, try a couple more times to
* see if it gets better before we give up. It could just be noise. */
if (rsk->crc8 == Crc8(rsk, offsetof(RollbackSpaceKernel, crc8)))
return TPM_SUCCESS;
VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
}
VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
return TPM_E_CORRUPTED_STATE;
}
uint32_t WriteSpaceKernel(RollbackSpaceKernel* rsk) {
RollbackSpaceKernel rsk2;
uint32_t r;
int attempts = 3;
/* All writes should use struct_version 2 or greater. */
if (rsk->struct_version < 2)
rsk->struct_version = 2;
rsk->crc8 = Crc8(rsk, offsetof(RollbackSpaceKernel, crc8));
while (attempts--) {
r = SafeWrite(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
/* Can't write, not gonna try again */
if (r != TPM_SUCCESS)
return r;
/* Read it back to be sure it got the right values. */
r = ReadSpaceKernel(&rsk2); /* This checks the CRC */
if (r == TPM_SUCCESS)
return r;
VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
/* Try writing it again. Maybe it was garbled on the way out. */
}
VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
return TPM_E_CORRUPTED_STATE;
}
uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware* rsf,
RollbackSpaceKernel* rsk) {
static const RollbackSpaceFirmware rsf_init = {
ROLLBACK_SPACE_FIRMWARE_VERSION, 0, 0, 0};
.struct_version = ROLLBACK_SPACE_FIRMWARE_VERSION,
};
static const RollbackSpaceKernel rsk_init = {
ROLLBACK_SPACE_KERNEL_VERSION, ROLLBACK_SPACE_KERNEL_UID, 0, 0};
.struct_version = ROLLBACK_SPACE_KERNEL_VERSION,
.uid = ROLLBACK_SPACE_KERNEL_UID,
};
TPM_PERMANENT_FLAGS pflags;
uint32_t result;