security/tpm: Fix TCPA log feature
[coreboot.git] / src / security / vboot / vboot_crtm.c
blob4e69b7cddd682f060c57b16cc5e6d4d2ea84291f
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2018 Facebook Inc.
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.
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.
16 #include <console/console.h>
17 #include <fmap.h>
18 #include <security/vboot/vboot_crtm.h>
19 #include <security/vboot/misc.h>
22 * This functions sets the TCPA log namespace
23 * for the cbfs file (region) lookup.
25 static int create_tcpa_metadata(const struct region_device *rdev,
26 const char *cbfs_name, char log_string[TCPA_PCR_HASH_NAME])
28 int i;
29 struct region_device fmap;
30 const static char *fmap_cbfs_names[] = {
31 "COREBOOT",
32 "FW_MAIN_A",
33 "FW_MAIN_B",
34 "RW_LEGACY"};
36 for (i = 0; i < ARRAY_SIZE(fmap_cbfs_names); i++) {
37 if (fmap_locate_area_as_rdev(fmap_cbfs_names[i], &fmap) == 0) {
38 if (region_is_subregion(region_device_region(&fmap),
39 region_device_region(rdev))) {
40 snprintf(log_string, TCPA_PCR_HASH_NAME,
41 "FMAP: %s CBFS: %s",
42 fmap_cbfs_names[i], cbfs_name);
43 return 0;
48 return -1;
51 uint32_t vboot_init_crtm(void)
53 struct prog bootblock = PROG_INIT(PROG_BOOTBLOCK, "bootblock");
54 struct prog verstage =
55 PROG_INIT(PROG_VERSTAGE, CONFIG_CBFS_PREFIX "/verstage");
56 struct prog romstage =
57 PROG_INIT(PROG_ROMSTAGE, CONFIG_CBFS_PREFIX "/romstage");
58 char tcpa_metadata[TCPA_PCR_HASH_NAME];
60 /* Initialize TCPE PRERAM log. */
61 tcpa_preram_log_clear();
63 /* measure bootblock from RO */
64 struct cbfsf bootblock_data;
65 struct region_device bootblock_fmap;
66 if (fmap_locate_area_as_rdev("BOOTBLOCK", &bootblock_fmap) == 0) {
67 if (tpm_measure_region(&bootblock_fmap,
68 TPM_CRTM_PCR,
69 "FMAP: BOOTBLOCK"))
70 return VB2_ERROR_UNKNOWN;
71 } else {
72 if (cbfs_boot_locate(&bootblock_data,
73 prog_name(&bootblock), NULL) == 0) {
74 cbfs_file_data(prog_rdev(&bootblock), &bootblock_data);
76 if (create_tcpa_metadata(prog_rdev(&bootblock),
77 prog_name(&bootblock), tcpa_metadata) < 0)
78 return VB2_ERROR_UNKNOWN;
80 if (tpm_measure_region(prog_rdev(&bootblock),
81 TPM_CRTM_PCR,
82 tcpa_metadata))
83 return VB2_ERROR_UNKNOWN;
84 } else {
85 printk(BIOS_INFO,
86 "VBOOT: Couldn't measure bootblock into CRTM!\n");
87 return VB2_ERROR_UNKNOWN;
91 if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)) {
92 struct cbfsf romstage_data;
93 /* measure romstage from RO */
94 if (cbfs_boot_locate(&romstage_data,
95 prog_name(&romstage), NULL) == 0) {
96 cbfs_file_data(prog_rdev(&romstage), &romstage_data);
98 if (create_tcpa_metadata(prog_rdev(&romstage),
99 prog_name(&romstage), tcpa_metadata) < 0)
100 return VB2_ERROR_UNKNOWN;
102 if (tpm_measure_region(prog_rdev(&romstage),
103 TPM_CRTM_PCR,
104 tcpa_metadata))
105 return VB2_ERROR_UNKNOWN;
106 } else {
107 printk(BIOS_INFO,
108 "VBOOT: Couldn't measure %s into CRTM!\n",
109 CONFIG_CBFS_PREFIX "/romstage");
110 return VB2_ERROR_UNKNOWN;
114 if (IS_ENABLED(CONFIG_VBOOT_SEPARATE_VERSTAGE)) {
115 struct cbfsf verstage_data;
116 /* measure verstage from RO */
117 if (cbfs_boot_locate(&verstage_data,
118 prog_name(&verstage), NULL) == 0) {
119 cbfs_file_data(prog_rdev(&verstage), &verstage_data);
121 if (create_tcpa_metadata(prog_rdev(&verstage),
122 prog_name(&verstage), tcpa_metadata) < 0)
123 return VB2_ERROR_UNKNOWN;
125 if (tpm_measure_region(prog_rdev(&verstage),
126 TPM_CRTM_PCR,
127 tcpa_metadata))
128 return VB2_ERROR_UNKNOWN;
129 } else {
130 printk(BIOS_INFO,
131 "VBOOT: Couldn't measure %s into CRTM!\n",
132 CONFIG_CBFS_PREFIX "/verstage");
133 return VB2_ERROR_UNKNOWN;
137 return VB2_SUCCESS;
140 static bool is_runtime_data(const char *name)
142 const char *whitelist = CONFIG_VBOOT_MEASURED_BOOT_RUNTIME_DATA;
143 size_t whitelist_len = sizeof(CONFIG_VBOOT_MEASURED_BOOT_RUNTIME_DATA) - 1;
144 size_t name_len = strlen(name);
145 int i;
147 if (!whitelist_len || !name_len)
148 return false;
150 for (i = 0; (i + name_len) <= whitelist_len; i++) {
151 if (!strcmp(whitelist + i, name))
152 return true;
155 return false;
158 uint32_t vboot_measure_cbfs_hook(struct cbfsf *fh, const char *name)
160 uint32_t pcr_index;
161 uint32_t cbfs_type;
162 struct region_device rdev;
163 char tcpa_metadata[TCPA_PCR_HASH_NAME];
165 if (!vb2_logic_executed())
166 return 0;
168 cbfsf_file_type(fh, &cbfs_type);
169 cbfs_file_data(&rdev, fh);
171 switch (cbfs_type) {
172 case CBFS_TYPE_MRC:
173 case CBFS_TYPE_MRC_CACHE:
174 pcr_index = TPM_RUNTIME_DATA_PCR;
175 break;
176 case CBFS_TYPE_STAGE:
177 case CBFS_TYPE_SELF:
178 case CBFS_TYPE_FIT:
179 pcr_index = TPM_CRTM_PCR;
180 break;
181 default:
182 if (is_runtime_data(name))
183 pcr_index = TPM_RUNTIME_DATA_PCR;
184 else
185 pcr_index = TPM_CRTM_PCR;
186 break;
189 if (create_tcpa_metadata(&rdev, name, tcpa_metadata) < 0)
190 return VB2_ERROR_UNKNOWN;
192 return tpm_measure_region(&rdev, pcr_index, tcpa_metadata);