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

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

Issue 3132014: Remove kernel backup space (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Fix debug output Created 10 years, 4 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/version.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
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 70
71 /* Functions to read and write firmware and kernel spaces. */ 71 /* Functions to read and write firmware and kernel spaces. */
72 static uint32_t ReadSpaceFirmware(RollbackSpaceFirmware* rsf) { 72 static uint32_t ReadSpaceFirmware(RollbackSpaceFirmware* rsf) {
73 return TlclRead(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware)); 73 return TlclRead(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware));
74 } 74 }
75 75
76 static uint32_t WriteSpaceFirmware(const RollbackSpaceFirmware* rsf) { 76 static uint32_t WriteSpaceFirmware(const RollbackSpaceFirmware* rsf) {
77 return SafeWrite(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware)); 77 return SafeWrite(FIRMWARE_NV_INDEX, rsf, sizeof(RollbackSpaceFirmware));
78 } 78 }
79 79
80 #ifndef DISABLE_ROLLBACK_TPM
80 static uint32_t ReadSpaceKernel(RollbackSpaceKernel* rsk) { 81 static uint32_t ReadSpaceKernel(RollbackSpaceKernel* rsk) {
81 return TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel)); 82 return TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
82 } 83 }
84 #endif
83 85
84 static uint32_t WriteSpaceKernel(const RollbackSpaceKernel* rsk) { 86 static uint32_t WriteSpaceKernel(const RollbackSpaceKernel* rsk) {
85 return SafeWrite(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel)); 87 return SafeWrite(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
86 } 88 }
87 89
88
89
90 /* Creates the NVRAM spaces, and sets their initial values as needed. */ 90 /* Creates the NVRAM spaces, and sets their initial values as needed. */
91 static uint32_t InitializeSpaces(RollbackSpaceFirmware* rsf, 91 static uint32_t InitializeSpaces(RollbackSpaceFirmware* rsf,
92 RollbackSpaceKernel* rsk) { 92 RollbackSpaceKernel* rsk) {
93 static const RollbackSpaceFirmware rsf_init = { 93 static const RollbackSpaceFirmware rsf_init = {
94 ROLLBACK_SPACE_FIRMWARE_VERSION, 0, 0, 0}; 94 ROLLBACK_SPACE_FIRMWARE_VERSION, 0, 0, 0};
95 static const RollbackSpaceKernel rsk_init = { 95 static const RollbackSpaceKernel rsk_init = {
96 ROLLBACK_SPACE_KERNEL_VERSION, ROLLBACK_SPACE_KERNEL_UID, 0, 0}; 96 ROLLBACK_SPACE_KERNEL_VERSION, ROLLBACK_SPACE_KERNEL_UID, 0, 0};
97 uint8_t nvlocked = 0; 97 uint8_t nvlocked = 0;
98 98
99 VBDEBUG(("TPM: Initializing spaces\n")); 99 VBDEBUG(("TPM: Initializing spaces\n"));
100 100
101 /* The TPM will not enforce the NV authorization restrictions until the 101 /* The TPM will not enforce the NV authorization restrictions until the
102 * execution of a TPM_NV_DefineSpace with the handle of TPM_NV_INDEX_LOCK. 102 * execution of a TPM_NV_DefineSpace with the handle of TPM_NV_INDEX_LOCK.
103 * Create that space if it doesn't already exist. */ 103 * Create that space if it doesn't already exist. */
104 RETURN_ON_FAILURE(TlclGetFlags(NULL, NULL, &nvlocked)); 104 RETURN_ON_FAILURE(TlclGetFlags(NULL, NULL, &nvlocked));
105 VBDEBUG(("TPM: nvlocked=%d\n", nvlocked)); 105 VBDEBUG(("TPM: nvlocked=%d\n", nvlocked));
106 if (!nvlocked) { 106 if (!nvlocked) {
107 VBDEBUG(("TPM: Enabling NV locking\n")); 107 VBDEBUG(("TPM: Enabling NV locking\n"));
108 RETURN_ON_FAILURE(TlclSetNvLocked()); 108 RETURN_ON_FAILURE(TlclSetNvLocked());
109 } 109 }
110 110
111 /* Initialize the firmware and kernel spaces */ 111 /* Initialize the firmware and kernel spaces */
112 Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware)); 112 Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware));
113 /* Initialize the backup copy of the kernel space to the same data
114 * as the kernel space */
115 Memcpy(&rsf->kernel_backup, &rsk_init, sizeof(RollbackSpaceKernel));
116 Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel)); 113 Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel));
117 114
118 /* Define and set firmware and kernel spaces */ 115 /* Define and set firmware and kernel spaces */
119 RETURN_ON_FAILURE(SafeDefineSpace(FIRMWARE_NV_INDEX, 116 RETURN_ON_FAILURE(SafeDefineSpace(FIRMWARE_NV_INDEX,
120 TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE, 117 TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE,
121 sizeof(RollbackSpaceFirmware))); 118 sizeof(RollbackSpaceFirmware)));
122 RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); 119 RETURN_ON_FAILURE(WriteSpaceFirmware(rsf));
123 RETURN_ON_FAILURE(SafeDefineSpace(KERNEL_NV_INDEX, TPM_NV_PER_PPWRITE, 120 RETURN_ON_FAILURE(SafeDefineSpace(KERNEL_NV_INDEX, TPM_NV_PER_PPWRITE,
124 sizeof(RollbackSpaceKernel))); 121 sizeof(RollbackSpaceKernel)));
125 RETURN_ON_FAILURE(WriteSpaceKernel(rsk)); 122 RETURN_ON_FAILURE(WriteSpaceKernel(rsk));
(...skipping 16 matching lines...) Expand all
142 * bricked device. 139 * bricked device.
143 * 140 *
144 * As a side note, observe that we go through considerable hoops to avoid using 141 * As a side note, observe that we go through considerable hoops to avoid using
145 * the STCLEAR permissions for the index spaces. We do this to avoid writing 142 * the STCLEAR permissions for the index spaces. We do this to avoid writing
146 * to the TPM flashram at every reboot or wake-up, because of concerns about 143 * to the TPM flashram at every reboot or wake-up, because of concerns about
147 * the durability of the NVRAM. 144 * the durability of the NVRAM.
148 */ 145 */
149 uint32_t SetupTPM(int recovery_mode, int developer_mode, 146 uint32_t SetupTPM(int recovery_mode, int developer_mode,
150 RollbackSpaceFirmware* rsf) { 147 RollbackSpaceFirmware* rsf) {
151 148
152 RollbackSpaceKernel rsk;
153 int rsf_dirty = 0; 149 int rsf_dirty = 0;
154 uint8_t new_flags = 0; 150 uint8_t new_flags = 0;
155
156 uint8_t disable; 151 uint8_t disable;
157 uint8_t deactivated; 152 uint8_t deactivated;
158 uint32_t result; 153 uint32_t result;
159 uint32_t perms;
160 154
161 VBDEBUG(("TPM: SetupTPM(r%d, d%d)\n", recovery_mode, developer_mode)); 155 VBDEBUG(("TPM: SetupTPM(r%d, d%d)\n", recovery_mode, developer_mode));
162 156
163 /* TODO: TlclLibInit() should be able to return failure */ 157 /* TODO: TlclLibInit() should be able to return failure */
164 TlclLibInit(); 158 TlclLibInit();
165 159
166 RETURN_ON_FAILURE(TlclStartup()); 160 RETURN_ON_FAILURE(TlclStartup());
167 #ifdef USE_CONTINUE_SELF_TEST 161 #ifdef USE_CONTINUE_SELF_TEST
168 /* TODO: ContinueSelfTest() should be faster than SelfTestFull, but 162 /* TODO: ContinueSelfTest() should be faster than SelfTestFull, but
169 * may also not work properly in older TPM firmware. For now, do 163 * may also not work properly in older TPM firmware. For now, do
(...skipping 11 matching lines...) Expand all
181 disable, deactivated)); 175 disable, deactivated));
182 RETURN_ON_FAILURE(TlclSetEnable()); 176 RETURN_ON_FAILURE(TlclSetEnable());
183 RETURN_ON_FAILURE(TlclSetDeactivated(0)); 177 RETURN_ON_FAILURE(TlclSetDeactivated(0));
184 VBDEBUG(("TPM: Must reboot to re-enable\n")); 178 VBDEBUG(("TPM: Must reboot to re-enable\n"));
185 return TPM_E_MUST_REBOOT; 179 return TPM_E_MUST_REBOOT;
186 } 180 }
187 181
188 /* Read the firmware space. */ 182 /* Read the firmware space. */
189 result = ReadSpaceFirmware(rsf); 183 result = ReadSpaceFirmware(rsf);
190 if (TPM_E_BADINDEX == result) { 184 if (TPM_E_BADINDEX == result) {
185 RollbackSpaceKernel rsk;
186
191 /* This is the first time we've run, and the TPM has not been 187 /* This is the first time we've run, and the TPM has not been
192 * initialized. Initialize it. */ 188 * initialized. Initialize it. */
193 VBDEBUG(("TPM: Not initialized yet.\n")); 189 VBDEBUG(("TPM: Not initialized yet.\n"));
194 RETURN_ON_FAILURE(InitializeSpaces(rsf, &rsk)); 190 RETURN_ON_FAILURE(InitializeSpaces(rsf, &rsk));
195 } else if (TPM_SUCCESS != result) { 191 } else if (TPM_SUCCESS != result) {
196 VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n")); 192 VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n"));
197 return TPM_E_CORRUPTED_STATE; 193 return TPM_E_CORRUPTED_STATE;
198 } 194 }
199 VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n", 195 VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n",
200 rsf->struct_version, rsf->flags, rsf->fw_versions)); 196 rsf->struct_version, rsf->flags, rsf->fw_versions));
201 197
202 /* Read the kernel space and verify its permissions. If the kernel
203 * space has the wrong permission, or it doesn't contain the right
204 * identifier, we give up. This will need to be fixed by the
205 * recovery kernel. We have to worry about this because at any time
206 * (even with PP turned off) the TPM owner can remove and redefine a
207 * PP-protected space (but not write to it). */
208 RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
209 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_NV_INDEX, &perms));
210 if (TPM_NV_PER_PPWRITE != perms || ROLLBACK_SPACE_KERNEL_UID != rsk.uid)
211 return TPM_E_CORRUPTED_STATE;
212 VBDEBUG(("TPM: Kernel space sv%d v%x\n",
213 rsk.struct_version, rsk.kernel_versions));
214
215 /* If the kernel space and its backup are different, we need to copy
216 * one to the other. Which one we copy depends on whether the
217 * use-backup flag is set. */
218 if (0 != Memcmp(&rsk, &rsf->kernel_backup, sizeof(RollbackSpaceKernel))) {
219 VBDEBUG(("TPM: kernel space and backup are different\n"));
220
221 if (rsf->flags & FLAG_KERNEL_SPACE_USE_BACKUP) {
222 VBDEBUG(("TPM: use backup kernel space\n"));
223 Memcpy(&rsk, &rsf->kernel_backup, sizeof(RollbackSpaceKernel));
224 RETURN_ON_FAILURE(WriteSpaceKernel(&rsk));
225 } else if (rsk.kernel_versions < rsf->kernel_backup.kernel_versions) {
226 VBDEBUG(("TPM: kernel versions %x < backup versions %x\n",
227 rsk.kernel_versions, rsf->kernel_backup.kernel_versions));
228 return TPM_E_INTERNAL_INCONSISTENCY;
229 } else {
230 VBDEBUG(("TPM: copy kernel space to backup\n"));
231 Memcpy(&rsf->kernel_backup, &rsk, sizeof(RollbackSpaceKernel));
232 rsf_dirty = 1;
233 }
234 }
235
236 /* Clear ownership if developer flag has toggled */ 198 /* Clear ownership if developer flag has toggled */
237 if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) != 199 if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) !=
238 (rsf->flags & FLAG_LAST_BOOT_DEVELOPER)) { 200 (rsf->flags & FLAG_LAST_BOOT_DEVELOPER)) {
239 VBDEBUG(("TPM: Developer flag changed; clearing owner.\n")); 201 VBDEBUG(("TPM: Developer flag changed; clearing owner.\n"));
240 RETURN_ON_FAILURE(TPMClearAndReenable()); 202 RETURN_ON_FAILURE(TPMClearAndReenable());
241 } 203 }
242 204
243 /* Update flags */ 205 /* Update flags */
244 if (developer_mode) 206 if (developer_mode)
245 new_flags |= FLAG_LAST_BOOT_DEVELOPER; 207 new_flags |= FLAG_LAST_BOOT_DEVELOPER;
246 if (recovery_mode) { 208 if (recovery_mode)
247 new_flags |= FLAG_KERNEL_SPACE_USE_BACKUP;
248 g_rollback_recovery_mode = 1; /* Global variables are usable in 209 g_rollback_recovery_mode = 1; /* Global variables are usable in
249 * recovery mode */ 210 * recovery mode */
250 } 211
251 if (rsf->flags != new_flags) { 212 if (rsf->flags != new_flags) {
252 rsf->flags = new_flags; 213 rsf->flags = new_flags;
253 rsf_dirty = 1; 214 rsf_dirty = 1;
254 } 215 }
255 216
256 /* If firmware space is dirty, flush it back to the TPM */ 217 /* If firmware space is dirty, flush it back to the TPM */
257 if (rsf_dirty) { 218 if (rsf_dirty) {
258 VBDEBUG(("TPM: Updating firmware space.\n")); 219 VBDEBUG(("TPM: Updating firmware space.\n"));
259 RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); 220 RETURN_ON_FAILURE(WriteSpaceFirmware(rsf));
260 } 221 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 return TPM_SUCCESS; 277 return TPM_SUCCESS;
317 } 278 }
318 279
319 #else 280 #else
320 281
321 uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) { 282 uint32_t RollbackFirmwareSetup(int developer_mode, uint32_t* version) {
322 RollbackSpaceFirmware rsf; 283 RollbackSpaceFirmware rsf;
323 284
324 RETURN_ON_FAILURE(SetupTPM(0, developer_mode, &rsf)); 285 RETURN_ON_FAILURE(SetupTPM(0, developer_mode, &rsf));
325 *version = rsf.fw_versions; 286 *version = rsf.fw_versions;
326 VBDEBUG(("TPM: RollbackFirmwareSetup %x %x %x\n", (int)rsf.fw_versions)); 287 VBDEBUG(("TPM: RollbackFirmwareSetup %x\n", (int)rsf.fw_versions));
327 return TPM_SUCCESS; 288 return TPM_SUCCESS;
328 } 289 }
329 290
330 uint32_t RollbackFirmwareWrite(uint32_t version) { 291 uint32_t RollbackFirmwareWrite(uint32_t version) {
331 RollbackSpaceFirmware rsf; 292 RollbackSpaceFirmware rsf;
332 293
333 RETURN_ON_FAILURE(ReadSpaceFirmware(&rsf)); 294 RETURN_ON_FAILURE(ReadSpaceFirmware(&rsf));
334 VBDEBUG(("TPM: RollbackFirmwareWrite %x --> %x\n", (int)rsf.fw_versions, 295 VBDEBUG(("TPM: RollbackFirmwareWrite %x --> %x\n", (int)rsf.fw_versions,
335 (int)version)); 296 (int)version));
336 rsf.fw_versions = version; 297 rsf.fw_versions = version;
(...skipping 17 matching lines...) Expand all
354 /* We still return the result of SetupTPM even though we expect the caller to 315 /* We still return the result of SetupTPM even though we expect the caller to
355 * ignore it. It's useful in unit testing. */ 316 * ignore it. It's useful in unit testing. */
356 return result; 317 return result;
357 } 318 }
358 319
359 uint32_t RollbackKernelRead(uint32_t* version) { 320 uint32_t RollbackKernelRead(uint32_t* version) {
360 if (g_rollback_recovery_mode) { 321 if (g_rollback_recovery_mode) {
361 *version = 0; 322 *version = 0;
362 } else { 323 } else {
363 RollbackSpaceKernel rsk; 324 RollbackSpaceKernel rsk;
325 uint32_t perms;
326
327 /* Read the kernel space and verify its permissions. If the kernel
328 * space has the wrong permission, or it doesn't contain the right
329 * identifier, we give up. This will need to be fixed by the
330 * recovery kernel. We have to worry about this because at any time
331 * (even with PP turned off) the TPM owner can remove and redefine a
332 * PP-protected space (but not write to it). */
364 RETURN_ON_FAILURE(ReadSpaceKernel(&rsk)); 333 RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
334 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_NV_INDEX, &perms));
335 if (TPM_NV_PER_PPWRITE != perms || ROLLBACK_SPACE_KERNEL_UID != rsk.uid)
336 return TPM_E_CORRUPTED_STATE;
337
365 *version = rsk.kernel_versions; 338 *version = rsk.kernel_versions;
366 VBDEBUG(("TPM: RollbackKernelRead %x\n", (int)rsk.kernel_versions)); 339 VBDEBUG(("TPM: RollbackKernelRead %x\n", (int)rsk.kernel_versions));
367 } 340 }
368 return TPM_SUCCESS; 341 return TPM_SUCCESS;
369 } 342 }
370 343
371 uint32_t RollbackKernelWrite(uint32_t version) { 344 uint32_t RollbackKernelWrite(uint32_t version) {
372 if (g_rollback_recovery_mode) { 345 if (g_rollback_recovery_mode) {
373 return TPM_SUCCESS; 346 return TPM_SUCCESS;
374 } else { 347 } else {
375 RollbackSpaceKernel rsk; 348 RollbackSpaceKernel rsk;
376 RETURN_ON_FAILURE(ReadSpaceKernel(&rsk)); 349 RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
377 VBDEBUG(("TPM: RollbackKernelWrite %x --> %x\n", (int)rsk.kernel_versions, 350 VBDEBUG(("TPM: RollbackKernelWrite %x --> %x\n", (int)rsk.kernel_versions,
378 (int)version)); 351 (int)version));
379 rsk.kernel_versions = version; 352 rsk.kernel_versions = version;
380 return WriteSpaceKernel(&rsk); 353 return WriteSpaceKernel(&rsk);
381 } 354 }
382 } 355 }
383 356
384 uint32_t RollbackKernelLock(void) { 357 uint32_t RollbackKernelLock(void) {
385 if (g_rollback_recovery_mode) { 358 if (g_rollback_recovery_mode) {
386 return TPM_SUCCESS; 359 return TPM_SUCCESS;
387 } else { 360 } else {
388 return TlclLockPhysicalPresence(); 361 return TlclLockPhysicalPresence();
389 } 362 }
390 } 363 }
391 364
392 #endif // DISABLE_ROLLBACK_TPM 365 #endif // DISABLE_ROLLBACK_TPM
OLDNEW
« no previous file with comments | « firmware/lib/include/rollback_index.h ('k') | firmware/version.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698