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>
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
])
29 struct region_device fmap
;
30 const static char *fmap_cbfs_names
[] = {
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
,
42 fmap_cbfs_names
[i
], cbfs_name
);
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
,
70 return VB2_ERROR_UNKNOWN
;
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
),
83 return VB2_ERROR_UNKNOWN
;
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
),
105 return VB2_ERROR_UNKNOWN
;
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
),
128 return VB2_ERROR_UNKNOWN
;
131 "VBOOT: Couldn't measure %s into CRTM!\n",
132 CONFIG_CBFS_PREFIX
"/verstage");
133 return VB2_ERROR_UNKNOWN
;
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
);
147 if (!whitelist_len
|| !name_len
)
150 for (i
= 0; (i
+ name_len
) <= whitelist_len
; i
++) {
151 if (!strcmp(whitelist
+ i
, name
))
158 uint32_t vboot_measure_cbfs_hook(struct cbfsf
*fh
, const char *name
)
162 struct region_device rdev
;
163 char tcpa_metadata
[TCPA_PCR_HASH_NAME
];
165 if (!vb2_logic_executed())
168 cbfsf_file_type(fh
, &cbfs_type
);
169 cbfs_file_data(&rdev
, fh
);
173 case CBFS_TYPE_MRC_CACHE
:
174 pcr_index
= TPM_RUNTIME_DATA_PCR
;
176 case CBFS_TYPE_STAGE
:
179 pcr_index
= TPM_CRTM_PCR
;
182 if (is_runtime_data(name
))
183 pcr_index
= TPM_RUNTIME_DATA_PCR
;
185 pcr_index
= TPM_CRTM_PCR
;
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
);