blob: 84eee0083aca8279151b8a3398a75c7b33e17cb3 [file] [log] [blame]
Randall Spanglera3eac792013-01-23 13:04:05 -08001/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
Gaurav Shahce0cc302010-03-24 13:48:55 -07002 * 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
Bill Richardson0c3ba242013-03-29 11:09:30 -07009#include "sysincludes.h"
10
Randall Spanglerbf6263d2016-10-13 16:27:45 -070011#include "2crc8.h"
Gaurav Shahce0cc302010-03-24 13:48:55 -070012#include "rollback_index.h"
Gaurav Shahce0cc302010-03-24 13:48:55 -070013#include "tlcl.h"
Gaurav Shah887e3d42010-04-27 16:26:48 -070014#include "tss_constants.h"
Randall Spanglerf3029052010-06-16 13:42:58 -070015#include "utility.h"
Randall Spanglere49e8af2011-07-08 13:03:32 -070016#include "vboot_api.h"
Gaurav Shahce0cc302010-03-24 13:48:55 -070017
Bill Richardsonfeac0772012-05-16 10:04:38 -070018#ifndef offsetof
19#define offsetof(A,B) __builtin_offsetof(A,B)
20#endif
21
Aaron Durbin612797e2013-02-26 09:40:55 -060022/*
23 * Provide protoypes for functions not in the header file. These prototypes
24 * fix -Wmissing-prototypes warnings.
25 */
26uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf);
27uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf);
28uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk);
29uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk);
30
Randall Spangler17f8d342013-01-11 10:55:11 -080031#ifdef FOR_TEST
Randall Spangler7993f252013-01-29 15:01:12 -080032/*
33 * Compiling for unit test, so we need the real implementations of
Randall Spangler46d37cf2011-08-29 12:37:15 -070034 * rollback functions. The unit test mocks the underlying tlcl
Randall Spangler7993f252013-01-29 15:01:12 -080035 * functions, so this is ok to run on the host.
36 */
Randall Spangler46d37cf2011-08-29 12:37:15 -070037#undef CHROMEOS_ENVIRONMENT
38#undef DISABLE_ROLLBACK_TPM
39#endif
40
Randall Spangler7993f252013-01-29 15:01:12 -080041#define RETURN_ON_FAILURE(tpm_command) do { \
Aaron Durbinab63d3c2013-02-26 09:51:58 -060042 uint32_t result_; \
43 if ((result_ = (tpm_command)) != TPM_SUCCESS) { \
Randall Spangler7993f252013-01-29 15:01:12 -080044 VBDEBUG(("Rollback: %08x returned by " #tpm_command \
Aaron Durbinab63d3c2013-02-26 09:51:58 -060045 "\n", (int)result_)); \
46 return result_; \
Randall Spangler7993f252013-01-29 15:01:12 -080047 } \
48 } while (0)
Luigi Semenzato59204c52010-06-09 13:37:15 -070049
Randall Spangler4abede32010-08-12 16:40:32 -070050
Randall Spanglera3eac792013-01-23 13:04:05 -080051uint32_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));
Randall Spanglerada3fa92010-07-20 15:35:49 -070057
Randall Spanglera3eac792013-01-23 13:04:05 -080058 return TPM_SUCCESS;
Luigi Semenzato361049c2010-06-22 13:37:53 -070059}
60
Randall Spanglera3eac792013-01-23 13:04:05 -080061uint32_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 }
Luigi Semenzato361049c2010-06-22 13:37:53 -070070}
71
Randall Spangler4abede32010-08-12 16:40:32 -070072/* Functions to read and write firmware and kernel spaces. */
Randall Spanglera3eac792013-01-23 13:04:05 -080073uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf)
74{
75 uint32_t r;
76 int attempts = 3;
Bill Richardsonfeac0772012-05-16 10:04:38 -070077
Randall Spanglera3eac792013-01-23 13:04:05 -080078 while (attempts--) {
79 r = TlclRead(FIRMWARE_NV_INDEX, rsf,
80 sizeof(RollbackSpaceFirmware));
81 if (r != TPM_SUCCESS)
82 return r;
Bill Richardsonfeac0772012-05-16 10:04:38 -070083
Randall Spanglera3eac792013-01-23 13:04:05 -080084 /*
85 * No CRC in this version, so we'll create one when we write
86 * it. Note that we're marking this as version 2, not
87 * ROLLBACK_SPACE_FIRMWARE_VERSION, because version 2 just
88 * added the CRC. Later versions will need to set default
89 * values for any extra fields explicitly (probably here).
90 */
91 if (rsf->struct_version < 2) {
92 /* Danger Will Robinson! Danger! */
93 rsf->struct_version = 2;
94 return TPM_SUCCESS;
95 }
Bill Richardsonfeac0772012-05-16 10:04:38 -070096
Randall Spanglera3eac792013-01-23 13:04:05 -080097 /*
98 * If the CRC is good, we're done. If it's bad, try a couple
99 * more times to see if it gets better before we give up. It
100 * could just be noise.
101 */
Randall Spanglerbf6263d2016-10-13 16:27:45 -0700102 if (rsf->crc8 == vb2_crc8(rsf,
Randall Spanglera3eac792013-01-23 13:04:05 -0800103 offsetof(RollbackSpaceFirmware, crc8)))
104 return TPM_SUCCESS;
Bill Richardsonfeac0772012-05-16 10:04:38 -0700105
Randall Spanglera3eac792013-01-23 13:04:05 -0800106 VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
107 }
Bill Richardsonfeac0772012-05-16 10:04:38 -0700108
Randall Spanglera3eac792013-01-23 13:04:05 -0800109 VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
110 return TPM_E_CORRUPTED_STATE;
Luigi Semenzato4f11c362010-06-10 11:01:04 -0700111}
112
Randall Spanglera3eac792013-01-23 13:04:05 -0800113uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf)
114{
115 RollbackSpaceFirmware rsf2;
116 uint32_t r;
117 int attempts = 3;
Bill Richardsonfeac0772012-05-16 10:04:38 -0700118
Randall Spanglera3eac792013-01-23 13:04:05 -0800119 /* All writes should use struct_version 2 or greater. */
120 if (rsf->struct_version < 2)
121 rsf->struct_version = 2;
Randall Spanglerbf6263d2016-10-13 16:27:45 -0700122 rsf->crc8 = vb2_crc8(rsf, offsetof(RollbackSpaceFirmware, crc8));
Bill Richardsonfeac0772012-05-16 10:04:38 -0700123
Randall Spanglera3eac792013-01-23 13:04:05 -0800124 while (attempts--) {
125 r = SafeWrite(FIRMWARE_NV_INDEX, rsf,
126 sizeof(RollbackSpaceFirmware));
127 /* Can't write, not gonna try again */
128 if (r != TPM_SUCCESS)
129 return r;
Bill Richardsonfeac0772012-05-16 10:04:38 -0700130
Randall Spanglera3eac792013-01-23 13:04:05 -0800131 /* Read it back to be sure it got the right values. */
132 r = ReadSpaceFirmware(&rsf2); /* This checks the CRC */
133 if (r == TPM_SUCCESS)
134 return r;
Bill Richardsonfeac0772012-05-16 10:04:38 -0700135
Randall Spanglera3eac792013-01-23 13:04:05 -0800136 VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
137 /* Try writing it again. Maybe it was garbled on the way out. */
138 }
Bill Richardsonfeac0772012-05-16 10:04:38 -0700139
Randall Spanglera3eac792013-01-23 13:04:05 -0800140 VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
141 return TPM_E_CORRUPTED_STATE;
Luigi Semenzato4f11c362010-06-10 11:01:04 -0700142}
143
Randall Spanglera3eac792013-01-23 13:04:05 -0800144uint32_t SetVirtualDevMode(int val)
145{
146 RollbackSpaceFirmware rsf;
Bill Richardsonec8df162012-06-07 04:21:14 -0700147
Randall Spanglera3eac792013-01-23 13:04:05 -0800148 VBDEBUG(("TPM: Entering %s()\n", __func__));
149 if (TPM_SUCCESS != ReadSpaceFirmware(&rsf))
150 return VBERROR_TPM_FIRMWARE_SETUP;
Bill Richardsonec8df162012-06-07 04:21:14 -0700151
Randall Spanglera3eac792013-01-23 13:04:05 -0800152 VBDEBUG(("TPM: flags were 0x%02x\n", rsf.flags));
153 if (val)
154 rsf.flags |= FLAG_VIRTUAL_DEV_MODE_ON;
155 else
156 rsf.flags &= ~FLAG_VIRTUAL_DEV_MODE_ON;
157 /*
158 * NOTE: This doesn't update the FLAG_LAST_BOOT_DEVELOPER bit. That
Randall Spangler2afa8732016-05-19 09:36:46 -0700159 * will be done on the next boot.
Randall Spanglera3eac792013-01-23 13:04:05 -0800160 */
161 VBDEBUG(("TPM: flags are now 0x%02x\n", rsf.flags));
Bill Richardsonec8df162012-06-07 04:21:14 -0700162
Randall Spanglera3eac792013-01-23 13:04:05 -0800163 if (TPM_SUCCESS != WriteSpaceFirmware(&rsf))
164 return VBERROR_TPM_SET_BOOT_MODE_STATE;
Bill Richardsonec8df162012-06-07 04:21:14 -0700165
Randall Spanglera3eac792013-01-23 13:04:05 -0800166 VBDEBUG(("TPM: Leaving %s()\n", __func__));
167 return VBERROR_SUCCESS;
Bill Richardsonec8df162012-06-07 04:21:14 -0700168}
169
Randall Spanglera3eac792013-01-23 13:04:05 -0800170uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk)
171{
172 uint32_t r;
173 int attempts = 3;
Randall Spangler4abede32010-08-12 16:40:32 -0700174
Randall Spanglera3eac792013-01-23 13:04:05 -0800175 while (attempts--) {
176 r = TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
177 if (r != TPM_SUCCESS)
178 return r;
Bill Richardsonfeac0772012-05-16 10:04:38 -0700179
Randall Spanglera3eac792013-01-23 13:04:05 -0800180 /*
181 * No CRC in this version, so we'll create one when we write
182 * it. Note that we're marking this as version 2, not
183 * ROLLBACK_SPACE_KERNEL_VERSION, because version 2 just added
184 * the CRC. Later versions will need to set default values for
185 * any extra fields explicitly (probably here).
186 */
187 if (rsk->struct_version < 2) {
188 /* Danger Will Robinson! Danger! */
189 rsk->struct_version = 2;
190 return TPM_SUCCESS;
191 }
Bill Richardsonfeac0772012-05-16 10:04:38 -0700192
Randall Spanglera3eac792013-01-23 13:04:05 -0800193 /*
194 * If the CRC is good, we're done. If it's bad, try a couple
195 * more times to see if it gets better before we give up. It
196 * could just be noise.
197 */
Randall Spanglerbf6263d2016-10-13 16:27:45 -0700198 if (rsk->crc8 ==
199 vb2_crc8(rsk, offsetof(RollbackSpaceKernel, crc8)))
Randall Spanglera3eac792013-01-23 13:04:05 -0800200 return TPM_SUCCESS;
Bill Richardsonfeac0772012-05-16 10:04:38 -0700201
Randall Spanglera3eac792013-01-23 13:04:05 -0800202 VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
203 }
Bill Richardsonfeac0772012-05-16 10:04:38 -0700204
Randall Spanglera3eac792013-01-23 13:04:05 -0800205 VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
206 return TPM_E_CORRUPTED_STATE;
Bill Richardsonfeac0772012-05-16 10:04:38 -0700207}
208
Randall Spanglera3eac792013-01-23 13:04:05 -0800209uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk)
210{
211 RollbackSpaceKernel rsk2;
212 uint32_t r;
213 int attempts = 3;
Bill Richardsonfeac0772012-05-16 10:04:38 -0700214
Randall Spanglera3eac792013-01-23 13:04:05 -0800215 /* All writes should use struct_version 2 or greater. */
216 if (rsk->struct_version < 2)
217 rsk->struct_version = 2;
Randall Spanglerbf6263d2016-10-13 16:27:45 -0700218 rsk->crc8 = vb2_crc8(rsk, offsetof(RollbackSpaceKernel, crc8));
Bill Richardsonfeac0772012-05-16 10:04:38 -0700219
Randall Spanglera3eac792013-01-23 13:04:05 -0800220 while (attempts--) {
221 r = SafeWrite(KERNEL_NV_INDEX, rsk,
222 sizeof(RollbackSpaceKernel));
223 /* Can't write, not gonna try again */
224 if (r != TPM_SUCCESS)
225 return r;
Bill Richardsonfeac0772012-05-16 10:04:38 -0700226
Randall Spanglera3eac792013-01-23 13:04:05 -0800227 /* Read it back to be sure it got the right values. */
228 r = ReadSpaceKernel(&rsk2); /* This checks the CRC */
229 if (r == TPM_SUCCESS)
230 return r;
Bill Richardsonfeac0772012-05-16 10:04:38 -0700231
Randall Spanglera3eac792013-01-23 13:04:05 -0800232 VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
233 /* Try writing it again. Maybe it was garbled on the way out. */
234 }
Bill Richardsonfeac0772012-05-16 10:04:38 -0700235
Randall Spanglera3eac792013-01-23 13:04:05 -0800236 VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
237 return TPM_E_CORRUPTED_STATE;
238}
239
Randall Spangler39f66112010-07-14 09:10:23 -0700240#ifdef DISABLE_ROLLBACK_TPM
Randall Spanglerada3fa92010-07-20 15:35:49 -0700241/* Dummy implementations which don't support TPM rollback protection */
Randall Spangler39f66112010-07-14 09:10:23 -0700242
Randall Spanglera3eac792013-01-23 13:04:05 -0800243uint32_t RollbackKernelRead(uint32_t* version)
244{
245 *version = 0;
246 return TPM_SUCCESS;
Randall Spangler39f66112010-07-14 09:10:23 -0700247}
248
Randall Spanglera3eac792013-01-23 13:04:05 -0800249uint32_t RollbackKernelWrite(uint32_t version)
250{
251 return TPM_SUCCESS;
Randall Spangler39f66112010-07-14 09:10:23 -0700252}
253
Shawn Nematbakhsh964144b2013-07-22 13:33:46 -0700254uint32_t RollbackKernelLock(int recovery_mode)
Randall Spanglera3eac792013-01-23 13:04:05 -0800255{
256 return TPM_SUCCESS;
Randall Spangler39f66112010-07-14 09:10:23 -0700257}
258
Randall Spangler53195652016-05-10 09:45:05 -0700259uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp)
260{
Randall Spangler664096b2016-10-13 16:16:41 -0700261 memset(fwmp, 0, sizeof(*fwmp));
Randall Spangler53195652016-05-10 09:45:05 -0700262 return TPM_SUCCESS;
263}
264
Randall Spangler39f66112010-07-14 09:10:23 -0700265#else
Randall Spangler1fe16072010-09-02 11:37:51 -0700266
Randall Spanglera3eac792013-01-23 13:04:05 -0800267uint32_t RollbackKernelRead(uint32_t* version)
268{
269 RollbackSpaceKernel rsk;
Randall Spanglerbb5d9f12010-08-16 15:36:07 -0700270
Randall Spanglera3eac792013-01-23 13:04:05 -0800271 /*
272 * Read the kernel space and verify its permissions. If the kernel
273 * space has the wrong permission, or it doesn't contain the right
274 * identifier, we give up. This will need to be fixed by the
275 * recovery kernel. We have to worry about this because at any time
276 * (even with PP turned off) the TPM owner can remove and redefine a
277 * PP-protected space (but not write to it).
278 */
279 RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
Vadim Bendebury3c9acf82016-06-28 10:15:11 -0700280#ifndef TPM2_MODE
281 /*
282 * TODO(vbendeb): restore this when it is defined how the kernel space
283 * gets protected.
284 */
285 {
286 uint32_t perms, uid;
Randall Spanglerbb5d9f12010-08-16 15:36:07 -0700287
Vadim Bendebury3c9acf82016-06-28 10:15:11 -0700288 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_NV_INDEX, &perms));
Randall Spangler664096b2016-10-13 16:16:41 -0700289 memcpy(&uid, &rsk.uid, sizeof(uid));
Vadim Bendebury3c9acf82016-06-28 10:15:11 -0700290 if (TPM_NV_PER_PPWRITE != perms ||
291 ROLLBACK_SPACE_KERNEL_UID != uid)
292 return TPM_E_CORRUPTED_STATE;
293 }
294#endif
Randall Spangler664096b2016-10-13 16:16:41 -0700295 memcpy(version, &rsk.kernel_versions, sizeof(*version));
Gabe Black522da3e2013-03-02 21:00:03 -0800296 VBDEBUG(("TPM: RollbackKernelRead %x\n", (int)*version));
Randall Spanglera3eac792013-01-23 13:04:05 -0800297 return TPM_SUCCESS;
Randall Spangler10788382010-06-23 15:35:31 -0700298}
299
Randall Spanglera3eac792013-01-23 13:04:05 -0800300uint32_t RollbackKernelWrite(uint32_t version)
301{
302 RollbackSpaceKernel rsk;
Gabe Black522da3e2013-03-02 21:00:03 -0800303 uint32_t old_version;
Randall Spanglera3eac792013-01-23 13:04:05 -0800304 RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
Randall Spangler664096b2016-10-13 16:16:41 -0700305 memcpy(&old_version, &rsk.kernel_versions, sizeof(old_version));
Randall Spanglera3eac792013-01-23 13:04:05 -0800306 VBDEBUG(("TPM: RollbackKernelWrite %x --> %x\n",
Gabe Black522da3e2013-03-02 21:00:03 -0800307 (int)old_version, (int)version));
Randall Spangler664096b2016-10-13 16:16:41 -0700308 memcpy(&rsk.kernel_versions, &version, sizeof(version));
Randall Spanglera3eac792013-01-23 13:04:05 -0800309 return WriteSpaceKernel(&rsk);
Randall Spangler10788382010-06-23 15:35:31 -0700310}
311
Shawn Nematbakhsh964144b2013-07-22 13:33:46 -0700312uint32_t RollbackKernelLock(int recovery_mode)
Randall Spanglera3eac792013-01-23 13:04:05 -0800313{
Julius Werner957b4242015-05-08 22:54:14 -0700314 static int kernel_locked = 0;
315 uint32_t r;
316
317 if (recovery_mode || kernel_locked)
Randall Spanglera3eac792013-01-23 13:04:05 -0800318 return TPM_SUCCESS;
Julius Werner957b4242015-05-08 22:54:14 -0700319
320 r = TlclLockPhysicalPresence();
321 if (TPM_SUCCESS == r)
322 kernel_locked = 1;
323 return r;
Randall Spangler10788382010-06-23 15:35:31 -0700324}
Randall Spangler39f66112010-07-14 09:10:23 -0700325
Randall Spangler946abf12016-04-15 14:49:40 -0700326uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp)
327{
Randall Spanglerb3a625f2016-07-21 15:33:31 -0700328 union {
329 /*
330 * Use a union for buf and bf, rather than making bf a pointer
331 * to a bare uint8_t[] buffer. This ensures bf will be aligned
332 * if necesssary for the target platform.
333 */
334 uint8_t buf[FWMP_NV_MAX_SIZE];
335 struct RollbackSpaceFwmp bf;
336 } u;
Randall Spangler946abf12016-04-15 14:49:40 -0700337 uint32_t r;
338 int attempts = 3;
339
340 /* Clear destination in case error or FWMP not present */
Randall Spangler664096b2016-10-13 16:16:41 -0700341 memset(fwmp, 0, sizeof(*fwmp));
Randall Spangler946abf12016-04-15 14:49:40 -0700342
343 while (attempts--) {
344 /* Try to read entire 1.0 struct */
Randall Spanglerb3a625f2016-07-21 15:33:31 -0700345 r = TlclRead(FWMP_NV_INDEX, u.buf, sizeof(u.bf));
Randall Spangler946abf12016-04-15 14:49:40 -0700346 if (r == TPM_E_BADINDEX) {
347 /* Missing space is not an error; use defaults */
348 VBDEBUG(("TPM: %s() - no FWMP space\n", __func__));
349 return TPM_SUCCESS;
350 } else if (r != TPM_SUCCESS) {
351 VBDEBUG(("TPM: %s() - read returned 0x%x\n",
352 __func__, r));
353 return r;
354 }
355
356 /*
357 * Struct must be at least big enough for 1.0, but not bigger
358 * than our buffer size.
359 */
Randall Spanglerb3a625f2016-07-21 15:33:31 -0700360 if (u.bf.struct_size < sizeof(u.bf) ||
361 u.bf.struct_size > sizeof(u.buf))
Randall Spangler946abf12016-04-15 14:49:40 -0700362 return TPM_E_STRUCT_SIZE;
363
364 /*
365 * If space is bigger than we expect, re-read so we properly
366 * compute the CRC.
367 */
Randall Spanglerb3a625f2016-07-21 15:33:31 -0700368 if (u.bf.struct_size > sizeof(u.bf)) {
369 r = TlclRead(FWMP_NV_INDEX, u.buf, u.bf.struct_size);
Randall Spangler946abf12016-04-15 14:49:40 -0700370 if (r != TPM_SUCCESS)
371 return r;
372 }
373
374 /* Verify CRC */
Randall Spanglerbf6263d2016-10-13 16:27:45 -0700375 if (u.bf.crc != vb2_crc8(u.buf + 2, u.bf.struct_size - 2)) {
Randall Spangler946abf12016-04-15 14:49:40 -0700376 VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
377 continue;
378 }
379
380 /* Verify major version is compatible */
Randall Spanglerb3a625f2016-07-21 15:33:31 -0700381 if ((u.bf.struct_version >> 4) !=
Randall Spangler946abf12016-04-15 14:49:40 -0700382 (ROLLBACK_SPACE_FWMP_VERSION >> 4))
383 return TPM_E_STRUCT_VERSION;
384
385 /*
386 * Copy to destination. Note that if the space is bigger than
387 * we expect (due to a minor version change), we only copy the
388 * part of the FWMP that we know what to do with.
389 *
390 * If this were a 1.1+ reader and the source was a 1.0 struct,
391 * we would need to take care of initializing the extra fields
392 * added in 1.1+. But that's not an issue yet.
393 */
Randall Spangler664096b2016-10-13 16:16:41 -0700394 memcpy(fwmp, &u.bf, sizeof(*fwmp));
Randall Spangler946abf12016-04-15 14:49:40 -0700395 return TPM_SUCCESS;
396 }
397
398 VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
399 return TPM_E_CORRUPTED_STATE;
400}
401
Randall Spangler53195652016-05-10 09:45:05 -0700402#endif /* DISABLE_ROLLBACK_TPM */