diff --git a/firmware/include/rollback_index.h b/firmware/include/rollback_index.h index c359b4bbb4..b1366dd4fd 100644 --- a/firmware/include/rollback_index.h +++ b/firmware/include/rollback_index.h @@ -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 diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c index 234b07e5f2..f3970580be 100644 --- a/firmware/lib/rollback_index.c +++ b/firmware/lib/rollback_index.c @@ -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; +} diff --git a/firmware/lib/vboot_firmware.c b/firmware/lib/vboot_firmware.c index 6f20641af5..a59b238e85 100644 --- a/firmware/lib/vboot_firmware.c +++ b/firmware/lib/vboot_firmware.c @@ -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, - (uint16_t)lowest_fw_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; } diff --git a/firmware/lib/vboot_kernel.c b/firmware/lib/vboot_kernel.c index d26ef6ff0d..a0a7656674 100644 --- a/firmware/lib/vboot_kernel.c +++ b/firmware/lib/vboot_kernel.c @@ -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"); - return LOAD_KERNEL_RECOVERY; + /* 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,25 +366,18 @@ 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()) - return LOAD_KERNEL_RECOVERY; + /* 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; } /* Success! */ diff --git a/firmware/linktest/main.c b/firmware/linktest/main.c index e6659a991a..f91da9950e 100644 --- a/firmware/linktest/main.c +++ b/firmware/linktest/main.c @@ -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();