xref: /aosp_15_r20/external/coreboot/src/security/vboot/secdata_tpm.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 
3 /*
4  * Functions for querying, manipulating and locking rollback indices
5  * stored in the TPM NVRAM.
6  */
7 
8 #include <console/console.h>
9 #include <security/tpm/tspi.h>
10 #include <security/vboot/antirollback.h>
11 #include <vb2_api.h>
12 
13 #include "secdata_tpm_private.h"
14 
antirollback_read_space_kernel(struct vb2_context * ctx)15 tpm_result_t antirollback_read_space_kernel(struct vb2_context *ctx)
16 {
17 	if (tlcl_get_family() == TPM_1) {
18 		/*
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).
25 		 */
26 		uint32_t perms;
27 
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;
33 		}
34 	}
35 
36 	uint8_t size = VB2_SECDATA_KERNEL_SIZE;
37 	tpm_result_t rc;
38 
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);
46 	}
47 	RETURN_ON_FAILURE(rc);
48 
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));
52 
53 	return TPM_SUCCESS;
54 }
55 
safe_write(uint32_t index,const void * data,uint32_t length)56 tpm_result_t safe_write(uint32_t index, const void *data, uint32_t length)
57 {
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.
65 		 */
66 		RETURN_ON_FAILURE(tpm_clear_and_reenable());
67 		rc = tlcl_write(index, data, length);
68 	}
69 	return rc;
70 }
71 
_factory_initialize_tpm(struct vb2_context * ctx)72 static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
73 {
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;
79 }
80 
antirollback_lock_space_firmware(void)81 uint32_t antirollback_lock_space_firmware(void)
82 {
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;
88 }
89 
90 /**
91  * Perform one-time initializations.
92  *
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.
96  */
factory_initialize_tpm(struct vb2_context * ctx)97 static tpm_result_t factory_initialize_tpm(struct vb2_context *ctx)
98 {
99 	tpm_result_t rc;
100 
101 	VBDEBUG("TPM: factory initialization\n");
102 
103 	/*
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.
110 	 */
111 	rc = tlcl_self_test_full();
112 	if (rc != TPM_SUCCESS)
113 		return rc;
114 
115 	rc = _factory_initialize_tpm(ctx);
116 	if (rc != TPM_SUCCESS)
117 		return rc;
118 
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);
123 
124 	VBDEBUG("TPM: factory initialization successful\n");
125 
126 	return TPM_SUCCESS;
127 }
128 
antirollback_read_space_firmware(struct vb2_context * ctx)129 tpm_result_t antirollback_read_space_firmware(struct vb2_context *ctx)
130 {
131 	tpm_result_t rc;
132 
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;
141 	}
142 
143 	return rc;
144 }
145 
antirollback_write_space_firmware(struct vb2_context * ctx)146 tpm_result_t antirollback_write_space_firmware(struct vb2_context *ctx)
147 {
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);
152 }
153 
antirollback_write_space_kernel(struct vb2_context * ctx)154 tpm_result_t antirollback_write_space_kernel(struct vb2_context *ctx)
155 {
156 	/* Learn the expected size. */
157 	uint8_t size = VB2_SECDATA_KERNEL_MIN_SIZE;
158 	vb2api_secdata_kernel_check(ctx, &size);
159 
160 	/*
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.
166 	 */
167 	if (CONFIG(TPM_GOOGLE_IMMEDIATELY_COMMIT_FW_SECDATA))
168 		tlcl_cr50_enable_nvcommits();
169 
170 	return safe_write(KERNEL_NV_INDEX, ctx->secdata_kernel, size);
171 }
172 
vb2ex_tpm_clear_owner(struct vb2_context * ctx)173 vb2_error_t vb2ex_tpm_clear_owner(struct vb2_context *ctx)
174 {
175 	printk(BIOS_INFO, "Clearing TPM owner\n");
176 	return tpm_clear_and_reenable() == TPM_SUCCESS ? VB2_SUCCESS : VB2_ERROR_EX_TPM_CLEAR_OWNER;
177 }
178