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

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

Issue 2857030: Exhaustive test for rollback code (Closed) Base URL: ssh://git@chromiumos-git/vboot_reference.git
Patch Set: Fix write count handling and improve comments. 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/tss_constants.h ('k') | firmware/linktest/main.c » ('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 return result; \ 23 return result; \
24 } \ 24 } \
25 } while (0) 25 } while (0)
26 26
27 static uint32_t TPMClearAndReenable() { 27 uint32_t TPMClearAndReenable(void) {
28 RETURN_ON_FAILURE(TlclForceClear()); 28 RETURN_ON_FAILURE(TlclForceClear());
29 RETURN_ON_FAILURE(TlclSetEnable()); 29 RETURN_ON_FAILURE(TlclSetEnable());
30 RETURN_ON_FAILURE(TlclSetDeactivated(0)); 30 RETURN_ON_FAILURE(TlclSetDeactivated(0));
31 return TPM_SUCCESS; 31 return TPM_SUCCESS;
32 } 32 }
33 33
34 /* Like TlclWrite(), but checks for write errors due to hitting the 64-write 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 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). 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. 37 * This is not expected to happen frequently, but it could happen.
(...skipping 13 matching lines...) Expand all
51 TPM_NV_PER_PPWRITE, KERNEL_SPACE_SIZE)); 51 TPM_NV_PER_PPWRITE, KERNEL_SPACE_SIZE));
52 RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX, KERNEL_SPACE_INIT_DATA, 52 RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX, KERNEL_SPACE_INIT_DATA,
53 KERNEL_SPACE_SIZE)); 53 KERNEL_SPACE_SIZE));
54 return TPM_SUCCESS; 54 return TPM_SUCCESS;
55 } 55 }
56 56
57 /* 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
58 * 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
59 * *|initialized| is not changed. 59 * *|initialized| is not changed.
60 */ 60 */
61 static uint32_t GetSpacesInitialized(int* initialized) { 61 uint32_t GetSpacesInitialized(int* initialized) {
62 uint32_t space_holder; 62 uint32_t space_holder;
63 uint32_t result; 63 uint32_t result;
64 result = TlclRead(TPM_IS_INITIALIZED_NV_INDEX, 64 result = TlclRead(TPM_IS_INITIALIZED_NV_INDEX,
65 (uint8_t*) &space_holder, sizeof(space_holder)); 65 (uint8_t*) &space_holder, sizeof(space_holder));
66 switch (result) { 66 switch (result) {
67 case TPM_SUCCESS: 67 case TPM_SUCCESS:
68 *initialized = 1; 68 *initialized = 1;
69 break; 69 break;
70 case TPM_E_BADINDEX: 70 case TPM_E_BADINDEX:
71 *initialized = 0; 71 *initialized = 0;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 /* If we can't read the kernel space, or it has the wrong permission, or it 147 /* If we can't read the kernel space, or it has the wrong permission, or it
148 * doesn't contain the right identifier, we give up. This will need to be 148 * doesn't contain the right identifier, we give up. This will need to be
149 * fixed by the recovery kernel. We have to worry about this because at any 149 * fixed by the recovery kernel. We have to worry about this because at any
150 * time (even with PP turned off) the TPM owner can remove and redefine a 150 * time (even with PP turned off) the TPM owner can remove and redefine a
151 * PP-protected space (but not write to it). 151 * PP-protected space (but not write to it).
152 */ 152 */
153 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &buffer, 153 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &buffer,
154 KERNEL_SPACE_SIZE)); 154 KERNEL_SPACE_SIZE));
155 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_VERSIONS_NV_INDEX, &perms)); 155 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_VERSIONS_NV_INDEX, &perms));
156 if (perms != TPM_NV_PER_PPWRITE || 156 if (perms != TPM_NV_PER_PPWRITE ||
157 !Memcmp(buffer + sizeof(uint32_t), KERNEL_SPACE_UID, 157 Memcmp(buffer + sizeof(uint32_t), KERNEL_SPACE_UID,
158 KERNEL_SPACE_UID_SIZE)) { 158 KERNEL_SPACE_UID_SIZE) != 0) {
159 return TPM_E_CORRUPTED_STATE; 159 return TPM_E_CORRUPTED_STATE;
160 } 160 }
161 161
162 if (must_use_backup) { 162 if (must_use_backup) {
163 /* We must use the backup space because in the preceding boot cycle the 163 /* We must use the backup space because in the preceding boot cycle the
164 * primary space was left unlocked and cannot be trusted. 164 * primary space was left unlocked and cannot be trusted.
165 */ 165 */
166 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, 166 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX,
167 (uint8_t*) &backup_combined_versions, 167 (uint8_t*) &backup_combined_versions,
168 sizeof(uint32_t))); 168 sizeof(uint32_t)));
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 * 226 *
227 * As a side note, observe that we go through considerable hoops to avoid using 227 * As a side note, observe that we go through considerable hoops to avoid using
228 * the STCLEAR permissions for the index spaces. We do this to avoid writing 228 * the STCLEAR permissions for the index spaces. We do this to avoid writing
229 * to the TPM flashram at every reboot or wake-up, because of concerns about 229 * to the TPM flashram at every reboot or wake-up, because of concerns about
230 * the durability of the NVRAM. 230 * the durability of the NVRAM.
231 */ 231 */
232 static uint32_t SetupTPM(int recovery_mode, 232 static uint32_t SetupTPM(int recovery_mode,
233 int developer_mode) { 233 int developer_mode) {
234 uint8_t disable; 234 uint8_t disable;
235 uint8_t deactivated; 235 uint8_t deactivated;
236 uint32_t result;
236 237
237 TlclLibInit(); 238 TlclLibInit();
238 RETURN_ON_FAILURE(TlclStartup()); 239 RETURN_ON_FAILURE(TlclStartup());
239 RETURN_ON_FAILURE(TlclContinueSelfTest()); 240 RETURN_ON_FAILURE(TlclContinueSelfTest());
240 RETURN_ON_FAILURE(TlclAssertPhysicalPresence()); 241 RETURN_ON_FAILURE(TlclAssertPhysicalPresence());
241 /* Checks that the TPM is enabled and activated. */ 242 /* Checks that the TPM is enabled and activated. */
242 RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated)); 243 RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated));
243 if (disable || deactivated) { 244 if (disable || deactivated) {
244 RETURN_ON_FAILURE(TlclSetEnable()); 245 RETURN_ON_FAILURE(TlclSetEnable());
245 RETURN_ON_FAILURE(TlclSetDeactivated(0)); 246 RETURN_ON_FAILURE(TlclSetDeactivated(0));
246 return TPM_E_MUST_REBOOT; 247 return TPM_E_MUST_REBOOT;
247 } 248 }
248 /* We expect this to fail the first time we run on a device, because the TPM 249 result = RecoverKernelSpace();
249 * has not been initialized yet. 250 if (result != TPM_SUCCESS) {
250 */ 251 /* Check if this is the first time we run and the TPM has not been
251 if (RecoverKernelSpace() != TPM_SUCCESS) { 252 * initialized yet.
253 */
252 int initialized = 0; 254 int initialized = 0;
253 RETURN_ON_FAILURE(GetSpacesInitialized(&initialized)); 255 RETURN_ON_FAILURE(GetSpacesInitialized(&initialized));
254 if (initialized) { 256 if (initialized) {
255 return TPM_E_ALREADY_INITIALIZED; 257 return result;
256 } else { 258 } else {
257 RETURN_ON_FAILURE(InitializeSpaces()); 259 RETURN_ON_FAILURE(InitializeSpaces());
258 RETURN_ON_FAILURE(RecoverKernelSpace()); 260 RETURN_ON_FAILURE(RecoverKernelSpace());
259 } 261 }
260 } 262 }
261 RETURN_ON_FAILURE(BackupKernelSpace()); 263 RETURN_ON_FAILURE(BackupKernelSpace());
262 RETURN_ON_FAILURE(SetDistrustKernelSpaceAtNextBoot(recovery_mode)); 264 RETURN_ON_FAILURE(SetDistrustKernelSpaceAtNextBoot(recovery_mode));
263 RETURN_ON_FAILURE(CheckDeveloperModeTransition(developer_mode)); 265 RETURN_ON_FAILURE(CheckDeveloperModeTransition(developer_mode));
264 266
265 if (recovery_mode) { 267 if (recovery_mode) {
(...skipping 26 matching lines...) Expand all
292 return SafeWrite(FIRMWARE_VERSIONS_NV_INDEX, 294 return SafeWrite(FIRMWARE_VERSIONS_NV_INDEX,
293 (uint8_t*) &combined_version, 295 (uint8_t*) &combined_version,
294 sizeof(uint32_t)); 296 sizeof(uint32_t));
295 } 297 }
296 298
297 uint32_t RollbackFirmwareLock(void) { 299 uint32_t RollbackFirmwareLock(void) {
298 return TlclSetGlobalLock(); 300 return TlclSetGlobalLock();
299 } 301 }
300 302
301 uint32_t RollbackKernelRecovery(int developer_mode) { 303 uint32_t RollbackKernelRecovery(int developer_mode) {
302 (void) SetupTPM(1, developer_mode); 304 uint32_t result = SetupTPM(1, developer_mode);
303 /* In recovery mode we ignore TPM malfunctions or corruptions, and leave the 305 /* 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 306 * 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 307 * recovery kernel will fix the TPM (if needed) and lock it ASAP. We leave
306 * Physical Presence on in either case. 308 * Physical Presence on in either case.
307 */ 309 */
308 if (!developer_mode) { 310 if (!developer_mode) {
309 RETURN_ON_FAILURE(TlclSetGlobalLock()); 311 RETURN_ON_FAILURE(TlclSetGlobalLock());
310 } 312 }
311 return TPM_SUCCESS; 313 /* We still return the result of SetupTPM even though we expect the caller to
314 * ignore it. It's useful in unit testing.
315 */
316 return result;
312 } 317 }
313 318
314 uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version) { 319 uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version) {
315 uint32_t kernel_versions; 320 uint32_t kernel_versions;
316 if (g_rollback_recovery_mode) { 321 if (g_rollback_recovery_mode) {
317 *key_version = 0; 322 *key_version = 0;
318 *version = 0; 323 *version = 0;
319 } else { 324 } else {
320 /* Reads kernel versions from TPM. */ 325 /* Reads kernel versions from TPM. */
321 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, 326 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX,
(...skipping 15 matching lines...) Expand all
337 return TPM_SUCCESS; 342 return TPM_SUCCESS;
338 } 343 }
339 344
340 uint32_t RollbackKernelLock(void) { 345 uint32_t RollbackKernelLock(void) {
341 if (!g_rollback_recovery_mode) { 346 if (!g_rollback_recovery_mode) {
342 return TlclLockPhysicalPresence(); 347 return TlclLockPhysicalPresence();
343 } else { 348 } else {
344 return TPM_SUCCESS; 349 return TPM_SUCCESS;
345 } 350 }
346 } 351 }
OLDNEW
« no previous file with comments | « firmware/lib/include/tss_constants.h ('k') | firmware/linktest/main.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698