1 /* SPDX-License-Identifier: BSD-3-Clause */
4 * Functions for querying, manipulating and locking rollback indices
5 * stored in the TPM NVRAM.
8 #include <console/console.h>
9 #include <security/tpm/tspi.h>
10 #include <security/vboot/antirollback.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).
28 RETURN_ON_FAILURE(tlcl1_get_permissions(KERNEL_NV_INDEX
, &perms
));
29 if (perms
!= TPM_NV_PER_PPWRITE
) {
31 "TPM: invalid secdata_kernel permissions\n");
32 return TPM_CB_CORRUPTED_STATE
;
36 uint8_t size
= VB2_SECDATA_KERNEL_SIZE
;
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
));
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
) {
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
);
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
;
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
97 static tpm_result_t
factory_initialize_tpm(struct vb2_context
*ctx
)
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
)
115 rc
= _factory_initialize_tpm(ctx
);
116 if (rc
!= TPM_SUCCESS
)
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");
129 tpm_result_t
antirollback_read_space_firmware(struct vb2_context
*ctx
)
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
;
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
;