mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 10:14:55 +00:00
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:
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user