1 /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Functions for querying, manipulating and locking rollback indices
6  * stored in the TPM NVRAM.
7  */
8 
9 #include "sysincludes.h"
10 
11 #include "crc8.h"
12 #include "rollback_index.h"
13 #include "tlcl.h"
14 #include "tss_constants.h"
15 #include "utility.h"
16 #include "vboot_api.h"
17 
18 #ifndef offsetof
19 #define offsetof(A,B) __builtin_offsetof(A,B)
20 #endif
21 
22 /*
23  * Provide protoypes for functions not in the header file. These prototypes
24  * fix -Wmissing-prototypes warnings.
25  */
26 uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf);
27 uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf);
28 uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk);
29 uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk);
30 
31 #ifdef FOR_TEST
32 /*
33  * Compiling for unit test, so we need the real implementations of
34  * rollback functions.  The unit test mocks the underlying tlcl
35  * functions, so this is ok to run on the host.
36  */
37 #undef CHROMEOS_ENVIRONMENT
38 #undef DISABLE_ROLLBACK_TPM
39 #endif
40 
41 #define RETURN_ON_FAILURE(tpm_command) do {				\
42 		uint32_t result_;					\
43 		if ((result_ = (tpm_command)) != TPM_SUCCESS) {		\
44 			VBDEBUG(("Rollback: %08x returned by " #tpm_command \
45 				 "\n", (int)result_));			\
46 			return result_;					\
47 		}							\
48 	} while (0)
49 
50 
TPMClearAndReenable(void)51 uint32_t TPMClearAndReenable(void)
52 {
53 	VBDEBUG(("TPM: Clear and re-enable\n"));
54 	RETURN_ON_FAILURE(TlclForceClear());
55 	RETURN_ON_FAILURE(TlclSetEnable());
56 	RETURN_ON_FAILURE(TlclSetDeactivated(0));
57 
58 	return TPM_SUCCESS;
59 }
60 
SafeWrite(uint32_t index,const void * data,uint32_t length)61 uint32_t SafeWrite(uint32_t index, const void *data, uint32_t length)
62 {
63 	uint32_t result = TlclWrite(index, data, length);
64 	if (result == TPM_E_MAXNVWRITES) {
65 		RETURN_ON_FAILURE(TPMClearAndReenable());
66 		return TlclWrite(index, data, length);
67 	} else {
68 		return result;
69 	}
70 }
71 
SafeDefineSpace(uint32_t index,uint32_t perm,uint32_t size)72 uint32_t SafeDefineSpace(uint32_t index, uint32_t perm, uint32_t size)
73 {
74 	uint32_t result = TlclDefineSpace(index, perm, size);
75 	if (result == TPM_E_MAXNVWRITES) {
76 		RETURN_ON_FAILURE(TPMClearAndReenable());
77 		return TlclDefineSpace(index, perm, size);
78 	} else {
79 		return result;
80 	}
81 }
82 
83 /* Functions to read and write firmware and kernel spaces. */
ReadSpaceFirmware(RollbackSpaceFirmware * rsf)84 uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf)
85 {
86 	uint32_t r;
87 	int attempts = 3;
88 
89 	while (attempts--) {
90 		r = TlclRead(FIRMWARE_NV_INDEX, rsf,
91 			     sizeof(RollbackSpaceFirmware));
92 		if (r != TPM_SUCCESS)
93 			return r;
94 
95 		/*
96 		 * No CRC in this version, so we'll create one when we write
97 		 * it. Note that we're marking this as version 2, not
98 		 * ROLLBACK_SPACE_FIRMWARE_VERSION, because version 2 just
99 		 * added the CRC. Later versions will need to set default
100 		 * values for any extra fields explicitly (probably here).
101 		 */
102 		if (rsf->struct_version < 2) {
103 			/* Danger Will Robinson! Danger! */
104 			rsf->struct_version = 2;
105 			return TPM_SUCCESS;
106 		}
107 
108 		/*
109 		 * If the CRC is good, we're done. If it's bad, try a couple
110 		 * more times to see if it gets better before we give up. It
111 		 * could just be noise.
112 		 */
113 		if (rsf->crc8 == Crc8(rsf,
114 				      offsetof(RollbackSpaceFirmware, crc8)))
115 			return TPM_SUCCESS;
116 
117 		VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
118 	}
119 
120 	VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
121 	return TPM_E_CORRUPTED_STATE;
122 }
123 
WriteSpaceFirmware(RollbackSpaceFirmware * rsf)124 uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf)
125 {
126 	RollbackSpaceFirmware rsf2;
127 	uint32_t r;
128 	int attempts = 3;
129 
130 	/* All writes should use struct_version 2 or greater. */
131 	if (rsf->struct_version < 2)
132 		rsf->struct_version = 2;
133 	rsf->crc8 = Crc8(rsf, offsetof(RollbackSpaceFirmware, crc8));
134 
135 	while (attempts--) {
136 		r = SafeWrite(FIRMWARE_NV_INDEX, rsf,
137 			      sizeof(RollbackSpaceFirmware));
138 		/* Can't write, not gonna try again */
139 		if (r != TPM_SUCCESS)
140 			return r;
141 
142 		/* Read it back to be sure it got the right values. */
143 		r = ReadSpaceFirmware(&rsf2);    /* This checks the CRC */
144 		if (r == TPM_SUCCESS)
145 			return r;
146 
147 		VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
148 		/* Try writing it again. Maybe it was garbled on the way out. */
149 	}
150 
151 	VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
152 	return TPM_E_CORRUPTED_STATE;
153 }
154 
SetVirtualDevMode(int val)155 uint32_t SetVirtualDevMode(int val)
156 {
157 	RollbackSpaceFirmware rsf;
158 
159 	VBDEBUG(("TPM: Entering %s()\n", __func__));
160 	if (TPM_SUCCESS != ReadSpaceFirmware(&rsf))
161 		return VBERROR_TPM_FIRMWARE_SETUP;
162 
163 	VBDEBUG(("TPM: flags were 0x%02x\n", rsf.flags));
164 	if (val)
165 		rsf.flags |= FLAG_VIRTUAL_DEV_MODE_ON;
166 	else
167 		rsf.flags &= ~FLAG_VIRTUAL_DEV_MODE_ON;
168 	/*
169 	 * NOTE: This doesn't update the FLAG_LAST_BOOT_DEVELOPER bit.  That
170 	 * will be done by SetupTPM() on the next boot.
171 	 */
172 	VBDEBUG(("TPM: flags are now 0x%02x\n", rsf.flags));
173 
174 	if (TPM_SUCCESS != WriteSpaceFirmware(&rsf))
175 		return VBERROR_TPM_SET_BOOT_MODE_STATE;
176 
177 	VBDEBUG(("TPM: Leaving %s()\n", __func__));
178 	return VBERROR_SUCCESS;
179 }
180 
ReadSpaceKernel(RollbackSpaceKernel * rsk)181 uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk)
182 {
183 	uint32_t r;
184 	int attempts = 3;
185 
186 	while (attempts--) {
187 		r = TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
188 		if (r != TPM_SUCCESS)
189 			return r;
190 
191 		/*
192 		 * No CRC in this version, so we'll create one when we write
193 		 * it. Note that we're marking this as version 2, not
194 		 * ROLLBACK_SPACE_KERNEL_VERSION, because version 2 just added
195 		 * the CRC. Later versions will need to set default values for
196 		 * any extra fields explicitly (probably here).
197 		 */
198 		if (rsk->struct_version < 2) {
199 			/* Danger Will Robinson! Danger! */
200 			rsk->struct_version = 2;
201 			return TPM_SUCCESS;
202 		}
203 
204 		/*
205 		 * If the CRC is good, we're done. If it's bad, try a couple
206 		 * more times to see if it gets better before we give up. It
207 		 * could just be noise.
208 		 */
209 		if (rsk->crc8 == Crc8(rsk, offsetof(RollbackSpaceKernel, crc8)))
210 			return TPM_SUCCESS;
211 
212 		VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
213 	}
214 
215 	VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
216 	return TPM_E_CORRUPTED_STATE;
217 }
218 
WriteSpaceKernel(RollbackSpaceKernel * rsk)219 uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk)
220 {
221 	RollbackSpaceKernel rsk2;
222 	uint32_t r;
223 	int attempts = 3;
224 
225 	/* All writes should use struct_version 2 or greater. */
226 	if (rsk->struct_version < 2)
227 		rsk->struct_version = 2;
228 	rsk->crc8 = Crc8(rsk, offsetof(RollbackSpaceKernel, crc8));
229 
230 	while (attempts--) {
231 		r = SafeWrite(KERNEL_NV_INDEX, rsk,
232 			      sizeof(RollbackSpaceKernel));
233 		/* Can't write, not gonna try again */
234 		if (r != TPM_SUCCESS)
235 			return r;
236 
237 		/* Read it back to be sure it got the right values. */
238 		r = ReadSpaceKernel(&rsk2);    /* This checks the CRC */
239 		if (r == TPM_SUCCESS)
240 			return r;
241 
242 		VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
243 		/* Try writing it again. Maybe it was garbled on the way out. */
244 	}
245 
246 	VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
247 	return TPM_E_CORRUPTED_STATE;
248 }
249 
OneTimeInitializeTPM(RollbackSpaceFirmware * rsf,RollbackSpaceKernel * rsk)250 uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf,
251                               RollbackSpaceKernel *rsk)
252 {
253 	static const RollbackSpaceFirmware rsf_init = {
254 		.struct_version = ROLLBACK_SPACE_FIRMWARE_VERSION,
255 	};
256 	static const RollbackSpaceKernel rsk_init = {
257 		.struct_version = ROLLBACK_SPACE_KERNEL_VERSION,
258 		.uid = ROLLBACK_SPACE_KERNEL_UID,
259 	};
260 	TPM_PERMANENT_FLAGS pflags;
261 	uint32_t result;
262 
263 	VBDEBUG(("TPM: One-time initialization\n"));
264 
265 	/*
266 	 * Do a full test.  This only happens the first time the device is
267 	 * turned on in the factory, so performance is not an issue.  This is
268 	 * almost certainly not necessary, but it gives us more confidence
269 	 * about some code paths below that are difficult to
270 	 * test---specifically the ones that set lifetime flags, and are only
271 	 * executed once per physical TPM.
272 	 */
273 	result = TlclSelfTestFull();
274 	if (result != TPM_SUCCESS)
275 		return result;
276 
277 	result = TlclGetPermanentFlags(&pflags);
278 	if (result != TPM_SUCCESS)
279 		return result;
280 
281 	/*
282 	 * TPM may come from the factory without physical presence finalized.
283 	 * Fix if necessary.
284 	 */
285 	VBDEBUG(("TPM: physicalPresenceLifetimeLock=%d\n",
286 		 pflags.physicalPresenceLifetimeLock));
287 	if (!pflags.physicalPresenceLifetimeLock) {
288 		VBDEBUG(("TPM: Finalizing physical presence\n"));
289 		RETURN_ON_FAILURE(TlclFinalizePhysicalPresence());
290 	}
291 
292 	/*
293 	 * The TPM will not enforce the NV authorization restrictions until the
294 	 * execution of a TPM_NV_DefineSpace with the handle of
295 	 * TPM_NV_INDEX_LOCK.  Here we create that space if it doesn't already
296 	 * exist. */
297 	VBDEBUG(("TPM: nvLocked=%d\n", pflags.nvLocked));
298 	if (!pflags.nvLocked) {
299 		VBDEBUG(("TPM: Enabling NV locking\n"));
300 		RETURN_ON_FAILURE(TlclSetNvLocked());
301 	}
302 
303 	/* Clear TPM owner, in case the TPM is already owned for some reason. */
304 	VBDEBUG(("TPM: Clearing owner\n"));
305 	RETURN_ON_FAILURE(TPMClearAndReenable());
306 
307 	/* Initializes the firmware and kernel spaces */
308 	Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware));
309 	Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel));
310 
311 	/* Define the backup space. No need to initialize it, though. */
312 	RETURN_ON_FAILURE(SafeDefineSpace(
313 			BACKUP_NV_INDEX, TPM_NV_PER_PPWRITE, BACKUP_NV_SIZE));
314 
315 	/* Define and initialize the kernel space */
316 	RETURN_ON_FAILURE(SafeDefineSpace(KERNEL_NV_INDEX, TPM_NV_PER_PPWRITE,
317 					  sizeof(RollbackSpaceKernel)));
318 	RETURN_ON_FAILURE(WriteSpaceKernel(rsk));
319 
320 	/* Do the firmware space last, so we retry if we don't get this far. */
321 	RETURN_ON_FAILURE(SafeDefineSpace(
322 			FIRMWARE_NV_INDEX,
323 			TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE,
324 			sizeof(RollbackSpaceFirmware)));
325 	RETURN_ON_FAILURE(WriteSpaceFirmware(rsf));
326 
327 	return TPM_SUCCESS;
328 }
329 
330 
331 /*
332  * SetupTPM starts the TPM and establishes the root of trust for the
333  * anti-rollback mechanism.  SetupTPM can fail for three reasons.  1 A bug. 2 a
334  * TPM hardware failure. 3 An unexpected TPM state due to some attack.  In
335  * general we cannot easily distinguish the kind of failure, so our strategy is
336  * to reboot in recovery mode in all cases.  The recovery mode calls SetupTPM
337  * again, which executes (almost) the same sequence of operations.  There is a
338  * good chance that, if recovery mode was entered because of a TPM failure, the
339  * failure will repeat itself.  (In general this is impossible to guarantee
340  * because we have no way of creating the exact TPM initial state at the
341  * previous boot.)  In recovery mode, we ignore the failure and continue, thus
342  * giving the recovery kernel a chance to fix things (that's why we don't set
343  * bGlobalLock).  The choice is between a knowingly insecure device and a
344  * bricked device.
345  *
346  * As a side note, observe that we go through considerable hoops to avoid using
347  * the STCLEAR permissions for the index spaces.  We do this to avoid writing
348  * to the TPM flashram at every reboot or wake-up, because of concerns about
349  * the durability of the NVRAM.
350  */
SetupTPM(int developer_mode,int disable_dev_request,int clear_tpm_owner_request,RollbackSpaceFirmware * rsf)351 uint32_t SetupTPM(int developer_mode, int disable_dev_request,
352                   int clear_tpm_owner_request, RollbackSpaceFirmware* rsf)
353 {
354 	uint8_t in_flags;
355 	uint8_t disable;
356 	uint8_t deactivated;
357 	uint32_t result;
358 	uint32_t versions;
359 
360 	RETURN_ON_FAILURE(TlclLibInit());
361 
362 #ifdef TEGRA_SOFT_REBOOT_WORKAROUND
363 	result = TlclStartup();
364 	if (result == TPM_E_INVALID_POSTINIT) {
365 		/*
366 		 * Some prototype hardware doesn't reset the TPM on a CPU
367 		 * reset.  We do a hard reset to get around this.
368 		 */
369 		VBDEBUG(("TPM: soft reset detected\n", result));
370 		return TPM_E_MUST_REBOOT;
371 	} else if (result != TPM_SUCCESS) {
372 		VBDEBUG(("TPM: TlclStartup returned %08x\n", result));
373 		return result;
374 	}
375 #else
376 	RETURN_ON_FAILURE(TlclStartup());
377 #endif
378 
379   /*
380    * Some TPMs start the self test automatically at power on.  In that case we
381    * don't need to call ContinueSelfTest.  On some (other) TPMs,
382    * ContinueSelfTest may block.  In that case, we definitely don't want to
383    * call it here.  For TPMs in the intersection of these two sets, we're
384    * screwed.  (In other words: TPMs that require manually starting the
385    * self-test AND block will have poor performance until we split
386    * TlclSendReceive() into Send() and Receive(), and have a state machine to
387    * control setup.)
388    *
389    * This comment is likely to become obsolete in the near future, so don't
390    * trust it.  It may have not been updated.
391    */
392 #ifdef TPM_MANUAL_SELFTEST
393 #ifdef TPM_BLOCKING_CONTINUESELFTEST
394 #warning "lousy TPM!"
395 #endif
396 	RETURN_ON_FAILURE(TlclContinueSelfTest());
397 #endif
398 	result = TlclAssertPhysicalPresence();
399 	if (result != TPM_SUCCESS) {
400 		/*
401 		 * It is possible that the TPM was delivered with the physical
402 		 * presence command disabled.  This tries enabling it, then
403 		 * tries asserting PP again.
404 		 */
405 		RETURN_ON_FAILURE(TlclPhysicalPresenceCMDEnable());
406 		RETURN_ON_FAILURE(TlclAssertPhysicalPresence());
407 	}
408 
409 	/* Check that the TPM is enabled and activated. */
410 	RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated, NULL));
411 	if (disable || deactivated) {
412 		VBDEBUG(("TPM: disabled (%d) or deactivated (%d).  Fixing...\n",
413 			 disable, deactivated));
414 		RETURN_ON_FAILURE(TlclSetEnable());
415 		RETURN_ON_FAILURE(TlclSetDeactivated(0));
416 		VBDEBUG(("TPM: Must reboot to re-enable\n"));
417 		return TPM_E_MUST_REBOOT;
418 	}
419 
420 	/* Read the firmware space. */
421 	result = ReadSpaceFirmware(rsf);
422 	if (TPM_E_BADINDEX == result) {
423 		RollbackSpaceKernel rsk;
424 
425 		/*
426 		 * This is the first time we've run, and the TPM has not been
427 		 * initialized.  Initialize it.
428 		 */
429 		VBDEBUG(("TPM: Not initialized yet.\n"));
430 		RETURN_ON_FAILURE(OneTimeInitializeTPM(rsf, &rsk));
431 	} else if (TPM_SUCCESS != result) {
432 		VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n"));
433 		return TPM_E_CORRUPTED_STATE;
434 	}
435 	Memcpy(&versions, &rsf->fw_versions, sizeof(versions));
436 	VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n",
437 		 rsf->struct_version, rsf->flags, versions));
438 	in_flags = rsf->flags;
439 
440 	/* If we've been asked to clear the virtual dev-mode flag, do so now */
441 	if (disable_dev_request) {
442 		rsf->flags &= ~FLAG_VIRTUAL_DEV_MODE_ON;
443 		VBDEBUG(("TPM: Clearing virt dev-switch: f%x\n", rsf->flags));
444 	}
445 
446 	/*
447 	 * The developer_mode value that's passed in is only set by a hardware
448 	 * dev-switch. We should OR it with the virtual switch, whether or not
449 	 * the virtual switch is used. If it's not used, it shouldn't change,
450 	 * so it doesn't matter.
451 	 */
452 	if (rsf->flags & FLAG_VIRTUAL_DEV_MODE_ON)
453 		developer_mode = 1;
454 
455 	/*
456 	 * Clear ownership if developer flag has toggled, or if an owner-clear
457 	 * has been requested.
458 	 */
459 	if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) !=
460 	    (in_flags & FLAG_LAST_BOOT_DEVELOPER)) {
461 		VBDEBUG(("TPM: Developer flag changed; clearing owner.\n"));
462 		RETURN_ON_FAILURE(TPMClearAndReenable());
463 	} else if (clear_tpm_owner_request) {
464 		VBDEBUG(("TPM: Clearing owner as specifically requested.\n"));
465 		RETURN_ON_FAILURE(TPMClearAndReenable());
466 	}
467 
468 	if (developer_mode)
469 		rsf->flags |= FLAG_LAST_BOOT_DEVELOPER;
470 	else
471 		rsf->flags &= ~FLAG_LAST_BOOT_DEVELOPER;
472 
473 
474 	/* If firmware space is dirty, flush it back to the TPM */
475 	if (rsf->flags != in_flags) {
476 		VBDEBUG(("TPM: Updating firmware space.\n"));
477 		RETURN_ON_FAILURE(WriteSpaceFirmware(rsf));
478 	}
479 
480 	VBDEBUG(("TPM: SetupTPM() succeeded\n"));
481 	return TPM_SUCCESS;
482 }
483 
484 
485 #ifdef DISABLE_ROLLBACK_TPM
486 /* Dummy implementations which don't support TPM rollback protection */
487 
RollbackS3Resume(void)488 uint32_t RollbackS3Resume(void)
489 {
490 #ifndef CHROMEOS_ENVIRONMENT
491 	/*
492 	 * Initialize the TPM, but ignore return codes.  In ChromeOS
493 	 * environment, don't even talk to the TPM.
494 	 */
495 	TlclLibInit();
496 	TlclResume();
497 #endif
498 	return TPM_SUCCESS;
499 }
500 
RollbackFirmwareSetup(int is_hw_dev,int disable_dev_request,int clear_tpm_owner_request,int * is_virt_dev,uint32_t * version)501 uint32_t RollbackFirmwareSetup(int is_hw_dev,
502                                int disable_dev_request,
503                                int clear_tpm_owner_request,
504                                int *is_virt_dev, uint32_t *version)
505 {
506 #ifndef CHROMEOS_ENVIRONMENT
507 	/*
508 	 * Initialize the TPM, but ignores return codes.  In ChromeOS
509 	 * environment, don't even talk to the TPM.
510 	 */
511 	TlclLibInit();
512 	TlclStartup();
513 	TlclContinueSelfTest();
514 #endif
515 	*is_virt_dev = 0;
516 	*version = 0;
517 	return TPM_SUCCESS;
518 }
519 
RollbackFirmwareWrite(uint32_t version)520 uint32_t RollbackFirmwareWrite(uint32_t version)
521 {
522 	return TPM_SUCCESS;
523 }
524 
RollbackFirmwareLock(void)525 uint32_t RollbackFirmwareLock(void)
526 {
527 	return TPM_SUCCESS;
528 }
529 
RollbackKernelRead(uint32_t * version)530 uint32_t RollbackKernelRead(uint32_t* version)
531 {
532 	*version = 0;
533 	return TPM_SUCCESS;
534 }
535 
RollbackKernelWrite(uint32_t version)536 uint32_t RollbackKernelWrite(uint32_t version)
537 {
538 	return TPM_SUCCESS;
539 }
540 
RollbackBackupRead(uint8_t * raw)541 uint32_t RollbackBackupRead(uint8_t *raw)
542 {
543 	return TPM_SUCCESS;
544 }
545 
RollbackBackupWrite(uint8_t * raw)546 uint32_t RollbackBackupWrite(uint8_t *raw)
547 {
548 	return TPM_SUCCESS;
549 }
550 
RollbackKernelLock(int recovery_mode)551 uint32_t RollbackKernelLock(int recovery_mode)
552 {
553 	return TPM_SUCCESS;
554 }
555 
556 #else
557 
RollbackS3Resume(void)558 uint32_t RollbackS3Resume(void)
559 {
560 	uint32_t result;
561 	RETURN_ON_FAILURE(TlclLibInit());
562 	result = TlclResume();
563 	if (result == TPM_E_INVALID_POSTINIT) {
564 		/*
565 		 * We're on a platform where the TPM maintains power in S3, so
566 		 * it's already initialized.
567 		 */
568 		return TPM_SUCCESS;
569 	}
570 	return result;
571 }
572 
RollbackFirmwareSetup(int is_hw_dev,int disable_dev_request,int clear_tpm_owner_request,int * is_virt_dev,uint32_t * version)573 uint32_t RollbackFirmwareSetup(int is_hw_dev,
574                                int disable_dev_request,
575                                int clear_tpm_owner_request,
576                                int *is_virt_dev, uint32_t *version)
577 {
578 	RollbackSpaceFirmware rsf;
579 
580 	/* Set version to 0 in case we fail */
581 	*version = 0;
582 
583 	RETURN_ON_FAILURE(SetupTPM(is_hw_dev, disable_dev_request,
584 				   clear_tpm_owner_request, &rsf));
585 	Memcpy(version, &rsf.fw_versions, sizeof(*version));
586 	*is_virt_dev = (rsf.flags & FLAG_VIRTUAL_DEV_MODE_ON) ? 1 : 0;
587 	VBDEBUG(("TPM: RollbackFirmwareSetup %x\n", (int)*version));
588 	return TPM_SUCCESS;
589 }
590 
RollbackFirmwareWrite(uint32_t version)591 uint32_t RollbackFirmwareWrite(uint32_t version)
592 {
593 	RollbackSpaceFirmware rsf;
594 	uint32_t old_version;
595 
596 	RETURN_ON_FAILURE(ReadSpaceFirmware(&rsf));
597 	Memcpy(&old_version, &rsf.fw_versions, sizeof(old_version));
598 	VBDEBUG(("TPM: RollbackFirmwareWrite %x --> %x\n", (int)old_version,
599 		 (int)version));
600 	Memcpy(&rsf.fw_versions, &version, sizeof(version));
601 	return WriteSpaceFirmware(&rsf);
602 }
603 
RollbackFirmwareLock(void)604 uint32_t RollbackFirmwareLock(void)
605 {
606 	return TlclSetGlobalLock();
607 }
608 
RollbackKernelRead(uint32_t * version)609 uint32_t RollbackKernelRead(uint32_t* version)
610 {
611 	RollbackSpaceKernel rsk;
612 	uint32_t perms, uid;
613 
614 	/*
615 	 * Read the kernel space and verify its permissions.  If the kernel
616 	 * space has the wrong permission, or it doesn't contain the right
617 	 * identifier, we give up.  This will need to be fixed by the
618 	 * recovery kernel.  We have to worry about this because at any time
619 	 * (even with PP turned off) the TPM owner can remove and redefine a
620 	 * PP-protected space (but not write to it).
621 	 */
622 	RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
623 	RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_NV_INDEX, &perms));
624 	Memcpy(&uid, &rsk.uid, sizeof(uid));
625 	if (TPM_NV_PER_PPWRITE != perms || ROLLBACK_SPACE_KERNEL_UID != uid)
626 		return TPM_E_CORRUPTED_STATE;
627 
628 	Memcpy(version, &rsk.kernel_versions, sizeof(*version));
629 	VBDEBUG(("TPM: RollbackKernelRead %x\n", (int)*version));
630 	return TPM_SUCCESS;
631 }
632 
RollbackKernelWrite(uint32_t version)633 uint32_t RollbackKernelWrite(uint32_t version)
634 {
635 	RollbackSpaceKernel rsk;
636 	uint32_t old_version;
637 	RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
638 	Memcpy(&old_version, &rsk.kernel_versions, sizeof(old_version));
639 	VBDEBUG(("TPM: RollbackKernelWrite %x --> %x\n",
640 		 (int)old_version, (int)version));
641 	Memcpy(&rsk.kernel_versions, &version, sizeof(version));
642 	return WriteSpaceKernel(&rsk);
643 }
644 
645 /*
646  * We don't really care whether the TPM owner has been messing with this or
647  * not. We lock it along with the Kernel space just to avoid problems, but it's
648  * only useful in dev-mode and only when the battery has been drained
649  * completely. There aren't any security issues. It's just in the TPM because
650  * we don't have any other place to keep it.
651  */
RollbackBackupRead(uint8_t * raw)652 uint32_t RollbackBackupRead(uint8_t *raw)
653 {
654 	uint32_t r;
655 	r = TlclRead(BACKUP_NV_INDEX, raw, BACKUP_NV_SIZE);
656 	VBDEBUG(("TPM: %s returning 0x%x\n", __func__, r));
657 	return r;
658 }
659 
RollbackBackupWrite(uint8_t * raw)660 uint32_t RollbackBackupWrite(uint8_t *raw)
661 {
662 	uint32_t r;
663 	r = TlclWrite(BACKUP_NV_INDEX, raw, BACKUP_NV_SIZE);
664 	VBDEBUG(("TPM: %s returning 0x%x\n", __func__, r));
665 	return r;
666 }
667 
RollbackKernelLock(int recovery_mode)668 uint32_t RollbackKernelLock(int recovery_mode)
669 {
670 	if (recovery_mode)
671 		return TPM_SUCCESS;
672 	else
673 		return TlclLockPhysicalPresence();
674 }
675 
676 #endif /* DISABLE_ROLLBACK_TPM */
677