blob: c5d08ce27f9657adfb0fb243a40e2da13f050dd0 [file] [log] [blame]
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -07001/* 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
Daisuke Nojiri57990972014-07-15 19:47:32 -07009#include <antirollback.h>
Randall Spangler144c2282014-12-03 17:35:53 -080010#include <stdlib.h>
11#include <string.h>
Daisuke Nojiri57990972014-07-15 19:47:32 -070012#include <tpm_lite/tlcl.h>
Randall Spangler144c2282014-12-03 17:35:53 -080013#include <vb2_api.h>
Vadim Bendebury10ea1042016-06-06 12:12:34 -070014#include <console/console.h>
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070015
16#ifndef offsetof
17#define offsetof(A,B) __builtin_offsetof(A,B)
18#endif
19
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070020#ifdef FOR_TEST
Daisuke Nojiri57990972014-07-15 19:47:32 -070021#include <stdio.h>
22#define VBDEBUG(format, args...) printf(format, ## args)
23#else
24#include <console/console.h>
25#define VBDEBUG(format, args...) \
26 printk(BIOS_INFO, "%s():%d: " format, __func__, __LINE__, ## args)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070027#endif
28
Daisuke Nojiri57990972014-07-15 19:47:32 -070029#define RETURN_ON_FAILURE(tpm_cmd) do { \
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070030 uint32_t result_; \
Daisuke Nojiri57990972014-07-15 19:47:32 -070031 if ((result_ = (tpm_cmd)) != TPM_SUCCESS) { \
32 VBDEBUG("Antirollback: %08x returned by " #tpm_cmd \
33 "\n", (int)result_); \
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070034 return result_; \
35 } \
36 } while (0)
37
Julius Werner76e33032015-01-30 18:45:27 -080038
Vadim Bendebury10ea1042016-06-06 12:12:34 -070039static uint32_t safe_write(uint32_t index, const void *data, uint32_t length);
40
Julius Werner76e33032015-01-30 18:45:27 -080041uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr,
42 enum vb2_pcr_digest which_digest)
43{
44 uint8_t buffer[VB2_PCR_DIGEST_RECOMMENDED_SIZE];
45 uint32_t size = sizeof(buffer);
46 int rv;
47
48 rv = vb2api_get_pcr_digest(ctx, which_digest, buffer, &size);
49 if (rv != VB2_SUCCESS)
50 return rv;
51 if (size < TPM_PCR_DIGEST)
52 return VB2_ERROR_UNKNOWN;
53
54 return tlcl_extend(pcr, buffer, NULL);
55}
56
Daisuke Nojiri57990972014-07-15 19:47:32 -070057static uint32_t read_space_firmware(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070058{
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070059 int attempts = 3;
60
61 while (attempts--) {
Daisuke Nojiri57990972014-07-15 19:47:32 -070062 RETURN_ON_FAILURE(tlcl_read(FIRMWARE_NV_INDEX, ctx->secdata,
63 VB2_SECDATA_SIZE));
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070064
Daisuke Nojiri57990972014-07-15 19:47:32 -070065 if (vb2api_secdata_check(ctx) == VB2_SUCCESS)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070066 return TPM_SUCCESS;
67
Daisuke Nojiri57990972014-07-15 19:47:32 -070068 VBDEBUG("TPM: %s() - bad CRC\n", __func__);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070069 }
70
Daisuke Nojiri57990972014-07-15 19:47:32 -070071 VBDEBUG("TPM: %s() - too many bad CRCs, giving up\n", __func__);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070072 return TPM_E_CORRUPTED_STATE;
73}
74
Furquan Shaikhb038f412016-11-07 23:47:11 -080075static uint32_t read_space_rec_hash(uint8_t *data)
76{
77 RETURN_ON_FAILURE(tlcl_read(REC_HASH_NV_INDEX, data,
78 REC_HASH_NV_SIZE));
79 return TPM_SUCCESS;
80}
81
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -070082static uint32_t write_secdata(uint32_t index,
83 const uint8_t *secdata,
84 uint32_t len)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070085{
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -070086 uint8_t sd[32];
87 uint32_t rv;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070088 int attempts = 3;
89
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -070090 if (len > sizeof(sd)) {
91 VBDEBUG("TPM: %s() - data is too large\n", __func__);
92 return TPM_E_WRITE_FAILURE;
93 }
94
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070095 while (attempts--) {
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -070096 rv = safe_write(index, secdata, len);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070097 /* Can't write, not gonna try again */
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -070098 if (rv != TPM_SUCCESS)
99 return rv;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700100
101 /* Read it back to be sure it got the right values. */
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700102 rv = tlcl_read(index, sd, len);
103 if (rv == TPM_SUCCESS && memcmp(secdata, sd, len) == 0)
104 return rv;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700105
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700106 VBDEBUG("TPM: %s() failed. trying again\n", __func__);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700107 /* Try writing it again. Maybe it was garbled on the way out. */
108 }
109
Daisuke Nojiri57990972014-07-15 19:47:32 -0700110 VBDEBUG("TPM: %s() - too many failures, giving up\n", __func__);
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700111
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700112 return TPM_E_CORRUPTED_STATE;
113}
114
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700115/*
116 * This is derived from rollback_index.h of vboot_reference. see struct
117 * RollbackSpaceKernel for details.
118 */
119static const uint8_t secdata_kernel[] = {
120 0x02,
121 0x4C, 0x57, 0x52, 0x47,
122 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00,
124 0xE8,
125};
126
Furquan Shaikhb038f412016-11-07 23:47:11 -0800127/*
128 * This is used to initialize the TPM space for recovery hash after defining
129 * it. Since there is no data available to calculate hash at the point where TPM
130 * space is defined, initialize it to all 0s.
131 */
132static const uint8_t rec_hash_data[REC_HASH_NV_SIZE] = { };
133
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700134#if IS_ENABLED(CONFIG_TPM2)
135
136/* Nothing special in the TPM2 path yet. */
137static uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
138{
139 return tlcl_write(index, data, length);
140}
141
142static uint32_t set_firmware_space(const void *firmware_blob)
143{
144 RETURN_ON_FAILURE(tlcl_define_space(FIRMWARE_NV_INDEX,
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700145 VB2_SECDATA_SIZE));
146 RETURN_ON_FAILURE(safe_write(FIRMWARE_NV_INDEX, firmware_blob,
147 VB2_SECDATA_SIZE));
148 return TPM_SUCCESS;
149}
150
151static uint32_t set_kernel_space(const void *kernel_blob)
152{
Vadim Bendebury38837012016-11-14 16:36:26 -0800153 uint32_t rv;
154
155 rv = tlcl_define_space(KERNEL_NV_INDEX, sizeof(secdata_kernel));
156 if (rv == TPM_E_NV_DEFINED) {
157 VBDEBUG("%s: kernel space already exists\n", __func__);
158 return TPM_SUCCESS;
159 }
160
161 if (rv != TPM_SUCCESS)
162 return rv;
163
164 return safe_write(KERNEL_NV_INDEX, kernel_blob, sizeof(secdata_kernel));
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700165}
166
Furquan Shaikhb038f412016-11-07 23:47:11 -0800167static uint32_t set_rec_hash_space(const uint8_t *data)
168{
Vadim Bendebury38837012016-11-14 16:36:26 -0800169 uint32_t rv;
170
171 rv = tlcl_define_space(REC_HASH_NV_INDEX, REC_HASH_NV_SIZE);
172 if (rv == TPM_E_NV_DEFINED) {
173 VBDEBUG("%s: MRC Hash space already exists\n", __func__);
174 return TPM_SUCCESS;
175 }
176
177 if (rv != TPM_SUCCESS)
178 return rv;
179
180 return safe_write(REC_HASH_NV_INDEX, data, REC_HASH_NV_SIZE);
Furquan Shaikhb038f412016-11-07 23:47:11 -0800181}
182
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700183static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
184{
Vadim Bendeburyadfbbde2016-07-03 15:56:41 -0700185 RETURN_ON_FAILURE(tlcl_force_clear());
Vadim Bendebury38837012016-11-14 16:36:26 -0800186
187 /*
188 * Of all NVRAM spaces defined by this function the firmware space
189 * must be defined last, because its existence is considered an
190 * indication that TPM factory initialization was successfully
191 * completed.
192 */
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700193 RETURN_ON_FAILURE(set_kernel_space(secdata_kernel));
Furquan Shaikhb038f412016-11-07 23:47:11 -0800194
195 if (IS_ENABLED(CONFIG_VBOOT_HAS_REC_HASH_SPACE))
196 RETURN_ON_FAILURE(set_rec_hash_space(rec_hash_data));
197
Vadim Bendebury38837012016-11-14 16:36:26 -0800198 RETURN_ON_FAILURE(set_firmware_space(ctx->secdata));
199
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700200 return TPM_SUCCESS;
201}
202
203uint32_t tpm_clear_and_reenable(void)
204{
205 VBDEBUG("TPM: Clear and re-enable\n");
Vadim Bendebury494d3982016-09-28 18:59:39 -0700206 RETURN_ON_FAILURE(tlcl_force_clear());
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700207 return TPM_SUCCESS;
208}
209
Vadim Bendebury4c0851c2016-07-03 17:08:10 -0700210uint32_t antirollback_lock_space_firmware(void)
211{
212 return tlcl_lock_nv_write(FIRMWARE_NV_INDEX);
213}
214
Furquan Shaikhb038f412016-11-07 23:47:11 -0800215uint32_t antirollback_lock_space_rec_hash(void)
216{
217 return tlcl_lock_nv_write(REC_HASH_NV_INDEX);
218}
219
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700220#else
221
222uint32_t tpm_clear_and_reenable(void)
223{
224 VBDEBUG("TPM: Clear and re-enable\n");
225 RETURN_ON_FAILURE(tlcl_force_clear());
226 RETURN_ON_FAILURE(tlcl_set_enable());
227 RETURN_ON_FAILURE(tlcl_set_deactivated(0));
228
229 return TPM_SUCCESS;
230}
231
232/**
233 * Like tlcl_write(), but checks for write errors due to hitting the 64-write
234 * limit and clears the TPM when that happens. This can only happen when the
235 * TPM is unowned, so it is OK to clear it (and we really have no choice).
236 * This is not expected to happen frequently, but it could happen.
237 */
238
239static uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
240{
241 uint32_t result = tlcl_write(index, data, length);
242 if (result == TPM_E_MAXNVWRITES) {
243 RETURN_ON_FAILURE(tpm_clear_and_reenable());
244 return tlcl_write(index, data, length);
245 } else {
246 return result;
247 }
248}
249
250/**
251 * Similarly to safe_write(), this ensures we don't fail a DefineSpace because
252 * we hit the TPM write limit. This is even less likely to happen than with
253 * writes because we only define spaces once at initialization, but we'd
254 * rather be paranoid about this.
255 */
256static uint32_t safe_define_space(uint32_t index, uint32_t perm, uint32_t size)
257{
258 uint32_t result = tlcl_define_space(index, perm, size);
259 if (result == TPM_E_MAXNVWRITES) {
260 RETURN_ON_FAILURE(tpm_clear_and_reenable());
261 return tlcl_define_space(index, perm, size);
262 } else {
263 return result;
264 }
265}
266
Furquan Shaikhb038f412016-11-07 23:47:11 -0800267static uint32_t set_rec_hash_space(const uint8_t *data)
268{
269 RETURN_ON_FAILURE(safe_define_space(REC_HASH_NV_INDEX,
270 TPM_NV_PER_GLOBALLOCK |
271 TPM_NV_PER_PPWRITE,
272 REC_HASH_NV_SIZE));
273 RETURN_ON_FAILURE(write_secdata(REC_HASH_NV_INDEX, data,
274 REC_HASH_NV_SIZE));
275
276 return TPM_SUCCESS;
277}
278
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700279static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700280{
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700281 TPM_PERMANENT_FLAGS pflags;
282 uint32_t result;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700283
Daisuke Nojiri57990972014-07-15 19:47:32 -0700284 result = tlcl_get_permanent_flags(&pflags);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700285 if (result != TPM_SUCCESS)
286 return result;
287
288 /*
289 * TPM may come from the factory without physical presence finalized.
290 * Fix if necessary.
291 */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700292 VBDEBUG("TPM: physicalPresenceLifetimeLock=%d\n",
293 pflags.physicalPresenceLifetimeLock);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700294 if (!pflags.physicalPresenceLifetimeLock) {
Daisuke Nojiri57990972014-07-15 19:47:32 -0700295 VBDEBUG("TPM: Finalizing physical presence\n");
296 RETURN_ON_FAILURE(tlcl_finalize_physical_presence());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700297 }
298
299 /*
300 * The TPM will not enforce the NV authorization restrictions until the
301 * execution of a TPM_NV_DefineSpace with the handle of
302 * TPM_NV_INDEX_LOCK. Here we create that space if it doesn't already
303 * exist. */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700304 VBDEBUG("TPM: nvLocked=%d\n", pflags.nvLocked);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700305 if (!pflags.nvLocked) {
Daisuke Nojiri57990972014-07-15 19:47:32 -0700306 VBDEBUG("TPM: Enabling NV locking\n");
307 RETURN_ON_FAILURE(tlcl_set_nv_locked());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700308 }
309
310 /* Clear TPM owner, in case the TPM is already owned for some reason. */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700311 VBDEBUG("TPM: Clearing owner\n");
312 RETURN_ON_FAILURE(tpm_clear_and_reenable());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700313
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700314 /* Define and initialize the kernel space */
315 RETURN_ON_FAILURE(safe_define_space(KERNEL_NV_INDEX,
316 TPM_NV_PER_PPWRITE,
317 sizeof(secdata_kernel)));
318 RETURN_ON_FAILURE(write_secdata(KERNEL_NV_INDEX,
319 secdata_kernel,
320 sizeof(secdata_kernel)));
321
Daisuke Nojiri57990972014-07-15 19:47:32 -0700322 /* Defines and sets vb2 secdata space */
323 vb2api_secdata_create(ctx);
324 RETURN_ON_FAILURE(safe_define_space(FIRMWARE_NV_INDEX,
325 TPM_NV_PER_GLOBALLOCK |
326 TPM_NV_PER_PPWRITE,
327 VB2_SECDATA_SIZE));
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700328 RETURN_ON_FAILURE(write_secdata(FIRMWARE_NV_INDEX,
329 ctx->secdata,
330 VB2_SECDATA_SIZE));
Furquan Shaikhb038f412016-11-07 23:47:11 -0800331
332 /* Define and set rec hash space, if available. */
333 if (IS_ENABLED(CONFIG_VBOOT_HAS_REC_HASH_SPACE))
334 RETURN_ON_FAILURE(set_rec_hash_space(rec_hash_data));
335
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700336 return TPM_SUCCESS;
337}
Vadim Bendebury4c0851c2016-07-03 17:08:10 -0700338
339uint32_t antirollback_lock_space_firmware(void)
340{
341 return tlcl_set_global_lock();
342}
Furquan Shaikhb038f412016-11-07 23:47:11 -0800343
344uint32_t antirollback_lock_space_rec_hash(void)
345{
346 /*
347 * Nothing needs to be done here, since global lock is already set while
348 * locking firmware space.
349 */
350 return TPM_SUCCESS;
351}
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700352#endif
353
Vadim Bendebury673a2662016-11-11 09:33:43 -0800354/**
355 * Perform one-time initializations.
356 *
357 * Create the NVRAM spaces, and set their initial values as needed. Sets the
358 * nvLocked bit and ensures the physical presence command is enabled and
359 * locked.
360 */
361static uint32_t factory_initialize_tpm(struct vb2_context *ctx)
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700362{
363 uint32_t result;
364
365 /* Defines and sets vb2 secdata space */
366 vb2api_secdata_create(ctx);
367
368 VBDEBUG("TPM: factory initialization\n");
369
370 /*
371 * Do a full test. This only happens the first time the device is
372 * turned on in the factory, so performance is not an issue. This is
373 * almost certainly not necessary, but it gives us more confidence
374 * about some code paths below that are difficult to
375 * test---specifically the ones that set lifetime flags, and are only
376 * executed once per physical TPM.
377 */
378 result = tlcl_self_test_full();
379 if (result != TPM_SUCCESS)
380 return result;
381
382 result = _factory_initialize_tpm(ctx);
383 if (result != TPM_SUCCESS)
384 return result;
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700385
386 VBDEBUG("TPM: factory initialization successful\n");
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700387
388 return TPM_SUCCESS;
389}
390
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700391/*
392 * SetupTPM starts the TPM and establishes the root of trust for the
393 * anti-rollback mechanism. SetupTPM can fail for three reasons. 1 A bug. 2 a
394 * TPM hardware failure. 3 An unexpected TPM state due to some attack. In
395 * general we cannot easily distinguish the kind of failure, so our strategy is
396 * to reboot in recovery mode in all cases. The recovery mode calls SetupTPM
397 * again, which executes (almost) the same sequence of operations. There is a
398 * good chance that, if recovery mode was entered because of a TPM failure, the
399 * failure will repeat itself. (In general this is impossible to guarantee
400 * because we have no way of creating the exact TPM initial state at the
401 * previous boot.) In recovery mode, we ignore the failure and continue, thus
402 * giving the recovery kernel a chance to fix things (that's why we don't set
403 * bGlobalLock). The choice is between a knowingly insecure device and a
404 * bricked device.
405 *
406 * As a side note, observe that we go through considerable hoops to avoid using
407 * the STCLEAR permissions for the index spaces. We do this to avoid writing
408 * to the TPM flashram at every reboot or wake-up, because of concerns about
409 * the durability of the NVRAM.
410 */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700411uint32_t setup_tpm(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700412{
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700413 uint8_t disable;
414 uint8_t deactivated;
415 uint32_t result;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700416
Daisuke Nojiri57990972014-07-15 19:47:32 -0700417 RETURN_ON_FAILURE(tlcl_lib_init());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700418
Duncan Lauriea613a312016-03-14 09:32:08 -0700419 /* Handle special init for S3 resume path */
420 if (ctx->flags & VB2_CONTEXT_S3_RESUME) {
421 result = tlcl_resume();
422 if (result == TPM_E_INVALID_POSTINIT)
423 printk(BIOS_DEBUG, "TPM: Already initialized.\n");
424 return TPM_SUCCESS;
425 }
426
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700427#ifdef TEGRA_SOFT_REBOOT_WORKAROUND
Daisuke Nojiri57990972014-07-15 19:47:32 -0700428 result = tlcl_startup();
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700429 if (result == TPM_E_INVALID_POSTINIT) {
430 /*
431 * Some prototype hardware doesn't reset the TPM on a CPU
432 * reset. We do a hard reset to get around this.
433 */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700434 VBDEBUG("TPM: soft reset detected\n", result);
Furquan Shaikh6fecb712015-09-17 12:40:23 -0700435 ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700436 return TPM_E_MUST_REBOOT;
437 } else if (result != TPM_SUCCESS) {
Daisuke Nojiri57990972014-07-15 19:47:32 -0700438 VBDEBUG("TPM: tlcl_startup returned %08x\n", result);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700439 return result;
440 }
441#else
Daisuke Nojiri57990972014-07-15 19:47:32 -0700442 RETURN_ON_FAILURE(tlcl_startup());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700443#endif
444
Daisuke Nojiri57990972014-07-15 19:47:32 -0700445 /*
446 * Some TPMs start the self test automatically at power on. In that case
447 * we don't need to call ContinueSelfTest. On some (other) TPMs,
448 * continue_self_test may block. In that case, we definitely don't want
449 * to call it here. For TPMs in the intersection of these two sets, we
450 * are screwed. (In other words: TPMs that require manually starting the
451 * self-test AND block will have poor performance until we split
452 * tlcl_send_receive() into send() and receive(), and have a state
453 * machine to control setup.)
454 *
455 * This comment is likely to become obsolete in the near future, so
456 * don't trust it. It may have not been updated.
457 */
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700458#ifdef TPM_MANUAL_SELFTEST
459#ifdef TPM_BLOCKING_CONTINUESELFTEST
460#warning "lousy TPM!"
461#endif
Daisuke Nojiri57990972014-07-15 19:47:32 -0700462 RETURN_ON_FAILURE(tlcl_continue_self_test());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700463#endif
Daisuke Nojiri57990972014-07-15 19:47:32 -0700464 result = tlcl_assert_physical_presence();
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700465 if (result != TPM_SUCCESS) {
466 /*
467 * It is possible that the TPM was delivered with the physical
468 * presence command disabled. This tries enabling it, then
469 * tries asserting PP again.
470 */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700471 RETURN_ON_FAILURE(tlcl_physical_presence_cmd_enable());
472 RETURN_ON_FAILURE(tlcl_assert_physical_presence());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700473 }
474
475 /* Check that the TPM is enabled and activated. */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700476 RETURN_ON_FAILURE(tlcl_get_flags(&disable, &deactivated, NULL));
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700477 if (disable || deactivated) {
Daisuke Nojiri57990972014-07-15 19:47:32 -0700478 VBDEBUG("TPM: disabled (%d) or deactivated (%d). Fixing...\n",
479 disable, deactivated);
480 RETURN_ON_FAILURE(tlcl_set_enable());
481 RETURN_ON_FAILURE(tlcl_set_deactivated(0));
482 VBDEBUG("TPM: Must reboot to re-enable\n");
Furquan Shaikh6fecb712015-09-17 12:40:23 -0700483 ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700484 return TPM_E_MUST_REBOOT;
485 }
486
Daisuke Nojiri57990972014-07-15 19:47:32 -0700487 VBDEBUG("TPM: SetupTPM() succeeded\n");
488 return TPM_SUCCESS;
489}
490
491uint32_t antirollback_read_space_firmware(struct vb2_context *ctx)
492{
493 uint32_t rv;
494
495 rv = setup_tpm(ctx);
496 if (rv)
497 return rv;
498
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700499 /* Read the firmware space. */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700500 rv = read_space_firmware(ctx);
501 if (rv == TPM_E_BADINDEX) {
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700502 /*
Daisuke Nojiri57990972014-07-15 19:47:32 -0700503 * This seems the first time we've run. Initialize the TPM.
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700504 */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700505 VBDEBUG("TPM: Not initialized yet.\n");
506 RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
507 } else if (rv != TPM_SUCCESS) {
508 VBDEBUG("TPM: Firmware space in a bad state; giving up.\n");
509 //RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700510 return TPM_E_CORRUPTED_STATE;
511 }
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700512
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700513 return TPM_SUCCESS;
514}
515
Daisuke Nojiri57990972014-07-15 19:47:32 -0700516uint32_t antirollback_write_space_firmware(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700517{
Aaron Durbineeb77372017-03-08 11:23:11 -0600518 if (IS_ENABLED(CONFIG_CR50_IMMEDIATELY_COMMIT_FW_SECDATA))
519 tlcl_cr50_enable_nvcommits();
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700520 return write_secdata(FIRMWARE_NV_INDEX, ctx->secdata, VB2_SECDATA_SIZE);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700521}
Furquan Shaikhb038f412016-11-07 23:47:11 -0800522
523uint32_t antirollback_read_space_rec_hash(uint8_t *data, uint32_t size)
524{
525 if (size != REC_HASH_NV_SIZE) {
526 VBDEBUG("TPM: Incorrect buffer size for rec hash. "
527 "(Expected=0x%x Actual=0x%x).\n", REC_HASH_NV_SIZE,
528 size);
529 return TPM_E_READ_FAILURE;
530 }
531 return read_space_rec_hash(data);
532}
533
534uint32_t antirollback_write_space_rec_hash(const uint8_t *data, uint32_t size)
535{
536 uint8_t spc_data[REC_HASH_NV_SIZE];
537 uint32_t rv;
538
539 if (size != REC_HASH_NV_SIZE) {
540 VBDEBUG("TPM: Incorrect buffer size for rec hash. "
541 "(Expected=0x%x Actual=0x%x).\n", REC_HASH_NV_SIZE,
542 size);
543 return TPM_E_WRITE_FAILURE;
544 }
545
546 rv = read_space_rec_hash(spc_data);
547 if (rv == TPM_E_BADINDEX) {
548 /*
549 * If space is not defined already for recovery hash, define
550 * new space.
551 */
552 VBDEBUG("TPM: Initializing recovery hash space.\n");
553 return set_rec_hash_space(data);
554 }
555
556 if (rv != TPM_SUCCESS)
557 return rv;
558
559 return write_secdata(REC_HASH_NV_INDEX, data, size);
560}