blob: 36dffb857630cf7a95f733f7903f4df934532da9 [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>
Sergii Dmytruk26203e72022-11-10 17:56:26 +02005#include <bootstate.h>
Bill XIEc79e96b2019-08-22 20:28:36 +08006#include <cbfs.h>
Sergii Dmytruk26203e72022-11-10 17:56:26 +02007#include <symbols.h>
Bill XIEc79e96b2019-08-22 20:28:36 +08008#include "crtm.h"
9#include <string.h>
10
Sergii Dmytruk2710df72022-11-10 00:40:51 +020011static int tpm_log_initialized;
12static inline int tpm_log_available(void)
Bill XIEc79e96b2019-08-22 20:28:36 +080013{
14 if (ENV_BOOTBLOCK)
Sergii Dmytruk2710df72022-11-10 00:40:51 +020015 return tpm_log_initialized;
Bill XIEc79e96b2019-08-22 20:28:36 +080016
17 return 1;
18}
19
Arthur Heymans17cb5be2021-06-14 09:17:49 +020020/*
21 * Initializes the Core Root of Trust for Measurements
22 * in coreboot. The initial code in a chain of trust must measure
23 * itself.
24 *
25 * Summary:
26 * + Measures the FMAP FMAP partition.
27 * + Measures bootblock in CBFS or BOOTBLOCK FMAP partition.
28 * + If vboot starts in romstage, it measures the romstage
29 * in CBFS.
30 * + Measure the verstage if it is compiled as separate
31 * stage.
32 *
33 * Takes the current vboot context as parameter for s3 checks.
34 * returns on success VB2_SUCCESS, else a vboot error.
35 */
36static uint32_t tspi_init_crtm(void)
Bill XIEc79e96b2019-08-22 20:28:36 +080037{
Sergii Dmytruk2710df72022-11-10 00:40:51 +020038 /* Initialize TPM PRERAM log. */
39 if (!tpm_log_available()) {
40 tpm_preram_log_clear();
41 tpm_log_initialized = 1;
Bill XIEc79e96b2019-08-22 20:28:36 +080042 } else {
43 printk(BIOS_WARNING, "TSPI: CRTM already initialized!\n");
44 return VB2_SUCCESS;
45 }
46
Arthur Heymansf28dcbc2021-04-29 09:31:01 +020047 struct region_device fmap;
48 if (fmap_locate_area_as_rdev("FMAP", &fmap) == 0) {
Sergii Dmytruk4129c262022-10-24 01:17:41 +030049 if (tpm_measure_region(&fmap, CONFIG_PCR_SRTM, "FMAP: FMAP")) {
Arthur Heymansf28dcbc2021-04-29 09:31:01 +020050 printk(BIOS_ERR,
51 "TSPI: Couldn't measure FMAP into CRTM!\n");
52 return VB2_ERROR_UNKNOWN;
53 }
54 } else {
55 printk(BIOS_ERR, "TSPI: Could not find FMAP!\n");
56 }
57
Bill XIEc79e96b2019-08-22 20:28:36 +080058 /* measure bootblock from RO */
Werner Zeh823b7b32022-05-19 14:14:13 +020059 if (!CONFIG(ARCH_X86)) {
60 struct region_device bootblock_fmap;
61 if (fmap_locate_area_as_rdev("BOOTBLOCK", &bootblock_fmap) == 0) {
62 if (tpm_measure_region(&bootblock_fmap,
Sergii Dmytruk4129c262022-10-24 01:17:41 +030063 CONFIG_PCR_SRTM,
Werner Zeh823b7b32022-05-19 14:14:13 +020064 "FMAP: BOOTBLOCK"))
65 return VB2_ERROR_UNKNOWN;
66 }
Arthur Heymans9642e972022-05-17 09:57:01 +020067 } else if (CONFIG(BOOTBLOCK_IN_CBFS)){
Julius Werner7e7cc1a2021-08-11 18:19:23 -070068 /* Mapping measures the file. We know we can safely map here because
69 bootblock-as-a-file is only used on x86, where we don't need cache to map. */
70 enum cbfs_type type = CBFS_TYPE_BOOTBLOCK;
71 void *mapping = cbfs_ro_type_map("bootblock", NULL, &type);
72 if (!mapping) {
Bill XIEc79e96b2019-08-22 20:28:36 +080073 printk(BIOS_INFO,
74 "TSPI: Couldn't measure bootblock into CRTM!\n");
75 return VB2_ERROR_UNKNOWN;
76 }
Julius Werner7e7cc1a2021-08-11 18:19:23 -070077 cbfs_unmap(mapping);
Werner Zeh5c808e02022-05-19 09:16:28 +020078 } else {
79 /* Since none of the above conditions are met let the SOC code measure the
80 * bootblock. This accomplishes for cases where the bootblock is treated
81 * in a special way (e.g. part of IFWI or located in a different CBFS). */
Sergii Dmytruk4129c262022-10-24 01:17:41 +030082 if (tspi_soc_measure_bootblock(CONFIG_PCR_SRTM)) {
Werner Zeh5c808e02022-05-19 09:16:28 +020083 printk(BIOS_INFO,
84 "TSPI: Couldn't measure bootblock into CRTM on SoC level!\n");
85 return VB2_ERROR_UNKNOWN;
86 }
87 }
Bill XIEc79e96b2019-08-22 20:28:36 +080088
89 return VB2_SUCCESS;
90}
91
92static bool is_runtime_data(const char *name)
93{
Duncan Laurieab673ce2020-06-12 10:41:32 -070094 const char *allowlist = CONFIG_TPM_MEASURED_BOOT_RUNTIME_DATA;
95 size_t allowlist_len = sizeof(CONFIG_TPM_MEASURED_BOOT_RUNTIME_DATA) - 1;
Bill XIEc79e96b2019-08-22 20:28:36 +080096 size_t name_len = strlen(name);
harshitaae16332020-05-12 12:55:39 +053097 const char *end;
Bill XIEc79e96b2019-08-22 20:28:36 +080098
Duncan Laurieab673ce2020-06-12 10:41:32 -070099 if (!allowlist_len || !name_len)
Bill XIEc79e96b2019-08-22 20:28:36 +0800100 return false;
101
Duncan Laurieab673ce2020-06-12 10:41:32 -0700102 while ((end = strchr(allowlist, ' '))) {
103 if (end - allowlist == name_len && !strncmp(allowlist, name, name_len))
Bill XIEc79e96b2019-08-22 20:28:36 +0800104 return true;
Duncan Laurieab673ce2020-06-12 10:41:32 -0700105 allowlist = end + 1;
Bill XIEc79e96b2019-08-22 20:28:36 +0800106 }
107
Duncan Laurieab673ce2020-06-12 10:41:32 -0700108 return !strcmp(allowlist, name);
Bill XIEc79e96b2019-08-22 20:28:36 +0800109}
110
Julius Werner7e7cc1a2021-08-11 18:19:23 -0700111uint32_t tspi_cbfs_measurement(const char *name, uint32_t type, const struct vb2_hash *hash)
Bill XIEc79e96b2019-08-22 20:28:36 +0800112{
113 uint32_t pcr_index;
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200114 char tpm_log_metadata[TPM_CB_LOG_PCR_HASH_NAME];
Bill XIEc79e96b2019-08-22 20:28:36 +0800115
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200116 if (!tpm_log_available()) {
Bill XIEc79e96b2019-08-22 20:28:36 +0800117 if (tspi_init_crtm() != VB2_SUCCESS) {
118 printk(BIOS_WARNING,
Frans Hendriks4622a2f2020-10-22 15:12:32 +0200119 "Initializing CRTM failed!\n");
Bill XIEc79e96b2019-08-22 20:28:36 +0800120 return 0;
121 }
Frans Hendriks4622a2f2020-10-22 15:12:32 +0200122 printk(BIOS_DEBUG, "CRTM initialized.\n");
Bill XIEc79e96b2019-08-22 20:28:36 +0800123 }
124
Julius Werner7e7cc1a2021-08-11 18:19:23 -0700125 switch (type) {
Bill XIEc79e96b2019-08-22 20:28:36 +0800126 case CBFS_TYPE_MRC_CACHE:
Sergii Dmytruk4129c262022-10-24 01:17:41 +0300127 pcr_index = CONFIG_PCR_RUNTIME_DATA;
Bill XIEc79e96b2019-08-22 20:28:36 +0800128 break;
Bill XIEbad08c22020-02-13 11:11:35 +0800129 /*
130 * mrc.bin is code executed on CPU, so it
131 * should not be considered runtime data
132 */
133 case CBFS_TYPE_MRC:
Bill XIEc79e96b2019-08-22 20:28:36 +0800134 case CBFS_TYPE_STAGE:
135 case CBFS_TYPE_SELF:
Julius Werner00572622022-05-26 20:29:42 -0700136 case CBFS_TYPE_FIT_PAYLOAD:
Sergii Dmytruk4129c262022-10-24 01:17:41 +0300137 pcr_index = CONFIG_PCR_SRTM;
Bill XIEc79e96b2019-08-22 20:28:36 +0800138 break;
139 default:
140 if (is_runtime_data(name))
Sergii Dmytruk4129c262022-10-24 01:17:41 +0300141 pcr_index = CONFIG_PCR_RUNTIME_DATA;
Bill XIEc79e96b2019-08-22 20:28:36 +0800142 else
Sergii Dmytruk4129c262022-10-24 01:17:41 +0300143 pcr_index = CONFIG_PCR_SRTM;
Bill XIEc79e96b2019-08-22 20:28:36 +0800144 break;
145 }
146
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200147 snprintf(tpm_log_metadata, TPM_CB_LOG_PCR_HASH_NAME, "CBFS: %s", name);
Bill XIEc79e96b2019-08-22 20:28:36 +0800148
Julius Werner7e7cc1a2021-08-11 18:19:23 -0700149 return tpm_extend_pcr(pcr_index, hash->algo, hash->raw, vb2_digest_size(hash->algo),
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200150 tpm_log_metadata);
Bill XIEc79e96b2019-08-22 20:28:36 +0800151}
152
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200153void *tpm_log_init(void)
154{
155 static void *tclt;
156
157 /* We are dealing here with pre CBMEM environment.
158 * If cbmem isn't available use CAR or SRAM */
159 if (!cbmem_possibly_online() &&
160 !CONFIG(VBOOT_RETURN_FROM_VERSTAGE))
161 return _tpm_log;
162 else if (ENV_CREATES_CBMEM
163 && !CONFIG(VBOOT_RETURN_FROM_VERSTAGE)) {
164 tclt = tpm_log_cbmem_init();
165 if (!tclt)
166 return _tpm_log;
167 } else {
168 tclt = tpm_log_cbmem_init();
169 }
170
171 return tclt;
172}
173
Bill XIEc79e96b2019-08-22 20:28:36 +0800174int tspi_measure_cache_to_pcr(void)
175{
176 int i;
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200177 int pcr;
178 const char *event_name;
179 const uint8_t *digest_data;
180 enum vb2_hash_algorithm digest_algo;
Bill XIEc79e96b2019-08-22 20:28:36 +0800181
Arthur Heymansd873fa82021-06-14 09:18:45 +0200182 /* This means the table is empty. */
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200183 if (!tpm_log_available())
Arthur Heymansd873fa82021-06-14 09:18:45 +0200184 return VB2_SUCCESS;
185
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200186 if (tpm_log_init() == NULL) {
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200187 printk(BIOS_WARNING, "TPM LOG: log non-existent!\n");
Bill XIEc79e96b2019-08-22 20:28:36 +0800188 return VB2_ERROR_UNKNOWN;
189 }
Bill XIEc79e96b2019-08-22 20:28:36 +0800190
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200191 printk(BIOS_DEBUG, "TPM: Write digests cached in TPM log to PCR\n");
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200192 i = 0;
193 while (!tpm_log_get(i++, &pcr, &digest_data, &digest_algo, &event_name)) {
194 printk(BIOS_DEBUG, "TPM: Write digest for %s into PCR %d\n", event_name, pcr);
195 int result = tlcl_extend(pcr, digest_data, digest_algo);
196 if (result != TPM_SUCCESS) {
197 printk(BIOS_ERR,
198 "TPM: Writing digest of %s into PCR failed with error %d\n",
199 event_name, result);
200 return VB2_ERROR_UNKNOWN;
Bill XIEc79e96b2019-08-22 20:28:36 +0800201 }
202 }
203
204 return VB2_SUCCESS;
205}
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200206
207#if !CONFIG(VBOOT_RETURN_FROM_VERSTAGE)
208static void recover_tpm_log(int is_recovery)
209{
210 const void *preram_log = _tpm_log;
211 void *ram_log = tpm_log_cbmem_init();
212
213 if (tpm_log_get_size(preram_log) > MAX_PRERAM_TPM_LOG_ENTRIES) {
214 printk(BIOS_WARNING, "TPM LOG: pre-RAM log is too full, possible corruption\n");
215 return;
216 }
217
218 if (ram_log == NULL) {
219 printk(BIOS_WARNING, "TPM LOG: CBMEM not available, something went wrong\n");
220 return;
221 }
222
223 tpm_log_copy_entries(_tpm_log, ram_log);
224}
225CBMEM_CREATION_HOOK(recover_tpm_log);
226#endif
227
228BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, tpm_log_dump, NULL);