Refactor rollback interface for LoadKernel(), LoadFirmware().

Review URL: http://codereview.chromium.org/2861020
This commit is contained in:
Randall Spangler
2010-06-23 15:35:31 -07:00
parent 1114b661f5
commit 1078838fff
5 changed files with 114 additions and 44 deletions

View File

@@ -43,6 +43,58 @@ extern uint16_t g_kernel_version;
/* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */
/*
Call from LoadFirmware()
Normal or developer mode (not recovery)
Wants firmware versions
Must send in developer flag
RollbackFirmwareSetup(IN devmode, OUT firmware versions)
(maybe) RollbackFirmwareWrite()
RollbackFirmwareLock()
Call from LoadKernel()
RollbackKernelRecovery(IN devmode)
(implies LockFirmwareVersions() inside the setup)
RollbackKernelRead(OUT kernel versions)
(maybe) RollbackKernelWrite()
RollbackKernelLock()
Any mode
If recovery mode, this is the first time we've been called
Must send in developer flag
If not recovery mode, wants kernel versions
Must send in developer and recovery flags
*/
/* These functions are callable from LoadFirmware(). They cannot use
* global variables. */
/* Setup must be called. */
uint32_t RollbackFirmwareSetup(int developer_mode,
uint16_t* key_version, uint16_t* version);
/* Write may be called if the versions change */
uint32_t RollbackFirmwareWrite(uint16_t key_version, uint16_t version);
/* Lock must be called */
uint32_t RollbackFirmwareLock(void);
/* These functions are callable from LoadKernel(). They may use global
* variables. */
/* Recovery may be called. If it is, this is the first time a
* rollback function has been called this boot, so it needs to know if
* we're in developer mode. */
uint32_t RollbackKernelRecovery(int developer_mode);
/* Read and write may be called if not in developer mode. If called in
* recovery mode, these are ignored and/or return 0 versions. */
uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version);
uint32_t RollbackKernelWrite(uint16_t key_version, uint16_t version);
/* Lock must be called. Internally, it's ignored in recovery mode. */
uint32_t RollbackKernelLock(void);
/* SetupTPM is called on boot and on starting the RW firmware, passing the
* appripriate MODE and DEVELOPER_FLAG parameters. MODE can be one of
* RO_RECOVERY_MODE, RO_NORMAL_MODE, RW_NORMAL_MODE. DEVELOPER_FLAG is 1 when

View File

@@ -368,3 +368,36 @@ uint32_t LockFirmwareVersions() {
uint32_t LockKernelVersionsByLockingPP() {
return TlclLockPhysicalPresence();
}
/* NEW APIS! HELP ME LUIGI, YOU'RE MY ONLY HOPE! */
uint32_t RollbackFirmwareSetup(int developer_mode,
uint16_t* key_version, uint16_t* version) {
return TPM_SUCCESS;
}
uint32_t RollbackFirmwareWrite(uint16_t key_version, uint16_t version) {
return TPM_SUCCESS;
}
uint32_t RollbackFirmwareLock(void) {
return TPM_SUCCESS;
}
uint32_t RollbackKernelRecovery(int developer_mode) {
return TPM_SUCCESS;
}
uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version) {
return TPM_SUCCESS;
}
uint32_t RollbackKernelWrite(uint16_t key_version, uint16_t version) {
return TPM_SUCCESS;
}
uint32_t RollbackKernelLock(void) {
return TPM_SUCCESS;
}

View File

