| OLD | NEW |
| 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
| 3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
| 4 * | 4 * |
| 5 * Functions for querying, manipulating and locking rollback indices | 5 * Functions for querying, manipulating and locking rollback indices |
| 6 * stored in the TPM NVRAM. | 6 * stored in the TPM NVRAM. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "rollback_index.h" | 9 #include "rollback_index.h" |
| 10 | 10 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 } | 129 } |
| 130 return TPM_SUCCESS; | 130 return TPM_SUCCESS; |
| 131 } | 131 } |
| 132 | 132 |
| 133 /* Checks if the kernel version space has been mucked with. If it has, | 133 /* Checks if the kernel version space has been mucked with. If it has, |
| 134 * reconstructs it using the backup value. | 134 * reconstructs it using the backup value. |
| 135 */ | 135 */ |
| 136 uint32_t RecoverKernelSpace(void) { | 136 uint32_t RecoverKernelSpace(void) { |
| 137 uint32_t perms = 0; | 137 uint32_t perms = 0; |
| 138 uint8_t buffer[KERNEL_SPACE_SIZE]; | 138 uint8_t buffer[KERNEL_SPACE_SIZE]; |
| 139 int read_OK = 0; | |
| 140 int perms_OK = 0; | |
| 141 uint32_t backup_combined_versions; | 139 uint32_t backup_combined_versions; |
| 142 uint32_t must_use_backup; | 140 uint32_t must_use_backup; |
| 141 uint32_t zero = 0; |
| 143 | 142 |
| 144 RETURN_ON_FAILURE(TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX, | 143 RETURN_ON_FAILURE(TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX, |
| 145 (uint8_t*) &must_use_backup, sizeof(uint32_t))); | 144 (uint8_t*) &must_use_backup, sizeof(uint32_t))); |
| 146 /* must_use_backup is true if the previous boot entered recovery mode. */ | 145 /* must_use_backup is true if the previous boot entered recovery mode. */ |
| 147 | 146 |
| 148 read_OK = TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &buffer, | 147 /* If we can't read the kernel space, or it has the wrong permission, or it |
| 149 KERNEL_SPACE_SIZE) == TPM_SUCCESS; | 148 * doesn't contain the right identifier, we give up. This will need to be |
| 150 if (read_OK) { | 149 * fixed by the recovery kernel. We have to worry about this because at any |
| 151 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_VERSIONS_NV_INDEX, &perms)); | 150 * time (even with PP turned off) the TPM owner can remove and redefine a |
| 152 perms_OK = perms == TPM_NV_PER_PPWRITE; | 151 * PP-protected space (but not write to it). |
| 153 } | 152 */ |
| 154 if (!must_use_backup && read_OK && perms_OK && | 153 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &buffer, |
| 154 KERNEL_SPACE_SIZE)); |
| 155 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_VERSIONS_NV_INDEX, &perms)); |
| 156 if (perms != TPM_NV_PER_PPWRITE || |
| 155 !Memcmp(buffer + sizeof(uint32_t), KERNEL_SPACE_UID, | 157 !Memcmp(buffer + sizeof(uint32_t), KERNEL_SPACE_UID, |
| 156 KERNEL_SPACE_UID_SIZE)) { | 158 KERNEL_SPACE_UID_SIZE)) { |
| 157 /* Everything is fine. This is the normal, frequent path. */ | 159 return TPM_E_CORRUPTED_STATE; |
| 158 return TPM_SUCCESS; | |
| 159 } | 160 } |
| 160 | 161 |
| 161 /* Either we detected that something went wrong, or we cannot trust the | |
| 162 * PP-protected kernel space. Attempts to fix. It is not always necessary | |
| 163 * to redefine the space, but we might as well, since this path should be | |
| 164 * taken quite seldom (after recovery mode and after an attack). | |
| 165 */ | |
| 166 RETURN_ON_FAILURE(InitializeKernelVersionsSpaces()); | |
| 167 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, | |
| 168 (uint8_t*) &backup_combined_versions, | |
| 169 sizeof(uint32_t))); | |
| 170 RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX, | |
| 171 (uint8_t*) &backup_combined_versions, | |
| 172 sizeof(uint32_t))); | |
| 173 if (must_use_backup) { | 162 if (must_use_backup) { |
| 174 uint32_t zero = 0; | 163 /* We must use the backup space because in the preceding boot cycle the |
| 164 * primary space was left unlocked and cannot be trusted. |
| 165 */ |
| 166 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, |
| 167 (uint8_t*) &backup_combined_versions, |
| 168 sizeof(uint32_t))); |
| 169 RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX, |
| 170 (uint8_t*) &backup_combined_versions, |
| 171 sizeof(uint32_t))); |
| 175 RETURN_ON_FAILURE(SafeWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX, | 172 RETURN_ON_FAILURE(SafeWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX, |
| 176 (uint8_t*) &zero, 0)); | 173 (uint8_t*) &zero, 0)); |
| 177 } | 174 } |
| 178 return TPM_SUCCESS; | 175 return TPM_SUCCESS; |
| 179 } | 176 } |
| 180 | 177 |
| 181 static uint32_t BackupKernelSpace(void) { | 178 static uint32_t BackupKernelSpace(void) { |
| 182 uint32_t kernel_versions; | 179 uint32_t kernel_versions; |
| 183 uint32_t backup_versions; | 180 uint32_t backup_versions; |
| 184 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, | 181 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 return SafeWrite(FIRMWARE_VERSIONS_NV_INDEX, | 292 return SafeWrite(FIRMWARE_VERSIONS_NV_INDEX, |
| 296 (uint8_t*) &combined_version, | 293 (uint8_t*) &combined_version, |
| 297 sizeof(uint32_t)); | 294 sizeof(uint32_t)); |
| 298 } | 295 } |
| 299 | 296 |
| 300 uint32_t RollbackFirmwareLock(void) { | 297 uint32_t RollbackFirmwareLock(void) { |
| 301 return TlclSetGlobalLock(); | 298 return TlclSetGlobalLock(); |
| 302 } | 299 } |
| 303 | 300 |
| 304 uint32_t RollbackKernelRecovery(int developer_mode) { | 301 uint32_t RollbackKernelRecovery(int developer_mode) { |
| 305 uint32_t result = SetupTPM(1, developer_mode); | 302 (void) SetupTPM(1, developer_mode); |
| 306 if (result == TPM_SUCCESS) { | 303 /* In recovery mode we ignore TPM malfunctions or corruptions, and leave the |
| 304 * TPM completely unlocked if and only if the dev mode switch is ON. The |
| 305 * recovery kernel will fix the TPM (if needed) and lock it ASAP. We leave |
| 306 * Physical Presence on in either case. |
| 307 */ |
| 308 if (!developer_mode) { |
| 307 RETURN_ON_FAILURE(TlclSetGlobalLock()); | 309 RETURN_ON_FAILURE(TlclSetGlobalLock()); |
| 308 } | 310 } |
| 309 return TPM_SUCCESS; | 311 return TPM_SUCCESS; |
| 310 } | 312 } |
| 311 | 313 |
| 312 uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version) { | 314 uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version) { |
| 313 uint32_t kernel_versions; | 315 uint32_t kernel_versions; |
| 314 if (g_rollback_recovery_mode) { | 316 if (g_rollback_recovery_mode) { |
| 315 *key_version = 0; | 317 *key_version = 0; |
| 316 *version = 0; | 318 *version = 0; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 335 return TPM_SUCCESS; | 337 return TPM_SUCCESS; |
| 336 } | 338 } |
| 337 | 339 |
| 338 uint32_t RollbackKernelLock(void) { | 340 uint32_t RollbackKernelLock(void) { |
| 339 if (!g_rollback_recovery_mode) { | 341 if (!g_rollback_recovery_mode) { |
| 340 return TlclLockPhysicalPresence(); | 342 return TlclLockPhysicalPresence(); |
| 341 } else { | 343 } else { |
| 342 return TPM_SUCCESS; | 344 return TPM_SUCCESS; |
| 343 } | 345 } |
| 344 } | 346 } |
| OLD | NEW |