Add TPM version checking

Change-Id: Ic32b7bcf0bc5501e21dc84e79419a256d9b0d095

R=semenzato@chromium.org,reinauer@chromium.org
BUG=chrome-os-partner:2832
TEST=manual

crossystem tpm_fwver tpm_kernver
On a debug system, this will return 0x00010001 0x00010001

Review URL: http://codereview.chromium.org/6685075
This commit is contained in:
Randall Spangler
2011-03-17 17:58:56 -07:00
parent f4ba19d81d
commit 5ac39bfff0
8 changed files with 74 additions and 33 deletions

View File

@@ -204,9 +204,13 @@ typedef struct VbSharedDataHeader {
uint8_t check_fw_b_result; /* Result of checking RW firmware B */ uint8_t check_fw_b_result; /* Result of checking RW firmware B */
uint8_t firmware_index; /* Firmware index returned by uint8_t firmware_index; /* Firmware index returned by
* LoadFirmware() or 0xFF if failure */ * LoadFirmware() or 0xFF if failure */
uint32_t fw_version_tpm_start; /* Firmware TPM version at start */ uint32_t fw_version_tpm_start; /* Firmware TPM version at start of
* LoadFirmware() */
uint32_t fw_version_lowest; /* Firmware lowest version found */ uint32_t fw_version_lowest; /* Firmware lowest version found */
uint32_t fw_version_tpm; /* Current firmware version in TPM */
uint32_t kernel_version_tpm; /* Current kernel version in TPM */
/* After read-only firmware which uses version 1 is released, any additional /* After read-only firmware which uses version 1 is released, any additional
* fields must be added below, and the struct version must be increased. * fields must be added below, and the struct version must be increased.
* Before reading/writing those fields, make sure that the struct being * Before reading/writing those fields, make sure that the struct being

View File

@@ -94,6 +94,11 @@ uint32_t RollbackS3Resume(void);
* mode. */ * mode. */
uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version); uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version);
/* Read may be called to get the version. This is not necessary in
* the normal boot path, because RollbackFirmwareSetup() provides the
* same information. It may be used in the recovery path. */
uint32_t RollbackFirmwareRead(uint32_t* version);
/* Write may be called if the versions change */ /* Write may be called if the versions change */
uint32_t RollbackFirmwareWrite(uint32_t version); uint32_t RollbackFirmwareWrite(uint32_t version);
@@ -109,8 +114,7 @@ uint32_t RollbackFirmwareLock(void);
* mode. */ * mode. */
uint32_t RollbackKernelRecovery(int developer_mode); uint32_t RollbackKernelRecovery(int developer_mode);
/* Read and write may be called if not in developer mode. If called in /* Read and write may be called to read and write the kernel version. */
* recovery mode, the effect is undefined. */
uint32_t RollbackKernelRead(uint32_t* version); uint32_t RollbackKernelRead(uint32_t* version);
uint32_t RollbackKernelWrite(uint32_t version); uint32_t RollbackKernelWrite(uint32_t version);

View File

