From ac4896fbcb07b01a10d177fead4c3e82268e0531 Mon Sep 17 00:00:00 2001 From: Wim Vervoorn Date: Wed, 30 Oct 2019 15:55:21 +0100 Subject: vendorcode/eltan/security: Use vb2 public key Start using the vb2 public key format and process the signature verification using the vb2 routines. This allows us to use the futility to prepare the keys and eliminates the need for custom tools. BUG=N/A TEST=tested on fbg1701 board Change-Id: Id5d28595bbfb1f5ca5bca0fcfb06134bb1143f25 Signed-off-by: Wim Vervoorn Reviewed-on: https://review.coreboot.org/c/coreboot/+/36480 Tested-by: build bot (Jenkins) Reviewed-by: Frans Hendriks --- .../eltan/security/verified_boot/Kconfig | 9 +- .../eltan/security/verified_boot/Makefile.inc | 4 +- .../eltan/security/verified_boot/vboot_check.c | 202 +++++++++------------ 3 files changed, 96 insertions(+), 119 deletions(-) (limited to 'src') diff --git a/src/vendorcode/eltan/security/verified_boot/Kconfig b/src/vendorcode/eltan/security/verified_boot/Kconfig index 3177529dc9..d9e989f2b2 100644 --- a/src/vendorcode/eltan/security/verified_boot/Kconfig +++ b/src/vendorcode/eltan/security/verified_boot/Kconfig @@ -55,9 +55,14 @@ config VENDORCODE_ELTAN_VBOOT_KEY_LOCATION depends on VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST default 0xFFFFF500 +config VENDORCODE_ELTAN_VBOOT_KEY_FILE + string "Verified boot Key File" + depends on VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST + default "3rdparty/eltan/verified_boot/Keys/key.vbpubk2" + config VENDORCODE_ELTAN_VBOOT_KEY_SIZE int - default 554 if VENDORCODE_ELTAN_VBOOT_USE_SHA512 - default 520 + default 610 if VENDORCODE_ELTAN_VBOOT_USE_SHA512 + default 576 endmenu # Verified Boot (verified_boot) diff --git a/src/vendorcode/eltan/security/verified_boot/Makefile.inc b/src/vendorcode/eltan/security/verified_boot/Makefile.inc index 3f6ba904c4..357e520298 100644 --- a/src/vendorcode/eltan/security/verified_boot/Makefile.inc +++ b/src/vendorcode/eltan/security/verified_boot/Makefile.inc @@ -37,12 +37,10 @@ endif # ($(CONFIG_VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST),y) ifeq ($(CONFIG_VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST),y) cbfs-files-y += vboot_public_key.bin -vboot_public_key.bin-file := $(obj)/vboot_public_key.bin +vboot_public_key.bin-file := $(call strip_quotes, $(CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_FILE)) vboot_public_key.bin-position := $(CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_LOCATION) vboot_public_key.bin-type := raw -$(obj)/vboot_public_key.bin: - dd if=/dev/zero of=$@ bs=$(CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_SIZE) count=1 endif # ($(CONFIG_VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST),y) endif # CONFIG_VENDORCODE_ELTAN_VBOOT diff --git a/src/vendorcode/eltan/security/verified_boot/vboot_check.c b/src/vendorcode/eltan/security/verified_boot/vboot_check.c index e2258b9cdd..07c69020c8 100644 --- a/src/vendorcode/eltan/security/verified_boot/vboot_check.c +++ b/src/vendorcode/eltan/security/verified_boot/vboot_check.c @@ -23,65 +23,66 @@ #if CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512) #define DIGEST_SIZE VB2_SHA512_DIGEST_SIZE +#define HASH_ALG VB2_HASH_SHA512 #else #define DIGEST_SIZE VB2_SHA256_DIGEST_SIZE +#define HASH_ALG VB2_HASH_SHA256 #endif int verified_boot_check_manifest(void) { - struct vb2_public_key key; - const struct vb2_workbuf wb; uint8_t *buffer; - uint8_t digest[DIGEST_SIZE]; - uint8_t *signature = NULL; + uint8_t sig_buffer[1024]; /* used to build vb21_signature */ size_t size = 0; - int hash_algorithm; - int status; - - cbfs_boot_map_with_leak("oemmanifest.bin", CBFS_TYPE_RAW, &size); + struct vb2_public_key key; + struct vb2_workbuf wb; + struct vb21_signature *vb2_sig_hdr = (struct vb21_signature *)sig_buffer; + uint8_t wb_buffer[1024]; - if (size != (CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * - DIGEST_SIZE) + 256) { - printk(BIOS_ERR, "ERROR: Incorrect manifest size!\n"); + buffer = cbfs_boot_map_with_leak(RSA_PUBLICKEY_FILE_NAME, CBFS_TYPE_RAW, &size); + if (!buffer || !size) { + printk(BIOS_ERR, "ERROR: Public key not found!\n"); goto fail; } - buffer = cbfs_boot_map_with_leak(RSA_PUBLICKEY_FILE_NAME, - CBFS_TYPE_RAW, &size); - - size = DIGEST_SIZE; - if (!vb2_unpack_key_data(&key, buffer, size)) { - printk(BIOS_ERR, "ERROR: Unable to create RSA Public Key !\n"); + if ((size != CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_SIZE) || + (buffer != (void *)CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_LOCATION)) { + printk(BIOS_ERR, "ERROR: Illegal public key!\n"); goto fail; } - if (CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512)) { - key.hash_alg = VB2_HASH_SHA512; - hash_algorithm = VB2_HASH_SHA512; - } else { - key.sig_alg = VB2_HASH_SHA256; - hash_algorithm = VB2_HASH_SHA256; + if (vb21_unpack_key(&key, buffer, size)) { + printk(BIOS_ERR, "ERROR: Invalid public key!\n"); + goto fail; } - /* Create a big endian digest */ - status = cb_sha_endian(hash_algorithm, - (const uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC, - CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE, - digest, BIG_ENDIAN_ALGORITHM); - if (status) + cbfs_boot_map_with_leak("oemmanifest.bin", CBFS_TYPE_RAW, &size); + if (size != (CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE) + + vb2_rsa_sig_size(VB2_SIG_RSA2048)) { + printk(BIOS_ERR, "ERROR: Incorrect manifest size!\n"); goto fail; + } - signature = (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC + - CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE; - - if (!vb2_rsa_verify_digest(&key, signature, digest, &wb)) { - printk(BIOS_ERR, "ERROR: Signature verification failed for" - "hash table !!\n"); + /* prepare work buffer structure */ + wb.buf = (uint8_t *)&wb_buffer; + wb.size = sizeof(wb_buffer); + + /* Build vb2_sig_hdr buffer */ + vb2_sig_hdr->sig_offset = sizeof(struct vb21_signature) + + (CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE); + vb2_sig_hdr->sig_alg = VB2_SIG_RSA2048; + vb2_sig_hdr->sig_size = vb2_rsa_sig_size(VB2_SIG_RSA2048); + vb2_sig_hdr->hash_alg = HASH_ALG; + vb2_sig_hdr->data_size = CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE; + memcpy(&sig_buffer[sizeof(struct vb21_signature)], (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC, size); + + if (vb21_verify_data(&sig_buffer[sizeof(struct vb21_signature)], vb2_sig_hdr->data_size, + (struct vb21_signature *)&sig_buffer, &key, &wb)) { + printk(BIOS_ERR, "ERROR: Signature verification failed for hash table\n"); goto fail; } - printk(BIOS_DEBUG, "%s: Successfully verified hash_table signature.\n", - __func__); + printk(BIOS_INFO, "%s: Successfully verified hash_table signature.\n", __func__); return 0; fail: @@ -151,39 +152,32 @@ static int measure_item(uint32_t pcr, uint8_t *hashData, uint32_t hashDataLen, int8_t *event_msg, TCG_EVENTTYPE eventType) { int status = TPM_SUCCESS; - EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrs; TCG_PCR_EVENT2_HDR tcgEventHdr; - ActivePcrs = tpm2_get_active_pcrs(); - memset(&tcgEventHdr, 0, sizeof(tcgEventHdr)); tcgEventHdr.pcrIndex = pcr; tcgEventHdr.eventType = eventType; if (event_msg) { - status = mboot_hash_extend_log(ActivePcrs, MBOOT_HASH_PROVIDED, - hashData, hashDataLen, &tcgEventHdr, - (uint8_t *)event_msg, 0); - if (status == TPM_SUCCESS) { - printk(BIOS_DEBUG, "%s: Success! %s measured to pcr" - "%d.\n", __func__, event_msg, pcr); - } else { - printk(BIOS_DEBUG, "%s: Fail! %s can't be measured. " - "ABORTING!!!\n", __func__, event_msg); - return status; - } + status = mboot_hash_extend_log(MBOOT_HASH_PROVIDED, hashData, + hashDataLen, &tcgEventHdr, + (uint8_t *)event_msg); + if (status == TPM_SUCCESS) + printk(BIOS_INFO, "%s: Success! %s measured to pcr %d.\n", __func__, + event_msg, pcr); } return status; } #endif -static void verified_boot_check_buffer(const char *name, void *start, - size_t size, uint32_t hash_index, int32_t pcr) +static void verified_boot_check_buffer(const char *name, void *start, size_t size, + uint32_t hash_index, int32_t pcr) { uint8_t digest[DIGEST_SIZE]; int hash_algorithm; - int status; - printk(BIOS_DEBUG, "%s: %s HASH verification buffer %p size %d\n", - __func__, name, start, (int) size); + vb2_error_t status; + + printk(BIOS_DEBUG, "%s: %s HASH verification buffer %p size %d\n", __func__, name, + start, (int)size); if (start && size) { if (CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512)) @@ -191,66 +185,51 @@ static void verified_boot_check_buffer(const char *name, void *start, else hash_algorithm = VB2_HASH_SHA256; - status = cb_sha_endian(hash_algorithm, (const uint8_t *)start, - size, digest, LITTLE_ENDIAN_ALGORITHM); - + status = cb_sha_endian(hash_algorithm, (const uint8_t *)start, size, digest); if ((CONFIG(VENDORCODE_ELTAN_VBOOT) && memcmp((void *)( (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC + - sizeof(digest) * hash_index), digest, sizeof(digest))) || - status) { + sizeof(digest) * hash_index), digest, sizeof(digest))) || status) { printk(BIOS_DEBUG, "%s: buffer hash\n", __func__); hexdump(digest, sizeof(digest)); printk(BIOS_DEBUG, "%s: manifest hash\n", __func__); - hexdump((void *)( - (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC + - sizeof(digest) * hash_index), sizeof(digest)); + hexdump((void *)( (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC + + sizeof(digest) * hash_index), sizeof(digest)); printk(BIOS_EMERG, "%s ", name); die("HASH verification failed!\n"); } else { #ifndef __BOOTBLOCK__ if (CONFIG(VENDORCODE_ELTAN_MBOOT)) { if (pcr != -1) { - printk(BIOS_DEBUG, "%s: measuring %s\n", - __func__, name); - status = measure_item(pcr, digest, - sizeof(digest), - (int8_t *)name, 0); + printk(BIOS_DEBUG, "%s: measuring %s\n", __func__, name); + if (measure_item(pcr, digest, sizeof(digest), + (int8_t *)name, 0)) + printk(BIOS_DEBUG, "%s: measuring failed!\n", __func__); } } #endif if (CONFIG(VENDORCODE_ELTAN_VBOOT)) - printk(BIOS_DEBUG, "%s HASH verification " - "success\n", name); + printk(BIOS_DEBUG, "%s HASH verification success\n", name); } } else { - printk(BIOS_EMERG, "Invalid buffer "); + printk(BIOS_EMERG, "Invalid buffer\n"); die("HASH verification failed!\n"); } } -void verified_boot_check_cbfsfile(const char *name, uint32_t type, - uint32_t hash_index, void **buffer, uint32_t *filesize, - int32_t pcr) +void verified_boot_check_cbfsfile(const char *name, uint32_t type, uint32_t hash_index, + void **buffer, uint32_t *filesize, int32_t pcr) { void *start; size_t size; - start = cbfs_boot_map_with_leak(name, type & ~VERIFIED_BOOT_COPY_BLOCK, - &size); + start = cbfs_boot_map_with_leak(name, type & ~VERIFIED_BOOT_COPY_BLOCK, &size); if (start && size) { - /* - * Speed up processing by copying the file content to memory - * first - */ + /* Speed up processing by copying the file content to memory first */ #ifndef __PRE_RAM__ - if ((type & VERIFIED_BOOT_COPY_BLOCK) && (buffer) && - (*buffer) && + if ((type & VERIFIED_BOOT_COPY_BLOCK) && (buffer) && (*buffer) && ((uint32_t) start > (uint32_t)(~(CONFIG_CBFS_SIZE-1)))) { - printk(BIOS_DEBUG, "%s: move buffer to " - "memory\n", __func__); - /* Move the file to a memory bufferof which we know it - * doesn't harm - */ + printk(BIOS_DEBUG, "%s: move buffer to memory\n", __func__); + /* Move the file to a memory bufferof which we know it doesn't harm */ memcpy(*buffer, start, size); start = *buffer; printk(BIOS_DEBUG, "%s: done\n", __func__); @@ -258,8 +237,7 @@ void verified_boot_check_cbfsfile(const char *name, uint32_t type, #endif // __PRE_RAM__ verified_boot_check_buffer(name, start, size, hash_index, pcr); } else { - printk(BIOS_EMERG, "CBFS Failed to get file content for %s\n", - name); + printk(BIOS_EMERG, "CBFS Failed to get file content for %s\n", name); die("HASH verification failed!\n"); } if (buffer) @@ -275,25 +253,22 @@ void process_verify_list(const verify_item_t list[]) while (list[i].type != VERIFY_TERMINATOR) { switch (list[i].type) { case VERIFY_FILE: - verified_boot_check_cbfsfile(list[i].name, - list[i].data.file.cbfs_type, - list[i].hash_index, NULL, NULL, - list[i].pcr); + verified_boot_check_cbfsfile(list[i].name, list[i].data.file.cbfs_type, + list[i].hash_index, NULL, NULL, list[i].pcr); if (list[i].data.file.related_items) { printk(BIOS_SPEW, "process related items\n"); - process_verify_list((verify_item_t *) - list[i].data.file.related_items); + process_verify_list( + (verify_item_t *)list[i].data.file.related_items); } break; case VERIFY_BLOCK: verified_boot_check_buffer(list[i].name, - (void *) list[i].data.block.start, - list[i].data.block.size, - list[i].hash_index, list[i].pcr); + (void *)list[i].data.block.start, + list[i].data.block.size, + list[i].hash_index, list[i].pcr); break; default: - printk(BIOS_EMERG, "INVALID TYPE IN VERIFY" - "LIST 0x%x\n", list[i].type); + printk(BIOS_EMERG, "INVALID TYPE IN VERIFY LIST 0x%x\n", list[i].type); die("HASH verification failed!\n"); } i++; @@ -392,9 +367,8 @@ static int process_oprom_list(const verify_item_t list[], uint32_t viddevid = 0; if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) { - printk(BIOS_ERR, "Incorrect expansion ROM header " - "signature %04x DONT START\n", - le32_to_cpu(rom_header->signature)); + printk(BIOS_ERR, "Incorrect expansion ROM header signature %04x DONT START\n", + le32_to_cpu(rom_header->signature)); return 0; } @@ -408,22 +382,22 @@ static int process_oprom_list(const verify_item_t list[], case VERIFY_OPROM: if (viddevid == list[i].data.oprom.viddev) { verified_boot_check_buffer(list[i].name, - (void *) rom_header, - rom_header->size * 512, - list[i].hash_index, list[i].pcr); + (void *)rom_header, + rom_header->size * 512, + list[i].hash_index, list[i].pcr); if (list[i].data.oprom.related_items) { - printk(BIOS_SPEW, "%s: process" - " related items\n", __func__); - process_verify_list((verify_item_t *)list[i].data.oprom.related_items); + printk(BIOS_SPEW, "%s: process related items\n", + __func__); + process_verify_list( + (verify_item_t *)list[i].data.oprom.related_items); } - printk(BIOS_SPEW, "%s: option rom can be" - " started\n", __func__); + printk(BIOS_SPEW, "%s: option rom can be started\n", __func__); return 1; } break; default: - printk(BIOS_EMERG, "%s: INVALID TYPE IN OPTION ROM LIST" - "0x%x\n", __func__, list[i].type); + printk(BIOS_EMERG, "%s: INVALID TYPE IN OPTION ROM LIST 0x%x\n", + __func__, list[i].type); die("HASH verification failed!\n"); } i++; -- cgit v1.2.3