blob: 24133d9f9fc5cc47a724d2ac94d65364c41b0876 [file] [log] [blame]
Angel Pons986d50e2020-04-02 23:48:53 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Bill XIEc79e96b2019-08-22 20:28:36 +08002
3#include <console/console.h>
4#include <fmap.h>
5#include <cbfs.h>
6#include "crtm.h"
7#include <string.h>
8
Bill XIEc79e96b2019-08-22 20:28:36 +08009static int tcpa_log_initialized;
10static inline int tcpa_log_available(void)
11{
12 if (ENV_BOOTBLOCK)
13 return tcpa_log_initialized;
14
15 return 1;
16}
17
Arthur Heymans17cb5be2021-06-14 09:17:49 +020018/*
19 * Initializes the Core Root of Trust for Measurements
20 * in coreboot. The initial code in a chain of trust must measure
21 * itself.
22 *
23 * Summary:
24 * + Measures the FMAP FMAP partition.
25 * + Measures bootblock in CBFS or BOOTBLOCK FMAP partition.
26 * + If vboot starts in romstage, it measures the romstage
27 * in CBFS.
28 * + Measure the verstage if it is compiled as separate
29 * stage.
30 *
31 * Takes the current vboot context as parameter for s3 checks.
32 * returns on success VB2_SUCCESS, else a vboot error.
33 */
34static uint32_t tspi_init_crtm(void)
Bill XIEc79e96b2019-08-22 20:28:36 +080035{
Bill XIEc79e96b2019-08-22 20:28:36 +080036 /* Initialize TCPA PRERAM log. */
37 if (!tcpa_log_available()) {
38 tcpa_preram_log_clear();
39 tcpa_log_initialized = 1;
40 } else {
41 printk(BIOS_WARNING, "TSPI: CRTM already initialized!\n");
42 return VB2_SUCCESS;
43 }
44
Arthur Heymansf28dcbc2021-04-29 09:31:01 +020045 struct region_device fmap;
46 if (fmap_locate_area_as_rdev("FMAP", &fmap) == 0) {
Arthur Heymansb0ccac092021-05-06 09:33:25 +020047 if (tpm_measure_region(&fmap, TPM_CRTM_PCR, "FMAP: FMAP")) {
Arthur Heymansf28dcbc2021-04-29 09:31:01 +020048 printk(BIOS_ERR,
49 "TSPI: Couldn't measure FMAP into CRTM!\n");
50 return VB2_ERROR_UNKNOWN;
51 }
52 } else {
53 printk(BIOS_ERR, "TSPI: Could not find FMAP!\n");
54 }
55
Bill XIEc79e96b2019-08-22 20:28:36 +080056 /* measure bootblock from RO */
Werner Zeh823b7b32022-05-19 14:14:13 +020057 if (!CONFIG(ARCH_X86)) {
58 struct region_device bootblock_fmap;
59 if (fmap_locate_area_as_rdev("BOOTBLOCK", &bootblock_fmap) == 0) {
60 if (tpm_measure_region(&bootblock_fmap,
61 TPM_CRTM_PCR,
62 "FMAP: BOOTBLOCK"))
63 return VB2_ERROR_UNKNOWN;
64 }
Arthur Heymans9642e972022-05-17 09:57:01 +020065 } else if (CONFIG(BOOTBLOCK_IN_CBFS)){
Julius Werner7e7cc1a2021-08-11 18:19:23 -070066 /* Mapping measures the file. We know we can safely map here because
67 bootblock-as-a-file is only used on x86, where we don't need cache to map. */
68 enum cbfs_type type = CBFS_TYPE_BOOTBLOCK;
69 void *mapping = cbfs_ro_type_map("bootblock", NULL, &type);
70 if (!mapping) {
Bill XIEc79e96b2019-08-22 20:28:36 +080071 printk(BIOS_INFO,
72 "TSPI: Couldn't measure bootblock into CRTM!\n");
73 return VB2_ERROR_UNKNOWN;
74 }
Julius Werner7e7cc1a2021-08-11 18:19:23 -070075 cbfs_unmap(mapping);
Werner Zeh5c808e02022-05-19 09:16:28 +020076 } else {
77 /* Since none of the above conditions are met let the SOC code measure the
78 * bootblock. This accomplishes for cases where the bootblock is treated
79 * in a special way (e.g. part of IFWI or located in a different CBFS). */
80 if (tspi_soc_measure_bootblock(TPM_CRTM_PCR)) {
81 printk(BIOS_INFO,
82 "TSPI: Couldn't measure bootblock into CRTM on SoC level!\n");
83 return VB2_ERROR_UNKNOWN;
84 }
85 }
Bill XIEc79e96b2019-08-22 20:28:36 +080086
87 return VB2_SUCCESS;
88}
89
90static bool is_runtime_data(const char *name)
91{
Duncan Laurieab673ce2020-06-12 10:41:32 -070092 const char *allowlist = CONFIG_TPM_MEASURED_BOOT_RUNTIME_DATA;
93 size_t allowlist_len = sizeof(CONFIG_TPM_MEASURED_BOOT_RUNTIME_DATA) - 1;
Bill XIEc79e96b2019-08-22 20:28:36 +080094 size_t name_len = strlen(name);
harshitaae16332020-05-12 12:55:39 +053095 const char *end;
Bill XIEc79e96b2019-08-22 20:28:36 +080096
Duncan Laurieab673ce2020-06-12 10:41:32 -070097 if (!allowlist_len || !name_len)
Bill XIEc79e96b2019-08-22 20:28:36 +080098 return false;
99
Duncan Laurieab673ce2020-06-12 10:41:32 -0700100 while ((end = strchr(allowlist, ' '))) {
101 if (end - allowlist == name_len && !strncmp(allowlist, name, name_len))
Bill XIEc79e96b2019-08-22 20:28:36 +0800102 return true;
Duncan Laurieab673ce2020-06-12 10:41:32 -0700103 allowlist = end + 1;
Bill XIEc79e96b2019-08-22 20:28:36 +0800104 }
105
Duncan Laurieab673ce2020-06-12 10:41:32 -0700106 return !strcmp(allowlist, name);
Bill XIEc79e96b2019-08-22 20:28:36 +0800107}
108
Julius Werner7e7cc1a2021-08-11 18:19:23 -0700109uint32_t tspi_cbfs_measurement(const char *name, uint32_t type, const struct vb2_hash *hash)
Bill XIEc79e96b2019-08-22 20:28:36 +0800110{
111 uint32_t pcr_index;
Bill XIEc79e96b2019-08-22 20:28:36 +0800112 char tcpa_metadata[TCPA_PCR_HASH_NAME];
113
114 if (!tcpa_log_available()) {
115 if (tspi_init_crtm() != VB2_SUCCESS) {
116 printk(BIOS_WARNING,
Frans Hendriks4622a2f2020-10-22 15:12:32 +0200117 "Initializing CRTM failed!\n");
Bill XIEc79e96b2019-08-22 20:28:36 +0800118 return 0;
119 }
Frans Hendriks4622a2f2020-10-22 15:12:32 +0200120 printk(BIOS_DEBUG, "CRTM initialized.\n");
Bill XIEc79e96b2019-08-22 20:28:36 +0800121 }
122
Julius Werner7e7cc1a2021-08-11 18:19:23 -0700123 switch (type) {
Bill XIEc79e96b2019-08-22 20:28:36 +0800124 case CBFS_TYPE_MRC_CACHE:
125 pcr_index = TPM_RUNTIME_DATA_PCR;
126 break;
Bill XIEbad08c22020-02-13 11:11:35 +0800127 /*
128 * mrc.bin is code executed on CPU, so it
129 * should not be considered runtime data
130 */
131 case CBFS_TYPE_MRC:
Bill XIEc79e96b2019-08-22 20:28:36 +0800132 case CBFS_TYPE_STAGE:
133 case CBFS_TYPE_SELF:
Julius Werner00572622022-05-26 20:29:42 -0700134 case CBFS_TYPE_FIT_PAYLOAD:
Bill XIEc79e96b2019-08-22 20:28:36 +0800135 pcr_index = TPM_CRTM_PCR;
136 break;
137 default:
138 if (is_runtime_data(name))
139 pcr_index = TPM_RUNTIME_DATA_PCR;
140 else
141 pcr_index = TPM_CRTM_PCR;
142 break;
143 }
144
Julius Werner7e7cc1a2021-08-11 18:19:23 -0700145 snprintf(tcpa_metadata, TCPA_PCR_HASH_NAME, "CBFS: %s", name);
Bill XIEc79e96b2019-08-22 20:28:36 +0800146
Julius Werner7e7cc1a2021-08-11 18:19:23 -0700147 return tpm_extend_pcr(pcr_index, hash->algo, hash->raw, vb2_digest_size(hash->algo),
148 tcpa_metadata);
Bill XIEc79e96b2019-08-22 20:28:36 +0800149}
150
151int tspi_measure_cache_to_pcr(void)
152{
153 int i;
Bill XIEc79e96b2019-08-22 20:28:36 +0800154 struct tcpa_table *tclt = tcpa_log_init();
155
Arthur Heymansd873fa82021-06-14 09:18:45 +0200156 /* This means the table is empty. */
157 if (!tcpa_log_available())
158 return VB2_SUCCESS;
159
Bill XIEc79e96b2019-08-22 20:28:36 +0800160 if (!tclt) {
161 printk(BIOS_WARNING, "TCPA: Log non-existent!\n");
162 return VB2_ERROR_UNKNOWN;
163 }
Bill XIEc79e96b2019-08-22 20:28:36 +0800164
Bill XIEc79e96b2019-08-22 20:28:36 +0800165 printk(BIOS_DEBUG, "TPM: Write digests cached in TCPA log to PCR\n");
166 for (i = 0; i < tclt->num_entries; i++) {
167 struct tcpa_entry *tce = &tclt->entries[i];
168 if (tce) {
169 printk(BIOS_DEBUG, "TPM: Write digest for"
170 " %s into PCR %d\n",
171 tce->name, tce->pcr);
172 int result = tlcl_extend(tce->pcr,
173 tce->digest,
174 NULL);
175 if (result != TPM_SUCCESS) {
176 printk(BIOS_ERR, "TPM: Writing digest"
177 " of %s into PCR failed with error"
178 " %d\n",
179 tce->name, result);
180 return VB2_ERROR_UNKNOWN;
181 }
182 }
183 }
184
185 return VB2_SUCCESS;
186}