diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c index b632305886..0d9b23c9ce 100644 --- a/firmware/lib/rollback_index.c +++ b/firmware/lib/rollback_index.c @@ -98,20 +98,25 @@ static uint32_t WriteSpaceKernel(const RollbackSpaceKernel* rsk) { return SafeWrite(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel)); } -/* Creates the NVRAM spaces, and sets their initial values as needed. */ -static uint32_t InitializeSpaces(RollbackSpaceFirmware* rsf, - RollbackSpaceKernel* rsk) { +/* Performs one-time initializations. Creates the NVRAM spaces, and sets their + * initial values as needed. Sets the nvLocked bit and ensures the physical + * presence command is enabled and locked. + */ +static uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware* rsf, + RollbackSpaceKernel* rsk) { static const RollbackSpaceFirmware rsf_init = { ROLLBACK_SPACE_FIRMWARE_VERSION, 0, 0, 0}; static const RollbackSpaceKernel rsk_init = { ROLLBACK_SPACE_KERNEL_VERSION, ROLLBACK_SPACE_KERNEL_UID, 0, 0}; uint8_t nvlocked = 0; - VBDEBUG(("TPM: Initializing spaces\n")); + VBDEBUG(("TPM: One-time initialization\n")); + + RETURN_ON_FAILURE(TlclFinalizePhysicalPresence()); /* The TPM will not enforce the NV authorization restrictions until the * execution of a TPM_NV_DefineSpace with the handle of TPM_NV_INDEX_LOCK. - * Create that space if it doesn't already exist. */ + * Here we create that space if it doesn't already exist. */ RETURN_ON_FAILURE(TlclGetFlags(NULL, NULL, &nvlocked)); VBDEBUG(("TPM: nvlocked=%d\n", nvlocked)); if (!nvlocked) { @@ -119,11 +124,11 @@ static uint32_t InitializeSpaces(RollbackSpaceFirmware* rsf, RETURN_ON_FAILURE(TlclSetNvLocked()); } - /* Initialize the firmware and kernel spaces */ + /* Initializes the firmware and kernel spaces */ Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware)); Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel)); - /* Define and set firmware and kernel spaces */ + /* Defines and sets firmware and kernel spaces */ RETURN_ON_FAILURE(SafeDefineSpace(FIRMWARE_NV_INDEX, TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE, sizeof(RollbackSpaceFirmware))); @@ -177,9 +182,17 @@ uint32_t SetupTPM(int recovery_mode, int developer_mode, #else RETURN_ON_FAILURE(TlclSelfTestFull()); #endif - RETURN_ON_FAILURE(TlclAssertPhysicalPresence()); + result = TlclAssertPhysicalPresence(); + if (result != 0) { + /* It is possible that the TPM was delivered with the physical presence + * command disabled. This tries enabling it, then tries asserting PP + * again. + */ + RETURN_ON_FAILURE(TlclPhysicalPresenceCMDEnable()); + RETURN_ON_FAILURE(TlclAssertPhysicalPresence()); + } - /* Check that the TPM is enabled and activated. */ + /* Checks that the TPM is enabled and activated. */ RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated, NULL)); if (disable || deactivated) { VBDEBUG(("TPM: disabled (%d) or deactivated (%d). Fixing...\n", @@ -190,15 +203,15 @@ uint32_t SetupTPM(int recovery_mode, int developer_mode, return TPM_E_MUST_REBOOT; } - /* Read the firmware space. */ + /* Reads the firmware space. */ result = ReadSpaceFirmware(rsf); if (TPM_E_BADINDEX == result) { RollbackSpaceKernel rsk; /* This is the first time we've run, and the TPM has not been - * initialized. Initialize it. */ + * initialized. This initializes it. */ VBDEBUG(("TPM: Not initialized yet.\n")); - RETURN_ON_FAILURE(InitializeSpaces(rsf, &rsk)); + RETURN_ON_FAILURE(OneTimeInitializeTPM(rsf, &rsk)); } else if (TPM_SUCCESS != result) { VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n")); return TPM_E_CORRUPTED_STATE; @@ -206,14 +219,14 @@ uint32_t SetupTPM(int recovery_mode, int developer_mode, VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n", rsf->struct_version, rsf->flags, rsf->fw_versions)); - /* Clear ownership if developer flag has toggled */ + /* Clears ownership if developer flag has toggled */ if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) != (rsf->flags & FLAG_LAST_BOOT_DEVELOPER)) { VBDEBUG(("TPM: Developer flag changed; clearing owner.\n")); RETURN_ON_FAILURE(TPMClearAndReenable()); } - /* Update flags */ + /* Updates flags */ if (developer_mode) new_flags |= FLAG_LAST_BOOT_DEVELOPER; if (recovery_mode) @@ -225,7 +238,7 @@ uint32_t SetupTPM(int recovery_mode, int developer_mode, rsf_dirty = 1; } - /* If firmware space is dirty, flush it back to the TPM */ + /* If firmware space is dirty, this flushes it back to the TPM */ if (rsf_dirty) { VBDEBUG(("TPM: Updating firmware space.\n")); RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); @@ -245,8 +258,8 @@ __pragma(warning (disable: 4100)) 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. */ + /* Initializes the TPM, but ignores return codes. In ChromeOS + * environment, doesn't even talk to the TPM. */ TlclLibInit(); TlclStartup(); TlclSelfTestFull(); @@ -266,8 +279,8 @@ uint32_t RollbackFirmwareLock(void) { uint32_t RollbackKernelRecovery(int developer_mode) { #ifndef CHROMEOS_ENVIRONMENT - /* Initialize the TPM, but ignore return codes. In ChromeOS - * environment, don't even talk to the TPM. */ + /* Initializes the TPM, but ignore return codes. In ChromeOS + * environment, doesn't even talk to the TPM. */ TlclLibInit(); TlclStartup(); TlclSelfTestFull(); diff --git a/firmware/lib/tpm_lite/include/tlcl.h b/firmware/lib/tpm_lite/include/tlcl.h index 8a65621e8d..c3f7373742 100644 --- a/firmware/lib/tpm_lite/include/tlcl.h +++ b/firmware/lib/tpm_lite/include/tlcl.h @@ -88,10 +88,15 @@ uint32_t TlclReadLock(uint32_t index); */ uint32_t TlclAssertPhysicalPresence(void); -/* Enable the physical presence command. The TPM error code is returned. +/* Enables the physical presence command. The TPM error code is returned. */ uint32_t TlclPhysicalPresenceCMDEnable(void); +/* Finalizes the physical presence settings: sofware PP is enabled, hardware PP + * is disabled, and the lifetime lock is set. The TPM error code is returned. + */ +uint32_t TlclFinalizePhysicalPresence(void); + /* Turns off physical presence and locks it off until next reboot. The TPM * error code is returned. */ diff --git a/firmware/lib/tpm_lite/include/tlcl_structures.h b/firmware/lib/tpm_lite/include/tlcl_structures.h index c35ecbecc6..51f461e5bf 100644 --- a/firmware/lib/tpm_lite/include/tlcl_structures.h +++ b/firmware/lib/tpm_lite/include/tlcl_structures.h @@ -64,6 +64,11 @@ struct s_tpm_startup_cmd{ } tpm_startup_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1, }, }; +struct s_tpm_finalizepp_cmd{ + uint8_t buffer[12]; +} tpm_finalizepp_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0, }, +}; + struct s_tpm_pplock_cmd{ uint8_t buffer[12]; } tpm_pplock_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x4, }, diff --git a/firmware/lib/tpm_lite/tlcl.c b/firmware/lib/tpm_lite/tlcl.c index 5a28f67b50..2bbb20dcd0 100644 --- a/firmware/lib/tpm_lite/tlcl.c +++ b/firmware/lib/tpm_lite/tlcl.c @@ -181,6 +181,11 @@ uint32_t TlclPhysicalPresenceCMDEnable(void) { return Send(tpm_ppenable_cmd.buffer); } +uint32_t TlclFinalizePhysicalPresence(void) { + VBDEBUG(("TPM: Enable PP cmd, disable HW pp, and set lifetime lock\n")); + return Send(tpm_finalizepp_cmd.buffer); +} + uint32_t TlclAssertPhysicalPresenceResult(void) { uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; return TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response)); @@ -199,7 +204,8 @@ uint32_t TlclSetNvLocked(void) { int TlclIsOwned(void) { uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE]; uint32_t result; - result = TlclSendReceive(tpm_readpubek_cmd.buffer, response, sizeof(response)); + result = TlclSendReceive(tpm_readpubek_cmd.buffer, + response, sizeof(response)); return (result != TPM_SUCCESS); } diff --git a/firmware/version.c b/firmware/version.c index b6e6b2297b..efa3c1ab41 100644 --- a/firmware/version.c +++ b/firmware/version.c @@ -1 +1 @@ -char* VbootVersion = "VBOOv=2c899e79"; +char* VbootVersion = "VBOOv=c0776686"; diff --git a/utility/tlcl_generator.c b/utility/tlcl_generator.c index cf2e48528d..89d15d6f53 100644 --- a/utility/tlcl_generator.c +++ b/utility/tlcl_generator.c @@ -190,6 +190,18 @@ Command* BuildPPEnableCommand(void) { return cmd; } +Command* BuildFinalizePPCommand(void) { + int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE); + Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size); + cmd->name = "tpm_finalizepp_cmd"; + AddInitializedField(cmd, kTpmRequestHeaderLength, + sizeof(TPM_PHYSICAL_PRESENCE), + TPM_PHYSICAL_PRESENCE_CMD_ENABLE | + TPM_PHYSICAL_PRESENCE_HW_DISABLE | + TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK); + return cmd; +} + Command* BuildPPLockCommand(void) { int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE); Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size); @@ -428,6 +440,7 @@ Command* (*builders[])(void) = { BuildPPAssertCommand, BuildPPEnableCommand, BuildPPLockCommand, + BuildFinalizePPCommand, BuildStartupCommand, BuildSelftestfullCommand, BuildContinueSelfTestCommand,