mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-27 19:53:42 +00:00
Fix normal/recovery mode, and RO firmware vs. RW firmware behavior.
Review URL: http://codereview.chromium.org/2792009
This commit is contained in:
@@ -16,7 +16,7 @@ uint16_t g_firmware_version = 0;
|
|||||||
uint16_t g_kernel_key_version = 0;
|
uint16_t g_kernel_key_version = 0;
|
||||||
uint16_t g_kernel_version = 0;
|
uint16_t g_kernel_version = 0;
|
||||||
|
|
||||||
uint32_t SetupTPM(void) {
|
uint32_t SetupTPM(int mode, int developer_flag) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
debug("Rollback Index Library Mock: TPM initialized.\n");
|
debug("Rollback Index Library Mock: TPM initialized.\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,12 +20,18 @@ extern uint16_t g_kernel_version;
|
|||||||
#define FIRMWARE_VERSIONS 0
|
#define FIRMWARE_VERSIONS 0
|
||||||
#define KERNEL_VERSIONS 1
|
#define KERNEL_VERSIONS 1
|
||||||
|
|
||||||
|
/* Initialization mode */
|
||||||
|
#define RO_RECOVERY_MODE 0
|
||||||
|
#define RO_NORMAL_MODE 1
|
||||||
|
#define RW_NORMAL_MODE 2
|
||||||
|
|
||||||
/* TPM NVRAM location indices. */
|
/* TPM NVRAM location indices. */
|
||||||
#define FIRMWARE_VERSIONS_NV_INDEX 0x1001
|
#define FIRMWARE_VERSIONS_NV_INDEX 0x1001
|
||||||
#define KERNEL_VERSIONS_NV_INDEX 0x1002
|
#define KERNEL_VERSIONS_NV_INDEX 0x1002
|
||||||
#define TPM_IS_INITIALIZED_NV_INDEX 0x1003
|
#define TPM_IS_INITIALIZED_NV_INDEX 0x1003
|
||||||
#define KERNEL_VERSIONS_BACKUP_NV_INDEX 0x1004
|
#define KERNEL_VERSIONS_BACKUP_NV_INDEX 0x1004
|
||||||
#define KERNEL_MUST_USE_BACKUP_NV_INDEX 0x1005
|
#define KERNEL_MUST_USE_BACKUP_NV_INDEX 0x1005
|
||||||
|
#define DEVELOPER_MODE_NV_INDEX 0x1006
|
||||||
|
|
||||||
/* Unique ID to detect kernel space redefinition */
|
/* Unique ID to detect kernel space redefinition */
|
||||||
#define KERNEL_SPACE_UID "GRWL" /* unique ID with secret meaning */
|
#define KERNEL_SPACE_UID "GRWL" /* unique ID with secret meaning */
|
||||||
@@ -33,8 +39,23 @@ extern uint16_t g_kernel_version;
|
|||||||
#define KERNEL_SPACE_INIT_DATA ((uint8_t*) "\0\0\0\0" KERNEL_SPACE_UID)
|
#define KERNEL_SPACE_INIT_DATA ((uint8_t*) "\0\0\0\0" KERNEL_SPACE_UID)
|
||||||
#define KERNEL_SPACE_SIZE (sizeof(uint32_t) + KERNEL_SPACE_UID_SIZE)
|
#define KERNEL_SPACE_SIZE (sizeof(uint32_t) + KERNEL_SPACE_UID_SIZE)
|
||||||
|
|
||||||
/* All functions return 0 if successful, non-zero if error */
|
/* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */
|
||||||
uint32_t SetupTPM(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
|
||||||
|
* the developer switch is ON, 0 otherwise.
|
||||||
|
*
|
||||||
|
* If SetupTPM returns TPM_SUCCESS, the caller may proceed. If it returns
|
||||||
|
* TPM_E_MUST_REBOOT, the caller must reboot in normal mode. For all other
|
||||||
|
* return values, the caller must reboot in recovery mode.
|
||||||
|
*
|
||||||
|
* This function has many side effects on the TPM state. In particular, when
|
||||||
|
* called with mode = RECOVERY_MODE it locks the firmware versions before
|
||||||
|
* returning. In all other cases, the caller is responsible for locking the
|
||||||
|
* firmware versions once it decides it doesn't need to update them.
|
||||||
|
*/
|
||||||
|
uint32_t SetupTPM(int mode, int developer_flag);
|
||||||
uint32_t GetStoredVersions(int type, uint16_t* key_version, uint16_t* version);
|
uint32_t GetStoredVersions(int type, uint16_t* key_version, uint16_t* version);
|
||||||
uint32_t WriteStoredVersions(int type, uint16_t key_version, uint16_t version);
|
uint32_t WriteStoredVersions(int type, uint16_t key_version, uint16_t version);
|
||||||
uint32_t LockFirmwareVersions(void);
|
uint32_t LockFirmwareVersions(void);
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ int VerifyFirmwareDriver_f(uint8_t* root_key_blob,
|
|||||||
uint16_t version, key_version; /* Temporary variables */
|
uint16_t version, key_version; /* Temporary variables */
|
||||||
|
|
||||||
/* Initialize the TPM since we'll be reading the rollback indices. */
|
/* Initialize the TPM since we'll be reading the rollback indices. */
|
||||||
SetupTPM();
|
SetupTPM(0, 0);
|
||||||
|
|
||||||
/* We get the key versions by reading directly from the image blobs without
|
/* We get the key versions by reading directly from the image blobs without
|
||||||
* any additional (expensive) sanity checking on the blob since it's faster to
|
* any additional (expensive) sanity checking on the blob since it's faster to
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#define TPM_E_MAXNVWRITES ((uint32_t)0x00000048)
|
#define TPM_E_MAXNVWRITES ((uint32_t)0x00000048)
|
||||||
#define TPM_E_ALREADY_INITIALIZED ((uint32_t)0x00005000) /* vboot local */
|
#define TPM_E_ALREADY_INITIALIZED ((uint32_t)0x00005000) /* vboot local */
|
||||||
#define TPM_E_INTERNAL_INCONSISTENCY ((uint32_t)0x00005001) /* vboot local */
|
#define TPM_E_INTERNAL_INCONSISTENCY ((uint32_t)0x00005001) /* vboot local */
|
||||||
|
#define TPM_E_MUST_REBOOT ((uint32_t)0x00005002) /* vboot local */
|
||||||
|
|
||||||
#define TPM_NV_INDEX0 ((uint32_t)0x00000000)
|
#define TPM_NV_INDEX0 ((uint32_t)0x00000000)
|
||||||
#define TPM_NV_INDEX_LOCK ((uint32_t)0xffffffff)
|
#define TPM_NV_INDEX_LOCK ((uint32_t)0xffffffff)
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ static uint32_t InitializeKernelVersionsSpaces(void) {
|
|||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* When the return value is TPM_SUCCESS, this function sets *|initialized| to 1
|
||||||
|
* if the spaces have been fully initialized, to 0 if not. Otherwise
|
||||||
|
* *|initialized| is not changed.
|
||||||
|
*/
|
||||||
static uint32_t GetSpacesInitialized(int* initialized) {
|
static uint32_t GetSpacesInitialized(int* initialized) {
|
||||||
uint32_t space_holder;
|
uint32_t space_holder;
|
||||||
uint32_t result;
|
uint32_t result;
|
||||||
@@ -51,6 +55,8 @@ static uint32_t GetSpacesInitialized(int* initialized) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Creates the NVRAM spaces, and sets their initial values as needed.
|
||||||
|
*/
|
||||||
static uint32_t InitializeSpaces(void) {
|
static uint32_t InitializeSpaces(void) {
|
||||||
uint32_t zero = 0;
|
uint32_t zero = 0;
|
||||||
uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE;
|
uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE;
|
||||||
@@ -67,9 +73,8 @@ static uint32_t InitializeSpaces(void) {
|
|||||||
RETURN_ON_FAILURE(InitializeKernelVersionsSpaces());
|
RETURN_ON_FAILURE(InitializeKernelVersionsSpaces());
|
||||||
|
|
||||||
/* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel
|
/* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel
|
||||||
* versions when entering recovery mode. The content of space
|
* versions. The content of space KERNEL_MUST_USE_BACKUP determines whether
|
||||||
* KERNEL_MUST_USE_BACKUP determines whether the backup value (1) or the
|
* only the backup value should be trusted.
|
||||||
* regular value (0) should be trusted.
|
|
||||||
*/
|
*/
|
||||||
RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_BACKUP_NV_INDEX,
|
RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_BACKUP_NV_INDEX,
|
||||||
firmware_perm, sizeof(uint32_t)));
|
firmware_perm, sizeof(uint32_t)));
|
||||||
@@ -79,6 +84,10 @@ static uint32_t InitializeSpaces(void) {
|
|||||||
firmware_perm, sizeof(uint32_t)));
|
firmware_perm, sizeof(uint32_t)));
|
||||||
RETURN_ON_FAILURE(TlclWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX,
|
RETURN_ON_FAILURE(TlclWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX,
|
||||||
(uint8_t*) &zero, sizeof(uint32_t)));
|
(uint8_t*) &zero, sizeof(uint32_t)));
|
||||||
|
RETURN_ON_FAILURE(TlclDefineSpace(DEVELOPER_MODE_NV_INDEX,
|
||||||
|
firmware_perm, sizeof(uint32_t)));
|
||||||
|
RETURN_ON_FAILURE(TlclWrite(DEVELOPER_MODE_NV_INDEX,
|
||||||
|
(uint8_t*) &zero, sizeof(uint32_t)));
|
||||||
|
|
||||||
/* The space TPM_IS_INITIALIZED_NV_INDEX is used to indicate that the TPM
|
/* The space TPM_IS_INITIALIZED_NV_INDEX is used to indicate that the TPM
|
||||||
* initialization has completed. Without it we cannot be sure that the last
|
* initialization has completed. Without it we cannot be sure that the last
|
||||||
@@ -90,68 +99,18 @@ static uint32_t InitializeSpaces(void) {
|
|||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enters the recovery mode. If |unlocked| is true, there is some problem with
|
static uint32_t SetDistrustKernelSpaceAtNextBoot(uint32_t distrust) {
|
||||||
* the TPM, so do not attempt to do any more TPM operations, and particularly
|
|
||||||
* do not set bGlobalLock.
|
|
||||||
*/
|
|
||||||
void EnterRecovery(int unlocked) {
|
|
||||||
uint32_t combined_versions;
|
|
||||||
uint32_t backup_versions;
|
|
||||||
uint32_t must_use_backup;
|
uint32_t must_use_backup;
|
||||||
uint32_t result;
|
RETURN_ON_FAILURE(TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX,
|
||||||
|
(uint8_t*) &must_use_backup, sizeof(uint32_t)));
|
||||||
if (!unlocked) {
|
if (must_use_backup != distrust) {
|
||||||
/* Saves the kernel versions and indicates that we should trust the saved
|
RETURN_ON_FAILURE(TlclWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX,
|
||||||
* ones.
|
(uint8_t*) &distrust, sizeof(uint32_t)));
|
||||||
*/
|
|
||||||
if (TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &combined_versions,
|
|
||||||
sizeof(uint32_t)) != TPM_SUCCESS)
|
|
||||||
goto recovery_mode;
|
|
||||||
if (TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, (uint8_t*) &backup_versions,
|
|
||||||
sizeof(uint32_t)) != TPM_SUCCESS)
|
|
||||||
goto recovery_mode;
|
|
||||||
/* Avoids idempotent writes. */
|
|
||||||
if (combined_versions != backup_versions) {
|
|
||||||
result = TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX,
|
|
||||||
(uint8_t*) &combined_versions, sizeof(uint32_t));
|
|
||||||
if (result == TPM_E_MAXNVWRITES) {
|
|
||||||
goto forceclear_and_reboot;
|
|
||||||
} else if (result != TPM_SUCCESS) {
|
|
||||||
goto recovery_mode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX, (uint8_t*) &must_use_backup,
|
|
||||||
sizeof(uint32_t)) != TPM_SUCCESS)
|
|
||||||
goto recovery_mode;
|
|
||||||
if (must_use_backup != 1) {
|
|
||||||
must_use_backup = 1;
|
|
||||||
result = TlclWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX,
|
|
||||||
(uint8_t*) &must_use_backup, sizeof(uint32_t));
|
|
||||||
if (result == TPM_E_MAXNVWRITES) {
|
|
||||||
goto forceclear_and_reboot;
|
|
||||||
} else if (result != TPM_SUCCESS) {
|
|
||||||
goto recovery_mode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Protects the firmware and backup kernel versions. */
|
|
||||||
if (LockFirmwareVersions() != TPM_SUCCESS)
|
|
||||||
goto recovery_mode;
|
|
||||||
}
|
}
|
||||||
|
return TPM_SUCCESS;
|
||||||
recovery_mode:
|
|
||||||
debug("entering recovery mode");
|
|
||||||
|
|
||||||
/* TODO(nelson): code for entering recovery mode. */
|
|
||||||
|
|
||||||
forceclear_and_reboot:
|
|
||||||
if (TlclForceClear() != TPM_SUCCESS) {
|
|
||||||
goto recovery_mode;
|
|
||||||
}
|
|
||||||
/* TODO: reboot */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t GetTPMRollbackIndices(void) {
|
static uint32_t GetTPMRollbackIndices(int type) {
|
||||||
uint32_t firmware_versions;
|
uint32_t firmware_versions;
|
||||||
uint32_t kernel_versions;
|
uint32_t kernel_versions;
|
||||||
|
|
||||||
@@ -159,17 +118,22 @@ static uint32_t GetTPMRollbackIndices(void) {
|
|||||||
* rollback index locations are missing or somehow messed up. We let the
|
* rollback index locations are missing or somehow messed up. We let the
|
||||||
* caller deal with that.
|
* caller deal with that.
|
||||||
*/
|
*/
|
||||||
RETURN_ON_FAILURE(TlclRead(FIRMWARE_VERSIONS_NV_INDEX,
|
switch (type) {
|
||||||
(uint8_t*) &firmware_versions,
|
case FIRMWARE_VERSIONS:
|
||||||
sizeof(firmware_versions)));
|
RETURN_ON_FAILURE(TlclRead(FIRMWARE_VERSIONS_NV_INDEX,
|
||||||
RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX,
|
(uint8_t*) &firmware_versions,
|
||||||
(uint8_t*) &kernel_versions,
|
sizeof(firmware_versions)));
|
||||||
sizeof(kernel_versions)));
|
g_firmware_key_version = firmware_versions >> 16;
|
||||||
|
g_firmware_version = firmware_versions && 0xffff;
|
||||||
g_firmware_key_version = firmware_versions >> 16;
|
break;
|
||||||
g_firmware_version = firmware_versions && 0xffff;
|
case KERNEL_VERSIONS:
|
||||||
g_kernel_key_version = kernel_versions >> 16;
|
RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX,
|
||||||
g_kernel_version = kernel_versions && 0xffff;
|
(uint8_t*) &kernel_versions,
|
||||||
|
sizeof(kernel_versions)));
|
||||||
|
g_kernel_key_version = kernel_versions >> 16;
|
||||||
|
g_kernel_version = kernel_versions && 0xffff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -241,7 +205,31 @@ static uint32_t BackupKernelSpace(void) {
|
|||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t SetupTPM_(void) {
|
/* Checks for transitions between protected mode to developer mode. When going
|
||||||
|
* into developer mode, clear the TPM.
|
||||||
|
*/
|
||||||
|
static uint32_t CheckDeveloperModeTransition(uint32_t current_developer) {
|
||||||
|
uint32_t past_developer;
|
||||||
|
int must_clear;
|
||||||
|
RETURN_ON_FAILURE(TlclRead(DEVELOPER_MODE_NV_INDEX,
|
||||||
|
(uint8_t*) &past_developer,
|
||||||
|
sizeof(past_developer)));
|
||||||
|
must_clear = current_developer && !past_developer;
|
||||||
|
if (must_clear) {
|
||||||
|
RETURN_ON_FAILURE(TlclForceClear());
|
||||||
|
}
|
||||||
|
if (past_developer != current_developer) {
|
||||||
|
/* (Unauthorized) writes to the TPM succeed even when the TPM is disabled
|
||||||
|
* and deactivated.
|
||||||
|
*/
|
||||||
|
RETURN_ON_FAILURE(TlclWrite(DEVELOPER_MODE_NV_INDEX,
|
||||||
|
(uint8_t*) ¤t_developer,
|
||||||
|
sizeof(current_developer)));
|
||||||
|
}
|
||||||
|
return must_clear ? TPM_E_MUST_REBOOT : TPM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t SetupTPM_(int mode, int developer_flag) {
|
||||||
uint8_t disable;
|
uint8_t disable;
|
||||||
uint8_t deactivated;
|
uint8_t deactivated;
|
||||||
TlclLibInit();
|
TlclLibInit();
|
||||||
@@ -253,11 +241,11 @@ static uint32_t SetupTPM_(void) {
|
|||||||
if (disable || deactivated) {
|
if (disable || deactivated) {
|
||||||
RETURN_ON_FAILURE(TlclSetEnable());
|
RETURN_ON_FAILURE(TlclSetEnable());
|
||||||
RETURN_ON_FAILURE(TlclSetDeactivated(0));
|
RETURN_ON_FAILURE(TlclSetDeactivated(0));
|
||||||
/* TODO: Reboot */
|
return TPM_E_MUST_REBOOT;
|
||||||
return 9999;
|
|
||||||
}
|
}
|
||||||
/* We expect this to fail the first time we run on a device, indicating that
|
/* We expect this to fail the first time we run on a device, because the TPM
|
||||||
* the TPM has not been initialized yet. */
|
* has not been initialized yet.
|
||||||
|
*/
|
||||||
if (RecoverKernelSpace() != TPM_SUCCESS) {
|
if (RecoverKernelSpace() != TPM_SUCCESS) {
|
||||||
int initialized = 0;
|
int initialized = 0;
|
||||||
RETURN_ON_FAILURE(GetSpacesInitialized(&initialized));
|
RETURN_ON_FAILURE(GetSpacesInitialized(&initialized));
|
||||||
@@ -269,32 +257,73 @@ static uint32_t SetupTPM_(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
RETURN_ON_FAILURE(BackupKernelSpace());
|
RETURN_ON_FAILURE(BackupKernelSpace());
|
||||||
RETURN_ON_FAILURE(GetTPMRollbackIndices());
|
RETURN_ON_FAILURE(SetDistrustKernelSpaceAtNextBoot(mode == RO_RECOVERY_MODE));
|
||||||
|
RETURN_ON_FAILURE(GetTPMRollbackIndices(FIRMWARE_VERSIONS));
|
||||||
|
RETURN_ON_FAILURE(GetTPMRollbackIndices(KERNEL_VERSIONS));
|
||||||
|
|
||||||
|
RETURN_ON_FAILURE(CheckDeveloperModeTransition(developer_flag));
|
||||||
|
|
||||||
|
/* As a courtesy (I hope) to the caller, lock the firmware versions if we are
|
||||||
|
* in recovery mode. The normal mode may need to update the firmware
|
||||||
|
* versions, so they cannot be locked here.
|
||||||
|
*/
|
||||||
|
if (mode == RO_RECOVERY_MODE) {
|
||||||
|
RETURN_ON_FAILURE(LockFirmwareVersions());
|
||||||
|
}
|
||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SetupTPM(void) {
|
/* SetupTPM starts the TPM and establishes the root of trust for the
|
||||||
uint32_t result = SetupTPM_();
|
* anti-rollback mechanism. SetupTPM can fail for three reasons. 1 A bug. 2 a
|
||||||
if (result == TPM_E_MAXNVWRITES) {
|
* TPM hardware failure. 3 An unexpected TPM state due to some attack. In
|
||||||
/* ForceClears and reboots */
|
* general we cannot easily distinguish the kind of failure, so our strategy is
|
||||||
RETURN_ON_FAILURE(TlclForceClear());
|
* to reboot in recovery mode in all cases. The recovery mode calls SetupTPM
|
||||||
/* TODO: reboot */
|
* again, which executes (almost) the same sequence of operations. There is a
|
||||||
return 9999;
|
* good chance that, if recovery mode was entered because of a TPM failure, the
|
||||||
} else {
|
* failure will repeat itself. (In general this is impossible to guarantee
|
||||||
return result;
|
* because we have no way of creating the exact TPM initial state at the
|
||||||
|
* previous boot.) In recovery mode, we ignore the failure and continue, thus
|
||||||
|
* giving the recovery kernel a chance to fix things (that's why we don't set
|
||||||
|
* bGlobalLock). The choice is between a knowingly insecure device and a
|
||||||
|
* bricked device.
|
||||||
|
*
|
||||||
|
* As a side note, observe that we go through considerable hoops to avoid using
|
||||||
|
* the STCLEAR permissions for the index spaces. We do this to avoid writing
|
||||||
|
* to the TPM flashram at every reboot or wake-up, because of concerns about
|
||||||
|
* the durability of the NVRAM.
|
||||||
|
*/
|
||||||
|
uint32_t SetupTPM(int mode, int developer_flag) {
|
||||||
|
switch (mode) {
|
||||||
|
case RO_RECOVERY_MODE:
|
||||||
|
case RO_NORMAL_MODE: {
|
||||||
|
uint32_t result = SetupTPM_(mode, developer_flag);
|
||||||
|
if (result == TPM_E_MAXNVWRITES) {
|
||||||
|
/* ForceClears and reboots */
|
||||||
|
RETURN_ON_FAILURE(TlclForceClear());
|
||||||
|
return TPM_E_MUST_REBOOT;
|
||||||
|
} else if (mode == RO_NORMAL_MODE) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
/* In recovery mode we want to keep going even if there are errors. */
|
||||||
|
return TPM_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case RW_NORMAL_MODE:
|
||||||
|
/* There are no TPM writes here, so no need to check for write limit errors.
|
||||||
|
*/
|
||||||
|
RETURN_ON_FAILURE(GetTPMRollbackIndices(KERNEL_VERSIONS));
|
||||||
|
default:
|
||||||
|
return TPM_E_INTERNAL_INCONSISTENCY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GetStoredVersions(int type, uint16_t* key_version, uint16_t* version) {
|
uint32_t GetStoredVersions(int type, uint16_t* key_version, uint16_t* version) {
|
||||||
|
/* TODO: should verify that SetupTPM() has been called.
|
||||||
/* TODO: should verify that SetupTPM() has been called. Note that
|
*
|
||||||
* SetupTPM() does hardware setup AND sets global variables. When we
|
* Note that SetupTPM() does hardware setup AND sets global variables. When
|
||||||
* get down into kernel verification, the hardware setup persists, but
|
* we get down into kernel verification, the hardware setup persists, but we
|
||||||
* we don't have access to the global variables. So I guess we DO need
|
* lose the global variables.
|
||||||
* to call SetupTPM() there, and have it be smart enough not to redo the
|
*/
|
||||||
* hardware init, but it still needs to re-read the flags... */
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case FIRMWARE_VERSIONS:
|
case FIRMWARE_VERSIONS:
|
||||||
*key_version = g_firmware_key_version;
|
*key_version = g_firmware_key_version;
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ int LoadFirmware2(LoadFirmwareParams* params) {
|
|||||||
return LOAD_FIRMWARE_RECOVERY;
|
return LOAD_FIRMWARE_RECOVERY;
|
||||||
|
|
||||||
/* Initialize the TPM and read rollback indices. */
|
/* Initialize the TPM and read rollback indices. */
|
||||||
if (0 != SetupTPM() )
|
/* TODO: fix SetupTPM parameter */
|
||||||
|
if (0 != SetupTPM(0, 0) )
|
||||||
return LOAD_FIRMWARE_RECOVERY;
|
return LOAD_FIRMWARE_RECOVERY;
|
||||||
if (0 != GetStoredVersions(FIRMWARE_VERSIONS,
|
if (0 != GetStoredVersions(FIRMWARE_VERSIONS,
|
||||||
&tpm_key_version, &tpm_fw_version))
|
&tpm_key_version, &tpm_fw_version))
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ int main(void)
|
|||||||
LoadKernel(0);
|
LoadKernel(0);
|
||||||
|
|
||||||
/* rollback_index.h */
|
/* rollback_index.h */
|
||||||
SetupTPM();
|
SetupTPM(0, 0);
|
||||||
GetStoredVersions(0, &x, &y);
|
GetStoredVersions(0, &x, &y);
|
||||||
WriteStoredVersions(0, 0, 0);
|
WriteStoredVersions(0, 0, 0);
|
||||||
LockFirmwareVersions();
|
LockFirmwareVersions();
|
||||||
|
|||||||
Reference in New Issue
Block a user