| 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 #ifndef DISABLE_ROLLBACK_TPM | 91 #ifndef DISABLE_ROLLBACK_TPM |
| 92 static uint32_t ReadSpaceKernel(RollbackSpaceKernel* rsk) { | 92 static uint32_t ReadSpaceKernel(RollbackSpaceKernel* rsk) { |
| 93 return TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel)); | 93 return TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel)); |
| 94 } | 94 } |
| 95 #endif | 95 #endif |
| 96 | 96 |
| 97 static uint32_t WriteSpaceKernel(const RollbackSpaceKernel* rsk) { | 97 static uint32_t WriteSpaceKernel(const RollbackSpaceKernel* rsk) { |
| 98 return SafeWrite(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel)); | 98 return SafeWrite(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel)); |
| 99 } | 99 } |
| 100 | 100 |
| 101 /* Creates the NVRAM spaces, and sets their initial values as needed. */ | 101 /* Performs one-time initializations. Creates the NVRAM spaces, and sets their |
| 102 static uint32_t InitializeSpaces(RollbackSpaceFirmware* rsf, | 102 * initial values as needed. Sets the nvLocked bit and ensures the physical |
| 103 RollbackSpaceKernel* rsk) { | 103 * presence command is enabled and locked. |
| 104 */ |
| 105 static uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware* rsf, |
| 106 RollbackSpaceKernel* rsk) { |
| 104 static const RollbackSpaceFirmware rsf_init = { | 107 static const RollbackSpaceFirmware rsf_init = { |
| 105 ROLLBACK_SPACE_FIRMWARE_VERSION, 0, 0, 0}; | 108 ROLLBACK_SPACE_FIRMWARE_VERSION, 0, 0, 0}; |
| 106 static const RollbackSpaceKernel rsk_init = { | 109 static const RollbackSpaceKernel rsk_init = { |
| 107 ROLLBACK_SPACE_KERNEL_VERSION, ROLLBACK_SPACE_KERNEL_UID, 0, 0}; | 110 ROLLBACK_SPACE_KERNEL_VERSION, ROLLBACK_SPACE_KERNEL_UID, 0, 0}; |
| 108 uint8_t nvlocked = 0; | 111 uint8_t nvlocked = 0; |
| 109 | 112 |
| 110 VBDEBUG(("TPM: Initializing spaces\n")); | 113 VBDEBUG(("TPM: One-time initialization\n")); |
| 114 |
| 115 RETURN_ON_FAILURE(TlclFinalizePhysicalPresence()); |
| 111 | 116 |
| 112 /* The TPM will not enforce the NV authorization restrictions until the | 117 /* The TPM will not enforce the NV authorization restrictions until the |
| 113 * execution of a TPM_NV_DefineSpace with the handle of TPM_NV_INDEX_LOCK. | 118 * execution of a TPM_NV_DefineSpace with the handle of TPM_NV_INDEX_LOCK. |
| 114 * Create that space if it doesn't already exist. */ | 119 * Here we create that space if it doesn't already exist. */ |
| 115 RETURN_ON_FAILURE(TlclGetFlags(NULL, NULL, &nvlocked)); | 120 RETURN_ON_FAILURE(TlclGetFlags(NULL, NULL, &nvlocked)); |
| 116 VBDEBUG(("TPM: nvlocked=%d\n", nvlocked)); | 121 VBDEBUG(("TPM: nvlocked=%d\n", nvlocked)); |
| 117 if (!nvlocked) { | 122 if (!nvlocked) { |
| 118 VBDEBUG(("TPM: Enabling NV locking\n")); | 123 VBDEBUG(("TPM: Enabling NV locking\n")); |
| 119 RETURN_ON_FAILURE(TlclSetNvLocked()); | 124 RETURN_ON_FAILURE(TlclSetNvLocked()); |
| 120 } | 125 } |
| 121 | 126 |
| 122 /* Initialize the firmware and kernel spaces */ | 127 /* Initializes the firmware and kernel spaces */ |
| 123 Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware)); | 128 Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware)); |
| 124 Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel)); | 129 Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel)); |
| 125 | 130 |
| 126 /* Define and set firmware and kernel spaces */ | 131 /* Defines and sets firmware and kernel spaces */ |
| 127 RETURN_ON_FAILURE(SafeDefineSpace(FIRMWARE_NV_INDEX, | 132 RETURN_ON_FAILURE(SafeDefineSpace(FIRMWARE_NV_INDEX, |
| 128 TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE, | 133 TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE, |
| 129 sizeof(RollbackSpaceFirmware))); | 134 sizeof(RollbackSpaceFirmware))); |
| 130 RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); | 135 RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); |
| 131 RETURN_ON_FAILURE(SafeDefineSpace(KERNEL_NV_INDEX, TPM_NV_PER_PPWRITE, | 136 RETURN_ON_FAILURE(SafeDefineSpace(KERNEL_NV_INDEX, TPM_NV_PER_PPWRITE, |
| 132 sizeof(RollbackSpaceKernel))); | 137 sizeof(RollbackSpaceKernel))); |
| 133 RETURN_ON_FAILURE(WriteSpaceKernel(rsk)); | 138 RETURN_ON_FAILURE(WriteSpaceKernel(rsk)); |
| 134 return TPM_SUCCESS; | 139 return TPM_SUCCESS; |
| 135 } | 140 } |
| 136 | 141 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 | 175 |
| 171 RETURN_ON_FAILURE(TlclStartup()); | 176 RETURN_ON_FAILURE(TlclStartup()); |
| 172 #ifdef USE_CONTINUE_SELF_TEST | 177 #ifdef USE_CONTINUE_SELF_TEST |
| 173 /* TODO: ContinueSelfTest() should be faster than SelfTestFull, but | 178 /* TODO: ContinueSelfTest() should be faster than SelfTestFull, but |
| 174 * may also not work properly in older TPM firmware. For now, do | 179 * may also not work properly in older TPM firmware. For now, do |
| 175 * the full self test. */ | 180 * the full self test. */ |
| 176 RETURN_ON_FAILURE(TlclContinueSelfTest()); | 181 RETURN_ON_FAILURE(TlclContinueSelfTest()); |
| 177 #else | 182 #else |
| 178 RETURN_ON_FAILURE(TlclSelfTestFull()); | 183 RETURN_ON_FAILURE(TlclSelfTestFull()); |
| 179 #endif | 184 #endif |
| 180 RETURN_ON_FAILURE(TlclAssertPhysicalPresence()); | 185 result = TlclAssertPhysicalPresence(); |
| 186 if (result != 0) { |
| 187 /* It is possible that the TPM was delivered with the physical presence |
| 188 * command disabled. This tries enabling it, then tries asserting PP |
| 189 * again. |
| 190 */ |
| 191 RETURN_ON_FAILURE(TlclPhysicalPresenceCMDEnable()); |
| 192 RETURN_ON_FAILURE(TlclAssertPhysicalPresence()); |
| 193 } |
| 181 | 194 |
| 182 /* Check that the TPM is enabled and activated. */ | 195 /* Checks that the TPM is enabled and activated. */ |
| 183 RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated, NULL)); | 196 RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated, NULL)); |
| 184 if (disable || deactivated) { | 197 if (disable || deactivated) { |
| 185 VBDEBUG(("TPM: disabled (%d) or deactivated (%d). Fixing...\n", | 198 VBDEBUG(("TPM: disabled (%d) or deactivated (%d). Fixing...\n", |
| 186 disable, deactivated)); | 199 disable, deactivated)); |
| 187 RETURN_ON_FAILURE(TlclSetEnable()); | 200 RETURN_ON_FAILURE(TlclSetEnable()); |
| 188 RETURN_ON_FAILURE(TlclSetDeactivated(0)); | 201 RETURN_ON_FAILURE(TlclSetDeactivated(0)); |
| 189 VBDEBUG(("TPM: Must reboot to re-enable\n")); | 202 VBDEBUG(("TPM: Must reboot to re-enable\n")); |
| 190 return TPM_E_MUST_REBOOT; | 203 return TPM_E_MUST_REBOOT; |
| 191 } | 204 } |
| 192 | 205 |
| 193 /* Read the firmware space. */ | 206 /* Reads the firmware space. */ |
| 194 result = ReadSpaceFirmware(rsf); | 207 result = ReadSpaceFirmware(rsf); |
| 195 if (TPM_E_BADINDEX == result) { | 208 if (TPM_E_BADINDEX == result) { |
| 196 RollbackSpaceKernel rsk; | 209 RollbackSpaceKernel rsk; |
| 197 | 210 |
| 198 /* This is the first time we've run, and the TPM has not been | 211 /* This is the first time we've run, and the TPM has not been |
| 199 * initialized. Initialize it. */ | 212 * initialized. This initializes it. */ |
| 200 VBDEBUG(("TPM: Not initialized yet.\n")); | 213 VBDEBUG(("TPM: Not initialized yet.\n")); |
| 201 RETURN_ON_FAILURE(InitializeSpaces(rsf, &rsk)); | 214 RETURN_ON_FAILURE(OneTimeInitializeTPM(rsf, &rsk)); |
| 202 } else if (TPM_SUCCESS != result) { | 215 } else if (TPM_SUCCESS != result) { |
| 203 VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n")); | 216 VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n")); |
| 204 return TPM_E_CORRUPTED_STATE; | 217 return TPM_E_CORRUPTED_STATE; |
| 205 } | 218 } |
| 206 VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n", | 219 VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n", |
| 207 rsf->struct_version, rsf->flags, rsf->fw_versions)); | 220 rsf->struct_version, rsf->flags, rsf->fw_versions)); |
| 208 | 221 |
| 209 /* Clear ownership if developer flag has toggled */ | 222 /* Clears ownership if developer flag has toggled */ |
| 210 if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) != | 223 if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) != |
| 211 (rsf->flags & FLAG_LAST_BOOT_DEVELOPER)) { | 224 (rsf->flags & FLAG_LAST_BOOT_DEVELOPER)) { |
| 212 VBDEBUG(("TPM: Developer flag changed; clearing owner.\n")); | 225 VBDEBUG(("TPM: Developer flag changed; clearing owner.\n")); |
| 213 RETURN_ON_FAILURE(TPMClearAndReenable()); | 226 RETURN_ON_FAILURE(TPMClearAndReenable()); |
| 214 } | 227 } |
| 215 | 228 |
| 216 /* Update flags */ | 229 /* Updates flags */ |
| 217 if (developer_mode) | 230 if (developer_mode) |
| 218 new_flags |= FLAG_LAST_BOOT_DEVELOPER; | 231 new_flags |= FLAG_LAST_BOOT_DEVELOPER; |
| 219 if (recovery_mode) | 232 if (recovery_mode) |
| 220 g_rollback_recovery_mode = 1; /* Global variables are usable in | 233 g_rollback_recovery_mode = 1; /* Global variables are usable in |
| 221 * recovery mode */ | 234 * recovery mode */ |
| 222 | 235 |
| 223 if (rsf->flags != new_flags) { | 236 if (rsf->flags != new_flags) { |
| 224 rsf->flags = new_flags; | 237 rsf->flags = new_flags; |
| 225 rsf_dirty = 1; | 238 rsf_dirty = 1; |
| 226 } | 239 } |
| 227 | 240 |
| 228 /* If firmware space is dirty, flush it back to the TPM */ | 241 /* If firmware space is dirty, this flushes it back to the TPM */ |
| 229 if (rsf_dirty) { | 242 if (rsf_dirty) { |
| 230 VBDEBUG(("TPM: Updating firmware space.\n")); | 243 VBDEBUG(("TPM: Updating firmware space.\n")); |
| 231 RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); | 244 RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); |
| 232 } | 245 } |
| 233 | 246 |
| 234 VBDEBUG(("TPM: SetupTPM() succeeded\n")); | 247 VBDEBUG(("TPM: SetupTPM() succeeded\n")); |
| 235 return TPM_SUCCESS; | 248 return TPM_SUCCESS; |
| 236 } | 249 } |
| 237 | 250 |
| 238 /* disable MSVC warnings on unused arguments */ | 251 /* disable MSVC warnings on unused arguments */ |
| 239 __pragma(warning (disable: 4100)) | 252 __pragma(warning (disable: 4100)) |
| 240 | 253 |
| 241 | 254 |
| 242 #ifdef DISABLE_ROLLBACK_TPM | 255 #ifdef DISABLE_ROLLBACK_TPM |
| 243 | 256 |
| 244 /* Dummy implementations which don't support TPM rollback protection */ | 257 /* Dummy implementations which don't support TPM rollback protection */ |
| 245 | 258 |
| 246 uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) { | 259 uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) { |
| 247 #ifndef CHROMEOS_ENVIRONMENT | 260 #ifndef CHROMEOS_ENVIRONMENT |
| 248 /* Initialize the TPM, but ignore return codes. In ChromeOS | 261 /* Initializes the TPM, but ignores return codes. In ChromeOS |
| 249 * environment, don't even talk to the TPM. */ | 262 * environment, doesn't even talk to the TPM. */ |
| 250 TlclLibInit(); | 263 TlclLibInit(); |
| 251 TlclStartup(); | 264 TlclStartup(); |
| 252 TlclSelfTestFull(); | 265 TlclSelfTestFull(); |
| 253 #endif | 266 #endif |
| 254 | 267 |
| 255 *version = 0; | 268 *version = 0; |
| 256 return TPM_SUCCESS; | 269 return TPM_SUCCESS; |
| 257 } | 270 } |
| 258 | 271 |
| 259 uint32_t RollbackFirmwareWrite(uint32_t version) { | 272 uint32_t RollbackFirmwareWrite(uint32_t version) { |
| 260 return TPM_SUCCESS; | 273 return TPM_SUCCESS; |
| 261 } | 274 } |
| 262 | 275 |
| 263 uint32_t RollbackFirmwareLock(void) { | 276 uint32_t RollbackFirmwareLock(void) { |
| 264 return TPM_SUCCESS; | 277 return TPM_SUCCESS; |
| 265 } | 278 } |
| 266 | 279 |
| 267 uint32_t RollbackKernelRecovery(int developer_mode) { | 280 uint32_t RollbackKernelRecovery(int developer_mode) { |
| 268 #ifndef CHROMEOS_ENVIRONMENT | 281 #ifndef CHROMEOS_ENVIRONMENT |
| 269 /* Initialize the TPM, but ignore return codes. In ChromeOS | 282 /* Initializes the TPM, but ignore return codes. In ChromeOS |
| 270 * environment, don't even talk to the TPM. */ | 283 * environment, doesn't even talk to the TPM. */ |
| 271 TlclLibInit(); | 284 TlclLibInit(); |
| 272 TlclStartup(); | 285 TlclStartup(); |
| 273 TlclSelfTestFull(); | 286 TlclSelfTestFull(); |
| 274 #endif | 287 #endif |
| 275 return TPM_SUCCESS; | 288 return TPM_SUCCESS; |
| 276 } | 289 } |
| 277 | 290 |
| 278 uint32_t RollbackKernelRead(uint32_t* version) { | 291 uint32_t RollbackKernelRead(uint32_t* version) { |
| 279 *version = 0; | 292 *version = 0; |
| 280 return TPM_SUCCESS; | 293 return TPM_SUCCESS; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 | 389 |
| 377 uint32_t RollbackKernelLock(void) { | 390 uint32_t RollbackKernelLock(void) { |
| 378 if (g_rollback_recovery_mode) { | 391 if (g_rollback_recovery_mode) { |
| 379 return TPM_SUCCESS; | 392 return TPM_SUCCESS; |
| 380 } else { | 393 } else { |
| 381 return TlclLockPhysicalPresence(); | 394 return TlclLockPhysicalPresence(); |
| 382 } | 395 } |
| 383 } | 396 } |
| 384 | 397 |
| 385 #endif // DISABLE_ROLLBACK_TPM | 398 #endif // DISABLE_ROLLBACK_TPM |
| OLD | NEW |