Change rollback interface so kernel/firmware version numbers are

packed in the calling code rather than in rollback_index.

Review URL: http://codereview.chromium.org/3114013
This commit is contained in:
Randall Spangler
2010-08-16 12:33:44 -07:00
parent 45a628251f
commit 666802822b
6 changed files with 58 additions and 102 deletions

View File

@@ -89,13 +89,10 @@ Call from LoadKernel()
/* Setup must be called. Pass developer_mode=nonzero if in developer
* mode. */
/* TODO: use a 32-bit version instead of 2 version pieces */
uint32_t RollbackFirmwareSetup(int developer_mode, uint16_t* key_version,
uint16_t* version);
uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version);
/* Write may be called if the versions change */
/* TODO: use a 32-bit version instead of 2 version pieces */
uint32_t RollbackFirmwareWrite(uint16_t key_version, uint16_t version);
uint32_t RollbackFirmwareWrite(uint32_t version);
/* Lock must be called */
uint32_t RollbackFirmwareLock(void);
@@ -111,9 +108,8 @@ 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. */
/* TODO: use a 32-bit version instead of 2 version pieces */
uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version);
uint32_t RollbackKernelWrite(uint16_t key_version, uint16_t version);
uint32_t RollbackKernelRead(uint32_t* version);
uint32_t RollbackKernelWrite(uint32_t version);
/* Lock must be called. Internally, it's ignored in recovery mode. */
uint32_t RollbackKernelLock(void);

View File

