Add physical presence initialization and locking to one-time initializations.

Change-Id: If2b6041fe93bc97885e45bbb0cf7e1b81cb06c18

BUG=none
TEST=none

Review URL: http://codereview.chromium.org/3229011
This commit is contained in:
Luigi Semenzato
2010-08-31 13:20:53 -07:00
parent 60563ee0af
commit 377557fcb2
6 changed files with 64 additions and 22 deletions

View File

@@ -98,8 +98,11 @@ static uint32_t WriteSpaceKernel(const RollbackSpaceKernel* rsk) {
return SafeWrite(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel)); return SafeWrite(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
} }
/* Creates the NVRAM spaces, and sets their initial values as needed. */ /* Performs one-time initializations. Creates the NVRAM spaces, and sets their
static uint32_t InitializeSpaces(RollbackSpaceFirmware* rsf, * 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) { RollbackSpaceKernel* rsk) {
static const RollbackSpaceFirmware rsf_init = { static const RollbackSpaceFirmware rsf_init = {
ROLLBACK_SPACE_FIRMWARE_VERSION, 0, 0, 0}; ROLLBACK_SPACE_FIRMWARE_VERSION, 0, 0, 0};
@@ -107,11 +110,13 @@ static uint32_t InitializeSpaces(RollbackSpaceFirmware* rsf,
ROLLBACK_SPACE_KERNEL_VERSION, ROLLBACK_SPACE_KERNEL_UID, 0, 0}; ROLLBACK_SPACE_KERNEL_VERSION, ROLLBACK_SPACE_KERNEL_UID, 0, 0};
uint8_t nvlocked = 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 /* 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. * 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)); RETURN_ON_FAILURE(TlclGetFlags(NULL, NULL, &nvlocked));
VBDEBUG(("TPM: nvlocked=%d\n", nvlocked)); VBDEBUG(("TPM: nvlocked=%d\n", nvlocked));
if (!nvlocked) { if (!nvlocked) {
@@ -119,11 +124,11 @@ static uint32_t InitializeSpaces(RollbackSpaceFirmware* rsf,
RETURN_ON_FAILURE(TlclSetNvLocked()); RETURN_ON_FAILURE(TlclSetNvLocked());
} }
/* Initialize the firmware and kernel spaces */ /* Initializes the firmware and kernel spaces */
Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware)); Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware));
Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel)); 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, RETURN_ON_FAILURE(SafeDefineSpace(FIRMWARE_NV_INDEX,
TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE, TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE,
sizeof(RollbackSpaceFirmware))); sizeof(RollbackSpaceFirmware)));
@@ -177,9 +182,17 @@ uint32_t SetupTPM(int recovery_mode, int developer_mode,
#else #else
RETURN_ON_FAILURE(TlclSelfTestFull()); RETURN_ON_FAILURE(TlclSelfTestFull());
#endif #endif
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()); 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)); RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated, NULL));
if (disable || deactivated) { if (disable || deactivated) {
VBDEBUG(("TPM: disabled (%d) or deactivated (%d). Fixing...\n", 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; return TPM_E_MUST_REBOOT;
} }
/* Read the firmware space. */ /* Reads the firmware space. */
result = ReadSpaceFirmware(rsf); result = ReadSpaceFirmware(rsf);
if (TPM_E_BADINDEX == result) { if (TPM_E_BADINDEX == result) {
RollbackSpaceKernel rsk; RollbackSpaceKernel rsk;
/* This is the first time we've run, and the TPM has not been /* 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")); VBDEBUG(("TPM: Not initialized yet.\n"));
RETURN_ON_FAILURE(InitializeSpaces(rsf, &rsk)); RETURN_ON_FAILURE(OneTimeInitializeTPM(rsf, &rsk));
} else if (TPM_SUCCESS != result) { } else if (TPM_SUCCESS != result) {
VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n")); VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n"));
return TPM_E_CORRUPTED_STATE; 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", VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n",
rsf->struct_version, rsf->flags, rsf->fw_versions)); 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) != if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) !=
(rsf->flags & FLAG_LAST_BOOT_DEVELOPER)) { (rsf->flags & FLAG_LAST_BOOT_DEVELOPER)) {
VBDEBUG(("TPM: Developer flag changed; clearing owner.\n")); VBDEBUG(("TPM: Developer flag changed; clearing owner.\n"));
RETURN_ON_FAILURE(TPMClearAndReenable()); RETURN_ON_FAILURE(TPMClearAndReenable());
} }
/* Update flags */ /* Updates flags */
if (developer_mode) if (developer_mode)
new_flags |= FLAG_LAST_BOOT_DEVELOPER; new_flags |= FLAG_LAST_BOOT_DEVELOPER;
if (recovery_mode) if (recovery_mode)
@@ -225,7 +238,7 @@ uint32_t SetupTPM(int recovery_mode, int developer_mode,
rsf_dirty = 1; 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) { if (rsf_dirty) {
VBDEBUG(("TPM: Updating firmware space.\n")); VBDEBUG(("TPM: Updating firmware space.\n"));
RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); RETURN_ON_FAILURE(WriteSpaceFirmware(rsf));
@@ -245,8 +258,8 @@ __pragma(warning (disable: 4100))
uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) { uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) {
#ifndef CHROMEOS_ENVIRONMENT #ifndef CHROMEOS_ENVIRONMENT
/* Initialize the TPM, but ignore return codes. In ChromeOS /* Initializes the TPM, but ignores return codes. In ChromeOS
* environment, don't even talk to the TPM. */ * environment, doesn't even talk to the TPM. */
TlclLibInit(); TlclLibInit();
TlclStartup(); TlclStartup();
TlclSelfTestFull(); TlclSelfTestFull();
@@ -266,8 +279,8 @@ uint32_t RollbackFirmwareLock(void) {
uint32_t RollbackKernelRecovery(int developer_mode) { uint32_t RollbackKernelRecovery(int developer_mode) {
#ifndef CHROMEOS_ENVIRONMENT #ifndef CHROMEOS_ENVIRONMENT
/* Initialize the TPM, but ignore return codes. In ChromeOS /* Initializes the TPM, but ignore return codes. In ChromeOS
* environment, don't even talk to the TPM. */ * environment, doesn't even talk to the TPM. */
TlclLibInit(); TlclLibInit();
TlclStartup(); TlclStartup();
TlclSelfTestFull(); TlclSelfTestFull();

View File

@@ -88,10 +88,15 @@ uint32_t TlclReadLock(uint32_t index);
*/ */
uint32_t TlclAssertPhysicalPresence(void); 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); 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 /* Turns off physical presence and locks it off until next reboot. The TPM
* error code is returned. * error code is returned.
*/ */

View File

@@ -64,6 +64,11 @@ struct s_tpm_startup_cmd{
} tpm_startup_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1, }, } 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{ struct s_tpm_pplock_cmd{
uint8_t buffer[12]; uint8_t buffer[12];
} tpm_pplock_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x4, }, } tpm_pplock_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x4, },

View File

@@ -181,6 +181,11 @@ uint32_t TlclPhysicalPresenceCMDEnable(void) {
return Send(tpm_ppenable_cmd.buffer); 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) { uint32_t TlclAssertPhysicalPresenceResult(void) {
uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
return TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response)); return TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response));
@@ -199,7 +204,8 @@ uint32_t TlclSetNvLocked(void) {
int TlclIsOwned(void) { int TlclIsOwned(void) {
uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE]; uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE];
uint32_t result; 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); return (result != TPM_SUCCESS);
} }

View File

@@ -1 +1 @@
char* VbootVersion = "VBOOv=2c899e79"; char* VbootVersion = "VBOOv=c0776686";

View File

@@ -190,6 +190,18 @@ Command* BuildPPEnableCommand(void) {
return cmd; 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) { Command* BuildPPLockCommand(void) {
int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE); int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size); Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size);
@@ -428,6 +440,7 @@ Command* (*builders[])(void) = {
BuildPPAssertCommand, BuildPPAssertCommand,
BuildPPEnableCommand, BuildPPEnableCommand,
BuildPPLockCommand, BuildPPLockCommand,
BuildFinalizePPCommand,
BuildStartupCommand, BuildStartupCommand,
BuildSelftestfullCommand, BuildSelftestfullCommand,
BuildContinueSelfTestCommand, BuildContinueSelfTestCommand,