blob: 4e0a9b727ae459c43aa52e68a3a01e56a594ca63 [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"
Elyes Haouasbdd03c22024-05-27 11:20:07 +02009#include <stdio.h>
Bill XIEc79e96b2019-08-22 20:28:36 +080010#include <string.h>
11
Sergii Dmytruk2710df72022-11-10 00:40:51 +020012static int tpm_log_initialized;
13static inline int tpm_log_available(void)
Bill XIEc79e96b2019-08-22 20:28:36 +080014{
15 if (ENV_BOOTBLOCK)
Sergii Dmytruk2710df72022-11-10 00:40:51 +020016 return tpm_log_initialized;
Bill XIEc79e96b2019-08-22 20:28:36 +080017
18 return 1;
19}
20
Arthur Heymans17cb5be2021-06-14 09:17:49 +020021/*
22 * Initializes the Core Root of Trust for Measurements
23 * in coreboot. The initial code in a chain of trust must measure
24 * itself.
25 *
26 * Summary:
27 * + Measures the FMAP FMAP partition.
28 * + Measures bootblock in CBFS or BOOTBLOCK FMAP partition.
29 * + If vboot starts in romstage, it measures the romstage
30 * in CBFS.
31 * + Measure the verstage if it is compiled as separate
32 * stage.
33 *
34 * Takes the current vboot context as parameter for s3 checks.
Jon Murphyd7b8dc92023-09-05 11:36:43 -060035 * returns on success TPM_SUCCESS, else a TPM error.
Arthur Heymans17cb5be2021-06-14 09:17:49 +020036 */
Jon Murphyd7b8dc92023-09-05 11:36:43 -060037static tpm_result_t tspi_init_crtm(void)
Bill XIEc79e96b2019-08-22 20:28:36 +080038{
Jon Murphyd7b8dc92023-09-05 11:36:43 -060039 tpm_result_t rc = TPM_SUCCESS;
Sergii Dmytruk2710df72022-11-10 00:40:51 +020040 /* Initialize TPM PRERAM log. */
41 if (!tpm_log_available()) {
42 tpm_preram_log_clear();
43 tpm_log_initialized = 1;
Bill XIEc79e96b2019-08-22 20:28:36 +080044 } else {
45 printk(BIOS_WARNING, "TSPI: CRTM already initialized!\n");
Jon Murphyd7b8dc92023-09-05 11:36:43 -060046 return TPM_SUCCESS;
Bill XIEc79e96b2019-08-22 20:28:36 +080047 }
48
Arthur Heymansf28dcbc2021-04-29 09:31:01 +020049 struct region_device fmap;
50 if (fmap_locate_area_as_rdev("FMAP", &fmap) == 0) {
Jon Murphyd7b8dc92023-09-05 11:36:43 -060051 rc = tpm_measure_region(&fmap, CONFIG_PCR_SRTM, "FMAP: FMAP");
52 if (rc) {
Arthur Heymansf28dcbc2021-04-29 09:31:01 +020053 printk(BIOS_ERR,
Jon Murphyd7b8dc92023-09-05 11:36:43 -060054 "TSPI: Couldn't measure FMAP into CRTM! rc %#x\n", rc);
55 return rc;
Arthur Heymansf28dcbc2021-04-29 09:31:01 +020056 }
57 } else {
58 printk(BIOS_ERR, "TSPI: Could not find FMAP!\n");
59 }
60
Bill XIEc79e96b2019-08-22 20:28:36 +080061 /* measure bootblock from RO */
Werner Zeh823b7b32022-05-19 14:14:13 +020062 if (!CONFIG(ARCH_X86)) {
63 struct region_device bootblock_fmap;
64 if (fmap_locate_area_as_rdev("BOOTBLOCK", &bootblock_fmap) == 0) {
Jon Murphyd7b8dc92023-09-05 11:36:43 -060065 rc = tpm_measure_region(&bootblock_fmap,
Sergii Dmytruk4129c262022-10-24 01:17:41 +030066 CONFIG_PCR_SRTM,
Jon Murphyd7b8dc92023-09-05 11:36:43 -060067 "FMAP: BOOTBLOCK");
68 if (rc)
69 return rc;
Werner Zeh823b7b32022-05-19 14:14:13 +020070 }
Naveen R. Iyer93cbbbf2024-04-19 17:26:17 -050071 } else if (CONFIG(BOOTBLOCK_IN_CBFS)) {
Julius Werner7e7cc1a2021-08-11 18:19:23 -070072 /* Mapping measures the file. We know we can safely map here because
73 bootblock-as-a-file is only used on x86, where we don't need cache to map. */
74 enum cbfs_type type = CBFS_TYPE_BOOTBLOCK;
75 void *mapping = cbfs_ro_type_map("bootblock", NULL, &type);
76 if (!mapping) {
Bill XIEc79e96b2019-08-22 20:28:36 +080077 printk(BIOS_INFO,
78 "TSPI: Couldn't measure bootblock into CRTM!\n");
Jon Murphyd7b8dc92023-09-05 11:36:43 -060079 return TPM_CB_FAIL;
Bill XIEc79e96b2019-08-22 20:28:36 +080080 }
Julius Werner7e7cc1a2021-08-11 18:19:23 -070081 cbfs_unmap(mapping);
Werner Zeh5c808e02022-05-19 09:16:28 +020082 } else {
83 /* Since none of the above conditions are met let the SOC code measure the
84 * bootblock. This accomplishes for cases where the bootblock is treated
85 * in a special way (e.g. part of IFWI or located in a different CBFS). */
Sergii Dmytruk4129c262022-10-24 01:17:41 +030086 if (tspi_soc_measure_bootblock(CONFIG_PCR_SRTM)) {
Werner Zeh5c808e02022-05-19 09:16:28 +020087 printk(BIOS_INFO,
88 "TSPI: Couldn't measure bootblock into CRTM on SoC level!\n");
Jon Murphyd7b8dc92023-09-05 11:36:43 -060089 return TPM_CB_FAIL;
Werner Zeh5c808e02022-05-19 09:16:28 +020090 }
91 }
Bill XIEc79e96b2019-08-22 20:28:36 +080092
Jon Murphyd7b8dc92023-09-05 11:36:43 -060093 return TPM_SUCCESS;
Bill XIEc79e96b2019-08-22 20:28:36 +080094}
95
96static bool is_runtime_data(const char *name)
97{
Duncan Laurieab673ce2020-06-12 10:41:32 -070098 const char *allowlist = CONFIG_TPM_MEASURED_BOOT_RUNTIME_DATA;
99 size_t allowlist_len = sizeof(CONFIG_TPM_MEASURED_BOOT_RUNTIME_DATA) - 1;
Bill XIEc79e96b2019-08-22 20:28:36 +0800100 size_t name_len = strlen(name);
harshitaae16332020-05-12 12:55:39 +0530101 const char *end;
Bill XIEc79e96b2019-08-22 20:28:36 +0800102
Duncan Laurieab673ce2020-06-12 10:41:32 -0700103 if (!allowlist_len || !name_len)
Bill XIEc79e96b2019-08-22 20:28:36 +0800104 return false;
105
Duncan Laurieab673ce2020-06-12 10:41:32 -0700106 while ((end = strchr(allowlist, ' '))) {
107 if (end - allowlist == name_len && !strncmp(allowlist, name, name_len))
Bill XIEc79e96b2019-08-22 20:28:36 +0800108 return true;
Duncan Laurieab673ce2020-06-12 10:41:32 -0700109 allowlist = end + 1;
Bill XIEc79e96b2019-08-22 20:28:36 +0800110 }
111
Duncan Laurieab673ce2020-06-12 10:41:32 -0700112 return !strcmp(allowlist, name);
Bill XIEc79e96b2019-08-22 20:28:36 +0800113}
114
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600115tpm_result_t tspi_cbfs_measurement(const char *name, uint32_t type, const struct vb2_hash *hash)
Bill XIEc79e96b2019-08-22 20:28:36 +0800116{
117 uint32_t pcr_index;
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600118 tpm_result_t rc = TPM_SUCCESS;
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200119 char tpm_log_metadata[TPM_CB_LOG_PCR_HASH_NAME];
Bill XIEc79e96b2019-08-22 20:28:36 +0800120
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200121 if (!tpm_log_available()) {
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600122 rc = tspi_init_crtm();
123 if (rc) {
Bill XIEc79e96b2019-08-22 20:28:36 +0800124 printk(BIOS_WARNING,
Frans Hendriks4622a2f2020-10-22 15:12:32 +0200125 "Initializing CRTM failed!\n");
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600126 return rc;
Bill XIEc79e96b2019-08-22 20:28:36 +0800127 }
Frans Hendriks4622a2f2020-10-22 15:12:32 +0200128 printk(BIOS_DEBUG, "CRTM initialized.\n");
Bill XIEc79e96b2019-08-22 20:28:36 +0800129 }
130
Julius Werner7e7cc1a2021-08-11 18:19:23 -0700131 switch (type) {
Bill XIEc79e96b2019-08-22 20:28:36 +0800132 case CBFS_TYPE_MRC_CACHE:
Sergii Dmytruk4129c262022-10-24 01:17:41 +0300133 pcr_index = CONFIG_PCR_RUNTIME_DATA;
Bill XIEc79e96b2019-08-22 20:28:36 +0800134 break;
Bill XIEbad08c22020-02-13 11:11:35 +0800135 /*
136 * mrc.bin is code executed on CPU, so it
137 * should not be considered runtime data
138 */
139 case CBFS_TYPE_MRC:
Bill XIEc79e96b2019-08-22 20:28:36 +0800140 case CBFS_TYPE_STAGE:
141 case CBFS_TYPE_SELF:
Julius Werner00572622022-05-26 20:29:42 -0700142 case CBFS_TYPE_FIT_PAYLOAD:
Sergii Dmytruk4129c262022-10-24 01:17:41 +0300143 pcr_index = CONFIG_PCR_SRTM;
Bill XIEc79e96b2019-08-22 20:28:36 +0800144 break;
145 default:
146 if (is_runtime_data(name))
Sergii Dmytruk4129c262022-10-24 01:17:41 +0300147 pcr_index = CONFIG_PCR_RUNTIME_DATA;
Bill XIEc79e96b2019-08-22 20:28:36 +0800148 else
Sergii Dmytruk4129c262022-10-24 01:17:41 +0300149 pcr_index = CONFIG_PCR_SRTM;
Bill XIEc79e96b2019-08-22 20:28:36 +0800150 break;
151 }
152
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200153 snprintf(tpm_log_metadata, TPM_CB_LOG_PCR_HASH_NAME, "CBFS: %s", name);
Bill XIEc79e96b2019-08-22 20:28:36 +0800154
Julius Werner7e7cc1a2021-08-11 18:19:23 -0700155 return tpm_extend_pcr(pcr_index, hash->algo, hash->raw, vb2_digest_size(hash->algo),
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200156 tpm_log_metadata);
Bill XIEc79e96b2019-08-22 20:28:36 +0800157}
158
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200159void *tpm_log_init(void)
160{
161 static void *tclt;
162
163 /* We are dealing here with pre CBMEM environment.
164 * If cbmem isn't available use CAR or SRAM */
Arthur Heymansb7cbb7c2023-08-11 11:31:05 +0200165 if (!ENV_HAS_CBMEM && !CONFIG(VBOOT_RETURN_FROM_VERSTAGE))
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200166 return _tpm_log;
167 else if (ENV_CREATES_CBMEM
168 && !CONFIG(VBOOT_RETURN_FROM_VERSTAGE)) {
169 tclt = tpm_log_cbmem_init();
170 if (!tclt)
171 return _tpm_log;
172 } else {
173 tclt = tpm_log_cbmem_init();
174 }
175
176 return tclt;
177}
178
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600179tpm_result_t tspi_measure_cache_to_pcr(void)
Bill XIEc79e96b2019-08-22 20:28:36 +0800180{
181 int i;
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200182 int pcr;
183 const char *event_name;
184 const uint8_t *digest_data;
185 enum vb2_hash_algorithm digest_algo;
Bill XIEc79e96b2019-08-22 20:28:36 +0800186
Arthur Heymansd873fa82021-06-14 09:18:45 +0200187 /* This means the table is empty. */
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200188 if (!tpm_log_available())
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600189 return TPM_SUCCESS;
Arthur Heymansd873fa82021-06-14 09:18:45 +0200190
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200191 if (tpm_log_init() == NULL) {
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200192 printk(BIOS_WARNING, "TPM LOG: log non-existent!\n");
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600193 return TPM_CB_FAIL;
Bill XIEc79e96b2019-08-22 20:28:36 +0800194 }
Bill XIEc79e96b2019-08-22 20:28:36 +0800195
Sergii Dmytruk2710df72022-11-10 00:40:51 +0200196 printk(BIOS_DEBUG, "TPM: Write digests cached in TPM log to PCR\n");
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200197 i = 0;
198 while (!tpm_log_get(i++, &pcr, &digest_data, &digest_algo, &event_name)) {
199 printk(BIOS_DEBUG, "TPM: Write digest for %s into PCR %d\n", event_name, pcr);
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600200 tpm_result_t rc = tlcl_extend(pcr, digest_data, digest_algo);
Jon Murphy24604812023-09-05 10:37:05 -0600201 if (rc != TPM_SUCCESS) {
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200202 printk(BIOS_ERR,
203 "TPM: Writing digest of %s into PCR failed with error %d\n",
Jon Murphy24604812023-09-05 10:37:05 -0600204 event_name, rc);
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600205 return rc;
Bill XIEc79e96b2019-08-22 20:28:36 +0800206 }
207 }
208
Jon Murphyd7b8dc92023-09-05 11:36:43 -0600209 return TPM_SUCCESS;
Bill XIEc79e96b2019-08-22 20:28:36 +0800210}
Sergii Dmytruk26203e72022-11-10 17:56:26 +0200211
212#if !CONFIG(VBOOT_RETURN_FROM_VERSTAGE)
213static void recover_tpm_log(int is_recovery)
214{
215 const void *preram_log = _tpm_log;
216 void *ram_log = tpm_log_cbmem_init();
217
218 if (tpm_log_get_size(preram_log) > MAX_PRERAM_TPM_LOG_ENTRIES) {
219 printk(BIOS_WARNING, "TPM LOG: pre-RAM log is too full, possible corruption\n");
220 return;
221 }
222
223 if (ram_log == NULL) {
224 printk(BIOS_WARNING, "TPM LOG: CBMEM not available, something went wrong\n");
225 return;
226 }
227
228 tpm_log_copy_entries(_tpm_log, ram_log);
229}
230CBMEM_CREATION_HOOK(recover_tpm_log);
231#endif
232
233BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, tpm_log_dump, NULL);