blob: 88519bdd78ed3febbba8abb22f4f6380b13ffdda [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;
Wim Vervoorn944fdc42019-10-30 16:46:41 +010077 memcpy(&sig_buffer[sizeof(struct vb21_signature)],
78 (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC, size);
Wim Vervoornac4896f2019-10-30 15:55:21 +010079
80 if (vb21_verify_data(&sig_buffer[sizeof(struct vb21_signature)], vb2_sig_hdr->data_size,
81 (struct vb21_signature *)&sig_buffer, &key, &wb)) {
82 printk(BIOS_ERR, "ERROR: Signature verification failed for hash table\n");
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020083 goto fail;
84 }
85
Wim Vervoornac4896f2019-10-30 15:55:21 +010086 printk(BIOS_INFO, "%s: Successfully verified hash_table signature.\n", __func__);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +020087 return 0;
88
89fail:
90 die("HASH table verification failed!\n");
91 return -1;
92}
93
94static int vendor_secure_locate(struct cbfs_props *props)
95{
96 struct cbfs_header header;
97 const struct region_device *bdev;
98 int32_t rel_offset;
99 size_t offset;
100
101 bdev = boot_device_ro();
102
103 if (bdev == NULL)
104 return -1;
105
106 size_t fmap_top = ___FMAP__COREBOOT_BASE + ___FMAP__COREBOOT_SIZE;
107
108 /* Find location of header using signed 32-bit offset from
109 * end of CBFS region. */
110 offset = fmap_top - sizeof(int32_t);
111 if (rdev_readat(bdev, &rel_offset, offset, sizeof(int32_t)) < 0)
112 return -1;
113
114 offset = fmap_top + rel_offset;
115 if (rdev_readat(bdev, &header, offset, sizeof(header)) < 0)
116 return -1;
117
118 header.magic = ntohl(header.magic);
119 header.romsize = ntohl(header.romsize);
120 header.offset = ntohl(header.offset);
121
122 if (header.magic != CBFS_HEADER_MAGIC)
123 return -1;
124
125 props->offset = header.offset;
126 props->size = header.romsize;
127 props->size -= props->offset;
128
129 printk(BIOS_SPEW, "CBFS @ %zx size %zx\n", props->offset, props->size);
130
131 return 0;
132}
133
134#ifndef __BOOTBLOCK__
135
136/*
137 *
138 * measure_item
139 *
140 * extends the defined pcr using the hash calculated by the verified boot
141 * routines.
142 *
143 * @param[in] pcr PCR to extend
144 * @param[in] *hashData Pointer to the hash data
145 * @param[in] hashDataLen Length of the hash data
146 * @param[in] *event_msg Message to log or display
147 * @param[in] eventType Event type to use when logging
148
149 * @retval TPM_SUCCESS Operation completed successfully.
150 * @retval TPM_E_IOERROR Unexpected device behavior.
151 */
152static int measure_item(uint32_t pcr, uint8_t *hashData, uint32_t hashDataLen,
153 int8_t *event_msg, TCG_EVENTTYPE eventType)
154{
155 int status = TPM_SUCCESS;
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200156 TCG_PCR_EVENT2_HDR tcgEventHdr;
157
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200158 memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
159 tcgEventHdr.pcrIndex = pcr;
160 tcgEventHdr.eventType = eventType;
161 if (event_msg) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100162 status = mboot_hash_extend_log(MBOOT_HASH_PROVIDED, hashData,
163 hashDataLen, &tcgEventHdr,
164 (uint8_t *)event_msg);
165 if (status == TPM_SUCCESS)
166 printk(BIOS_INFO, "%s: Success! %s measured to pcr %d.\n", __func__,
167 event_msg, pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200168 }
169 return status;
170}
171#endif
172
Wim Vervoornac4896f2019-10-30 15:55:21 +0100173static void verified_boot_check_buffer(const char *name, void *start, size_t size,
174 uint32_t hash_index, int32_t pcr)
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200175{
176 uint8_t digest[DIGEST_SIZE];
177 int hash_algorithm;
Wim Vervoornac4896f2019-10-30 15:55:21 +0100178 vb2_error_t status;
179
180 printk(BIOS_DEBUG, "%s: %s HASH verification buffer %p size %d\n", __func__, name,
181 start, (int)size);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200182
183 if (start && size) {
184 if (CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512))
185 hash_algorithm = VB2_HASH_SHA512;
186 else
187 hash_algorithm = VB2_HASH_SHA256;
188
Wim Vervoorn944fdc42019-10-30 16:46:41 +0100189 status = cb_sha_little_endian(hash_algorithm, (const uint8_t *)start, size, digest);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200190 if ((CONFIG(VENDORCODE_ELTAN_VBOOT) && memcmp((void *)(
191 (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC +
Wim Vervoornac4896f2019-10-30 15:55:21 +0100192 sizeof(digest) * hash_index), digest, sizeof(digest))) || status) {
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200193 printk(BIOS_DEBUG, "%s: buffer hash\n", __func__);
194 hexdump(digest, sizeof(digest));
195 printk(BIOS_DEBUG, "%s: manifest hash\n", __func__);
Wim Vervoornac4896f2019-10-30 15:55:21 +0100196 hexdump((void *)( (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC +
197 sizeof(digest) * hash_index), sizeof(digest));
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200198 printk(BIOS_EMERG, "%s ", name);
199 die("HASH verification failed!\n");
200 } else {
201#ifndef __BOOTBLOCK__
202 if (CONFIG(VENDORCODE_ELTAN_MBOOT)) {
203 if (pcr != -1) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100204 printk(BIOS_DEBUG, "%s: measuring %s\n", __func__, name);
205 if (measure_item(pcr, digest, sizeof(digest),
206 (int8_t *)name, 0))
Wim Vervoorn944fdc42019-10-30 16:46:41 +0100207 printk(BIOS_DEBUG, "%s: measuring failed!\n",
208 __func__);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200209 }
210 }
211#endif
212 if (CONFIG(VENDORCODE_ELTAN_VBOOT))
Wim Vervoornac4896f2019-10-30 15:55:21 +0100213 printk(BIOS_DEBUG, "%s HASH verification success\n", name);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200214 }
215 } else {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100216 printk(BIOS_EMERG, "Invalid buffer\n");
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200217 die("HASH verification failed!\n");
218 }
219}
220
Wim Vervoornac4896f2019-10-30 15:55:21 +0100221void verified_boot_check_cbfsfile(const char *name, uint32_t type, uint32_t hash_index,
222 void **buffer, uint32_t *filesize, int32_t pcr)
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200223{
224 void *start;
225 size_t size;
226
Wim Vervoornac4896f2019-10-30 15:55:21 +0100227 start = cbfs_boot_map_with_leak(name, type & ~VERIFIED_BOOT_COPY_BLOCK, &size);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200228 if (start && size) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100229 /* Speed up processing by copying the file content to memory first */
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200230#ifndef __PRE_RAM__
Wim Vervoornac4896f2019-10-30 15:55:21 +0100231 if ((type & VERIFIED_BOOT_COPY_BLOCK) && (buffer) && (*buffer) &&
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200232 ((uint32_t) start > (uint32_t)(~(CONFIG_CBFS_SIZE-1)))) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100233 printk(BIOS_DEBUG, "%s: move buffer to memory\n", __func__);
234 /* Move the file to a memory bufferof which we know it doesn't harm */
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200235 memcpy(*buffer, start, size);
236 start = *buffer;
237 printk(BIOS_DEBUG, "%s: done\n", __func__);
238 }
239#endif // __PRE_RAM__
240 verified_boot_check_buffer(name, start, size, hash_index, pcr);
241 } else {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100242 printk(BIOS_EMERG, "CBFS Failed to get file content for %s\n", name);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200243 die("HASH verification failed!\n");
244 }
245 if (buffer)
246 *buffer = start;
247 if (filesize)
248 *filesize = size;
249}
250
251void process_verify_list(const verify_item_t list[])
252{
253 int i = 0;
254
255 while (list[i].type != VERIFY_TERMINATOR) {
256 switch (list[i].type) {
257 case VERIFY_FILE:
Wim Vervoornac4896f2019-10-30 15:55:21 +0100258 verified_boot_check_cbfsfile(list[i].name, list[i].data.file.cbfs_type,
259 list[i].hash_index, NULL, NULL, list[i].pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200260 if (list[i].data.file.related_items) {
261 printk(BIOS_SPEW, "process related items\n");
Wim Vervoornac4896f2019-10-30 15:55:21 +0100262 process_verify_list(
263 (verify_item_t *)list[i].data.file.related_items);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200264 }
265 break;
266 case VERIFY_BLOCK:
267 verified_boot_check_buffer(list[i].name,
Wim Vervoornac4896f2019-10-30 15:55:21 +0100268 (void *)list[i].data.block.start,
269 list[i].data.block.size,
270 list[i].hash_index, list[i].pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200271 break;
272 default:
Wim Vervoornac4896f2019-10-30 15:55:21 +0100273 printk(BIOS_EMERG, "INVALID TYPE IN VERIFY LIST 0x%x\n", list[i].type);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200274 die("HASH verification failed!\n");
275 }
276 i++;
277 }
278}
279#ifdef __BOOTBLOCK__
280/*
281 * BOOTBLOCK
282 */
283
284extern verify_item_t bootblock_verify_list[];
285
286void verified_boot_bootblock_check(void)
287{
288 printk(BIOS_SPEW, "%s: processing bootblock items\n", __func__);
289
290 if (CONFIG(VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST)) {
291 printk(BIOS_SPEW, "%s: check the manifest\n", __func__);
292 if (verified_boot_check_manifest() != 0)
293 die("invalid manifest");
294 }
295 printk(BIOS_SPEW, "%s: process bootblock verify list\n", __func__);
296 process_verify_list(bootblock_verify_list);
297}
298
299static void vendor_secure_prepare(void)
300{
301 printk(BIOS_SPEW, "%s: bootblock\n", __func__);
302 verified_boot_bootblock_check();
303}
304#endif //__BOOTBLOCK__
305
306#ifdef __ROMSTAGE__
307/*
308 * ROMSTAGE
309 */
310
311extern verify_item_t romstage_verify_list[];
312
313void verified_boot_early_check(void)
314{
315 printk(BIOS_SPEW, "%s: processing early items\n", __func__);
316
317 if (!CONFIG(C_ENVIRONMENT_BOOTBLOCK) &&
318 CONFIG(VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST)) {
319 printk(BIOS_SPEW, "%s: check the manifest\n", __func__);
320 if (verified_boot_check_manifest() != 0)
321 die("invalid manifest");
322 }
323
324 if (CONFIG(VENDORCODE_ELTAN_MBOOT)) {
325 printk(BIOS_DEBUG, "mb_measure returned 0x%x\n",
326 mb_measure(vboot_platform_is_resuming()));
327 }
328
329 printk(BIOS_SPEW, "%s: process early verify list\n", __func__);
330 process_verify_list(romstage_verify_list);
331}
332
333static int prepare_romstage = 0;
334
335static void vendor_secure_prepare(void)
336{
337 printk(BIOS_SPEW, "%s: romstage\n", __func__);
338 if (!prepare_romstage) {
339 verified_boot_early_check();
340 prepare_romstage = 1;
341 }
342}
343#endif //__ROMSTAGE__
344
345#ifdef __POSTCAR__
346/*
347 * POSTCAR
348 */
349
350extern verify_item_t postcar_verify_list[];
351
352static void vendor_secure_prepare(void)
353{
354 printk(BIOS_SPEW, "%s: postcar\n", __func__);
355 process_verify_list(postcar_verify_list);
356}
357#endif //__POSTCAR__
358
359#ifdef __RAMSTAGE__
360/*
361 * RAM STAGE
362 */
363
364static int process_oprom_list(const verify_item_t list[],
365 struct rom_header *rom_header)
366{
367 int i = 0;
368 struct pci_data *rom_data;
369 uint32_t viddevid = 0;
370
371 if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100372 printk(BIOS_ERR, "Incorrect expansion ROM header signature %04x DONT START\n",
373 le32_to_cpu(rom_header->signature));
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200374 return 0;
375 }
376
377 rom_data = (((void *)rom_header) + le32_to_cpu(rom_header->data));
378
379 viddevid |= (rom_data->vendor << 16);
380 viddevid |= rom_data->device;
381
382 while (list[i].type != VERIFY_TERMINATOR) {
383 switch (list[i].type) {
384 case VERIFY_OPROM:
385 if (viddevid == list[i].data.oprom.viddev) {
386 verified_boot_check_buffer(list[i].name,
Wim Vervoornac4896f2019-10-30 15:55:21 +0100387 (void *)rom_header,
388 rom_header->size * 512,
389 list[i].hash_index, list[i].pcr);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200390 if (list[i].data.oprom.related_items) {
Wim Vervoornac4896f2019-10-30 15:55:21 +0100391 printk(BIOS_SPEW, "%s: process related items\n",
392 __func__);
393 process_verify_list(
394 (verify_item_t *)list[i].data.oprom.related_items);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200395 }
Wim Vervoornac4896f2019-10-30 15:55:21 +0100396 printk(BIOS_SPEW, "%s: option rom can be started\n", __func__);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200397 return 1;
398 }
399 break;
400 default:
Wim Vervoornac4896f2019-10-30 15:55:21 +0100401 printk(BIOS_EMERG, "%s: INVALID TYPE IN OPTION ROM LIST 0x%x\n",
402 __func__, list[i].type);
Frans Hendriks72b3c3c2019-07-26 07:59:05 +0200403 die("HASH verification failed!\n");
404 }
405 i++;
406 }
407 printk(BIOS_ERR, "%s: option rom not in list DONT START\n", __func__);
408 return 0;
409}
410
411extern verify_item_t payload_verify_list[];
412
413extern verify_item_t oprom_verify_list[];
414
415int verified_boot_should_run_oprom(struct rom_header *rom_header)
416{
417 return process_oprom_list(oprom_verify_list, rom_header);
418}
419
420static void vendor_secure_prepare(void)
421{
422 printk(BIOS_SPEW, "%s: ramstage\n", __func__);
423 process_verify_list(payload_verify_list);
424}
425#endif //__RAMSTAGE__
426
427const struct cbfs_locator cbfs_master_header_locator = {
428 .name = "Vendorcode Header Locator",
429 .prepare = vendor_secure_prepare,
430 .locate = vendor_secure_locate
431};