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

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

Issue 2859016: Simplify ForceClear situations (Closed) Base URL: ssh://git@chromiumos-git/vboot_reference.git
Patch Set: Remove blank line Created 10 years, 6 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 | « no previous file | no next file » | 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 uint16_t g_firmware_key_version = 0; 15 uint16_t g_firmware_key_version = 0;
16 uint16_t g_firmware_version = 0; 16 uint16_t g_firmware_version = 0;
17 uint16_t g_kernel_key_version = 0; 17 uint16_t g_kernel_key_version = 0;
18 uint16_t g_kernel_version = 0; 18 uint16_t g_kernel_version = 0;
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 return result; \ 23 return result; \
24 } \ 24 } \
25 } while (0) 25 } while (0)
26 26
27 static uint32_t TPMClearAndReenable() {
28 RETURN_ON_FAILURE(TlclForceClear());
29 RETURN_ON_FAILURE(TlclSetEnable());
30 RETURN_ON_FAILURE(TlclSetDeactivated(0));
31 return TPM_SUCCESS;
32 }
33
34 /* Like TlclWrite(), but checks for write errors due to hitting the 64-write
35 * limit and clears the TPM when that happens. This can only happen when the
36 * TPM is unowned, so it is OK to clear it (and we really have no choice).
37 * This is not expected to happen frequently, but it could happen.
38 */
39 static uint32_t SafeWrite(uint32_t index, uint8_t* data, uint32_t length) {
40 uint32_t result = TlclWrite(index, data, length);
41 if (result == TPM_E_MAXNVWRITES) {
42 RETURN_ON_FAILURE(TPMClearAndReenable());
43 return TlclWrite(index, data, length);
44 } else {
45 return result;
46 }
47 }
48
27 static uint32_t InitializeKernelVersionsSpaces(void) { 49 static uint32_t InitializeKernelVersionsSpaces(void) {
28 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX, 50 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX,
29 TPM_NV_PER_PPWRITE, KERNEL_SPACE_SIZE)); 51 TPM_NV_PER_PPWRITE, KERNEL_SPACE_SIZE));
30 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX, KERNEL_SPACE_INIT_DATA, 52 RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX, KERNEL_SPACE_INIT_DATA,
31 KERNEL_SPACE_SIZE)); 53 KERNEL_SPACE_SIZE));
32 return TPM_SUCCESS; 54 return TPM_SUCCESS;
33 } 55 }
34 56
35 /* When the return value is TPM_SUCCESS, this function sets *|initialized| to 1 57 /* When the return value is TPM_SUCCESS, this function sets *|initialized| to 1
36 * if the spaces have been fully initialized, to 0 if not. Otherwise 58 * if the spaces have been fully initialized, to 0 if not. Otherwise
37 * *|initialized| is not changed. 59 * *|initialized| is not changed.
38 */ 60 */
39 static uint32_t GetSpacesInitialized(int* initialized) { 61 static uint32_t GetSpacesInitialized(int* initialized) {
40 uint32_t space_holder; 62 uint32_t space_holder;
(...skipping 17 matching lines...) Expand all
58 static uint32_t InitializeSpaces(void) { 80 static uint32_t InitializeSpaces(void) {
59 uint32_t zero = 0; 81 uint32_t zero = 0;
60 uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE; 82 uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE;
61 83
62 debug("Initializing spaces\n"); 84 debug("Initializing spaces\n");
63 85
64 RETURN_ON_FAILURE(TlclSetNvLocked()); 86 RETURN_ON_FAILURE(TlclSetNvLocked());
65 87
66 RETURN_ON_FAILURE(TlclDefineSpace(FIRMWARE_VERSIONS_NV_INDEX, 88 RETURN_ON_FAILURE(TlclDefineSpace(FIRMWARE_VERSIONS_NV_INDEX,
67 firmware_perm, sizeof(uint32_t))); 89 firmware_perm, sizeof(uint32_t)));
68 RETURN_ON_FAILURE(TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, 90 RETURN_ON_FAILURE(SafeWrite(FIRMWARE_VERSIONS_NV_INDEX,
69 (uint8_t*) &zero, sizeof(uint32_t))); 91 (uint8_t*) &zero, sizeof(uint32_t)));
70 92
71 RETURN_ON_FAILURE(InitializeKernelVersionsSpaces()); 93 RETURN_ON_FAILURE(InitializeKernelVersionsSpaces());
72 94
73 /* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel 95 /* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel
74 * versions. The content of space KERNEL_MUST_USE_BACKUP determines whether 96 * versions. The content of space KERNEL_MUST_USE_BACKUP determines whether
75 * only the backup value should be trusted. 97 * only the backup value should be trusted.
76 */ 98 */
77 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_BACKUP_NV_INDEX, 99 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_BACKUP_NV_INDEX,
78 firmware_perm, sizeof(uint32_t))); 100 firmware_perm, sizeof(uint32_t)));
79 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX, 101 RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX,
80 (uint8_t*) &zero, sizeof(uint32_t))); 102 (uint8_t*) &zero, sizeof(uint32_t)));
81 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_MUST_USE_BACKUP_NV_INDEX, 103 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_MUST_USE_BACKUP_NV_INDEX,
82 firmware_perm, sizeof(uint32_t))); 104 firmware_perm, sizeof(uint32_t)));
83 RETURN_ON_FAILURE(TlclWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX, 105 RETURN_ON_FAILURE(SafeWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX,
84 (uint8_t*) &zero, sizeof(uint32_t))); 106 (uint8_t*) &zero, sizeof(uint32_t)));
85 RETURN_ON_FAILURE(TlclDefineSpace(DEVELOPER_MODE_NV_INDEX, 107 RETURN_ON_FAILURE(TlclDefineSpace(DEVELOPER_MODE_NV_INDEX,
86 firmware_perm, sizeof(uint32_t))); 108 firmware_perm, sizeof(uint32_t)));
87 RETURN_ON_FAILURE(TlclWrite(DEVELOPER_MODE_NV_INDEX, 109 RETURN_ON_FAILURE(SafeWrite(DEVELOPER_MODE_NV_INDEX,
88 (uint8_t*) &zero, sizeof(uint32_t))); 110 (uint8_t*) &zero, sizeof(uint32_t)));
89 111
90 /* The space TPM_IS_INITIALIZED_NV_INDEX is used to indicate that the TPM 112 /* The space TPM_IS_INITIALIZED_NV_INDEX is used to indicate that the TPM
91 * initialization has completed. Without it we cannot be sure that the last 113 * initialization has completed. Without it we cannot be sure that the last
92 * space to be created was also initialized (power could have been lost right 114 * space to be created was also initialized (power could have been lost right
93 * after its creation). 115 * after its creation).
94 */ 116 */
95 RETURN_ON_FAILURE(TlclDefineSpace(TPM_IS_INITIALIZED_NV_INDEX, 117 RETURN_ON_FAILURE(TlclDefineSpace(TPM_IS_INITIALIZED_NV_INDEX,
96 firmware_perm, sizeof(uint32_t))); 118 firmware_perm, sizeof(uint32_t)));
97 return TPM_SUCCESS; 119 return TPM_SUCCESS;
98 } 120 }
99 121
100 static uint32_t SetDistrustKernelSpaceAtNextBoot(uint32_t distrust) { 122 static uint32_t SetDistrustKernelSpaceAtNextBoot(uint32_t distrust) {
101 uint32_t must_use_backup; 123 uint32_t must_use_backup;
102 RETURN_ON_FAILURE(TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX, 124 RETURN_ON_FAILURE(TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX,
103 (uint8_t*) &must_use_backup, sizeof(uint32_t))); 125 (uint8_t*) &must_use_backup, sizeof(uint32_t)));
104 if (must_use_backup != distrust) { 126 if (must_use_backup != distrust) {
105 RETURN_ON_FAILURE(TlclWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX, 127 RETURN_ON_FAILURE(SafeWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX,
106 (uint8_t*) &distrust, sizeof(uint32_t))); 128 (uint8_t*) &distrust, sizeof(uint32_t)));
107 } 129 }
108 return TPM_SUCCESS; 130 return TPM_SUCCESS;
109 } 131 }
110 132
111 static uint32_t GetTPMRollbackIndices(int type) { 133 static uint32_t GetTPMRollbackIndices(int type) {
112 uint32_t firmware_versions; 134 uint32_t firmware_versions;
113 uint32_t kernel_versions; 135 uint32_t kernel_versions;
114 136
115 /* We perform the reads, making sure they succeed. A failure means that the 137 /* We perform the reads, making sure they succeed. A failure means that the
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 188
167 /* Either we detected that something went wrong, or we cannot trust the 189 /* Either we detected that something went wrong, or we cannot trust the
168 * PP-protected kernel space. Attempts to fix. It is not always necessary 190 * PP-protected kernel space. Attempts to fix. It is not always necessary
169 * to redefine the space, but we might as well, since this path should be 191 * to redefine the space, but we might as well, since this path should be
170 * taken quite seldom (after recovery mode and after an attack). 192 * taken quite seldom (after recovery mode and after an attack).
171 */ 193 */
172 RETURN_ON_FAILURE(InitializeKernelVersionsSpaces()); 194 RETURN_ON_FAILURE(InitializeKernelVersionsSpaces());
173 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, 195 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX,
174 (uint8_t*) &backup_combined_versions, 196 (uint8_t*) &backup_combined_versions,
175 sizeof(uint32_t))); 197 sizeof(uint32_t)));
176 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX, 198 RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX,
177 (uint8_t*) &backup_combined_versions, 199 (uint8_t*) &backup_combined_versions,
178 sizeof(uint32_t))); 200 sizeof(uint32_t)));
179 if (must_use_backup) { 201 if (must_use_backup) {
180 uint32_t zero = 0; 202 uint32_t zero = 0;
181 RETURN_ON_FAILURE(TlclWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX, 203 RETURN_ON_FAILURE(SafeWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX,
182 (uint8_t*) &zero, 0)); 204 (uint8_t*) &zero, 0));
183
184 } 205 }
185 return TPM_SUCCESS; 206 return TPM_SUCCESS;
186 } 207 }
187 208
188 static uint32_t BackupKernelSpace(void) { 209 static uint32_t BackupKernelSpace(void) {
189 uint32_t kernel_versions; 210 uint32_t kernel_versions;
190 uint32_t backup_versions; 211 uint32_t backup_versions;
191 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, 212 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX,
192 (uint8_t*) &kernel_versions, sizeof(uint32_t))); 213 (uint8_t*) &kernel_versions, sizeof(uint32_t)));
193 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, 214 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX,
194 (uint8_t*) &backup_versions, sizeof(uint32_t))); 215 (uint8_t*) &backup_versions, sizeof(uint32_t)));
195 if (kernel_versions == backup_versions) { 216 if (kernel_versions == backup_versions) {
196 return TPM_SUCCESS; 217 return TPM_SUCCESS;
197 } else if (kernel_versions < backup_versions) { 218 } else if (kernel_versions < backup_versions) {
198 /* This cannot happen. We're screwed. */ 219 /* This cannot happen. We're screwed. */
199 return TPM_E_INTERNAL_INCONSISTENCY; 220 return TPM_E_INTERNAL_INCONSISTENCY;
200 } 221 }
201 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX, 222 RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX,
202 (uint8_t*) &kernel_versions, sizeof(uint32_t))); 223 (uint8_t*) &kernel_versions, sizeof(uint32_t)));
203 return TPM_SUCCESS; 224 return TPM_SUCCESS;
204 } 225 }
205 226
206 /* Checks for transitions between protected mode to developer mode. When going 227 /* Checks for transitions between protected mode to developer mode. When going
207 * into developer mode, clear the TPM. 228 * into developer mode, clear the TPM.
208 */ 229 */
209 static uint32_t CheckDeveloperModeTransition(uint32_t current_developer) { 230 static uint32_t CheckDeveloperModeTransition(uint32_t current_developer) {
210 uint32_t past_developer; 231 uint32_t past_developer;
211 int must_clear;
212 RETURN_ON_FAILURE(TlclRead(DEVELOPER_MODE_NV_INDEX, 232 RETURN_ON_FAILURE(TlclRead(DEVELOPER_MODE_NV_INDEX,
213 (uint8_t*) &past_developer, 233 (uint8_t*) &past_developer,
214 sizeof(past_developer))); 234 sizeof(past_developer)));
215 must_clear = current_developer != past_developer;
216 if (must_clear) {
217 RETURN_ON_FAILURE(TlclForceClear());
218 }
219 if (past_developer != current_developer) { 235 if (past_developer != current_developer) {
220 /* (Unauthorized) writes to the TPM succeed even when the TPM is disabled 236 RETURN_ON_FAILURE(TPMClearAndReenable());
221 * and deactivated. 237 RETURN_ON_FAILURE(SafeWrite(DEVELOPER_MODE_NV_INDEX,
222 */
223 RETURN_ON_FAILURE(TlclWrite(DEVELOPER_MODE_NV_INDEX,
224 (uint8_t*) &current_developer, 238 (uint8_t*) &current_developer,
225 sizeof(current_developer))); 239 sizeof(current_developer)));
226 } 240 }
227 return must_clear ? TPM_E_MUST_REBOOT : TPM_SUCCESS; 241 return TPM_SUCCESS;
228 } 242 }
229 243
230 static uint32_t SetupTPM_(int mode, int developer_flag) { 244 static uint32_t SetupTPM_(int mode, int developer_flag) {
231 uint8_t disable; 245 uint8_t disable;
232 uint8_t deactivated; 246 uint8_t deactivated;
233 TlclLibInit(); 247 TlclLibInit();
234 RETURN_ON_FAILURE(TlclStartup()); 248 RETURN_ON_FAILURE(TlclStartup());
235 RETURN_ON_FAILURE(TlclContinueSelfTest()); 249 RETURN_ON_FAILURE(TlclContinueSelfTest());
236 RETURN_ON_FAILURE(TlclAssertPhysicalPresence()); 250 RETURN_ON_FAILURE(TlclAssertPhysicalPresence());
237 /* Checks that the TPM is enabled and activated. */ 251 /* Checks that the TPM is enabled and activated. */
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 * As a side note, observe that we go through considerable hoops to avoid using 302 * As a side note, observe that we go through considerable hoops to avoid using
289 * the STCLEAR permissions for the index spaces. We do this to avoid writing 303 * the STCLEAR permissions for the index spaces. We do this to avoid writing
290 * to the TPM flashram at every reboot or wake-up, because of concerns about 304 * to the TPM flashram at every reboot or wake-up, because of concerns about
291 * the durability of the NVRAM. 305 * the durability of the NVRAM.
292 */ 306 */
293 uint32_t SetupTPM(int mode, int developer_flag) { 307 uint32_t SetupTPM(int mode, int developer_flag) {
294 switch (mode) { 308 switch (mode) {
295 case RO_RECOVERY_MODE: 309 case RO_RECOVERY_MODE:
296 case RO_NORMAL_MODE: { 310 case RO_NORMAL_MODE: {
297 uint32_t result = SetupTPM_(mode, developer_flag); 311 uint32_t result = SetupTPM_(mode, developer_flag);
298 if (result == TPM_E_MAXNVWRITES) { 312 if (mode == RO_NORMAL_MODE) {
299 /* ForceClears and reboots */
300 RETURN_ON_FAILURE(TlclForceClear());
301 return TPM_E_MUST_REBOOT;
302 } else if (mode == RO_NORMAL_MODE) {
303 return result; 313 return result;
304 } else { 314 } else {
305 /* In recovery mode we want to keep going even if there are errors. */ 315 /* In recovery mode we want to keep going even if there are errors. */
306 return TPM_SUCCESS; 316 return TPM_SUCCESS;
307 } 317 }
308 } 318 }
309 case RW_NORMAL_MODE: 319 case RW_NORMAL_MODE:
310 /* There are no TPM writes here, so no need to check for write limit errors.
311 */
312 RETURN_ON_FAILURE(GetTPMRollbackIndices(KERNEL_VERSIONS)); 320 RETURN_ON_FAILURE(GetTPMRollbackIndices(KERNEL_VERSIONS));
313 default: 321 default:
314 return TPM_E_INTERNAL_INCONSISTENCY; 322 return TPM_E_INTERNAL_INCONSISTENCY;
315 } 323 }
316 } 324 }
317 325
318 uint32_t GetStoredVersions(int type, uint16_t* key_version, uint16_t* version) { 326 uint32_t GetStoredVersions(int type, uint16_t* key_version, uint16_t* version) {
319 /* TODO: should verify that SetupTPM() has been called. 327 /* TODO: should verify that SetupTPM() has been called.
320 * 328 *
321 * Note that SetupTPM() does hardware setup AND sets global variables. When 329 * Note that SetupTPM() does hardware setup AND sets global variables. When
(...skipping 11 matching lines...) Expand all
333 break; 341 break;
334 } 342 }
335 343
336 return TPM_SUCCESS; 344 return TPM_SUCCESS;
337 } 345 }
338 346
339 uint32_t WriteStoredVersions(int type, uint16_t key_version, uint16_t version) { 347 uint32_t WriteStoredVersions(int type, uint16_t key_version, uint16_t version) {
340 uint32_t combined_version = (key_version << 16) & version; 348 uint32_t combined_version = (key_version << 16) & version;
341 switch (type) { 349 switch (type) {
342 case FIRMWARE_VERSIONS: 350 case FIRMWARE_VERSIONS:
343 RETURN_ON_FAILURE(TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, 351 RETURN_ON_FAILURE(SafeWrite(FIRMWARE_VERSIONS_NV_INDEX,
344 (uint8_t*) &combined_version, 352 (uint8_t*) &combined_version,
345 sizeof(uint32_t))); 353 sizeof(uint32_t)));
346 break; 354 break;
347 355
348 case KERNEL_VERSIONS: 356 case KERNEL_VERSIONS:
349 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX, 357 RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX,
350 (uint8_t*) &combined_version, 358 (uint8_t*) &combined_version,
351 sizeof(uint32_t))); 359 sizeof(uint32_t)));
352 } 360 }
353 return TPM_SUCCESS; 361 return TPM_SUCCESS;
354 } 362 }
355 363
356 uint32_t LockFirmwareVersions() { 364 uint32_t LockFirmwareVersions() {
357 return TlclSetGlobalLock(); 365 return TlclSetGlobalLock();
358 } 366 }
359 367
360 uint32_t LockKernelVersionsByLockingPP() { 368 uint32_t LockKernelVersionsByLockingPP() {
361 return TlclLockPhysicalPresence(); 369 return TlclLockPhysicalPresence();
362 } 370 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698