blob: e4266b2ca9d7c67ab4f70765596f98dd7f714571 [file] [log] [blame]
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2018 Facebook Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <console/console.h>
17#include <fmap.h>
Elyes HAOUAS28b38cd2019-03-18 11:30:08 +010018#include <cbfs.h>
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +010019#include <security/vboot/vboot_crtm.h>
20#include <security/vboot/misc.h>
Elyes HAOUASa1e22b82019-03-18 22:49:36 +010021#include <string.h>
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +010022
Philipp Deppenwiesec9b7d1f2018-11-10 00:35:02 +010023/*
24 * This functions sets the TCPA log namespace
25 * for the cbfs file (region) lookup.
26 */
27static int create_tcpa_metadata(const struct region_device *rdev,
28 const char *cbfs_name, char log_string[TCPA_PCR_HASH_NAME])
29{
30 int i;
31 struct region_device fmap;
32 const static char *fmap_cbfs_names[] = {
33 "COREBOOT",
34 "FW_MAIN_A",
35 "FW_MAIN_B",
36 "RW_LEGACY"};
37
38 for (i = 0; i < ARRAY_SIZE(fmap_cbfs_names); i++) {
39 if (fmap_locate_area_as_rdev(fmap_cbfs_names[i], &fmap) == 0) {
40 if (region_is_subregion(region_device_region(&fmap),
41 region_device_region(rdev))) {
42 snprintf(log_string, TCPA_PCR_HASH_NAME,
43 "FMAP: %s CBFS: %s",
44 fmap_cbfs_names[i], cbfs_name);
45 return 0;
46 }
47 }
48 }
49
50 return -1;
51}
52
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +010053uint32_t vboot_init_crtm(void)
54{
55 struct prog bootblock = PROG_INIT(PROG_BOOTBLOCK, "bootblock");
56 struct prog verstage =
57 PROG_INIT(PROG_VERSTAGE, CONFIG_CBFS_PREFIX "/verstage");
58 struct prog romstage =
59 PROG_INIT(PROG_ROMSTAGE, CONFIG_CBFS_PREFIX "/romstage");
Philipp Deppenwiesec9b7d1f2018-11-10 00:35:02 +010060 char tcpa_metadata[TCPA_PCR_HASH_NAME];
61
62 /* Initialize TCPE PRERAM log. */
63 tcpa_preram_log_clear();
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +010064
65 /* measure bootblock from RO */
66 struct cbfsf bootblock_data;
67 struct region_device bootblock_fmap;
68 if (fmap_locate_area_as_rdev("BOOTBLOCK", &bootblock_fmap) == 0) {
69 if (tpm_measure_region(&bootblock_fmap,
70 TPM_CRTM_PCR,
Philipp Deppenwiesec9b7d1f2018-11-10 00:35:02 +010071 "FMAP: BOOTBLOCK"))
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +010072 return VB2_ERROR_UNKNOWN;
73 } else {
74 if (cbfs_boot_locate(&bootblock_data,
75 prog_name(&bootblock), NULL) == 0) {
76 cbfs_file_data(prog_rdev(&bootblock), &bootblock_data);
77
Philipp Deppenwiesec9b7d1f2018-11-10 00:35:02 +010078 if (create_tcpa_metadata(prog_rdev(&bootblock),
79 prog_name(&bootblock), tcpa_metadata) < 0)
80 return VB2_ERROR_UNKNOWN;
81
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +010082 if (tpm_measure_region(prog_rdev(&bootblock),
Philipp Deppenwiesec9b7d1f2018-11-10 00:35:02 +010083 TPM_CRTM_PCR,
84 tcpa_metadata))
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +010085 return VB2_ERROR_UNKNOWN;
86 } else {
87 printk(BIOS_INFO,
88 "VBOOT: Couldn't measure bootblock into CRTM!\n");
89 return VB2_ERROR_UNKNOWN;
90 }
91 }
92
Julius Wernercd49cce2019-03-05 16:53:33 -080093 if (CONFIG(VBOOT_STARTS_IN_ROMSTAGE)) {
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +010094 struct cbfsf romstage_data;
95 /* measure romstage from RO */
96 if (cbfs_boot_locate(&romstage_data,
97 prog_name(&romstage), NULL) == 0) {
98 cbfs_file_data(prog_rdev(&romstage), &romstage_data);
99
Philipp Deppenwiesec9b7d1f2018-11-10 00:35:02 +0100100 if (create_tcpa_metadata(prog_rdev(&romstage),
101 prog_name(&romstage), tcpa_metadata) < 0)
102 return VB2_ERROR_UNKNOWN;
103
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +0100104 if (tpm_measure_region(prog_rdev(&romstage),
Philipp Deppenwiesec9b7d1f2018-11-10 00:35:02 +0100105 TPM_CRTM_PCR,
106 tcpa_metadata))
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +0100107 return VB2_ERROR_UNKNOWN;
108 } else {
109 printk(BIOS_INFO,
110 "VBOOT: Couldn't measure %s into CRTM!\n",
111 CONFIG_CBFS_PREFIX "/romstage");
112 return VB2_ERROR_UNKNOWN;
113 }
114 }
115
Julius Wernercd49cce2019-03-05 16:53:33 -0800116 if (CONFIG(VBOOT_SEPARATE_VERSTAGE)) {
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +0100117 struct cbfsf verstage_data;
118 /* measure verstage from RO */
119 if (cbfs_boot_locate(&verstage_data,
120 prog_name(&verstage), NULL) == 0) {
121 cbfs_file_data(prog_rdev(&verstage), &verstage_data);
122
Philipp Deppenwiesec9b7d1f2018-11-10 00:35:02 +0100123 if (create_tcpa_metadata(prog_rdev(&verstage),
124 prog_name(&verstage), tcpa_metadata) < 0)
125 return VB2_ERROR_UNKNOWN;
126
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +0100127 if (tpm_measure_region(prog_rdev(&verstage),
Philipp Deppenwiesec9b7d1f2018-11-10 00:35:02 +0100128 TPM_CRTM_PCR,
129 tcpa_metadata))
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +0100130 return VB2_ERROR_UNKNOWN;
131 } else {
132 printk(BIOS_INFO,
133 "VBOOT: Couldn't measure %s into CRTM!\n",
134 CONFIG_CBFS_PREFIX "/verstage");
135 return VB2_ERROR_UNKNOWN;
136 }
137 }
138
139 return VB2_SUCCESS;
140}
141
142static bool is_runtime_data(const char *name)
143{
144 const char *whitelist = CONFIG_VBOOT_MEASURED_BOOT_RUNTIME_DATA;
145 size_t whitelist_len = sizeof(CONFIG_VBOOT_MEASURED_BOOT_RUNTIME_DATA) - 1;
146 size_t name_len = strlen(name);
147 int i;
148
149 if (!whitelist_len || !name_len)
150 return false;
151
152 for (i = 0; (i + name_len) <= whitelist_len; i++) {
153 if (!strcmp(whitelist + i, name))
154 return true;
155 }
156
157 return false;
158}
159
160uint32_t vboot_measure_cbfs_hook(struct cbfsf *fh, const char *name)
161{
162 uint32_t pcr_index;
163 uint32_t cbfs_type;
164 struct region_device rdev;
Philipp Deppenwiesec9b7d1f2018-11-10 00:35:02 +0100165 char tcpa_metadata[TCPA_PCR_HASH_NAME];
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +0100166
Joel Kitchingaf8471c2019-03-13 22:38:07 +0800167 if (!vboot_logic_executed())
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +0100168 return 0;
169
170 cbfsf_file_type(fh, &cbfs_type);
171 cbfs_file_data(&rdev, fh);
172
173 switch (cbfs_type) {
174 case CBFS_TYPE_MRC:
175 case CBFS_TYPE_MRC_CACHE:
176 pcr_index = TPM_RUNTIME_DATA_PCR;
177 break;
178 case CBFS_TYPE_STAGE:
179 case CBFS_TYPE_SELF:
180 case CBFS_TYPE_FIT:
181 pcr_index = TPM_CRTM_PCR;
182 break;
183 default:
184 if (is_runtime_data(name))
185 pcr_index = TPM_RUNTIME_DATA_PCR;
186 else
187 pcr_index = TPM_CRTM_PCR;
188 break;
189 }
190
Philipp Deppenwiesec9b7d1f2018-11-10 00:35:02 +0100191 if (create_tcpa_metadata(&rdev, name, tcpa_metadata) < 0)
192 return VB2_ERROR_UNKNOWN;
193
194 return tpm_measure_region(&rdev, pcr_index, tcpa_metadata);
Philipp Deppenwiese66f9a092018-11-08 10:59:40 +0100195}