Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: firmware/lib/rollback_index.c

Issue 3041005: Add lots of debugging to TPM library. (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Fix TPM unit tests Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « firmware/lib/include/rollback_index.h ('k') | firmware/lib/tpm_lite/include/tlcl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 #include "tlcl.h" 11 #include "tlcl.h"
12 #include "tss_constants.h" 12 #include "tss_constants.h"
13 #include "utility.h" 13 #include "utility.h"
14 14
15 static int g_rollback_recovery_mode = 0; 15 static int g_rollback_recovery_mode = 0;
16 16
17 /* disable MSVC warning on const logical expression (as in } while(0);) */ 17 /* disable MSVC warning on const logical expression (as in } while(0);) */
18 __pragma(warning (disable: 4127)) 18 __pragma(warning (disable: 4127))
19 19
20 #define RETURN_ON_FAILURE(tpm_command) do { \ 20 #define RETURN_ON_FAILURE(tpm_command) do { \
21 uint32_t result; \ 21 uint32_t result; \
22 if ((result = (tpm_command)) != TPM_SUCCESS) { \ 22 if ((result = (tpm_command)) != TPM_SUCCESS) { \
23 VBDEBUG(("Rollback: %08x returned by " #tpm_command "\n", (int)result)); \ 23 VBDEBUG(("Rollback: %08x returned by " #tpm_command "\n", (int)result)); \
24 return result; \ 24 return result; \
25 } \ 25 } \
26 } while (0) 26 } while (0)
27 27
28 uint32_t TPMClearAndReenable(void) { 28 uint32_t TPMClearAndReenable(void) {
29 VBDEBUG(("TPM: Clear and re-enable\n"));
29 RETURN_ON_FAILURE(TlclForceClear()); 30 RETURN_ON_FAILURE(TlclForceClear());
30 RETURN_ON_FAILURE(TlclSetEnable()); 31 RETURN_ON_FAILURE(TlclSetEnable());
31 RETURN_ON_FAILURE(TlclSetDeactivated(0)); 32 RETURN_ON_FAILURE(TlclSetDeactivated(0));
33
32 return TPM_SUCCESS; 34 return TPM_SUCCESS;
33 } 35 }
34 36
35 /* Like TlclWrite(), but checks for write errors due to hitting the 64-write 37 /* Like TlclWrite(), but checks for write errors due to hitting the 64-write
36 * limit and clears the TPM when that happens. This can only happen when the 38 * limit and clears the TPM when that happens. This can only happen when the
37 * TPM is unowned, so it is OK to clear it (and we really have no choice). 39 * TPM is unowned, so it is OK to clear it (and we really have no choice).
38 * This is not expected to happen frequently, but it could happen. 40 * This is not expected to happen frequently, but it could happen.
39 */ 41 */
40 static uint32_t SafeWrite(uint32_t index, uint8_t* data, uint32_t length) { 42 static uint32_t SafeWrite(uint32_t index, uint8_t* data, uint32_t length) {
41 uint32_t result = TlclWrite(index, data, length); 43 uint32_t result = TlclWrite(index, data, length);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 break; 91 break;
90 } 92 }
91 return result; 93 return result;
92 } 94 }
93 95
94 /* Creates the NVRAM spaces, and sets their initial values as needed. 96 /* Creates the NVRAM spaces, and sets their initial values as needed.
95 */ 97 */
96 static uint32_t InitializeSpaces(void) { 98 static uint32_t InitializeSpaces(void) {
97 uint32_t zero = 0; 99 uint32_t zero = 0;
98 uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE; 100 uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE;
101 uint8_t nvlocked = 0;
102 uint32_t i;
99 103
100 VBDEBUG(("Initializing spaces\n")); 104 VBDEBUG(("TPM: Initializing spaces\n"));
101 105
102 RETURN_ON_FAILURE(TlclSetNvLocked()); 106 #ifdef FORCE_CLEAR_ON_INIT
107 /* Force the TPM clear, in case it previously had an owner, so that we can
108 * redefine the NVRAM spaces. */
109 RETURN_ON_FAILURE(TPMClearAndReenable());
110 #endif
111
112 /* 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.
114 * Create that space if it doesn't already exist. */
115 RETURN_ON_FAILURE(TlclGetFlags(NULL, NULL, &nvlocked));
116 VBDEBUG(("TPM: nvlocked=%d\n", nvlocked));
117 if (!nvlocked) {
118 VBDEBUG(("TPM: Enabling NV locking\n"));
119 RETURN_ON_FAILURE(TlclSetNvLocked());
120 }
121
122 /* If the spaces were previously defined, we need to undefine them before we
123 * can redefine them. Undefine by setting size=0. Ignore these return codes,
124 * since they fail if the spaces aren't actually defined? */
125 for (i = FIRST_ROLLBACK_NV_INDEX; i <= LAST_ROLLBACK_NV_INDEX; i++)
126 SafeDefineSpace(i, firmware_perm, 0);
103 127
104 RETURN_ON_FAILURE(SafeDefineSpace(FIRMWARE_VERSIONS_NV_INDEX, 128 RETURN_ON_FAILURE(SafeDefineSpace(FIRMWARE_VERSIONS_NV_INDEX,
105 firmware_perm, sizeof(uint32_t))); 129 firmware_perm, sizeof(uint32_t)));
106 RETURN_ON_FAILURE(SafeWrite(FIRMWARE_VERSIONS_NV_INDEX, 130 RETURN_ON_FAILURE(SafeWrite(FIRMWARE_VERSIONS_NV_INDEX,
107 (uint8_t*) &zero, sizeof(uint32_t))); 131 (uint8_t*) &zero, sizeof(uint32_t)));
108 132
109 RETURN_ON_FAILURE(InitializeKernelVersionsSpaces()); 133 RETURN_ON_FAILURE(InitializeKernelVersionsSpaces());
110 134
111 /* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel 135 /* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel
112 * versions. The content of space KERNEL_MUST_USE_BACKUP determines whether 136 * versions. The content of space KERNEL_MUST_USE_BACKUP determines whether
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 /* Checks if the kernel version space has been mucked with. If it has, 173 /* Checks if the kernel version space has been mucked with. If it has,
150 * reconstructs it using the backup value. 174 * reconstructs it using the backup value.
151 */ 175 */
152 uint32_t RecoverKernelSpace(void) { 176 uint32_t RecoverKernelSpace(void) {
153 uint32_t perms = 0; 177 uint32_t perms = 0;
154 uint8_t buffer[KERNEL_SPACE_SIZE]; 178 uint8_t buffer[KERNEL_SPACE_SIZE];
155 uint32_t backup_combined_versions; 179 uint32_t backup_combined_versions;
156 uint32_t must_use_backup; 180 uint32_t must_use_backup;
157 uint32_t zero = 0; 181 uint32_t zero = 0;
158 182
183 VBDEBUG(("TPM: RecoverKernelSpace()\n"));
184
159 RETURN_ON_FAILURE(TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX, 185 RETURN_ON_FAILURE(TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX,
160 (uint8_t*) &must_use_backup, sizeof(uint32_t))); 186 (uint8_t*) &must_use_backup, sizeof(uint32_t)));
161 /* must_use_backup is true if the previous boot entered recovery mode. */ 187 /* must_use_backup is true if the previous boot entered recovery mode. */
162 188
189 VBDEBUG(("TPM: must_use_backup = %d\n", must_use_backup));
190
163 /* If we can't read the kernel space, or it has the wrong permission, or it 191 /* If we can't read the kernel space, or it has the wrong permission, or it
164 * doesn't contain the right identifier, we give up. This will need to be 192 * doesn't contain the right identifier, we give up. This will need to be
165 * fixed by the recovery kernel. We have to worry about this because at any 193 * fixed by the recovery kernel. We have to worry about this because at any
166 * time (even with PP turned off) the TPM owner can remove and redefine a 194 * time (even with PP turned off) the TPM owner can remove and redefine a
167 * PP-protected space (but not write to it). 195 * PP-protected space (but not write to it).
168 */ 196 */
169 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &buffer, 197 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &buffer,
170 KERNEL_SPACE_SIZE)); 198 KERNEL_SPACE_SIZE));
171 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_VERSIONS_NV_INDEX, &perms)); 199 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_VERSIONS_NV_INDEX, &perms));
172 if (perms != TPM_NV_PER_PPWRITE || 200 if (perms != TPM_NV_PER_PPWRITE ||
(...skipping 14 matching lines...) Expand all
187 sizeof(uint32_t))); 215 sizeof(uint32_t)));
188 RETURN_ON_FAILURE(SafeWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX, 216 RETURN_ON_FAILURE(SafeWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX,
189 (uint8_t*) &zero, 0)); 217 (uint8_t*) &zero, 0));
190 } 218 }
191 return TPM_SUCCESS; 219 return TPM_SUCCESS;
192 } 220 }
193 221
194 static uint32_t BackupKernelSpace(void) { 222 static uint32_t BackupKernelSpace(void) {
195 uint32_t kernel_versions; 223 uint32_t kernel_versions;
196 uint32_t backup_versions; 224 uint32_t backup_versions;
225 VBDEBUG(("TPM: BackupKernelSpace()\n"));
197 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, 226 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX,
198 (uint8_t*) &kernel_versions, sizeof(uint32_t))); 227 (uint8_t*) &kernel_versions, sizeof(uint32_t)));
199 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, 228 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX,
200 (uint8_t*) &backup_versions, sizeof(uint32_t))); 229 (uint8_t*) &backup_versions, sizeof(uint32_t)));
201 if (kernel_versions == backup_versions) { 230 if (kernel_versions == backup_versions) {
202 return TPM_SUCCESS; 231 return TPM_SUCCESS;
203 } else if (kernel_versions < backup_versions) { 232 } else if (kernel_versions < backup_versions) {
204 /* This cannot happen. We're screwed. */ 233 /* This cannot happen. We're screwed. */
205 return TPM_E_INTERNAL_INCONSISTENCY; 234 return TPM_E_INTERNAL_INCONSISTENCY;
206 } 235 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 * As a side note, observe that we go through considerable hoops to avoid using 272 * As a side note, observe that we go through considerable hoops to avoid using
244 * the STCLEAR permissions for the index spaces. We do this to avoid writing 273 * the STCLEAR permissions for the index spaces. We do this to avoid writing
245 * to the TPM flashram at every reboot or wake-up, because of concerns about 274 * to the TPM flashram at every reboot or wake-up, because of concerns about
246 * the durability of the NVRAM. 275 * the durability of the NVRAM.
247 */ 276 */
248 uint32_t SetupTPM(int recovery_mode, int developer_mode) { 277 uint32_t SetupTPM(int recovery_mode, int developer_mode) {
249 uint8_t disable; 278 uint8_t disable;
250 uint8_t deactivated; 279 uint8_t deactivated;
251 uint32_t result; 280 uint32_t result;
252 281
282 VBDEBUG(("TPM: SetupTPM(r%d, d%d)\n", recovery_mode, developer_mode));
283
284 /* TODO: TlclLibInit() should be able to return failure */
253 TlclLibInit(); 285 TlclLibInit();
286
254 RETURN_ON_FAILURE(TlclStartup()); 287 RETURN_ON_FAILURE(TlclStartup());
288 #ifdef USE_CONTINUE_SELF_TEST
289 /* TODO: ContinueSelfTest() should be faster than SelfTestFull, but may also
290 * not work properly in older TPM firmware. For now, do the full self test. * /
255 RETURN_ON_FAILURE(TlclContinueSelfTest()); 291 RETURN_ON_FAILURE(TlclContinueSelfTest());
292 #else
293 RETURN_ON_FAILURE(TlclSelfTestFull());
294 #endif
256 RETURN_ON_FAILURE(TlclAssertPhysicalPresence()); 295 RETURN_ON_FAILURE(TlclAssertPhysicalPresence());
257 /* Checks that the TPM is enabled and activated. */ 296 /* Checks that the TPM is enabled and activated. */
258 RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated)); 297 RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated, NULL));
259 if (disable || deactivated) { 298 if (disable || deactivated) {
299 VBDEBUG(("TPM: disabled (%d) or deactivated (%d). Fixing...\n", disable, de activated));
260 RETURN_ON_FAILURE(TlclSetEnable()); 300 RETURN_ON_FAILURE(TlclSetEnable());
261 RETURN_ON_FAILURE(TlclSetDeactivated(0)); 301 RETURN_ON_FAILURE(TlclSetDeactivated(0));
302 VBDEBUG(("TPM: Must reboot to re-enable\n"));
262 return TPM_E_MUST_REBOOT; 303 return TPM_E_MUST_REBOOT;
263 } 304 }
264 result = RecoverKernelSpace(); 305 result = RecoverKernelSpace();
265 if (result != TPM_SUCCESS) { 306 if (result != TPM_SUCCESS) {
266 /* Check if this is the first time we run and the TPM has not been 307 /* Check if this is the first time we run and the TPM has not been
267 * initialized yet. 308 * initialized yet.
268 */ 309 */
269 int initialized = 0; 310 int initialized = 0;
311 VBDEBUG(("TPM: RecoverKernelSpace() failed\n"));
270 RETURN_ON_FAILURE(GetSpacesInitialized(&initialized)); 312 RETURN_ON_FAILURE(GetSpacesInitialized(&initialized));
271 if (initialized) { 313 if (initialized) {
314 VBDEBUG(("TPM: Already initialized, so give up\n"));
272 return result; 315 return result;
273 } else { 316 } else {
317 VBDEBUG(("TPM: Need to initialize spaces.\n"));
274 RETURN_ON_FAILURE(InitializeSpaces()); 318 RETURN_ON_FAILURE(InitializeSpaces());
319 VBDEBUG(("TPM: Retrying RecoverKernelSpace() now that spaces are initializ ed.\n"));
275 RETURN_ON_FAILURE(RecoverKernelSpace()); 320 RETURN_ON_FAILURE(RecoverKernelSpace());
276 } 321 }
277 } 322 }
278 RETURN_ON_FAILURE(BackupKernelSpace()); 323 RETURN_ON_FAILURE(BackupKernelSpace());
279 RETURN_ON_FAILURE(SetDistrustKernelSpaceAtNextBoot(recovery_mode)); 324 RETURN_ON_FAILURE(SetDistrustKernelSpaceAtNextBoot(recovery_mode));
280 RETURN_ON_FAILURE(CheckDeveloperModeTransition(developer_mode)); 325 RETURN_ON_FAILURE(CheckDeveloperModeTransition(developer_mode));
281 326
282 if (recovery_mode) { 327 if (recovery_mode) {
283 /* In recovery mode global variables are usable. */ 328 /* In recovery mode global variables are usable. */
284 g_rollback_recovery_mode = 1; 329 g_rollback_recovery_mode = 1;
285 } 330 }
331 VBDEBUG(("TPM: SetupTPM() succeeded\n"));
286 return TPM_SUCCESS; 332 return TPM_SUCCESS;
287 } 333 }
288 334
289 /* disable MSVC warnings on unused arguments */ 335 /* disable MSVC warnings on unused arguments */
290 __pragma(warning (disable: 4100)) 336 __pragma(warning (disable: 4100))
291 337
292 338
293 #ifdef DISABLE_ROLLBACK_TPM 339 #ifdef DISABLE_ROLLBACK_TPM
294 340
295 /* Dummy implementations which don't call into the tpm_lite library */ 341 /* Dummy implementations which don't call into the tpm_lite library */
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 446
401 uint32_t RollbackKernelLock(void) { 447 uint32_t RollbackKernelLock(void) {
402 if (!g_rollback_recovery_mode) { 448 if (!g_rollback_recovery_mode) {
403 return TlclLockPhysicalPresence(); 449 return TlclLockPhysicalPresence();
404 } else { 450 } else {
405 return TPM_SUCCESS; 451 return TPM_SUCCESS;
406 } 452 }
407 } 453 }
408 454
409 #endif // DISABLE_ROLLBACK_TPM 455 #endif // DISABLE_ROLLBACK_TPM
OLDNEW
« no previous file with comments | « firmware/lib/include/rollback_index.h ('k') | firmware/lib/tpm_lite/include/tlcl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698