summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2011-03-17 17:58:56 -0700
committerRandall Spangler <rspangler@chromium.org>2011-03-17 17:58:56 -0700
commit5ac39bfff0d9e2ad2c3e1fe9b3fd3f314b50a472 (patch)
treeb92352d8dfb4e721ec9127efdb142e77c182187b
parentf4ba19d81d4fefa0dba4efbdd57dc863138fde3a (diff)
downloadvboot-5ac39bfff0d9e2ad2c3e1fe9b3fd3f314b50a472.tar.gz
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
-rw-r--r--firmware/include/vboot_struct.h6
-rw-r--r--firmware/lib/include/rollback_index.h8
-rw-r--r--firmware/lib/rollback_index.c67
-rw-r--r--firmware/lib/vboot_firmware.c2
-rw-r--r--firmware/lib/vboot_kernel.c10
-rw-r--r--firmware/linktest/main.c1
-rw-r--r--host/lib/crossystem.c15
-rw-r--r--utility/crossystem_main.c2
8 files changed, 76 insertions, 35 deletions
diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h
index f4364274..7cf88032 100644
--- a/firmware/include/vboot_struct.h
+++ b/firmware/include/vboot_struct.h
@@ -204,9 +204,13 @@ typedef struct VbSharedDataHeader {
uint8_t check_fw_b_result; /* Result of checking RW firmware B */
uint8_t firmware_index; /* Firmware index returned by
* 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_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
* fields must be added below, and the struct version must be increased.
* Before reading/writing those fields, make sure that the struct being
diff --git a/firmware/lib/include/rollback_index.h b/firmware/lib/include/rollback_index.h
index 0e630dbb..7db85150 100644
--- a/firmware/lib/include/rollback_index.h
+++ b/firmware/lib/include/rollback_index.h
@@ -94,6 +94,11 @@ uint32_t RollbackS3Resume(void);
* mode. */
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 */
uint32_t RollbackFirmwareWrite(uint32_t version);
@@ -109,8 +114,7 @@ uint32_t RollbackFirmwareLock(void);
* mode. */
uint32_t RollbackKernelRecovery(int developer_mode);
-/* Read and write may be called if not in developer mode. If called in
- * recovery mode, the effect is undefined. */
+/* Read and write may be called to read and write the kernel version. */
uint32_t RollbackKernelRead(uint32_t* version);
uint32_t RollbackKernelWrite(uint32_t version);
diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c
index 9442b779..697bd0e7 100644
--- a/firmware/lib/rollback_index.c
+++ b/firmware/lib/rollback_index.c
@@ -301,6 +301,11 @@ uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) {
return TPM_SUCCESS;
}
+uint32_t RollbackFirmwareRead(uint32_t* version) {
+ *version = 0;
+ return TPM_SUCCESS;
+}
+
uint32_t RollbackFirmwareWrite(uint32_t version) {
return TPM_SUCCESS;
}
@@ -357,6 +362,16 @@ uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) {
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) {
RollbackSpaceFirmware rsf;
@@ -390,40 +405,32 @@ uint32_t RollbackKernelRecovery(int developer_mode) {
}
uint32_t RollbackKernelRead(uint32_t* version) {
- if (g_rollback_recovery_mode) {
- *version = 0;
- } else {
- RollbackSpaceKernel rsk;
- uint32_t perms;
-
- /* Read the kernel space and verify its permissions. If the kernel
- * space has the wrong permission, or it doesn't contain the right
- * identifier, we give up. This will need to be fixed by the
- * 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
- * PP-protected space (but not write to it). */
- RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
- RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_NV_INDEX, &perms));
- if (TPM_NV_PER_PPWRITE != perms || ROLLBACK_SPACE_KERNEL_UID != rsk.uid)
- return TPM_E_CORRUPTED_STATE;
-
- *version = rsk.kernel_versions;
- VBDEBUG(("TPM: RollbackKernelRead %x\n", (int)rsk.kernel_versions));
- }
+ RollbackSpaceKernel rsk;
+ uint32_t perms;
+
+ /* Read the kernel space and verify its permissions. If the kernel
+ * space has the wrong permission, or it doesn't contain the right
+ * identifier, we give up. This will need to be fixed by the
+ * 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
+ * PP-protected space (but not write to it). */
+ RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
+ RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_NV_INDEX, &perms));
+ if (TPM_NV_PER_PPWRITE != perms || ROLLBACK_SPACE_KERNEL_UID != rsk.uid)
+ return TPM_E_CORRUPTED_STATE;
+
+ *version = rsk.kernel_versions;
+ VBDEBUG(("TPM: RollbackKernelRead %x\n", (int)rsk.kernel_versions));
return TPM_SUCCESS;
}
uint32_t RollbackKernelWrite(uint32_t version) {
- if (g_rollback_recovery_mode) {
- return TPM_SUCCESS;
- } else {
- RollbackSpaceKernel rsk;
- RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
- VBDEBUG(("TPM: RollbackKernelWrite %x --> %x\n", (int)rsk.kernel_versions,
- (int)version));
- rsk.kernel_versions = version;
- return WriteSpaceKernel(&rsk);
- }
+ RollbackSpaceKernel rsk;
+ RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
+ VBDEBUG(("TPM: RollbackKernelWrite %x --> %x\n", (int)rsk.kernel_versions,
+ (int)version));
+ rsk.kernel_versions = version;
+ return WriteSpaceKernel(&rsk);
}
uint32_t RollbackKernelLock(void) {
diff --git a/firmware/lib/vboot_firmware.c b/firmware/lib/vboot_firmware.c
index dd006f3a..6c895e92 100644
--- a/firmware/lib/vboot_firmware.c
+++ b/firmware/lib/vboot_firmware.c
@@ -125,6 +125,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
goto LoadFirmwareExit;
}
shared->fw_version_tpm_start = tpm_version;
+ shared->fw_version_tpm = tpm_version;
VBPERFEND("VB_TPMI");
/* Read try-b count and decrement if necessary */
@@ -347,6 +348,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
recovery = VBNV_RECOVERY_RO_TPM_ERROR;
goto LoadFirmwareExit;
}
+ shared->fw_version_tpm = (uint32_t)lowest_version;
}
/* Lock firmware versions in TPM */
diff --git a/firmware/lib/vboot_kernel.c b/firmware/lib/vboot_kernel.c
index e50fd0f6..204874f6 100644
--- a/firmware/lib/vboot_kernel.c
+++ b/firmware/lib/vboot_kernel.c
@@ -232,6 +232,12 @@ int LoadKernel(LoadKernelParams* params) {
/* Ignore return code, since we need to boot recovery mode to
* 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 {
/* Use the kernel subkey passed from LoadFirmware(). */
kernel_subkey = &shared->kernel_subkey;
@@ -247,6 +253,8 @@ int LoadKernel(LoadKernelParams* params) {
recovery = VBNV_RECOVERY_RW_TPM_ERROR;
goto LoadKernelExit;
}
+ if (shared)
+ shared->kernel_version_tpm = tpm_version;
}
do {
@@ -521,6 +529,8 @@ int LoadKernel(LoadKernelParams* params) {
recovery = VBNV_RECOVERY_RW_TPM_ERROR;
goto LoadKernelExit;
}
+ if (shared)
+ shared->kernel_version_tpm = (uint32_t)lowest_version;
}
}
diff --git a/firmware/linktest/main.c b/firmware/linktest/main.c
index 16c4bf50..a3ed21a5 100644
--- a/firmware/linktest/main.c
+++ b/firmware/linktest/main.c
@@ -31,6 +31,7 @@ int main(void)
/* rollback_index.h */
RollbackS3Resume();
RollbackFirmwareSetup(0, 0);
+ RollbackFirmwareRead(0);
RollbackFirmwareWrite(0);
RollbackFirmwareLock();
RollbackKernelRecovery(0);
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index 6ba67e64..ca61f74f 100644
--- a/host/lib/crossystem.c
+++ b/host/lib/crossystem.c
@@ -101,7 +101,9 @@ typedef enum VdatStringField {
/* Fields that GetVdatInt() can get */
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;
@@ -670,7 +672,12 @@ int GetVdatInt(VdatIntField field) {
case VDAT_INT_FLAGS:
value = (int)sh->flags;
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);
@@ -747,6 +754,10 @@ int VbGetSystemPropertyInt(const char* name) {
value = VbGetCrosDebug();
} else if (!strcasecmp(name,"vdat_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;
diff --git a/utility/crossystem_main.c b/utility/crossystem_main.c
index fb842837..6f352ede 100644
--- a/utility/crossystem_main.c
+++ b/utility/crossystem_main.c
@@ -41,6 +41,8 @@ const Param sys_param_list[] = {
{"tried_fwb", 0, "Tried firmware B before A this boot"},
{"cros_debug", 0, "OS should allow debug features"},
{"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 */
{"hwid", IS_STRING, "Hardware ID"},
{"fwid", IS_STRING, "Active firmware ID"},