configs/config.msi_ms7d25_ddr4: enable UEFI capsule updates
[coreboot.git] / src / security / vboot / secdata_tpm.c
blob8714dd8fed54b180ff658a65894f887f03f20e67
1 /* SPDX-License-Identifier: BSD-3-Clause */
3 /*
4 * Functions for querying, manipulating and locking rollback indices
5 * stored in the TPM NVRAM.
6 */
8 #include <console/console.h>
9 #include <security/tpm/tspi.h>
10 #include <security/vboot/antirollback.h>
11 #include <vb2_api.h>
13 #include "secdata_tpm_private.h"
15 tpm_result_t antirollback_read_space_kernel(struct vb2_context *ctx)
17 if (tlcl_get_family() == TPM_1) {
19 * Before reading the kernel space, verify its permissions. If
20 * the kernel space has the wrong permission, we give up. This
21 * will need to be fixed by the recovery kernel. We will have
22 * to worry about this because at any time (even with PP turned
23 * off) the TPM owner can remove and redefine a PP-protected
24 * space (but not write to it).
26 uint32_t perms;
28 RETURN_ON_FAILURE(tlcl1_get_permissions(KERNEL_NV_INDEX, &perms));
29 if (perms != TPM_NV_PER_PPWRITE) {
30 printk(BIOS_ERR,
31 "TPM: invalid secdata_kernel permissions\n");
32 return TPM_CB_CORRUPTED_STATE;
36 uint8_t size = VB2_SECDATA_KERNEL_SIZE;
37 tpm_result_t rc;
39 /* Start with the version 1.0 size used by all modern Cr50/Ti50 boards. */
40 rc = tlcl_read(KERNEL_NV_INDEX, ctx->secdata_kernel, size);
41 if (rc == TPM_CB_RANGE) {
42 /* Fallback to version 0.2(minimum) size and re-read. */
43 VBDEBUG("Antirollback: NV read out of range, trying min size\n");
44 size = VB2_SECDATA_KERNEL_MIN_SIZE;
45 rc = tlcl_read(KERNEL_NV_INDEX, ctx->secdata_kernel, size);
47 RETURN_ON_FAILURE(rc);
49 if (vb2api_secdata_kernel_check(ctx, &size) == VB2_ERROR_SECDATA_KERNEL_INCOMPLETE)
50 /* Re-read. vboot will run the check and handle errors. */
51 RETURN_ON_FAILURE(tlcl_read(KERNEL_NV_INDEX, ctx->secdata_kernel, size));
53 return TPM_SUCCESS;
56 tpm_result_t safe_write(uint32_t index, const void *data, uint32_t length)
58 tpm_result_t rc = tlcl_write(index, data, length);
59 if (tlcl_get_family() == TPM_1 && rc == TPM_MAXNVWRITES) {
60 /**
61 * Clear the TPM on write error due to hitting the 64-write
62 * limit. This can only happen when the TPM is unowned, so it
63 * is OK to clear it (and we really have no choice). This is
64 * not expected to happen frequently, but it could happen.
66 RETURN_ON_FAILURE(tpm_clear_and_reenable());
67 rc = tlcl_write(index, data, length);
69 return rc;
72 static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
74 if (tlcl_get_family() == TPM_1)
75 return factory_initialize_tpm1(ctx);
76 if (tlcl_get_family() == TPM_2)
77 return factory_initialize_tpm2(ctx);
78 return TPM_CB_CORRUPTED_STATE;
81 uint32_t antirollback_lock_space_firmware(void)
83 if (tlcl_get_family() == TPM_1)
84 return tlcl1_set_global_lock();
85 if (tlcl_get_family() == TPM_2)
86 return tlcl2_lock_nv_write(FIRMWARE_NV_INDEX);
87 return TPM_CB_CORRUPTED_STATE;
90 /**
91 * Perform one-time initializations.
93 * Create the NVRAM spaces, and set their initial values as needed. Sets the
94 * nvLocked bit and ensures the physical presence command is enabled and
95 * locked.
97 static tpm_result_t factory_initialize_tpm(struct vb2_context *ctx)
99 tpm_result_t rc;
101 VBDEBUG("TPM: factory initialization\n");
104 * Do a full test. This only happens the first time the device is
105 * turned on in the factory, so performance is not an issue. This is
106 * almost certainly not necessary, but it gives us more confidence
107 * about some code paths below that are difficult to
108 * test---specifically the ones that set lifetime flags, and are only
109 * executed once per physical TPM.
111 rc = tlcl_self_test_full();
112 if (rc != TPM_SUCCESS)
113 return rc;
115 rc = _factory_initialize_tpm(ctx);
116 if (rc != TPM_SUCCESS)
117 return rc;
119 /* _factory_initialize_tpm() writes initial secdata values to TPM
120 immediately, so let vboot know that it's up to date now. */
121 ctx->flags &= ~(VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED |
122 VB2_CONTEXT_SECDATA_KERNEL_CHANGED);
124 VBDEBUG("TPM: factory initialization successful\n");
126 return TPM_SUCCESS;
129 tpm_result_t antirollback_read_space_firmware(struct vb2_context *ctx)
131 tpm_result_t rc;
133 rc = tlcl_read(FIRMWARE_NV_INDEX, ctx->secdata_firmware, VB2_SECDATA_FIRMWARE_SIZE);
134 if (rc == TPM_BADINDEX) {
135 /* This seems the first time we've run. Initialize the TPM. */
136 VBDEBUG("TPM: Not initialized yet\n");
137 RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
138 } else if (rc != TPM_SUCCESS) {
139 printk(BIOS_ERR, "TPM: Failed to read firmware space: %#x\n", rc);
140 return TPM_CB_CORRUPTED_STATE;
143 return rc;
146 tpm_result_t antirollback_write_space_firmware(struct vb2_context *ctx)
148 if (CONFIG(TPM_GOOGLE_IMMEDIATELY_COMMIT_FW_SECDATA))
149 tlcl_cr50_enable_nvcommits();
150 return safe_write(FIRMWARE_NV_INDEX, ctx->secdata_firmware,
151 VB2_SECDATA_FIRMWARE_SIZE);
154 tpm_result_t antirollback_write_space_kernel(struct vb2_context *ctx)
156 /* Learn the expected size. */
157 uint8_t size = VB2_SECDATA_KERNEL_MIN_SIZE;
158 vb2api_secdata_kernel_check(ctx, &size);
161 * Ensure that the TPM actually commits our changes to NVMEN in case
162 * there is a power loss or other unexpected event. The AP does not
163 * write to the TPM during normal boot flow; it only writes during
164 * recovery, software sync, or other special boot flows. When the AP
165 * wants to write, it is imporant to actually commit changes.
167 if (CONFIG(TPM_GOOGLE_IMMEDIATELY_COMMIT_FW_SECDATA))
168 tlcl_cr50_enable_nvcommits();
170 return safe_write(KERNEL_NV_INDEX, ctx->secdata_kernel, size);
173 vb2_error_t vb2ex_tpm_clear_owner(struct vb2_context *ctx)
175 printk(BIOS_INFO, "Clearing TPM owner\n");
176 return tpm_clear_and_reenable() == TPM_SUCCESS ? VB2_SUCCESS : VB2_ERROR_EX_TPM_CLEAR_OWNER;