@@ -301,6 +301,11 @@ uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) {
return TPM_SUCCESS; return TPM_SUCCESS;
} }
uint32_t RollbackFirmwareRead(uint32_t* version) {
*version = 0;
return TPM_SUCCESS;
}
uint32_t RollbackFirmwareWrite(uint32_t version) { uint32_t RollbackFirmwareWrite(uint32_t version) {
return TPM_SUCCESS; return TPM_SUCCESS;
} }
@@ -357,6 +362,16 @@ uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) {
return TPM_SUCCESS; return TPM_SUCCESS;
} }
uint32_t RollbackFirmwareRead(uint32_t* version) {
RollbackSpaceFirmware rsf;
RETURN_ON_FAILURE(ReadSpaceFirmware(&rsf));
VBDEBUG(("TPM: RollbackFirmwareRead %x --> %x\n", (int)rsf.fw_versions,
(int)version));
*version = rsf.fw_versions;
VBDEBUG(("TPM: RollbackFirmwareRead %x\n", (int)rsf.fw_versions));
return TPM_SUCCESS;
}
uint32_t RollbackFirmwareWrite(uint32_t version) { uint32_t RollbackFirmwareWrite(uint32_t version) {
RollbackSpaceFirmware rsf; RollbackSpaceFirmware rsf;
@@ -390,40 +405,32 @@ uint32_t RollbackKernelRecovery(int developer_mode) {
} }
uint32_t RollbackKernelRead(uint32_t* version) { uint32_t RollbackKernelRead(uint32_t* version) {
if (g_rollback_recovery_mode) { RollbackSpaceKernel rsk;
*version = 0; uint32_t perms;
} else {
RollbackSpaceKernel rsk;
uint32_t perms;
/* Read the kernel space and verify its permissions. If the kernel /* Read the kernel space and verify its permissions. If the kernel
* space has the wrong permission, or it doesn't contain the right * space has the wrong permission, or it doesn't contain the right
* identifier, we give up. This will need to be fixed by the * identifier, we give up. This will need to be fixed by the
* recovery kernel. We have to worry about this because at any time * recovery kernel. We have to worry about this because at any time
* (even with PP turned off) the TPM owner can remove and redefine a * (even with PP turned off) the TPM owner can remove and redefine a
* PP-protected space (but not write to it). */ * PP-protected space (but not write to it). */
RETURN_ON_FAILURE(ReadSpaceKernel(&rsk)); RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_NV_INDEX, &perms)); RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_NV_INDEX, &perms));
if (TPM_NV_PER_PPWRITE != perms || ROLLBACK_SPACE_KERNEL_UID != rsk.uid) if (TPM_NV_PER_PPWRITE != perms || ROLLBACK_SPACE_KERNEL_UID != rsk.uid)
return TPM_E_CORRUPTED_STATE; return TPM_E_CORRUPTED_STATE;
*version = rsk.kernel_versions; *version = rsk.kernel_versions;
VBDEBUG(("TPM: RollbackKernelRead %x\n", (int)rsk.kernel_versions)); VBDEBUG(("TPM: RollbackKernelRead %x\n", (int)rsk.kernel_versions));
}
return TPM_SUCCESS; return TPM_SUCCESS;
} }
uint32_t RollbackKernelWrite(uint32_t version) { uint32_t RollbackKernelWrite(uint32_t version) {
if (g_rollback_recovery_mode) { RollbackSpaceKernel rsk;
return TPM_SUCCESS; RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
} else { VBDEBUG(("TPM: RollbackKernelWrite %x --> %x\n", (int)rsk.kernel_versions,
RollbackSpaceKernel rsk; (int)version));
RETURN_ON_FAILURE(ReadSpaceKernel(&rsk)); rsk.kernel_versions = version;
VBDEBUG(("TPM: RollbackKernelWrite %x --> %x\n", (int)rsk.kernel_versions, return WriteSpaceKernel(&rsk);
(int)version));
rsk.kernel_versions = version;
return WriteSpaceKernel(&rsk);
}
} }
uint32_t RollbackKernelLock(void) { uint32_t RollbackKernelLock(void) {

View File

@@ -125,6 +125,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
goto LoadFirmwareExit; goto LoadFirmwareExit;
} }
shared->fw_version_tpm_start = tpm_version; shared->fw_version_tpm_start = tpm_version;
shared->fw_version_tpm = tpm_version;
VBPERFEND("VB_TPMI"); VBPERFEND("VB_TPMI");
/* Read try-b count and decrement if necessary */ /* Read try-b count and decrement if necessary */
@@ -347,6 +348,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
recovery = VBNV_RECOVERY_RO_TPM_ERROR; recovery = VBNV_RECOVERY_RO_TPM_ERROR;
goto LoadFirmwareExit; goto LoadFirmwareExit;
} }
shared->fw_version_tpm = (uint32_t)lowest_version;
} }
/* Lock firmware versions in TPM */ /* Lock firmware versions in TPM */

View File