@@ -58,12 +58,7 @@ int LoadFirmware(LoadFirmwareParams* params) {
/* Initialize the TPM and read rollback indices. */
/* TODO: fix SetupTPM parameter for developer mode */
if (0 != SetupTPM(RO_NORMAL_MODE, 0)) {
debug("SetupTPM failed\n");
return LOAD_FIRMWARE_RECOVERY;
}
if (0 != GetStoredVersions(FIRMWARE_VERSIONS,
&tpm_key_version, &tpm_fw_version)) {
if (0 != RollbackFirmwareSetup(0, &tpm_key_version, &tpm_fw_version)) {
debug("Unable to get stored versions.\n");
return LOAD_FIRMWARE_RECOVERY;
}
@@ -217,18 +212,15 @@ int LoadFirmware(LoadFirmwareParams* params) {
if ((lowest_key_version > tpm_key_version) ||
(lowest_key_version == tpm_key_version &&
lowest_fw_version > tpm_fw_version)) {
if (0 != WriteStoredVersions(FIRMWARE_VERSIONS,
(uint16_t)lowest_key_version,
if (0 != RollbackFirmwareWrite((uint16_t)lowest_key_version,
(uint16_t)lowest_fw_version)) {
debug("Unable to write stored versions.\n");
return LOAD_FIRMWARE_RECOVERY;
}
}
/* Lock Firmware TPM rollback indices from further writes. In
* this design, this is done by setting the globalLock bit, which
* is cleared only by TPM_Init at reboot. */
if (0 != LockFirmwareVersions()) {
/* Lock firmware versions in TPM */
if (0 != RollbackFirmwareLock()) {
debug("Unable to lock firmware versions.\n");
return LOAD_FIRMWARE_RECOVERY;
}

View File

@@ -134,22 +134,20 @@ int LoadKernel(LoadKernelParams* params) {
params->bootloader_address = 0;
params->bootloader_size = 0;
/* Set up TPM; required in all modes */
if (0 != SetupTPM(
((BOOT_FLAG_RECOVERY & params->boot_flags) ?
RO_RECOVERY_MODE : RW_NORMAL_MODE),
((BOOT_FLAG_DEVELOPER & params->boot_flags) ? 1 : 0))) {
debug("Error setting up TPM\n");
/* Let the TPM know if we're in recovery mode */
if (BOOT_FLAG_RECOVERY & params->boot_flags) {
if (0 != RollbackKernelRecovery(BOOT_FLAG_DEVELOPER & params->boot_flags
? 1 : 0)) {
debug("Error setting up TPM for recovery kernel\n");
return LOAD_KERNEL_RECOVERY;
}
}
if (is_normal) {
/* Read current kernel key index from TPM. Assumes TPM is already
* initialized. */
if (0 != GetStoredVersions(KERNEL_VERSIONS,
&tpm_key_version,
&tpm_kernel_version)) {
debug("Unable to get stored version from TPM\n");
if (0 != RollbackKernelRead(&tpm_key_version, &tpm_kernel_version)) {
debug("Unable to get kernel versions from TPM\n");
return LOAD_KERNEL_RECOVERY;
}
} else if (is_dev) {
@@ -368,24 +366,17 @@ int LoadKernel(LoadKernelParams* params) {
if ((lowest_key_version > tpm_key_version) ||
(lowest_key_version == tpm_key_version &&
lowest_kernel_version > tpm_kernel_version)) {
if (0 != WriteStoredVersions(KERNEL_VERSIONS,
(uint16_t)lowest_key_version,
(uint16_t)lowest_kernel_version))
if (0 != RollbackKernelWrite((uint16_t)lowest_key_version,
(uint16_t)lowest_kernel_version)) {
debug("Error writing kernel versions to TPM.\n");
return LOAD_KERNEL_RECOVERY;
}
}
}
if (!(BOOT_FLAG_RECOVERY & params->boot_flags)) {
/* We can lock the TPM now, since we've decided which kernel we
* like. If we don't find a good kernel, we leave the TPM
* unlocked so we can try again on the next boot device. If no
* kernels are good, we'll reboot to recovery mode, so it's ok to
* leave the TPM unlocked in that case too.
*
* If we're already in recovery mode, we need to leave PP unlocked,
* so don't lock the kernel versions. */
debug("Lock kernel versions\n");
if (0 != LockKernelVersionsByLockingPP())
/* Lock the kernel versions, since we're about to boot the kernel */
if (0 != RollbackKernelLock()) {
debug("Error locking kernel versions.\n");
return LOAD_KERNEL_RECOVERY;
}

View File

@@ -24,11 +24,13 @@ int main(void)
LoadKernel(0);
/* rollback_index.h */
SetupTPM(0, 0);
GetStoredVersions(0, &x, &y);
WriteStoredVersions(0, 0, 0);
LockFirmwareVersions();
LockKernelVersionsByLockingPP();
RollbackFirmwareSetup(0, &x, &y);
RollbackFirmwareWrite(0, 0);
RollbackFirmwareLock();
RollbackKernelRecovery(0);
RollbackKernelRead(&x, &y);
RollbackKernelWrite(0, 0);
RollbackKernelLock();
/* tlcl.h */
TlclLibInit();