blob: a757f02f98e09032640d6ba303eaf57a54a4c869 [file] [log] [blame]
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -07001/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -07002 *
Martin Roth08d808f2017-02-09 18:06:16 -08003 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following disclaimer
11 * in the documentation and/or other materials provided with the
12 * distribution.
13 * * Neither the name of Google Inc. nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070031 * Functions for querying, manipulating and locking rollback indices
32 * stored in the TPM NVRAM.
33 */
34
Philipp Deppenwiese64e2d192017-10-18 17:13:07 +020035#include <security/tpm/antirollback.h>
Randall Spangler144c2282014-12-03 17:35:53 -080036#include <stdlib.h>
37#include <string.h>
Philipp Deppenwiesed88fb362017-10-18 20:26:18 +020038#include <security/tpm/tss.h>
Randall Spangler144c2282014-12-03 17:35:53 -080039#include <vb2_api.h>
Vadim Bendebury10ea1042016-06-06 12:12:34 -070040#include <console/console.h>
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070041
42#ifndef offsetof
43#define offsetof(A,B) __builtin_offsetof(A,B)
44#endif
45
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070046#ifdef FOR_TEST
Daisuke Nojiri57990972014-07-15 19:47:32 -070047#include <stdio.h>
48#define VBDEBUG(format, args...) printf(format, ## args)
49#else
50#include <console/console.h>
51#define VBDEBUG(format, args...) \
52 printk(BIOS_INFO, "%s():%d: " format, __func__, __LINE__, ## args)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070053#endif
54
Daisuke Nojiri57990972014-07-15 19:47:32 -070055#define RETURN_ON_FAILURE(tpm_cmd) do { \
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070056 uint32_t result_; \
Daisuke Nojiri57990972014-07-15 19:47:32 -070057 if ((result_ = (tpm_cmd)) != TPM_SUCCESS) { \
58 VBDEBUG("Antirollback: %08x returned by " #tpm_cmd \
59 "\n", (int)result_); \
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070060 return result_; \
61 } \
62 } while (0)
63
Julius Werner76e33032015-01-30 18:45:27 -080064
Vadim Bendebury10ea1042016-06-06 12:12:34 -070065static uint32_t safe_write(uint32_t index, const void *data, uint32_t length);
66
Julius Werner76e33032015-01-30 18:45:27 -080067uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr,
68 enum vb2_pcr_digest which_digest)
69{
70 uint8_t buffer[VB2_PCR_DIGEST_RECOMMENDED_SIZE];
71 uint32_t size = sizeof(buffer);
72 int rv;
73
74 rv = vb2api_get_pcr_digest(ctx, which_digest, buffer, &size);
75 if (rv != VB2_SUCCESS)
76 return rv;
77 if (size < TPM_PCR_DIGEST)
78 return VB2_ERROR_UNKNOWN;
79
80 return tlcl_extend(pcr, buffer, NULL);
81}
82
Daisuke Nojiri57990972014-07-15 19:47:32 -070083static uint32_t read_space_firmware(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070084{
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070085 int attempts = 3;
86
87 while (attempts--) {
Daisuke Nojiri57990972014-07-15 19:47:32 -070088 RETURN_ON_FAILURE(tlcl_read(FIRMWARE_NV_INDEX, ctx->secdata,
89 VB2_SECDATA_SIZE));
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070090
Daisuke Nojiri57990972014-07-15 19:47:32 -070091 if (vb2api_secdata_check(ctx) == VB2_SUCCESS)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070092 return TPM_SUCCESS;
93
Daisuke Nojiri57990972014-07-15 19:47:32 -070094 VBDEBUG("TPM: %s() - bad CRC\n", __func__);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070095 }
96
Daisuke Nojiri57990972014-07-15 19:47:32 -070097 VBDEBUG("TPM: %s() - too many bad CRCs, giving up\n", __func__);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070098 return TPM_E_CORRUPTED_STATE;
99}
100
Furquan Shaikhb038f412016-11-07 23:47:11 -0800101static uint32_t read_space_rec_hash(uint8_t *data)
102{
103 RETURN_ON_FAILURE(tlcl_read(REC_HASH_NV_INDEX, data,
104 REC_HASH_NV_SIZE));
105 return TPM_SUCCESS;
106}
107
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700108static uint32_t write_secdata(uint32_t index,
109 const uint8_t *secdata,
110 uint32_t len)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700111{
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700112 uint8_t sd[32];
113 uint32_t rv;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700114 int attempts = 3;
115
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700116 if (len > sizeof(sd)) {
117 VBDEBUG("TPM: %s() - data is too large\n", __func__);
118 return TPM_E_WRITE_FAILURE;
119 }
120
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700121 while (attempts--) {
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700122 rv = safe_write(index, secdata, len);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700123 /* Can't write, not gonna try again */
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700124 if (rv != TPM_SUCCESS)
125 return rv;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700126
127 /* Read it back to be sure it got the right values. */
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700128 rv = tlcl_read(index, sd, len);
129 if (rv == TPM_SUCCESS && memcmp(secdata, sd, len) == 0)
130 return rv;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700131
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700132 VBDEBUG("TPM: %s() failed. trying again\n", __func__);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700133 /* Try writing it again. Maybe it was garbled on the way out. */
134 }
135
Daisuke Nojiri57990972014-07-15 19:47:32 -0700136 VBDEBUG("TPM: %s() - too many failures, giving up\n", __func__);
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700137
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700138 return TPM_E_CORRUPTED_STATE;
139}
140
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700141/*
142 * This is derived from rollback_index.h of vboot_reference. see struct
143 * RollbackSpaceKernel for details.
144 */
145static const uint8_t secdata_kernel[] = {
146 0x02,
147 0x4C, 0x57, 0x52, 0x47,
148 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00,
150 0xE8,
151};
152
Furquan Shaikhb038f412016-11-07 23:47:11 -0800153/*
154 * This is used to initialize the TPM space for recovery hash after defining
155 * it. Since there is no data available to calculate hash at the point where TPM
156 * space is defined, initialize it to all 0s.
157 */
158static const uint8_t rec_hash_data[REC_HASH_NV_SIZE] = { };
159
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700160#if IS_ENABLED(CONFIG_TPM2)
161
162/* Nothing special in the TPM2 path yet. */
163static uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
164{
165 return tlcl_write(index, data, length);
166}
167
Andrey Pronin278a5062018-01-26 12:47:51 -0800168static uint32_t set_space(const char *name, uint32_t index, const void *data,
169 uint32_t length)
170{
171 uint32_t rv;
172
173 rv = tlcl_define_space(index, length);
174 if (rv == TPM_E_NV_DEFINED) {
175 /*
176 * Continue with writing: it may be defined, but not written
177 * to. In that case a subsequent tlcl_read() would still return
178 * TPM_E_BADINDEX on TPM 2.0. The cases when some non-firmware
179 * space is defined while the firmware space is not there
180 * should be rare (interrupted initialization), so no big harm
181 * in writing once again even if it was written already.
182 */
183 VBDEBUG("%s: %s space already exists\n", __func__, name);
184 rv = TPM_SUCCESS;
185 }
186
187 if (rv != TPM_SUCCESS)
188 return rv;
189
190 return safe_write(index, data, length);
191}
192
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700193static uint32_t set_firmware_space(const void *firmware_blob)
194{
Andrey Pronin278a5062018-01-26 12:47:51 -0800195 return set_space("firmware", FIRMWARE_NV_INDEX, firmware_blob,
196 VB2_SECDATA_SIZE);
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700197}
198
199static uint32_t set_kernel_space(const void *kernel_blob)
200{
Andrey Pronin278a5062018-01-26 12:47:51 -0800201 return set_space("kernel", KERNEL_NV_INDEX, kernel_blob,
202 sizeof(secdata_kernel));
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700203}
204
Furquan Shaikhb038f412016-11-07 23:47:11 -0800205static uint32_t set_rec_hash_space(const uint8_t *data)
206{
Andrey Pronin278a5062018-01-26 12:47:51 -0800207 return set_space("MRC Hash", REC_HASH_NV_INDEX, data,
208 REC_HASH_NV_SIZE);
Furquan Shaikhb038f412016-11-07 23:47:11 -0800209}
210
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700211static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
212{
Vadim Bendeburyadfbbde2016-07-03 15:56:41 -0700213 RETURN_ON_FAILURE(tlcl_force_clear());
Vadim Bendebury38837012016-11-14 16:36:26 -0800214
215 /*
216 * Of all NVRAM spaces defined by this function the firmware space
217 * must be defined last, because its existence is considered an
218 * indication that TPM factory initialization was successfully
219 * completed.
220 */
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700221 RETURN_ON_FAILURE(set_kernel_space(secdata_kernel));
Furquan Shaikhb038f412016-11-07 23:47:11 -0800222
223 if (IS_ENABLED(CONFIG_VBOOT_HAS_REC_HASH_SPACE))
224 RETURN_ON_FAILURE(set_rec_hash_space(rec_hash_data));
225
Vadim Bendebury38837012016-11-14 16:36:26 -0800226 RETURN_ON_FAILURE(set_firmware_space(ctx->secdata));
227
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700228 return TPM_SUCCESS;
229}
230
231uint32_t tpm_clear_and_reenable(void)
232{
233 VBDEBUG("TPM: Clear and re-enable\n");
Vadim Bendebury494d3982016-09-28 18:59:39 -0700234 RETURN_ON_FAILURE(tlcl_force_clear());
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700235 return TPM_SUCCESS;
236}
237
Vadim Bendebury4c0851c2016-07-03 17:08:10 -0700238uint32_t antirollback_lock_space_firmware(void)
239{
240 return tlcl_lock_nv_write(FIRMWARE_NV_INDEX);
241}
242
Furquan Shaikhb038f412016-11-07 23:47:11 -0800243uint32_t antirollback_lock_space_rec_hash(void)
244{
245 return tlcl_lock_nv_write(REC_HASH_NV_INDEX);
246}
247
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700248#else
249
250uint32_t tpm_clear_and_reenable(void)
251{
252 VBDEBUG("TPM: Clear and re-enable\n");
253 RETURN_ON_FAILURE(tlcl_force_clear());
254 RETURN_ON_FAILURE(tlcl_set_enable());
255 RETURN_ON_FAILURE(tlcl_set_deactivated(0));
256
257 return TPM_SUCCESS;
258}
259
260/**
261 * Like tlcl_write(), but checks for write errors due to hitting the 64-write
262 * limit and clears the TPM when that happens. This can only happen when the
263 * TPM is unowned, so it is OK to clear it (and we really have no choice).
264 * This is not expected to happen frequently, but it could happen.
265 */
266
267static uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
268{
269 uint32_t result = tlcl_write(index, data, length);
270 if (result == TPM_E_MAXNVWRITES) {
271 RETURN_ON_FAILURE(tpm_clear_and_reenable());
272 return tlcl_write(index, data, length);
273 } else {
274 return result;
275 }
276}
277
278/**
279 * Similarly to safe_write(), this ensures we don't fail a DefineSpace because
280 * we hit the TPM write limit. This is even less likely to happen than with
281 * writes because we only define spaces once at initialization, but we'd
282 * rather be paranoid about this.
283 */
284static uint32_t safe_define_space(uint32_t index, uint32_t perm, uint32_t size)
285{
286 uint32_t result = tlcl_define_space(index, perm, size);
287 if (result == TPM_E_MAXNVWRITES) {
288 RETURN_ON_FAILURE(tpm_clear_and_reenable());
289 return tlcl_define_space(index, perm, size);
290 } else {
291 return result;
292 }
293}
294
Furquan Shaikhb038f412016-11-07 23:47:11 -0800295static uint32_t set_rec_hash_space(const uint8_t *data)
296{
297 RETURN_ON_FAILURE(safe_define_space(REC_HASH_NV_INDEX,
298 TPM_NV_PER_GLOBALLOCK |
299 TPM_NV_PER_PPWRITE,
300 REC_HASH_NV_SIZE));
301 RETURN_ON_FAILURE(write_secdata(REC_HASH_NV_INDEX, data,
302 REC_HASH_NV_SIZE));
303
304 return TPM_SUCCESS;
305}
306
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700307static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700308{
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700309 TPM_PERMANENT_FLAGS pflags;
310 uint32_t result;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700311
Daisuke Nojiri57990972014-07-15 19:47:32 -0700312 result = tlcl_get_permanent_flags(&pflags);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700313 if (result != TPM_SUCCESS)
314 return result;
315
316 /*
317 * TPM may come from the factory without physical presence finalized.
318 * Fix if necessary.
319 */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700320 VBDEBUG("TPM: physicalPresenceLifetimeLock=%d\n",
321 pflags.physicalPresenceLifetimeLock);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700322 if (!pflags.physicalPresenceLifetimeLock) {
Daisuke Nojiri57990972014-07-15 19:47:32 -0700323 VBDEBUG("TPM: Finalizing physical presence\n");
324 RETURN_ON_FAILURE(tlcl_finalize_physical_presence());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700325 }
326
327 /*
328 * The TPM will not enforce the NV authorization restrictions until the
329 * execution of a TPM_NV_DefineSpace with the handle of
330 * TPM_NV_INDEX_LOCK. Here we create that space if it doesn't already
331 * exist. */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700332 VBDEBUG("TPM: nvLocked=%d\n", pflags.nvLocked);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700333 if (!pflags.nvLocked) {
Daisuke Nojiri57990972014-07-15 19:47:32 -0700334 VBDEBUG("TPM: Enabling NV locking\n");
335 RETURN_ON_FAILURE(tlcl_set_nv_locked());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700336 }
337
338 /* Clear TPM owner, in case the TPM is already owned for some reason. */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700339 VBDEBUG("TPM: Clearing owner\n");
340 RETURN_ON_FAILURE(tpm_clear_and_reenable());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700341
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700342 /* Define and initialize the kernel space */
343 RETURN_ON_FAILURE(safe_define_space(KERNEL_NV_INDEX,
344 TPM_NV_PER_PPWRITE,
345 sizeof(secdata_kernel)));
346 RETURN_ON_FAILURE(write_secdata(KERNEL_NV_INDEX,
347 secdata_kernel,
348 sizeof(secdata_kernel)));
349
Daisuke Nojiri57990972014-07-15 19:47:32 -0700350 /* Defines and sets vb2 secdata space */
351 vb2api_secdata_create(ctx);
352 RETURN_ON_FAILURE(safe_define_space(FIRMWARE_NV_INDEX,
353 TPM_NV_PER_GLOBALLOCK |
354 TPM_NV_PER_PPWRITE,
355 VB2_SECDATA_SIZE));
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700356 RETURN_ON_FAILURE(write_secdata(FIRMWARE_NV_INDEX,
357 ctx->secdata,
358 VB2_SECDATA_SIZE));
Furquan Shaikhb038f412016-11-07 23:47:11 -0800359
360 /* Define and set rec hash space, if available. */
361 if (IS_ENABLED(CONFIG_VBOOT_HAS_REC_HASH_SPACE))
362 RETURN_ON_FAILURE(set_rec_hash_space(rec_hash_data));
363
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700364 return TPM_SUCCESS;
365}
Vadim Bendebury4c0851c2016-07-03 17:08:10 -0700366
367uint32_t antirollback_lock_space_firmware(void)
368{
369 return tlcl_set_global_lock();
370}
Furquan Shaikhb038f412016-11-07 23:47:11 -0800371
372uint32_t antirollback_lock_space_rec_hash(void)
373{
374 /*
375 * Nothing needs to be done here, since global lock is already set while
376 * locking firmware space.
377 */
378 return TPM_SUCCESS;
379}
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700380#endif
381
Vadim Bendebury673a2662016-11-11 09:33:43 -0800382/**
383 * Perform one-time initializations.
384 *
385 * Create the NVRAM spaces, and set their initial values as needed. Sets the
386 * nvLocked bit and ensures the physical presence command is enabled and
387 * locked.
388 */
389static uint32_t factory_initialize_tpm(struct vb2_context *ctx)
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700390{
391 uint32_t result;
392
393 /* Defines and sets vb2 secdata space */
394 vb2api_secdata_create(ctx);
395
396 VBDEBUG("TPM: factory initialization\n");
397
398 /*
399 * Do a full test. This only happens the first time the device is
400 * turned on in the factory, so performance is not an issue. This is
401 * almost certainly not necessary, but it gives us more confidence
402 * about some code paths below that are difficult to
403 * test---specifically the ones that set lifetime flags, and are only
404 * executed once per physical TPM.
405 */
406 result = tlcl_self_test_full();
407 if (result != TPM_SUCCESS)
408 return result;
409
410 result = _factory_initialize_tpm(ctx);
411 if (result != TPM_SUCCESS)
412 return result;
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700413
414 VBDEBUG("TPM: factory initialization successful\n");
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700415
416 return TPM_SUCCESS;
417}
418
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700419/*
420 * SetupTPM starts the TPM and establishes the root of trust for the
421 * anti-rollback mechanism. SetupTPM can fail for three reasons. 1 A bug. 2 a
422 * TPM hardware failure. 3 An unexpected TPM state due to some attack. In
423 * general we cannot easily distinguish the kind of failure, so our strategy is
424 * to reboot in recovery mode in all cases. The recovery mode calls SetupTPM
425 * again, which executes (almost) the same sequence of operations. There is a
426 * good chance that, if recovery mode was entered because of a TPM failure, the
427 * failure will repeat itself. (In general this is impossible to guarantee
428 * because we have no way of creating the exact TPM initial state at the
429 * previous boot.) In recovery mode, we ignore the failure and continue, thus
430 * giving the recovery kernel a chance to fix things (that's why we don't set
431 * bGlobalLock). The choice is between a knowingly insecure device and a
432 * bricked device.
433 *
434 * As a side note, observe that we go through considerable hoops to avoid using
435 * the STCLEAR permissions for the index spaces. We do this to avoid writing
436 * to the TPM flashram at every reboot or wake-up, because of concerns about
437 * the durability of the NVRAM.
438 */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700439uint32_t setup_tpm(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700440{
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700441 uint8_t disable;
442 uint8_t deactivated;
443 uint32_t result;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700444
Daisuke Nojiri57990972014-07-15 19:47:32 -0700445 RETURN_ON_FAILURE(tlcl_lib_init());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700446
Duncan Lauriea613a312016-03-14 09:32:08 -0700447 /* Handle special init for S3 resume path */
448 if (ctx->flags & VB2_CONTEXT_S3_RESUME) {
449 result = tlcl_resume();
450 if (result == TPM_E_INVALID_POSTINIT)
451 printk(BIOS_DEBUG, "TPM: Already initialized.\n");
452 return TPM_SUCCESS;
453 }
454
Lee Leahy33efd982017-03-13 17:25:36 -0700455 if (IS_ENABLED(CONFIG_VBOOT_SOFT_REBOOT_WORKAROUND)) {
456 result = tlcl_startup();
457 if (result == TPM_E_INVALID_POSTINIT) {
458 /*
459 * Some prototype hardware doesn't reset the TPM on a CPU
460 * reset. We do a hard reset to get around this.
461 */
462 VBDEBUG("TPM: soft reset detected\n");
463 ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT;
464 return TPM_E_MUST_REBOOT;
465 } else if (result != TPM_SUCCESS) {
466 VBDEBUG("TPM: tlcl_startup returned %08x\n", result);
467 return result;
468 }
469 } else
470 RETURN_ON_FAILURE(tlcl_startup());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700471
Daisuke Nojiri57990972014-07-15 19:47:32 -0700472 /*
473 * Some TPMs start the self test automatically at power on. In that case
474 * we don't need to call ContinueSelfTest. On some (other) TPMs,
475 * continue_self_test may block. In that case, we definitely don't want
476 * to call it here. For TPMs in the intersection of these two sets, we
477 * are screwed. (In other words: TPMs that require manually starting the
478 * self-test AND block will have poor performance until we split
479 * tlcl_send_receive() into send() and receive(), and have a state
480 * machine to control setup.)
481 *
482 * This comment is likely to become obsolete in the near future, so
483 * don't trust it. It may have not been updated.
484 */
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700485#ifdef TPM_MANUAL_SELFTEST
486#ifdef TPM_BLOCKING_CONTINUESELFTEST
487#warning "lousy TPM!"
488#endif
Daisuke Nojiri57990972014-07-15 19:47:32 -0700489 RETURN_ON_FAILURE(tlcl_continue_self_test());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700490#endif
Daisuke Nojiri57990972014-07-15 19:47:32 -0700491 result = tlcl_assert_physical_presence();
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700492 if (result != TPM_SUCCESS) {
493 /*
494 * It is possible that the TPM was delivered with the physical
495 * presence command disabled. This tries enabling it, then
496 * tries asserting PP again.
497 */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700498 RETURN_ON_FAILURE(tlcl_physical_presence_cmd_enable());
499 RETURN_ON_FAILURE(tlcl_assert_physical_presence());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700500 }
501
502 /* Check that the TPM is enabled and activated. */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700503 RETURN_ON_FAILURE(tlcl_get_flags(&disable, &deactivated, NULL));
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700504 if (disable || deactivated) {
Daisuke Nojiri57990972014-07-15 19:47:32 -0700505 VBDEBUG("TPM: disabled (%d) or deactivated (%d). Fixing...\n",
506 disable, deactivated);
507 RETURN_ON_FAILURE(tlcl_set_enable());
508 RETURN_ON_FAILURE(tlcl_set_deactivated(0));
509 VBDEBUG("TPM: Must reboot to re-enable\n");
Furquan Shaikh6fecb712015-09-17 12:40:23 -0700510 ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700511 return TPM_E_MUST_REBOOT;
512 }
513
Daisuke Nojiri57990972014-07-15 19:47:32 -0700514 VBDEBUG("TPM: SetupTPM() succeeded\n");
515 return TPM_SUCCESS;
516}
517
518uint32_t antirollback_read_space_firmware(struct vb2_context *ctx)
519{
520 uint32_t rv;
521
522 rv = setup_tpm(ctx);
523 if (rv)
524 return rv;
525
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700526 /* Read the firmware space. */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700527 rv = read_space_firmware(ctx);
528 if (rv == TPM_E_BADINDEX) {
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700529 /*
Daisuke Nojiri57990972014-07-15 19:47:32 -0700530 * This seems the first time we've run. Initialize the TPM.
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700531 */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700532 VBDEBUG("TPM: Not initialized yet.\n");
533 RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
534 } else if (rv != TPM_SUCCESS) {
535 VBDEBUG("TPM: Firmware space in a bad state; giving up.\n");
536 //RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700537 return TPM_E_CORRUPTED_STATE;
538 }
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700539
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700540 return TPM_SUCCESS;
541}
542
Daisuke Nojiri57990972014-07-15 19:47:32 -0700543uint32_t antirollback_write_space_firmware(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700544{
Aaron Durbineeb77372017-03-08 11:23:11 -0600545 if (IS_ENABLED(CONFIG_CR50_IMMEDIATELY_COMMIT_FW_SECDATA))
546 tlcl_cr50_enable_nvcommits();
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700547 return write_secdata(FIRMWARE_NV_INDEX, ctx->secdata, VB2_SECDATA_SIZE);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700548}
Furquan Shaikhb038f412016-11-07 23:47:11 -0800549
550uint32_t antirollback_read_space_rec_hash(uint8_t *data, uint32_t size)
551{
552 if (size != REC_HASH_NV_SIZE) {
553 VBDEBUG("TPM: Incorrect buffer size for rec hash. "
554 "(Expected=0x%x Actual=0x%x).\n", REC_HASH_NV_SIZE,
555 size);
556 return TPM_E_READ_FAILURE;
557 }
558 return read_space_rec_hash(data);
559}
560
561uint32_t antirollback_write_space_rec_hash(const uint8_t *data, uint32_t size)
562{
563 uint8_t spc_data[REC_HASH_NV_SIZE];
564 uint32_t rv;
565
566 if (size != REC_HASH_NV_SIZE) {
567 VBDEBUG("TPM: Incorrect buffer size for rec hash. "
568 "(Expected=0x%x Actual=0x%x).\n", REC_HASH_NV_SIZE,
569 size);
570 return TPM_E_WRITE_FAILURE;
571 }
572
573 rv = read_space_rec_hash(spc_data);
574 if (rv == TPM_E_BADINDEX) {
575 /*
576 * If space is not defined already for recovery hash, define
577 * new space.
578 */
579 VBDEBUG("TPM: Initializing recovery hash space.\n");
580 return set_rec_hash_space(data);
581 }
582
583 if (rv != TPM_SUCCESS)
584 return rv;
585
586 return write_secdata(REC_HASH_NV_INDEX, data, size);
587}