blob: f639e35423a64fb1fe1605b6c3aa2a3ab65488e5 [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 Deppenwiesec07f8fb2018-02-27 19:40:52 +010035#include <security/vboot/antirollback.h>
Randall Spangler144c2282014-12-03 17:35:53 -080036#include <stdlib.h>
37#include <string.h>
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +010038#include <security/tpm/tspi.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
Daisuke Nojiri57990972014-07-15 19:47:32 -070050#define VBDEBUG(format, args...) \
51 printk(BIOS_INFO, "%s():%d: " format, __func__, __LINE__, ## args)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070052#endif
53
Daisuke Nojiri57990972014-07-15 19:47:32 -070054#define RETURN_ON_FAILURE(tpm_cmd) do { \
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070055 uint32_t result_; \
Daisuke Nojiri57990972014-07-15 19:47:32 -070056 if ((result_ = (tpm_cmd)) != TPM_SUCCESS) { \
57 VBDEBUG("Antirollback: %08x returned by " #tpm_cmd \
58 "\n", (int)result_); \
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070059 return result_; \
60 } \
61 } while (0)
62
Philipp Deppenwiesef8499722018-07-30 01:27:47 +020063#define TPM_PCR_GBB_FLAGS_NAME "GBB flags"
64#define TPM_PCR_GBB_HWID_NAME "GBB HWID"
Julius Werner76e33032015-01-30 18:45:27 -080065
Vadim Bendebury10ea1042016-06-06 12:12:34 -070066static uint32_t safe_write(uint32_t index, const void *data, uint32_t length);
67
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +010068uint32_t vboot_extend_pcr(struct vb2_context *ctx, int pcr,
Philipp Deppenwiesef8499722018-07-30 01:27:47 +020069 enum vb2_pcr_digest which_digest)
Julius Werner76e33032015-01-30 18:45:27 -080070{
71 uint8_t buffer[VB2_PCR_DIGEST_RECOMMENDED_SIZE];
72 uint32_t size = sizeof(buffer);
73 int rv;
74
75 rv = vb2api_get_pcr_digest(ctx, which_digest, buffer, &size);
76 if (rv != VB2_SUCCESS)
77 return rv;
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +010078 if (size < TPM_PCR_MINIMUM_DIGEST_SIZE)
Julius Werner76e33032015-01-30 18:45:27 -080079 return VB2_ERROR_UNKNOWN;
80
Philipp Deppenwiesef8499722018-07-30 01:27:47 +020081 switch (which_digest) {
82 case BOOT_MODE_PCR:
83 return tpm_extend_pcr(pcr, buffer, size,
84 TPM_PCR_GBB_FLAGS_NAME);
85 case HWID_DIGEST_PCR:
86 return tpm_extend_pcr(pcr, buffer, size, TPM_PCR_GBB_HWID_NAME);
87 default:
88 return VB2_ERROR_UNKNOWN;
89 }
Julius Werner76e33032015-01-30 18:45:27 -080090}
91
Daisuke Nojiri57990972014-07-15 19:47:32 -070092static uint32_t read_space_firmware(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070093{
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070094 int attempts = 3;
95
96 while (attempts--) {
Daisuke Nojiri57990972014-07-15 19:47:32 -070097 RETURN_ON_FAILURE(tlcl_read(FIRMWARE_NV_INDEX, ctx->secdata,
98 VB2_SECDATA_SIZE));
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -070099
Daisuke Nojiri57990972014-07-15 19:47:32 -0700100 if (vb2api_secdata_check(ctx) == VB2_SUCCESS)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700101 return TPM_SUCCESS;
102
Daisuke Nojiri57990972014-07-15 19:47:32 -0700103 VBDEBUG("TPM: %s() - bad CRC\n", __func__);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700104 }
105
Daisuke Nojiri57990972014-07-15 19:47:32 -0700106 VBDEBUG("TPM: %s() - too many bad CRCs, giving up\n", __func__);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700107 return TPM_E_CORRUPTED_STATE;
108}
109
Furquan Shaikhb038f412016-11-07 23:47:11 -0800110static uint32_t read_space_rec_hash(uint8_t *data)
111{
112 RETURN_ON_FAILURE(tlcl_read(REC_HASH_NV_INDEX, data,
113 REC_HASH_NV_SIZE));
114 return TPM_SUCCESS;
115}
116
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700117static uint32_t write_secdata(uint32_t index,
118 const uint8_t *secdata,
119 uint32_t len)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700120{
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700121 uint8_t sd[32];
122 uint32_t rv;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700123 int attempts = 3;
124
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700125 if (len > sizeof(sd)) {
126 VBDEBUG("TPM: %s() - data is too large\n", __func__);
127 return TPM_E_WRITE_FAILURE;
128 }
129
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700130 while (attempts--) {
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700131 rv = safe_write(index, secdata, len);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700132 /* Can't write, not gonna try again */
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700133 if (rv != TPM_SUCCESS)
134 return rv;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700135
136 /* Read it back to be sure it got the right values. */
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700137 rv = tlcl_read(index, sd, len);
138 if (rv == TPM_SUCCESS && memcmp(secdata, sd, len) == 0)
139 return rv;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700140
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700141 VBDEBUG("TPM: %s() failed. trying again\n", __func__);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700142 /* Try writing it again. Maybe it was garbled on the way out. */
143 }
144
Daisuke Nojiri57990972014-07-15 19:47:32 -0700145 VBDEBUG("TPM: %s() - too many failures, giving up\n", __func__);
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700146
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700147 return TPM_E_CORRUPTED_STATE;
148}
149
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700150/*
151 * This is derived from rollback_index.h of vboot_reference. see struct
152 * RollbackSpaceKernel for details.
153 */
154static const uint8_t secdata_kernel[] = {
155 0x02,
156 0x4C, 0x57, 0x52, 0x47,
157 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00,
159 0xE8,
160};
161
Furquan Shaikhb038f412016-11-07 23:47:11 -0800162/*
163 * This is used to initialize the TPM space for recovery hash after defining
164 * it. Since there is no data available to calculate hash at the point where TPM
165 * space is defined, initialize it to all 0s.
166 */
167static const uint8_t rec_hash_data[REC_HASH_NV_SIZE] = { };
168
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700169#if IS_ENABLED(CONFIG_TPM2)
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +0100170/*
171 * Different sets of NVRAM space attributes apply to the "ro" spaces,
172 * i.e. those which should not be possible to delete or modify once
173 * the RO exits, and the rest of the NVRAM spaces.
174 */
175const static TPMA_NV ro_space_attributes = {
176 .TPMA_NV_PPWRITE = 1,
177 .TPMA_NV_AUTHREAD = 1,
178 .TPMA_NV_PPREAD = 1,
179 .TPMA_NV_PLATFORMCREATE = 1,
180 .TPMA_NV_WRITE_STCLEAR = 1,
181 .TPMA_NV_POLICY_DELETE = 1,
182};
183
184const static TPMA_NV rw_space_attributes = {
185 .TPMA_NV_PPWRITE = 1,
186 .TPMA_NV_AUTHREAD = 1,
187 .TPMA_NV_PPREAD = 1,
188 .TPMA_NV_PLATFORMCREATE = 1,
189};
190
191/*
192 * This policy digest was obtained using TPM2_PolicyPCR
193 * selecting only PCR_0 with a value of all zeros.
194 */
195const static uint8_t pcr0_unchanged_policy[] = {
196 0x09, 0x93, 0x3C, 0xCE, 0xEB, 0xB4, 0x41, 0x11, 0x18, 0x81, 0x1D,
197 0xD4, 0x47, 0x78, 0x80, 0x08, 0x88, 0x86, 0x62, 0x2D, 0xD7, 0x79,
198 0x94, 0x46, 0x62, 0x26, 0x68, 0x8E, 0xEE, 0xE6, 0x6A, 0xA1};
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700199
200/* Nothing special in the TPM2 path yet. */
201static uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
202{
203 return tlcl_write(index, data, length);
204}
205
Andrey Pronin278a5062018-01-26 12:47:51 -0800206static uint32_t set_space(const char *name, uint32_t index, const void *data,
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +0100207 uint32_t length, const TPMA_NV nv_attributes,
208 const uint8_t *nv_policy, size_t nv_policy_size)
Andrey Pronin278a5062018-01-26 12:47:51 -0800209{
210 uint32_t rv;
211
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +0100212 rv = tlcl_define_space(index, length, nv_attributes, nv_policy,
213 nv_policy_size);
Andrey Pronin278a5062018-01-26 12:47:51 -0800214 if (rv == TPM_E_NV_DEFINED) {
215 /*
216 * Continue with writing: it may be defined, but not written
217 * to. In that case a subsequent tlcl_read() would still return
218 * TPM_E_BADINDEX on TPM 2.0. The cases when some non-firmware
219 * space is defined while the firmware space is not there
220 * should be rare (interrupted initialization), so no big harm
221 * in writing once again even if it was written already.
222 */
223 VBDEBUG("%s: %s space already exists\n", __func__, name);
224 rv = TPM_SUCCESS;
225 }
226
227 if (rv != TPM_SUCCESS)
228 return rv;
229
230 return safe_write(index, data, length);
231}
232
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700233static uint32_t set_firmware_space(const void *firmware_blob)
234{
Andrey Pronin278a5062018-01-26 12:47:51 -0800235 return set_space("firmware", FIRMWARE_NV_INDEX, firmware_blob,
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +0100236 VB2_SECDATA_SIZE, ro_space_attributes,
237 pcr0_unchanged_policy, sizeof(pcr0_unchanged_policy));
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700238}
239
240static uint32_t set_kernel_space(const void *kernel_blob)
241{
Andrey Pronin278a5062018-01-26 12:47:51 -0800242 return set_space("kernel", KERNEL_NV_INDEX, kernel_blob,
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +0100243 sizeof(secdata_kernel), rw_space_attributes, NULL, 0);
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700244}
245
Furquan Shaikhb038f412016-11-07 23:47:11 -0800246static uint32_t set_rec_hash_space(const uint8_t *data)
247{
Andrey Pronin278a5062018-01-26 12:47:51 -0800248 return set_space("MRC Hash", REC_HASH_NV_INDEX, data,
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +0100249 REC_HASH_NV_SIZE,
250 ro_space_attributes, pcr0_unchanged_policy,
251 sizeof(pcr0_unchanged_policy));
Furquan Shaikhb038f412016-11-07 23:47:11 -0800252}
253
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700254static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
255{
Vadim Bendeburyadfbbde2016-07-03 15:56:41 -0700256 RETURN_ON_FAILURE(tlcl_force_clear());
Vadim Bendebury38837012016-11-14 16:36:26 -0800257
258 /*
259 * Of all NVRAM spaces defined by this function the firmware space
260 * must be defined last, because its existence is considered an
261 * indication that TPM factory initialization was successfully
262 * completed.
263 */
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700264 RETURN_ON_FAILURE(set_kernel_space(secdata_kernel));
Furquan Shaikhb038f412016-11-07 23:47:11 -0800265
266 if (IS_ENABLED(CONFIG_VBOOT_HAS_REC_HASH_SPACE))
267 RETURN_ON_FAILURE(set_rec_hash_space(rec_hash_data));
268
Vadim Bendebury38837012016-11-14 16:36:26 -0800269 RETURN_ON_FAILURE(set_firmware_space(ctx->secdata));
270
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700271 return TPM_SUCCESS;
272}
273
Vadim Bendebury4c0851c2016-07-03 17:08:10 -0700274uint32_t antirollback_lock_space_firmware(void)
275{
276 return tlcl_lock_nv_write(FIRMWARE_NV_INDEX);
277}
278
Furquan Shaikhb038f412016-11-07 23:47:11 -0800279uint32_t antirollback_lock_space_rec_hash(void)
280{
281 return tlcl_lock_nv_write(REC_HASH_NV_INDEX);
282}
283
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700284#else
285
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700286/**
287 * Like tlcl_write(), but checks for write errors due to hitting the 64-write
288 * limit and clears the TPM when that happens. This can only happen when the
289 * TPM is unowned, so it is OK to clear it (and we really have no choice).
290 * This is not expected to happen frequently, but it could happen.
291 */
292
293static uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
294{
295 uint32_t result = tlcl_write(index, data, length);
296 if (result == TPM_E_MAXNVWRITES) {
297 RETURN_ON_FAILURE(tpm_clear_and_reenable());
298 return tlcl_write(index, data, length);
299 } else {
300 return result;
301 }
302}
303
304/**
305 * Similarly to safe_write(), this ensures we don't fail a DefineSpace because
306 * we hit the TPM write limit. This is even less likely to happen than with
307 * writes because we only define spaces once at initialization, but we'd
308 * rather be paranoid about this.
309 */
310static uint32_t safe_define_space(uint32_t index, uint32_t perm, uint32_t size)
311{
312 uint32_t result = tlcl_define_space(index, perm, size);
313 if (result == TPM_E_MAXNVWRITES) {
314 RETURN_ON_FAILURE(tpm_clear_and_reenable());
315 return tlcl_define_space(index, perm, size);
316 } else {
317 return result;
318 }
319}
320
Furquan Shaikhb038f412016-11-07 23:47:11 -0800321static uint32_t set_rec_hash_space(const uint8_t *data)
322{
323 RETURN_ON_FAILURE(safe_define_space(REC_HASH_NV_INDEX,
324 TPM_NV_PER_GLOBALLOCK |
325 TPM_NV_PER_PPWRITE,
326 REC_HASH_NV_SIZE));
327 RETURN_ON_FAILURE(write_secdata(REC_HASH_NV_INDEX, data,
328 REC_HASH_NV_SIZE));
329
330 return TPM_SUCCESS;
331}
332
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700333static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700334{
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700335 TPM_PERMANENT_FLAGS pflags;
336 uint32_t result;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700337
Daisuke Nojiri57990972014-07-15 19:47:32 -0700338 result = tlcl_get_permanent_flags(&pflags);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700339 if (result != TPM_SUCCESS)
340 return result;
341
342 /*
343 * TPM may come from the factory without physical presence finalized.
344 * Fix if necessary.
345 */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700346 VBDEBUG("TPM: physicalPresenceLifetimeLock=%d\n",
347 pflags.physicalPresenceLifetimeLock);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700348 if (!pflags.physicalPresenceLifetimeLock) {
Daisuke Nojiri57990972014-07-15 19:47:32 -0700349 VBDEBUG("TPM: Finalizing physical presence\n");
350 RETURN_ON_FAILURE(tlcl_finalize_physical_presence());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700351 }
352
353 /*
354 * The TPM will not enforce the NV authorization restrictions until the
355 * execution of a TPM_NV_DefineSpace with the handle of
356 * TPM_NV_INDEX_LOCK. Here we create that space if it doesn't already
357 * exist. */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700358 VBDEBUG("TPM: nvLocked=%d\n", pflags.nvLocked);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700359 if (!pflags.nvLocked) {
Daisuke Nojiri57990972014-07-15 19:47:32 -0700360 VBDEBUG("TPM: Enabling NV locking\n");
361 RETURN_ON_FAILURE(tlcl_set_nv_locked());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700362 }
363
364 /* Clear TPM owner, in case the TPM is already owned for some reason. */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700365 VBDEBUG("TPM: Clearing owner\n");
366 RETURN_ON_FAILURE(tpm_clear_and_reenable());
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700367
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700368 /* Define and initialize the kernel space */
369 RETURN_ON_FAILURE(safe_define_space(KERNEL_NV_INDEX,
370 TPM_NV_PER_PPWRITE,
371 sizeof(secdata_kernel)));
372 RETURN_ON_FAILURE(write_secdata(KERNEL_NV_INDEX,
373 secdata_kernel,
374 sizeof(secdata_kernel)));
375
Daisuke Nojiri57990972014-07-15 19:47:32 -0700376 /* Defines and sets vb2 secdata space */
377 vb2api_secdata_create(ctx);
378 RETURN_ON_FAILURE(safe_define_space(FIRMWARE_NV_INDEX,
379 TPM_NV_PER_GLOBALLOCK |
380 TPM_NV_PER_PPWRITE,
381 VB2_SECDATA_SIZE));
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700382 RETURN_ON_FAILURE(write_secdata(FIRMWARE_NV_INDEX,
383 ctx->secdata,
384 VB2_SECDATA_SIZE));
Furquan Shaikhb038f412016-11-07 23:47:11 -0800385
386 /* Define and set rec hash space, if available. */
387 if (IS_ENABLED(CONFIG_VBOOT_HAS_REC_HASH_SPACE))
388 RETURN_ON_FAILURE(set_rec_hash_space(rec_hash_data));
389
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700390 return TPM_SUCCESS;
391}
Vadim Bendebury4c0851c2016-07-03 17:08:10 -0700392
393uint32_t antirollback_lock_space_firmware(void)
394{
395 return tlcl_set_global_lock();
396}
Furquan Shaikhb038f412016-11-07 23:47:11 -0800397
398uint32_t antirollback_lock_space_rec_hash(void)
399{
400 /*
401 * Nothing needs to be done here, since global lock is already set while
402 * locking firmware space.
403 */
404 return TPM_SUCCESS;
405}
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700406#endif
407
Vadim Bendebury673a2662016-11-11 09:33:43 -0800408/**
409 * Perform one-time initializations.
410 *
411 * Create the NVRAM spaces, and set their initial values as needed. Sets the
412 * nvLocked bit and ensures the physical presence command is enabled and
413 * locked.
414 */
415static uint32_t factory_initialize_tpm(struct vb2_context *ctx)
Vadim Bendebury10ea1042016-06-06 12:12:34 -0700416{
417 uint32_t result;
418
419 /* Defines and sets vb2 secdata space */
420 vb2api_secdata_create(ctx);
421
422 VBDEBUG("TPM: factory initialization\n");
423
424 /*
425 * Do a full test. This only happens the first time the device is
426 * turned on in the factory, so performance is not an issue. This is
427 * almost certainly not necessary, but it gives us more confidence
428 * about some code paths below that are difficult to
429 * test---specifically the ones that set lifetime flags, and are only
430 * executed once per physical TPM.
431 */
432 result = tlcl_self_test_full();
433 if (result != TPM_SUCCESS)
434 return result;
435
436 result = _factory_initialize_tpm(ctx);
437 if (result != TPM_SUCCESS)
438 return result;
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700439
440 VBDEBUG("TPM: factory initialization successful\n");
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700441
442 return TPM_SUCCESS;
443}
444
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +0100445uint32_t vboot_setup_tpm(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700446{
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700447 uint32_t result;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700448
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +0100449 result = tpm_setup(ctx->flags & VB2_CONTEXT_S3_RESUME);
450 if (result == TPM_E_MUST_REBOOT)
Furquan Shaikh6fecb712015-09-17 12:40:23 -0700451 ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT;
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700452
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +0100453 return result;
Daisuke Nojiri57990972014-07-15 19:47:32 -0700454}
455
456uint32_t antirollback_read_space_firmware(struct vb2_context *ctx)
457{
458 uint32_t rv;
459
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +0100460 rv = vboot_setup_tpm(ctx);
Daisuke Nojiri57990972014-07-15 19:47:32 -0700461 if (rv)
462 return rv;
463
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700464 /* Read the firmware space. */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700465 rv = read_space_firmware(ctx);
466 if (rv == TPM_E_BADINDEX) {
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700467 /*
Daisuke Nojiri57990972014-07-15 19:47:32 -0700468 * This seems the first time we've run. Initialize the TPM.
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700469 */
Daisuke Nojiri57990972014-07-15 19:47:32 -0700470 VBDEBUG("TPM: Not initialized yet.\n");
471 RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
472 } else if (rv != TPM_SUCCESS) {
473 VBDEBUG("TPM: Firmware space in a bad state; giving up.\n");
474 //RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700475 return TPM_E_CORRUPTED_STATE;
476 }
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700477
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700478 return TPM_SUCCESS;
479}
480
Daisuke Nojiri57990972014-07-15 19:47:32 -0700481uint32_t antirollback_write_space_firmware(struct vb2_context *ctx)
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700482{
Aaron Durbineeb77372017-03-08 11:23:11 -0600483 if (IS_ENABLED(CONFIG_CR50_IMMEDIATELY_COMMIT_FW_SECDATA))
484 tlcl_cr50_enable_nvcommits();
Daisuke Nojiri97ea9c02014-09-29 13:02:29 -0700485 return write_secdata(FIRMWARE_NV_INDEX, ctx->secdata, VB2_SECDATA_SIZE);
Daisuke Nojiriefb5cde2014-07-02 08:37:23 -0700486}
Furquan Shaikhb038f412016-11-07 23:47:11 -0800487
488uint32_t antirollback_read_space_rec_hash(uint8_t *data, uint32_t size)
489{
490 if (size != REC_HASH_NV_SIZE) {
491 VBDEBUG("TPM: Incorrect buffer size for rec hash. "
492 "(Expected=0x%x Actual=0x%x).\n", REC_HASH_NV_SIZE,
493 size);
494 return TPM_E_READ_FAILURE;
495 }
496 return read_space_rec_hash(data);
497}
498
499uint32_t antirollback_write_space_rec_hash(const uint8_t *data, uint32_t size)
500{
501 uint8_t spc_data[REC_HASH_NV_SIZE];
502 uint32_t rv;
503
504 if (size != REC_HASH_NV_SIZE) {
505 VBDEBUG("TPM: Incorrect buffer size for rec hash. "
506 "(Expected=0x%x Actual=0x%x).\n", REC_HASH_NV_SIZE,
507 size);
508 return TPM_E_WRITE_FAILURE;
509 }
510
511 rv = read_space_rec_hash(spc_data);
512 if (rv == TPM_E_BADINDEX) {
513 /*
514 * If space is not defined already for recovery hash, define
515 * new space.
516 */
517 VBDEBUG("TPM: Initializing recovery hash space.\n");
518 return set_rec_hash_space(data);
519 }
520
521 if (rv != TPM_SUCCESS)
522 return rv;
523
524 return write_secdata(REC_HASH_NV_INDEX, data, size);
525}
Philipp Deppenwiesec07f8fb2018-02-27 19:40:52 +0100526
527int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
528{
529 uint32_t rv;
530 printk(BIOS_INFO, "Clearing TPM owner\n");
531 rv = tpm_clear_and_reenable();
532 if (rv)
533 return VB2_ERROR_EX_TPM_CLEAR_OWNER;
534 return VB2_SUCCESS;
535}