| Index: firmware/lib/rollback_index.c
|
| diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c
|
| index 4629e6e4810de9b8c551e2ee72e9756312fa3a0c..a81bb9b86cea59f7ab4437684f14ae9257eec80c 100644
|
| --- a/firmware/lib/rollback_index.c
|
| +++ b/firmware/lib/rollback_index.c
|
| @@ -136,42 +136,39 @@ static uint32_t SetDistrustKernelSpaceAtNextBoot(uint32_t distrust) {
|
| uint32_t RecoverKernelSpace(void) {
|
| uint32_t perms = 0;
|
| uint8_t buffer[KERNEL_SPACE_SIZE];
|
| - int read_OK = 0;
|
| - int perms_OK = 0;
|
| uint32_t backup_combined_versions;
|
| uint32_t must_use_backup;
|
| + uint32_t zero = 0;
|
|
|
| RETURN_ON_FAILURE(TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX,
|
| (uint8_t*) &must_use_backup, sizeof(uint32_t)));
|
| /* must_use_backup is true if the previous boot entered recovery mode. */
|
|
|
| - read_OK = TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &buffer,
|
| - KERNEL_SPACE_SIZE) == TPM_SUCCESS;
|
| - if (read_OK) {
|
| - RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_VERSIONS_NV_INDEX, &perms));
|
| - perms_OK = perms == TPM_NV_PER_PPWRITE;
|
| - }
|
| - if (!must_use_backup && read_OK && perms_OK &&
|
| + /* If we can't read the kernel space, or it has the wrong permission, or it
|
| + * doesn't contain the right identifier, we give up. This will need to be
|
| + * fixed by the recovery kernel. We have to worry about this because at any
|
| + * time (even with PP turned off) the TPM owner can remove and redefine a
|
| + * PP-protected space (but not write to it).
|
| + */
|
| + RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &buffer,
|
| + KERNEL_SPACE_SIZE));
|
| + RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_VERSIONS_NV_INDEX, &perms));
|
| + if (perms != TPM_NV_PER_PPWRITE ||
|
| !Memcmp(buffer + sizeof(uint32_t), KERNEL_SPACE_UID,
|
| KERNEL_SPACE_UID_SIZE)) {
|
| - /* Everything is fine. This is the normal, frequent path. */
|
| - return TPM_SUCCESS;
|
| + return TPM_E_CORRUPTED_STATE;
|
| }
|
|
|
| - /* Either we detected that something went wrong, or we cannot trust the
|
| - * PP-protected kernel space. Attempts to fix. It is not always necessary
|
| - * to redefine the space, but we might as well, since this path should be
|
| - * taken quite seldom (after recovery mode and after an attack).
|
| - */
|
| - RETURN_ON_FAILURE(InitializeKernelVersionsSpaces());
|
| - RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX,
|
| - (uint8_t*) &backup_combined_versions,
|
| - sizeof(uint32_t)));
|
| - RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX,
|
| - (uint8_t*) &backup_combined_versions,
|
| - sizeof(uint32_t)));
|
| if (must_use_backup) {
|
| - uint32_t zero = 0;
|
| + /* We must use the backup space because in the preceding boot cycle the
|
| + * primary space was left unlocked and cannot be trusted.
|
| + */
|
| + RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX,
|
| + (uint8_t*) &backup_combined_versions,
|
| + sizeof(uint32_t)));
|
| + RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX,
|
| + (uint8_t*) &backup_combined_versions,
|
| + sizeof(uint32_t)));
|
| RETURN_ON_FAILURE(SafeWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX,
|
| (uint8_t*) &zero, 0));
|
| }
|
| @@ -302,8 +299,13 @@ uint32_t RollbackFirmwareLock(void) {
|
| }
|
|
|
| uint32_t RollbackKernelRecovery(int developer_mode) {
|
| - uint32_t result = SetupTPM(1, developer_mode);
|
| - if (result == TPM_SUCCESS) {
|
| + (void) SetupTPM(1, developer_mode);
|
| + /* In recovery mode we ignore TPM malfunctions or corruptions, and leave the
|
| + * TPM completely unlocked if and only if the dev mode switch is ON. The
|
| + * recovery kernel will fix the TPM (if needed) and lock it ASAP. We leave
|
| + * Physical Presence on in either case.
|
| + */
|
| + if (!developer_mode) {
|
| RETURN_ON_FAILURE(TlclSetGlobalLock());
|
| }
|
| return TPM_SUCCESS;
|
|
|