blob: 063304253942e13adb8dad652b272c0dcb16508a [file] [log] [blame]
Frans Hendriks72b3c3c2019-07-26 07:59:05 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2016 Intel Corp.
5 * Copyright (C) 2017-2019 Eltan B.V.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16#include <boot_device.h>
17#include <cbfs.h>
18#include <vboot_check.h>
19#include <vboot_common.h>
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020020
21#define RSA_PUBLICKEY_FILE_NAME "vboot_public_key.bin"
22
23#if CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512)
24#define DIGEST_SIZE VB2_SHA512_DIGEST_SIZE
Wim Vervoornac4896f2019-10-30 15:55:21 +010025#define HASH_ALG VB2_HASH_SHA512
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020026#else
27#define DIGEST_SIZE VB2_SHA256_DIGEST_SIZE
Wim Vervoornac4896f2019-10-30 15:55:21 +010028#define HASH_ALG VB2_HASH_SHA256
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020029#endif
30
31int verified_boot_check_manifest(void)
32{
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020033 uint8_t *buffer;
Wim Vervoornac4896f2019-10-30 15:55:21 +010034 uint8_t sig_buffer[1024]; /* used to build vb21_signature */
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020035 size_t size = 0;
Wim Vervoornac4896f2019-10-30 15:55:21 +010036 struct vb2_public_key key;
37 struct vb2_workbuf wb;
38 struct vb21_signature *vb2_sig_hdr = (struct vb21_signature *)sig_buffer;
39 uint8_t wb_buffer[1024];
40
41 buffer = cbfs_boot_map_with_leak(RSA_PUBLICKEY_FILE_NAME, CBFS_TYPE_RAW, &size);
42 if (!buffer || !size) {
43 printk(BIOS_ERR, "ERROR: Public key not found!\n");
44 goto fail;
45 }
46
47 if ((size != CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_SIZE) ||
48 (buffer != (void *)CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_LOCATION)) {
49 printk(BIOS_ERR, "ERROR: Illegal public key!\n");
50 goto fail;
51 }
52
53 if (vb21_unpack_key(&key, buffer, size)) {
54 printk(BIOS_ERR, "ERROR: Invalid public key!\n");
55 goto fail;
56 }
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020057
58 cbfs_boot_map_with_leak("oemmanifest.bin", CBFS_TYPE_RAW, &size);
Wim Vervoornac4896f2019-10-30 15:55:21 +010059 if (size != (CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE) +
60 vb2_rsa_sig_size(VB2_SIG_RSA2048)) {
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020061 printk(BIOS_ERR, "ERROR: Incorrect manifest size!\n");
62 goto fail;
63 }
64
Wim Vervoornac4896f2019-10-30 15:55:21 +010065 /* prepare work buffer structure */
66 wb.buf = (uint8_t *)&wb_buffer;
67 wb.size = sizeof(wb_buffer);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020068
Wim Vervoornac4896f2019-10-30 15:55:21 +010069 /* Build vb2_sig_hdr buffer */
70 vb2_sig_hdr->sig_offset = sizeof(struct vb21_signature) +
71 (CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE);
72 vb2_sig_hdr->sig_alg = VB2_SIG_RSA2048;
73 vb2_sig_hdr->sig_size = vb2_rsa_sig_size(VB2_SIG_RSA2048);
74 vb2_sig_hdr->hash_alg = HASH_ALG;
75 vb2_sig_hdr->data_size = CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE;
Wim Vervoorn944fdc42019-10-30 16:46:41 +010076 memcpy(&sig_buffer[sizeof(struct vb21_signature)],
77 (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC, size);
Wim Vervoornac4896f2019-10-30 15:55:21 +010078
79 if (vb21_verify_data(&sig_buffer[sizeof(struct vb21_signature)], vb2_sig_hdr->data_size,
80 (struct vb21_signature *)&sig_buffer, &key, &wb)) {
81 printk(BIOS_ERR, "ERROR: Signature verification failed for hash table\n");
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020082 goto fail;
83 }
84
Wim Vervoornac4896f2019-10-30 15:55:21 +010085 printk(BIOS_INFO, "%s: Successfully verified hash_table signature.\n", __func__);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020086 return 0;
87
88fail:
89 die("HASH table verification failed!\n");
90 return -1;
91}
92
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020093/*
94 *
95 * measure_item
96 *
97 * extends the defined pcr using the hash calculated by the verified boot
98 * routines.
99 *
100 * @param[in] pcr PCR to extend
101 * @param[in] *hashData Pointer to the hash data
102 * @param[in] hashDataLen Length of the hash data
103 * @param[in] *event_msg Message to log or display
104 * @param[in] eventType Event type to use when logging
105
106 * @retval TPM_SUCCESS Operation completed successfully.
107 * @retval TPM_E_IOERROR Unexpected device behavior.
108 */
109static int measure_item(uint32_t pcr, uint8_t *hashData, uint32_t hashDataLen,
110 int8_t *event_msg, TCG_EVENTTYPE eventType)
111{
112 int status = TPM_SUCCESS;
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200113 TCG_PCR_EVENT2_HDR tcgEventHdr;
114
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200115 memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
116 tcgEventHdr.pcrIndex = pcr;
117 tcgEventHdr.eventType = eventType;
118 if (event_msg) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100119 status = mboot_hash_extend_log(MBOOT_HASH_PROVIDED, hashData,
120 hashDataLen, &tcgEventHdr,
121 (uint8_t *)event_msg);
122 if (status == TPM_SUCCESS)
123 printk(BIOS_INFO, "%s: Success! %s measured to pcr %d.\n", __func__,
124 event_msg, pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200125 }
126 return status;
127}
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200128
Wim Vervoornac4896f2019-10-30 15:55:21 +0100129static void verified_boot_check_buffer(const char *name, void *start, size_t size,
130 uint32_t hash_index, int32_t pcr)
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200131{
132 uint8_t digest[DIGEST_SIZE];
133 int hash_algorithm;
Wim Vervoornac4896f2019-10-30 15:55:21 +0100134 vb2_error_t status;
135
136 printk(BIOS_DEBUG, "%s: %s HASH verification buffer %p size %d\n", __func__, name,
137 start, (int)size);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200138
139 if (start && size) {
140 if (CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512))
141 hash_algorithm = VB2_HASH_SHA512;
142 else
143 hash_algorithm = VB2_HASH_SHA256;
144
Wim Vervoornffe4eba2019-11-14 11:06:35 +0100145 status = cb_sha_little_endian(hash_algorithm, (const uint8_t *)start, size,
146 digest);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200147 if ((CONFIG(VENDORCODE_ELTAN_VBOOT) && memcmp((void *)(
148 (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC +
Wim Vervoornac4896f2019-10-30 15:55:21 +0100149 sizeof(digest) * hash_index), digest, sizeof(digest))) || status) {
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200150 printk(BIOS_DEBUG, "%s: buffer hash\n", __func__);
151 hexdump(digest, sizeof(digest));
152 printk(BIOS_DEBUG, "%s: manifest hash\n", __func__);
Wim Vervoornac4896f2019-10-30 15:55:21 +0100153 hexdump((void *)( (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC +
154 sizeof(digest) * hash_index), sizeof(digest));
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200155 printk(BIOS_EMERG, "%s ", name);
156 die("HASH verification failed!\n");
157 } else {
Kyösti Mälkkibf43f9e2019-11-05 17:55:15 +0200158 if (!ENV_BOOTBLOCK && CONFIG(VENDORCODE_ELTAN_MBOOT)) {
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200159 if (pcr != -1) {
Wim Vervoornffe4eba2019-11-14 11:06:35 +0100160 printk(BIOS_DEBUG, "%s: measuring %s\n", __func__,
161 name);
Wim Vervoornac4896f2019-10-30 15:55:21 +0100162 if (measure_item(pcr, digest, sizeof(digest),
163 (int8_t *)name, 0))
Wim Vervoorn944fdc42019-10-30 16:46:41 +0100164 printk(BIOS_DEBUG, "%s: measuring failed!\n",
165 __func__);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200166 }
167 }
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200168 if (CONFIG(VENDORCODE_ELTAN_VBOOT))
Wim Vervoornac4896f2019-10-30 15:55:21 +0100169 printk(BIOS_DEBUG, "%s HASH verification success\n", name);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200170 }
171 } else {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100172 printk(BIOS_EMERG, "Invalid buffer\n");
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200173 die("HASH verification failed!\n");
174 }
175}
176
Wim Vervoornac4896f2019-10-30 15:55:21 +0100177void verified_boot_check_cbfsfile(const char *name, uint32_t type, uint32_t hash_index,
178 void **buffer, uint32_t *filesize, int32_t pcr)
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200179{
180 void *start;
181 size_t size;
182
Wim Vervoornac4896f2019-10-30 15:55:21 +0100183 start = cbfs_boot_map_with_leak(name, type & ~VERIFIED_BOOT_COPY_BLOCK, &size);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200184 if (start && size) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100185 /* Speed up processing by copying the file content to memory first */
Kyösti Mälkkic7fa9112019-11-05 17:57:41 +0200186 if (!ENV_ROMSTAGE_OR_BEFORE && (type & VERIFIED_BOOT_COPY_BLOCK) && (buffer) &&
187 (*buffer) && ((uint32_t) start > (uint32_t)(~(CONFIG_CBFS_SIZE-1)))) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100188 printk(BIOS_DEBUG, "%s: move buffer to memory\n", __func__);
189 /* Move the file to a memory bufferof which we know it doesn't harm */
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200190 memcpy(*buffer, start, size);
191 start = *buffer;
192 printk(BIOS_DEBUG, "%s: done\n", __func__);
193 }
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200194 verified_boot_check_buffer(name, start, size, hash_index, pcr);
195 } else {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100196 printk(BIOS_EMERG, "CBFS Failed to get file content for %s\n", name);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200197 die("HASH verification failed!\n");
198 }
199 if (buffer)
200 *buffer = start;
201 if (filesize)
202 *filesize = size;
203}
204
205void process_verify_list(const verify_item_t list[])
206{
207 int i = 0;
208
209 while (list[i].type != VERIFY_TERMINATOR) {
210 switch (list[i].type) {
211 case VERIFY_FILE:
Wim Vervoornac4896f2019-10-30 15:55:21 +0100212 verified_boot_check_cbfsfile(list[i].name, list[i].data.file.cbfs_type,
213 list[i].hash_index, NULL, NULL, list[i].pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200214 if (list[i].data.file.related_items) {
215 printk(BIOS_SPEW, "process related items\n");
Wim Vervoornac4896f2019-10-30 15:55:21 +0100216 process_verify_list(
217 (verify_item_t *)list[i].data.file.related_items);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200218 }
219 break;
220 case VERIFY_BLOCK:
221 verified_boot_check_buffer(list[i].name,
Wim Vervoornac4896f2019-10-30 15:55:21 +0100222 (void *)list[i].data.block.start,
223 list[i].data.block.size,
224 list[i].hash_index, list[i].pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200225 break;
226 default:
Wim Vervoornac4896f2019-10-30 15:55:21 +0100227 printk(BIOS_EMERG, "INVALID TYPE IN VERIFY LIST 0x%x\n", list[i].type);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200228 die("HASH verification failed!\n");
229 }
230 i++;
231 }
232}
Kyösti Mälkkied8eaab2019-11-05 17:12:42 +0200233
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200234/*
235 * BOOTBLOCK
236 */
237
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200238void verified_boot_bootblock_check(void)
239{
240 printk(BIOS_SPEW, "%s: processing bootblock items\n", __func__);
241
242 if (CONFIG(VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST)) {
243 printk(BIOS_SPEW, "%s: check the manifest\n", __func__);
244 if (verified_boot_check_manifest() != 0)
245 die("invalid manifest");
246 }
247 printk(BIOS_SPEW, "%s: process bootblock verify list\n", __func__);
248 process_verify_list(bootblock_verify_list);
249}
250
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200251/*
252 * ROMSTAGE
253 */
254
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200255void verified_boot_early_check(void)
256{
257 printk(BIOS_SPEW, "%s: processing early items\n", __func__);
258
259 if (!CONFIG(C_ENVIRONMENT_BOOTBLOCK) &&
260 CONFIG(VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST)) {
261 printk(BIOS_SPEW, "%s: check the manifest\n", __func__);
262 if (verified_boot_check_manifest() != 0)
263 die("invalid manifest");
264 }
265
266 if (CONFIG(VENDORCODE_ELTAN_MBOOT)) {
267 printk(BIOS_DEBUG, "mb_measure returned 0x%x\n",
268 mb_measure(vboot_platform_is_resuming()));
269 }
270
271 printk(BIOS_SPEW, "%s: process early verify list\n", __func__);
272 process_verify_list(romstage_verify_list);
273}
274
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200275/*
276 * RAM STAGE
277 */
278
279static int process_oprom_list(const verify_item_t list[],
280 struct rom_header *rom_header)
281{
282 int i = 0;
283 struct pci_data *rom_data;
284 uint32_t viddevid = 0;
285
286 if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100287 printk(BIOS_ERR, "Incorrect expansion ROM header signature %04x DONT START\n",
288 le32_to_cpu(rom_header->signature));
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200289 return 0;
290 }
291
292 rom_data = (((void *)rom_header) + le32_to_cpu(rom_header->data));
293
294 viddevid |= (rom_data->vendor << 16);
295 viddevid |= rom_data->device;
296
297 while (list[i].type != VERIFY_TERMINATOR) {
298 switch (list[i].type) {
299 case VERIFY_OPROM:
300 if (viddevid == list[i].data.oprom.viddev) {
301 verified_boot_check_buffer(list[i].name,
Wim Vervoornac4896f2019-10-30 15:55:21 +0100302 (void *)rom_header,
303 rom_header->size * 512,
304 list[i].hash_index, list[i].pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200305 if (list[i].data.oprom.related_items) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100306 printk(BIOS_SPEW, "%s: process related items\n",
307 __func__);
308 process_verify_list(
309 (verify_item_t *)list[i].data.oprom.related_items);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200310 }
Wim Vervoornac4896f2019-10-30 15:55:21 +0100311 printk(BIOS_SPEW, "%s: option rom can be started\n", __func__);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200312 return 1;
313 }
314 break;
315 default:
Wim Vervoornac4896f2019-10-30 15:55:21 +0100316 printk(BIOS_EMERG, "%s: INVALID TYPE IN OPTION ROM LIST 0x%x\n",
317 __func__, list[i].type);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200318 die("HASH verification failed!\n");
319 }
320 i++;
321 }
322 printk(BIOS_ERR, "%s: option rom not in list DONT START\n", __func__);
323 return 0;
324}
325
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200326int verified_boot_should_run_oprom(struct rom_header *rom_header)
327{
328 return process_oprom_list(oprom_verify_list, rom_header);
329}
330
Wim Vervoorne05dc172019-11-14 09:50:59 +0100331int prog_locate_hook(struct prog *prog)
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200332{
Wim Vervoornf4a30472019-11-14 10:03:25 +0100333 if (ENV_BOOTBLOCK)
Kyösti Mälkkied8eaab2019-11-05 17:12:42 +0200334 verified_boot_bootblock_check();
Kyösti Mälkkied8eaab2019-11-05 17:12:42 +0200335
336 if (ENV_ROMSTAGE) {
Wim Vervoornf4a30472019-11-14 10:03:25 +0100337 if (prog->type == PROG_REFCODE)
Kyösti Mälkkied8eaab2019-11-05 17:12:42 +0200338 verified_boot_early_check();
Wim Vervoornf4a30472019-11-14 10:03:25 +0100339
340 if (CONFIG(POSTCAR_STAGE) && prog->type == PROG_POSTCAR)
341 process_verify_list(postcar_verify_list);
342
343 if (!CONFIG(POSTCAR_STAGE) && prog->type == PROG_RAMSTAGE)
344 process_verify_list(ramstage_verify_list);
Kyösti Mälkkied8eaab2019-11-05 17:12:42 +0200345 }
346
Wim Vervoornf4a30472019-11-14 10:03:25 +0100347 if (ENV_POSTCAR && prog->type == PROG_RAMSTAGE)
348 process_verify_list(ramstage_verify_list);
Kyösti Mälkkied8eaab2019-11-05 17:12:42 +0200349
Wim Vervoornf4a30472019-11-14 10:03:25 +0100350 if (ENV_RAMSTAGE && prog->type == PROG_PAYLOAD)
Kyösti Mälkkied8eaab2019-11-05 17:12:42 +0200351 process_verify_list(payload_verify_list);
Wim Vervoornf4a30472019-11-14 10:03:25 +0100352
Wim Vervoorne05dc172019-11-14 09:50:59 +0100353 return 0;
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200354}