blob: 07c69020c8ccfaa0cf4f0bd249b9cc715e948352 [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>
20#include "fmap_config.h"
21
22#define RSA_PUBLICKEY_FILE_NAME "vboot_public_key.bin"
23
24#if CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512)
25#define DIGEST_SIZE VB2_SHA512_DIGEST_SIZE
Wim Vervoornac4896f2019-10-30 15:55:21 +010026#define HASH_ALG VB2_HASH_SHA512
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020027#else
28#define DIGEST_SIZE VB2_SHA256_DIGEST_SIZE
Wim Vervoornac4896f2019-10-30 15:55:21 +010029#define HASH_ALG VB2_HASH_SHA256
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020030#endif
31
32int verified_boot_check_manifest(void)
33{
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020034 uint8_t *buffer;
Wim Vervoornac4896f2019-10-30 15:55:21 +010035 uint8_t sig_buffer[1024]; /* used to build vb21_signature */
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020036 size_t size = 0;
Wim Vervoornac4896f2019-10-30 15:55:21 +010037 struct vb2_public_key key;
38 struct vb2_workbuf wb;
39 struct vb21_signature *vb2_sig_hdr = (struct vb21_signature *)sig_buffer;
40 uint8_t wb_buffer[1024];
41
42 buffer = cbfs_boot_map_with_leak(RSA_PUBLICKEY_FILE_NAME, CBFS_TYPE_RAW, &size);
43 if (!buffer || !size) {
44 printk(BIOS_ERR, "ERROR: Public key not found!\n");
45 goto fail;
46 }
47
48 if ((size != CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_SIZE) ||
49 (buffer != (void *)CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_LOCATION)) {
50 printk(BIOS_ERR, "ERROR: Illegal public key!\n");
51 goto fail;
52 }
53
54 if (vb21_unpack_key(&key, buffer, size)) {
55 printk(BIOS_ERR, "ERROR: Invalid public key!\n");
56 goto fail;
57 }
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020058
59 cbfs_boot_map_with_leak("oemmanifest.bin", CBFS_TYPE_RAW, &size);
Wim Vervoornac4896f2019-10-30 15:55:21 +010060 if (size != (CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE) +
61 vb2_rsa_sig_size(VB2_SIG_RSA2048)) {
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020062 printk(BIOS_ERR, "ERROR: Incorrect manifest size!\n");
63 goto fail;
64 }
65
Wim Vervoornac4896f2019-10-30 15:55:21 +010066 /* prepare work buffer structure */
67 wb.buf = (uint8_t *)&wb_buffer;
68 wb.size = sizeof(wb_buffer);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020069
Wim Vervoornac4896f2019-10-30 15:55:21 +010070 /* Build vb2_sig_hdr buffer */
71 vb2_sig_hdr->sig_offset = sizeof(struct vb21_signature) +
72 (CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE);
73 vb2_sig_hdr->sig_alg = VB2_SIG_RSA2048;
74 vb2_sig_hdr->sig_size = vb2_rsa_sig_size(VB2_SIG_RSA2048);
75 vb2_sig_hdr->hash_alg = HASH_ALG;
76 vb2_sig_hdr->data_size = CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE;
77 memcpy(&sig_buffer[sizeof(struct vb21_signature)], (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC, size);
78
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
93static int vendor_secure_locate(struct cbfs_props *props)
94{
95 struct cbfs_header header;
96 const struct region_device *bdev;
97 int32_t rel_offset;
98 size_t offset;
99
100 bdev = boot_device_ro();
101
102 if (bdev == NULL)
103 return -1;
104
105 size_t fmap_top = ___FMAP__COREBOOT_BASE + ___FMAP__COREBOOT_SIZE;
106
107 /* Find location of header using signed 32-bit offset from
108 * end of CBFS region. */
109 offset = fmap_top - sizeof(int32_t);
110 if (rdev_readat(bdev, &rel_offset, offset, sizeof(int32_t)) < 0)
111 return -1;
112
113 offset = fmap_top + rel_offset;
114 if (rdev_readat(bdev, &header, offset, sizeof(header)) < 0)
115 return -1;
116
117 header.magic = ntohl(header.magic);
118 header.romsize = ntohl(header.romsize);
119 header.offset = ntohl(header.offset);
120
121 if (header.magic != CBFS_HEADER_MAGIC)
122 return -1;
123
124 props->offset = header.offset;
125 props->size = header.romsize;
126 props->size -= props->offset;
127
128 printk(BIOS_SPEW, "CBFS @ %zx size %zx\n", props->offset, props->size);
129
130 return 0;
131}
132
133#ifndef __BOOTBLOCK__
134
135/*
136 *
137 * measure_item
138 *
139 * extends the defined pcr using the hash calculated by the verified boot
140 * routines.
141 *
142 * @param[in] pcr PCR to extend
143 * @param[in] *hashData Pointer to the hash data
144 * @param[in] hashDataLen Length of the hash data
145 * @param[in] *event_msg Message to log or display
146 * @param[in] eventType Event type to use when logging
147
148 * @retval TPM_SUCCESS Operation completed successfully.
149 * @retval TPM_E_IOERROR Unexpected device behavior.
150 */
151static int measure_item(uint32_t pcr, uint8_t *hashData, uint32_t hashDataLen,
152 int8_t *event_msg, TCG_EVENTTYPE eventType)
153{
154 int status = TPM_SUCCESS;
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200155 TCG_PCR_EVENT2_HDR tcgEventHdr;
156
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200157 memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
158 tcgEventHdr.pcrIndex = pcr;
159 tcgEventHdr.eventType = eventType;
160 if (event_msg) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100161 status = mboot_hash_extend_log(MBOOT_HASH_PROVIDED, hashData,
162 hashDataLen, &tcgEventHdr,
163 (uint8_t *)event_msg);
164 if (status == TPM_SUCCESS)
165 printk(BIOS_INFO, "%s: Success! %s measured to pcr %d.\n", __func__,
166 event_msg, pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200167 }
168 return status;
169}
170#endif
171
Wim Vervoornac4896f2019-10-30 15:55:21 +0100172static void verified_boot_check_buffer(const char *name, void *start, size_t size,
173 uint32_t hash_index, int32_t pcr)
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200174{
175 uint8_t digest[DIGEST_SIZE];
176 int hash_algorithm;
Wim Vervoornac4896f2019-10-30 15:55:21 +0100177 vb2_error_t status;
178
179 printk(BIOS_DEBUG, "%s: %s HASH verification buffer %p size %d\n", __func__, name,
180 start, (int)size);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200181
182 if (start && size) {
183 if (CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512))
184 hash_algorithm = VB2_HASH_SHA512;
185 else
186 hash_algorithm = VB2_HASH_SHA256;
187
Wim Vervoornac4896f2019-10-30 15:55:21 +0100188 status = cb_sha_endian(hash_algorithm, (const uint8_t *)start, size, digest);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200189 if ((CONFIG(VENDORCODE_ELTAN_VBOOT) && memcmp((void *)(
190 (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC +
Wim Vervoornac4896f2019-10-30 15:55:21 +0100191 sizeof(digest) * hash_index), digest, sizeof(digest))) || status) {
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200192 printk(BIOS_DEBUG, "%s: buffer hash\n", __func__);
193 hexdump(digest, sizeof(digest));
194 printk(BIOS_DEBUG, "%s: manifest hash\n", __func__);
Wim Vervoornac4896f2019-10-30 15:55:21 +0100195 hexdump((void *)( (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC +
196 sizeof(digest) * hash_index), sizeof(digest));
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200197 printk(BIOS_EMERG, "%s ", name);
198 die("HASH verification failed!\n");
199 } else {
200#ifndef __BOOTBLOCK__
201 if (CONFIG(VENDORCODE_ELTAN_MBOOT)) {
202 if (pcr != -1) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100203 printk(BIOS_DEBUG, "%s: measuring %s\n", __func__, name);
204 if (measure_item(pcr, digest, sizeof(digest),
205 (int8_t *)name, 0))
206 printk(BIOS_DEBUG, "%s: measuring failed!\n", __func__);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200207 }
208 }
209#endif
210 if (CONFIG(VENDORCODE_ELTAN_VBOOT))
Wim Vervoornac4896f2019-10-30 15:55:21 +0100211 printk(BIOS_DEBUG, "%s HASH verification success\n", name);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200212 }
213 } else {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100214 printk(BIOS_EMERG, "Invalid buffer\n");
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200215 die("HASH verification failed!\n");
216 }
217}
218
Wim Vervoornac4896f2019-10-30 15:55:21 +0100219void verified_boot_check_cbfsfile(const char *name, uint32_t type, uint32_t hash_index,
220 void **buffer, uint32_t *filesize, int32_t pcr)
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200221{
222 void *start;
223 size_t size;
224
Wim Vervoornac4896f2019-10-30 15:55:21 +0100225 start = cbfs_boot_map_with_leak(name, type & ~VERIFIED_BOOT_COPY_BLOCK, &size);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200226 if (start && size) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100227 /* Speed up processing by copying the file content to memory first */
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200228#ifndef __PRE_RAM__
Wim Vervoornac4896f2019-10-30 15:55:21 +0100229 if ((type & VERIFIED_BOOT_COPY_BLOCK) && (buffer) && (*buffer) &&
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200230 ((uint32_t) start > (uint32_t)(~(CONFIG_CBFS_SIZE-1)))) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100231 printk(BIOS_DEBUG, "%s: move buffer to memory\n", __func__);
232 /* Move the file to a memory bufferof which we know it doesn't harm */
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200233 memcpy(*buffer, start, size);
234 start = *buffer;
235 printk(BIOS_DEBUG, "%s: done\n", __func__);
236 }
237#endif // __PRE_RAM__
238 verified_boot_check_buffer(name, start, size, hash_index, pcr);
239 } else {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100240 printk(BIOS_EMERG, "CBFS Failed to get file content for %s\n", name);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200241 die("HASH verification failed!\n");
242 }
243 if (buffer)
244 *buffer = start;
245 if (filesize)
246 *filesize = size;
247}
248
249void process_verify_list(const verify_item_t list[])
250{
251 int i = 0;
252
253 while (list[i].type != VERIFY_TERMINATOR) {
254 switch (list[i].type) {
255 case VERIFY_FILE:
Wim Vervoornac4896f2019-10-30 15:55:21 +0100256 verified_boot_check_cbfsfile(list[i].name, list[i].data.file.cbfs_type,
257 list[i].hash_index, NULL, NULL, list[i].pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200258 if (list[i].data.file.related_items) {
259 printk(BIOS_SPEW, "process related items\n");
Wim Vervoornac4896f2019-10-30 15:55:21 +0100260 process_verify_list(
261 (verify_item_t *)list[i].data.file.related_items);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200262 }
263 break;
264 case VERIFY_BLOCK:
265 verified_boot_check_buffer(list[i].name,
Wim Vervoornac4896f2019-10-30 15:55:21 +0100266 (void *)list[i].data.block.start,
267 list[i].data.block.size,
268 list[i].hash_index, list[i].pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200269 break;
270 default:
Wim Vervoornac4896f2019-10-30 15:55:21 +0100271 printk(BIOS_EMERG, "INVALID TYPE IN VERIFY LIST 0x%x\n", list[i].type);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200272 die("HASH verification failed!\n");
273 }
274 i++;
275 }
276}
277#ifdef __BOOTBLOCK__
278/*
279 * BOOTBLOCK
280 */
281
282extern verify_item_t bootblock_verify_list[];
283
284void verified_boot_bootblock_check(void)
285{
286 printk(BIOS_SPEW, "%s: processing bootblock items\n", __func__);
287
288 if (CONFIG(VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST)) {
289 printk(BIOS_SPEW, "%s: check the manifest\n", __func__);
290 if (verified_boot_check_manifest() != 0)
291 die("invalid manifest");
292 }
293 printk(BIOS_SPEW, "%s: process bootblock verify list\n", __func__);
294 process_verify_list(bootblock_verify_list);
295}
296
297static void vendor_secure_prepare(void)
298{
299 printk(BIOS_SPEW, "%s: bootblock\n", __func__);
300 verified_boot_bootblock_check();
301}
302#endif //__BOOTBLOCK__
303
304#ifdef __ROMSTAGE__
305/*
306 * ROMSTAGE
307 */
308
309extern verify_item_t romstage_verify_list[];
310
311void verified_boot_early_check(void)
312{
313 printk(BIOS_SPEW, "%s: processing early items\n", __func__);
314
315 if (!CONFIG(C_ENVIRONMENT_BOOTBLOCK) &&
316 CONFIG(VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST)) {
317 printk(BIOS_SPEW, "%s: check the manifest\n", __func__);
318 if (verified_boot_check_manifest() != 0)
319 die("invalid manifest");
320 }
321
322 if (CONFIG(VENDORCODE_ELTAN_MBOOT)) {
323 printk(BIOS_DEBUG, "mb_measure returned 0x%x\n",
324 mb_measure(vboot_platform_is_resuming()));
325 }
326
327 printk(BIOS_SPEW, "%s: process early verify list\n", __func__);
328 process_verify_list(romstage_verify_list);
329}
330
331static int prepare_romstage = 0;
332
333static void vendor_secure_prepare(void)
334{
335 printk(BIOS_SPEW, "%s: romstage\n", __func__);
336 if (!prepare_romstage) {
337 verified_boot_early_check();
338 prepare_romstage = 1;
339 }
340}
341#endif //__ROMSTAGE__
342
343#ifdef __POSTCAR__
344/*
345 * POSTCAR
346 */
347
348extern verify_item_t postcar_verify_list[];
349
350static void vendor_secure_prepare(void)
351{
352 printk(BIOS_SPEW, "%s: postcar\n", __func__);
353 process_verify_list(postcar_verify_list);
354}
355#endif //__POSTCAR__
356
357#ifdef __RAMSTAGE__
358/*
359 * RAM STAGE
360 */
361
362static int process_oprom_list(const verify_item_t list[],
363 struct rom_header *rom_header)
364{
365 int i = 0;
366 struct pci_data *rom_data;
367 uint32_t viddevid = 0;
368
369 if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100370 printk(BIOS_ERR, "Incorrect expansion ROM header signature %04x DONT START\n",
371 le32_to_cpu(rom_header->signature));
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200372 return 0;
373 }
374
375 rom_data = (((void *)rom_header) + le32_to_cpu(rom_header->data));
376
377 viddevid |= (rom_data->vendor << 16);
378 viddevid |= rom_data->device;
379
380 while (list[i].type != VERIFY_TERMINATOR) {
381 switch (list[i].type) {
382 case VERIFY_OPROM:
383 if (viddevid == list[i].data.oprom.viddev) {
384 verified_boot_check_buffer(list[i].name,
Wim Vervoornac4896f2019-10-30 15:55:21 +0100385 (void *)rom_header,
386 rom_header->size * 512,
387 list[i].hash_index, list[i].pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200388 if (list[i].data.oprom.related_items) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100389 printk(BIOS_SPEW, "%s: process related items\n",
390 __func__);
391 process_verify_list(
392 (verify_item_t *)list[i].data.oprom.related_items);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200393 }
Wim Vervoornac4896f2019-10-30 15:55:21 +0100394 printk(BIOS_SPEW, "%s: option rom can be started\n", __func__);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200395 return 1;
396 }
397 break;
398 default:
Wim Vervoornac4896f2019-10-30 15:55:21 +0100399 printk(BIOS_EMERG, "%s: INVALID TYPE IN OPTION ROM LIST 0x%x\n",
400 __func__, list[i].type);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200401 die("HASH verification failed!\n");
402 }
403 i++;
404 }
405 printk(BIOS_ERR, "%s: option rom not in list DONT START\n", __func__);
406 return 0;
407}
408
409extern verify_item_t payload_verify_list[];
410
411extern verify_item_t oprom_verify_list[];
412
413int verified_boot_should_run_oprom(struct rom_header *rom_header)
414{
415 return process_oprom_list(oprom_verify_list, rom_header);
416}
417
418static void vendor_secure_prepare(void)
419{
420 printk(BIOS_SPEW, "%s: ramstage\n", __func__);
421 process_verify_list(payload_verify_list);
422}
423#endif //__RAMSTAGE__
424
425const struct cbfs_locator cbfs_master_header_locator = {
426 .name = "Vendorcode Header Locator",
427 .prepare = vendor_secure_prepare,
428 .locate = vendor_secure_locate
429};