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 |