@@ -271,8 +271,7 @@ __pragma(warning (disable: 4100))
/* Dummy implementations which don't support TPM rollback protection */
uint32_t RollbackFirmwareSetup(int developer_mode,
uint16_t* key_version, uint16_t* version) {
uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) {
#ifndef CHROMEOS_ENVIRONMENT
/* Initialize the TPM, but ignore return codes. In ChromeOS
* environment, don't even talk to the TPM. */
@@ -281,11 +280,11 @@ uint32_t RollbackFirmwareSetup(int developer_mode,
TlclSelfTestFull();
#endif
*key_version = *version = 0;
*version = 0;
return TPM_SUCCESS;
}
uint32_t RollbackFirmwareWrite(uint16_t key_version, uint16_t version) {
uint32_t RollbackFirmwareWrite(uint32_t version) {
return TPM_SUCCESS;
}
@@ -304,12 +303,12 @@ uint32_t RollbackKernelRecovery(int developer_mode) {
return TPM_SUCCESS;
}
uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version) {
*key_version = *version = 0;
uint32_t RollbackKernelRead(uint32_t* version) {
*version = 0;
return TPM_SUCCESS;
}
uint32_t RollbackKernelWrite(uint16_t key_version, uint16_t version) {
uint32_t RollbackKernelWrite(uint32_t version) {
return TPM_SUCCESS;
}
@@ -319,28 +318,22 @@ uint32_t RollbackKernelLock(void) {
#else
uint32_t RollbackFirmwareSetup(int developer_mode, uint16_t* key_version,
uint16_t* version) {
uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) {
RollbackSpaceFirmware rsf;
RETURN_ON_FAILURE(SetupTPM(0, developer_mode, &rsf));
*key_version = (uint16_t)(rsf.fw_versions >> 16);
*version = (uint16_t)(rsf.fw_versions & 0xffff);
VBDEBUG(("TPM: RollbackFirmwareSetup %x %x %x\n", (int)rsf.fw_versions, (int)*key_version, (int)*version));
*version = rsf.fw_versions;
VBDEBUG(("TPM: RollbackFirmwareSetup %x %x %x\n", (int)rsf.fw_versions));
return TPM_SUCCESS;
}
uint32_t RollbackFirmwareWrite(uint16_t key_version, uint16_t version) {
uint32_t RollbackFirmwareWrite(uint32_t version) {
RollbackSpaceFirmware rsf;
uint32_t new_versions = ((uint32_t)key_version << 16) | version;
VBDEBUG(("TPM: RollbackFirmwareWrite(%d, %d)\n", (int)key_version, (int)version));
RETURN_ON_FAILURE(ReadSpaceFirmware(&rsf));
VBDEBUG(("TPM: RollbackFirmwareWrite %x --> %x\n", (int)rsf.fw_versions, (int)new_versions));
rsf.fw_versions = new_versions;
VBDEBUG(("TPM: RollbackFirmwareWrite %x --> %x\n", (int)rsf.fw_versions,
(int)version));
rsf.fw_versions = version;
return WriteSpaceFirmware(&rsf);
}
@@ -363,36 +356,27 @@ uint32_t RollbackKernelRecovery(int developer_mode) {
return result;
}
uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version) {
uint32_t RollbackKernelRead(uint32_t* version) {
if (g_rollback_recovery_mode) {
*key_version = 0;
*version = 0;
} else {
RollbackSpaceKernel rsk;
RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
*key_version = (uint16_t)(rsk.kernel_versions >> 16);
*version = (uint16_t)(rsk.kernel_versions & 0xffff);
VBDEBUG(("TPM: RollbackKernelRead %x %x %x\n", (int)rsk.kernel_versions,
(int)*key_version, (int)*version));
*version = rsk.kernel_versions;
VBDEBUG(("TPM: RollbackKernelRead %x\n", (int)rsk.kernel_versions));
}
return TPM_SUCCESS;
}
uint32_t RollbackKernelWrite(uint16_t key_version, uint16_t version) {
VBDEBUG(("TPM: RollbackKernelWrite(%d, %d)\n", (int)key_version,
(int)version));
uint32_t RollbackKernelWrite(uint32_t version) {
if (g_rollback_recovery_mode) {
return TPM_SUCCESS;
} else {
RollbackSpaceKernel rsk;
uint32_t new_versions = ((uint32_t)key_version << 16) | version;
RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
VBDEBUG(("TPM: RollbackKernelWrite %x --> %x\n", (int)rsk.kernel_versions,
(int)new_versions));
rsk.kernel_versions = new_versions;
(int)version));
rsk.kernel_versions = version;
return WriteSpaceKernel(&rsk);
}
}

View File

@@ -36,10 +36,8 @@ int LoadFirmware(LoadFirmwareParams* params) {
VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob;
VbLoadFirmwareInternal* lfi;
uint16_t tpm_key_version = 0;
uint16_t tpm_fw_version = 0;
uint64_t lowest_key_version = 0xFFFF;
uint64_t lowest_fw_version = 0xFFFF;
uint32_t tpm_version = 0;
uint64_t lowest_version = 0xFFFFFFFF;
uint32_t status;
int good_index = -1;
int index;
@@ -62,7 +60,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
/* Initialize the TPM and read rollback indices. */
status = RollbackFirmwareSetup(params->boot_flags & BOOT_FLAG_DEVELOPER,
&tpm_key_version, &tpm_fw_version);
&tpm_version);
if (0 != status) {
VBDEBUG(("Unable to setup TPM and read stored versions.\n"));
return (status == TPM_E_MUST_REBOOT ?
@@ -82,6 +80,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
VbFirmwarePreambleHeader* preamble;
RSAPublicKey* data_key;
uint64_t key_version;
uint64_t combined_version;
uint8_t* body_digest;
/* Verify the key block */
@@ -99,7 +98,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
/* Check for rollback of key version. */
key_version = key_block->data_key.key_version;
if (key_version < tpm_key_version) {
if (key_version < (tpm_version >> 16)) {
VBDEBUG(("Key rollback detected.\n"));
continue;
}
@@ -123,22 +122,17 @@ int LoadFirmware(LoadFirmwareParams* params) {
}
/* Check for rollback of firmware version. */
if (key_version == tpm_key_version &&
preamble->firmware_version < tpm_fw_version) {
combined_version = ((key_version << 16) |
(preamble->firmware_version & 0xFFFF));
if (combined_version < tpm_version) {
VBDEBUG(("Firmware version rollback detected.\n"));
RSAPublicKeyFree(data_key);
continue;
}
/* Check for lowest key version from a valid header. */
if (lowest_key_version > key_version) {
lowest_key_version = key_version;
lowest_fw_version = preamble->firmware_version;
}
else if (lowest_key_version == key_version &&
lowest_fw_version > preamble->firmware_version) {
lowest_fw_version = preamble->firmware_version;
}
if (lowest_version > combined_version)
lowest_version = combined_version;
/* If we already have good firmware, no need to read another one;
* we only needed to look at the versions to check for
@@ -202,8 +196,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
* then the TPM doesn't need updating; we can stop now.
* Otherwise, we'll check all the other headers to see if they
* contain a newer key. */
if (key_version == tpm_key_version &&
preamble->firmware_version == tpm_fw_version)
if (combined_version == tpm_version)
break;
}
}
@@ -216,12 +209,8 @@ int LoadFirmware(LoadFirmwareParams* params) {
if (good_index >= 0) {
/* Update TPM if necessary */
if ((lowest_key_version > tpm_key_version) ||
(lowest_key_version == tpm_key_version &&
lowest_fw_version > tpm_fw_version)) {
status = RollbackFirmwareWrite((uint16_t)lowest_key_version,
(uint16_t)lowest_fw_version);
if (lowest_version > tpm_version) {
status = RollbackFirmwareWrite((uint32_t)lowest_version);
if (0 != status) {
VBDEBUG(("Unable to write stored versions.\n"));
return (status == TPM_E_MUST_REBOOT ?

View File

@@ -120,10 +120,8 @@ int LoadKernel(LoadKernelParams* params) {
uint8_t* kbuf = NULL;
int found_partitions = 0;
int good_partition = -1;
uint16_t tpm_key_version = 0;
uint16_t tpm_kernel_version = 0;
uint64_t lowest_key_version = 0xFFFF;
uint64_t lowest_kernel_version = 0xFFFF;
uint32_t tpm_version = 0;
uint64_t lowest_version = 0xFFFFFFFF;
int is_dev;
int is_rec;
int is_normal;
@@ -164,7 +162,7 @@ int LoadKernel(LoadKernelParams* params) {
if (is_normal) {
/* Read current kernel key index from TPM. Assumes TPM is already
* initialized. */
status = RollbackKernelRead(&tpm_key_version, &tpm_kernel_version);
status = RollbackKernelRead(&tpm_version);
if (0 != status) {
VBDEBUG(("Unable to get kernel versions from TPM\n"));
return (status == TPM_E_MUST_REBOOT ?
@@ -202,6 +200,7 @@ int LoadKernel(LoadKernelParams* params) {
VbKernelPreambleHeader* preamble;
RSAPublicKey* data_key;
uint64_t key_version;
uint64_t combined_version;
uint64_t body_offset;
VBDEBUG(("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n",
@@ -244,7 +243,7 @@ int LoadKernel(LoadKernelParams* params) {
* skipped in recovery and developer modes because those set
* key_version=0 above. */
key_version = key_block->data_key.key_version;
if (key_version < tpm_key_version) {
if (key_version < (tpm_version >> 16)) {
VBDEBUG(("Key version too old.\n"));
continue;
}
@@ -265,10 +264,11 @@ int LoadKernel(LoadKernelParams* params) {
}
/* Check for rollback of kernel version. Note this is implicitly
* skipped in recovery and developer modes because those set
* key_version=0 and kernel_version=0 above. */
if (key_version == tpm_key_version &&
preamble->kernel_version < tpm_kernel_version) {
* skipped in recovery and developer modes because rollback_index
* sets those to 0 in those modes. */
combined_version = ((key_version << 16) |
(preamble->kernel_version & 0xFFFF));
if (combined_version < tpm_version) {
VBDEBUG(("Kernel version too low.\n"));
RSAPublicKeyFree(data_key);
continue;
@@ -276,15 +276,9 @@ int LoadKernel(LoadKernelParams* params) {
VBDEBUG(("Kernel preamble is good.\n"));
/* Check for lowest key version from a valid header. */
if (lowest_key_version > key_version) {
lowest_key_version = key_version;
lowest_kernel_version = preamble->kernel_version;
}
else if (lowest_key_version == key_version &&
lowest_kernel_version > preamble->kernel_version) {
lowest_kernel_version = preamble->kernel_version;
}
/* Check for lowest version from a valid header. */
if (lowest_version > combined_version)
lowest_version = combined_version;
/* If we already have a good kernel, no need to read another
* one; we only needed to look at the versions to check for
@@ -362,9 +356,8 @@ int LoadKernel(LoadKernelParams* params) {
* the same as the tpm, then the TPM doesn't need updating; we
* can stop now. Otherwise, we'll check all the other headers
* to see if they contain a newer key. */
if (key_version == tpm_key_version &&
preamble->kernel_version == tpm_kernel_version) {
VBDEBUG(("Same key version\n"));
if (combined_version == tpm_version) {
VBDEBUG(("Same kernel version\n"));
break;
}
} /* while(GptNextKernelEntry) */
@@ -390,12 +383,8 @@ int LoadKernel(LoadKernelParams* params) {
* anything we write gets blown away by the firmware when we go
* back to normal mode. */
VBDEBUG(("Boot_flags = is_normal\n"));
if ((lowest_key_version > tpm_key_version) ||
(lowest_key_version == tpm_key_version &&
lowest_kernel_version > tpm_kernel_version)) {
status = RollbackKernelWrite((uint16_t)lowest_key_version,
(uint16_t)lowest_kernel_version);
if (lowest_version > tpm_version) {
status = RollbackKernelWrite((uint32_t)lowest_version);
if (0 != status) {
VBDEBUG(("Error writing kernel versions to TPM.\n"));
return (status == TPM_E_MUST_REBOOT ?

View File

@@ -14,8 +14,6 @@
int main(void)
{
uint16_t x, y;
/* cgptlib.h */
GptInit(0);
GptNextKernelEntry(0, 0, 0);
@@ -29,12 +27,12 @@ int main(void)
LoadKernel(0);
/* rollback_index.h */
RollbackFirmwareSetup(0, &x, &y);
RollbackFirmwareWrite(0, 0);
RollbackFirmwareSetup(0, 0);
RollbackFirmwareWrite(0);
RollbackFirmwareLock();
RollbackKernelRecovery(0);
RollbackKernelRead(&x, &y);
RollbackKernelWrite(0, 0);
RollbackKernelRead(0);
RollbackKernelWrite(0);
RollbackKernelLock();
/* tlcl.h */

View File

@@ -1 +1 @@
char* VbootVersion = "VBOOv=38c0921e";
char* VbootVersion = "VBOOv=16e190d8";