@@ -232,6 +232,12 @@ int LoadKernel(LoadKernelParams* params) {
/* Ignore return code, since we need to boot recovery mode to /* Ignore return code, since we need to boot recovery mode to
* fix the TPM. */ * fix the TPM. */
} }
/* Read the key indices from the TPM; ignore any errors */
if (shared) {
RollbackFirmwareRead(&shared->fw_version_tpm);
RollbackKernelRead(&shared->kernel_version_tpm);
}
} else { } else {
/* Use the kernel subkey passed from LoadFirmware(). */ /* Use the kernel subkey passed from LoadFirmware(). */
kernel_subkey = &shared->kernel_subkey; kernel_subkey = &shared->kernel_subkey;
@@ -247,6 +253,8 @@ int LoadKernel(LoadKernelParams* params) {
recovery = VBNV_RECOVERY_RW_TPM_ERROR; recovery = VBNV_RECOVERY_RW_TPM_ERROR;
goto LoadKernelExit; goto LoadKernelExit;
} }
if (shared)
shared->kernel_version_tpm = tpm_version;
} }
do { do {
@@ -521,6 +529,8 @@ int LoadKernel(LoadKernelParams* params) {
recovery = VBNV_RECOVERY_RW_TPM_ERROR; recovery = VBNV_RECOVERY_RW_TPM_ERROR;
goto LoadKernelExit; goto LoadKernelExit;
} }
if (shared)
shared->kernel_version_tpm = (uint32_t)lowest_version;
} }
} }

View File

@@ -31,6 +31,7 @@ int main(void)
/* rollback_index.h */ /* rollback_index.h */
RollbackS3Resume(); RollbackS3Resume();
RollbackFirmwareSetup(0, 0); RollbackFirmwareSetup(0, 0);
RollbackFirmwareRead(0);
RollbackFirmwareWrite(0); RollbackFirmwareWrite(0);
RollbackFirmwareLock(); RollbackFirmwareLock();
RollbackKernelRecovery(0); RollbackKernelRecovery(0);

View File

@@ -101,7 +101,9 @@ typedef enum VdatStringField {
/* Fields that GetVdatInt() can get */ /* Fields that GetVdatInt() can get */
typedef enum VdatIntField { typedef enum VdatIntField {
VDAT_INT_FLAGS = 0 /* Flags */ VDAT_INT_FLAGS = 0, /* Flags */
VDAT_INT_FW_VERSION_TPM, /* Current firmware version in TPM */
VDAT_INT_KERNEL_VERSION_TPM /* Current kernel version in TPM */
} VdatIntField; } VdatIntField;
@@ -670,7 +672,12 @@ int GetVdatInt(VdatIntField field) {
case VDAT_INT_FLAGS: case VDAT_INT_FLAGS:
value = (int)sh->flags; value = (int)sh->flags;
break; break;
case VDAT_INT_FW_VERSION_TPM:
value = (int)sh->fw_version_tpm;
break;
case VDAT_INT_KERNEL_VERSION_TPM:
value = (int)sh->kernel_version_tpm;
break;
} }
Free(ab); Free(ab);
@@ -747,6 +754,10 @@ int VbGetSystemPropertyInt(const char* name) {
value = VbGetCrosDebug(); value = VbGetCrosDebug();
} else if (!strcasecmp(name,"vdat_flags")) { } else if (!strcasecmp(name,"vdat_flags")) {
value = GetVdatInt(VDAT_INT_FLAGS); value = GetVdatInt(VDAT_INT_FLAGS);
} else if (!strcasecmp(name,"tpm_fwver")) {
value = GetVdatInt(VDAT_INT_FW_VERSION_TPM);
} else if (!strcasecmp(name,"tpm_kernver")) {
value = GetVdatInt(VDAT_INT_KERNEL_VERSION_TPM);
} }
return value; return value;

View File

@@ -41,6 +41,8 @@ const Param sys_param_list[] = {
{"tried_fwb", 0, "Tried firmware B before A this boot"}, {"tried_fwb", 0, "Tried firmware B before A this boot"},
{"cros_debug", 0, "OS should allow debug features"}, {"cros_debug", 0, "OS should allow debug features"},
{"vdat_flags", 0, "Flags from VbSharedData", "0x%08x"}, {"vdat_flags", 0, "Flags from VbSharedData", "0x%08x"},
{"tpm_fwver", 0, "Firmware version stored in TPM", "0x%08x"},
{"tpm_kernver", 0, "Kernel version stored in TPM", "0x%08x"},
/* Read-only strings */ /* Read-only strings */
{"hwid", IS_STRING, "Hardware ID"}, {"hwid", IS_STRING, "Hardware ID"},
{"fwid", IS_STRING, "Active firmware ID"}, {"fwid", IS_STRING, "Active firmware ID"},