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 <wvervoorn@eltan.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/36480
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Frans Hendriks <fhendriks@eltan.com>
This commit is contained in:
Wim Vervoorn 2019-10-30 15:55:21 +01:00 committed by Patrick Georgi
parent eb48bb4fc8
commit ac4896fbcb
3 changed files with 100 additions and 123 deletions

View File

@ -55,9 +55,14 @@ config VENDORCODE_ELTAN_VBOOT_KEY_LOCATION
depends on VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST depends on VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST
default 0xFFFFF500 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 config VENDORCODE_ELTAN_VBOOT_KEY_SIZE
int int
default 554 if VENDORCODE_ELTAN_VBOOT_USE_SHA512 default 610 if VENDORCODE_ELTAN_VBOOT_USE_SHA512
default 520 default 576
endmenu # Verified Boot (verified_boot) endmenu # Verified Boot (verified_boot)

View File

@ -37,12 +37,10 @@ endif # ($(CONFIG_VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST),y)
ifeq ($(CONFIG_VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST),y) ifeq ($(CONFIG_VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST),y)
cbfs-files-y += vboot_public_key.bin 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-position := $(CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_LOCATION)
vboot_public_key.bin-type := raw 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_SIGNED_MANIFEST),y)
endif # CONFIG_VENDORCODE_ELTAN_VBOOT endif # CONFIG_VENDORCODE_ELTAN_VBOOT

View File

@ -23,65 +23,66 @@
#if CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512) #if CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512)
#define DIGEST_SIZE VB2_SHA512_DIGEST_SIZE #define DIGEST_SIZE VB2_SHA512_DIGEST_SIZE
#define HASH_ALG VB2_HASH_SHA512
#else #else
#define DIGEST_SIZE VB2_SHA256_DIGEST_SIZE #define DIGEST_SIZE VB2_SHA256_DIGEST_SIZE
#define HASH_ALG VB2_HASH_SHA256
#endif #endif
int verified_boot_check_manifest(void) int verified_boot_check_manifest(void)
{ {
struct vb2_public_key key;
const struct vb2_workbuf wb;
uint8_t *buffer; uint8_t *buffer;
uint8_t digest[DIGEST_SIZE]; uint8_t sig_buffer[1024]; /* used to build vb21_signature */
uint8_t *signature = NULL;
size_t size = 0; size_t size = 0;
int hash_algorithm; struct vb2_public_key key;
int status; struct vb2_workbuf wb;
struct vb21_signature *vb2_sig_hdr = (struct vb21_signature *)sig_buffer;
uint8_t wb_buffer[1024];
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;
}
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 (vb21_unpack_key(&key, buffer, size)) {
printk(BIOS_ERR, "ERROR: Invalid public key!\n");
goto fail;
}
cbfs_boot_map_with_leak("oemmanifest.bin", CBFS_TYPE_RAW, &size); cbfs_boot_map_with_leak("oemmanifest.bin", CBFS_TYPE_RAW, &size);
if (size != (CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE) +
if (size != (CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * vb2_rsa_sig_size(VB2_SIG_RSA2048)) {
DIGEST_SIZE) + 256) {
printk(BIOS_ERR, "ERROR: Incorrect manifest size!\n"); printk(BIOS_ERR, "ERROR: Incorrect manifest size!\n");
goto fail; goto fail;
} }
buffer = cbfs_boot_map_with_leak(RSA_PUBLICKEY_FILE_NAME, /* prepare work buffer structure */
CBFS_TYPE_RAW, &size); wb.buf = (uint8_t *)&wb_buffer;
wb.size = sizeof(wb_buffer);
size = DIGEST_SIZE; /* Build vb2_sig_hdr buffer */
if (!vb2_unpack_key_data(&key, buffer, size)) { vb2_sig_hdr->sig_offset = sizeof(struct vb21_signature) +
printk(BIOS_ERR, "ERROR: Unable to create RSA Public Key !\n"); (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; goto fail;
} }
if (CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512)) { printk(BIOS_INFO, "%s: Successfully verified hash_table signature.\n", __func__);
key.hash_alg = VB2_HASH_SHA512;
hash_algorithm = VB2_HASH_SHA512;
} else {
key.sig_alg = VB2_HASH_SHA256;
hash_algorithm = VB2_HASH_SHA256;
}
/* 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)
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");
goto fail;
}
printk(BIOS_DEBUG, "%s: Successfully verified hash_table signature.\n",
__func__);
return 0; return 0;
fail: 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) int8_t *event_msg, TCG_EVENTTYPE eventType)
{ {
int status = TPM_SUCCESS; int status = TPM_SUCCESS;
EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrs;
TCG_PCR_EVENT2_HDR tcgEventHdr; TCG_PCR_EVENT2_HDR tcgEventHdr;
ActivePcrs = tpm2_get_active_pcrs();
memset(&tcgEventHdr, 0, sizeof(tcgEventHdr)); memset(&tcgEventHdr, 0, sizeof(tcgEventHdr));
tcgEventHdr.pcrIndex = pcr; tcgEventHdr.pcrIndex = pcr;
tcgEventHdr.eventType = eventType; tcgEventHdr.eventType = eventType;
if (event_msg) { if (event_msg) {
status = mboot_hash_extend_log(ActivePcrs, MBOOT_HASH_PROVIDED, status = mboot_hash_extend_log(MBOOT_HASH_PROVIDED, hashData,
hashData, hashDataLen, &tcgEventHdr, hashDataLen, &tcgEventHdr,
(uint8_t *)event_msg, 0); (uint8_t *)event_msg);
if (status == TPM_SUCCESS) { if (status == TPM_SUCCESS)
printk(BIOS_DEBUG, "%s: Success! %s measured to pcr" printk(BIOS_INFO, "%s: Success! %s measured to pcr %d.\n", __func__,
"%d.\n", __func__, event_msg, pcr); event_msg, pcr);
} else {
printk(BIOS_DEBUG, "%s: Fail! %s can't be measured. "
"ABORTING!!!\n", __func__, event_msg);
return status;
}
} }
return status; return status;
} }
#endif #endif
static void verified_boot_check_buffer(const char *name, void *start, static void verified_boot_check_buffer(const char *name, void *start, size_t size,
size_t size, uint32_t hash_index, int32_t pcr) uint32_t hash_index, int32_t pcr)
{ {
uint8_t digest[DIGEST_SIZE]; uint8_t digest[DIGEST_SIZE];
int hash_algorithm; int hash_algorithm;
int status; vb2_error_t status;
printk(BIOS_DEBUG, "%s: %s HASH verification buffer %p size %d\n",
__func__, name, start, (int) size); printk(BIOS_DEBUG, "%s: %s HASH verification buffer %p size %d\n", __func__, name,
start, (int)size);
if (start && size) { if (start && size) {
if (CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512)) if (CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512))
@ -191,66 +185,51 @@ static void verified_boot_check_buffer(const char *name, void *start,
else else
hash_algorithm = VB2_HASH_SHA256; hash_algorithm = VB2_HASH_SHA256;
status = cb_sha_endian(hash_algorithm, (const uint8_t *)start, status = cb_sha_endian(hash_algorithm, (const uint8_t *)start, size, digest);
size, digest, LITTLE_ENDIAN_ALGORITHM);
if ((CONFIG(VENDORCODE_ELTAN_VBOOT) && memcmp((void *)( if ((CONFIG(VENDORCODE_ELTAN_VBOOT) && memcmp((void *)(
(uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC + (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC +
sizeof(digest) * hash_index), digest, sizeof(digest))) || sizeof(digest) * hash_index), digest, sizeof(digest))) || status) {
status) {
printk(BIOS_DEBUG, "%s: buffer hash\n", __func__); printk(BIOS_DEBUG, "%s: buffer hash\n", __func__);
hexdump(digest, sizeof(digest)); hexdump(digest, sizeof(digest));
printk(BIOS_DEBUG, "%s: manifest hash\n", __func__); printk(BIOS_DEBUG, "%s: manifest hash\n", __func__);
hexdump((void *)( hexdump((void *)( (uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC +
(uint8_t *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC + sizeof(digest) * hash_index), sizeof(digest));
sizeof(digest) * hash_index), sizeof(digest));
printk(BIOS_EMERG, "%s ", name); printk(BIOS_EMERG, "%s ", name);
die("HASH verification failed!\n"); die("HASH verification failed!\n");
} else { } else {
#ifndef __BOOTBLOCK__ #ifndef __BOOTBLOCK__
if (CONFIG(VENDORCODE_ELTAN_MBOOT)) { if (CONFIG(VENDORCODE_ELTAN_MBOOT)) {
if (pcr != -1) { if (pcr != -1) {
printk(BIOS_DEBUG, "%s: measuring %s\n", printk(BIOS_DEBUG, "%s: measuring %s\n", __func__, name);
__func__, name); if (measure_item(pcr, digest, sizeof(digest),
status = measure_item(pcr, digest, (int8_t *)name, 0))
sizeof(digest), printk(BIOS_DEBUG, "%s: measuring failed!\n", __func__);
(int8_t *)name, 0);
} }
} }
#endif #endif
if (CONFIG(VENDORCODE_ELTAN_VBOOT)) if (CONFIG(VENDORCODE_ELTAN_VBOOT))
printk(BIOS_DEBUG, "%s HASH verification " printk(BIOS_DEBUG, "%s HASH verification success\n", name);
"success\n", name);
} }
} else { } else {
printk(BIOS_EMERG, "Invalid buffer "); printk(BIOS_EMERG, "Invalid buffer\n");
die("HASH verification failed!\n"); die("HASH verification failed!\n");
} }
} }
void verified_boot_check_cbfsfile(const char *name, uint32_t type, void verified_boot_check_cbfsfile(const char *name, uint32_t type, uint32_t hash_index,
uint32_t hash_index, void **buffer, uint32_t *filesize, void **buffer, uint32_t *filesize, int32_t pcr)
int32_t pcr)
{ {
void *start; void *start;
size_t size; size_t size;
start = cbfs_boot_map_with_leak(name, type & ~VERIFIED_BOOT_COPY_BLOCK, start = cbfs_boot_map_with_leak(name, type & ~VERIFIED_BOOT_COPY_BLOCK, &size);
&size);
if (start && 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__ #ifndef __PRE_RAM__
if ((type & VERIFIED_BOOT_COPY_BLOCK) && (buffer) && if ((type & VERIFIED_BOOT_COPY_BLOCK) && (buffer) && (*buffer) &&
(*buffer) &&
((uint32_t) start > (uint32_t)(~(CONFIG_CBFS_SIZE-1)))) { ((uint32_t) start > (uint32_t)(~(CONFIG_CBFS_SIZE-1)))) {
printk(BIOS_DEBUG, "%s: move buffer to " printk(BIOS_DEBUG, "%s: move buffer to memory\n", __func__);
"memory\n", __func__); /* Move the file to a memory bufferof which we know it doesn't harm */
/* Move the file to a memory bufferof which we know it
* doesn't harm
*/
memcpy(*buffer, start, size); memcpy(*buffer, start, size);
start = *buffer; start = *buffer;
printk(BIOS_DEBUG, "%s: done\n", __func__); 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__ #endif // __PRE_RAM__
verified_boot_check_buffer(name, start, size, hash_index, pcr); verified_boot_check_buffer(name, start, size, hash_index, pcr);
} else { } else {
printk(BIOS_EMERG, "CBFS Failed to get file content for %s\n", printk(BIOS_EMERG, "CBFS Failed to get file content for %s\n", name);
name);
die("HASH verification failed!\n"); die("HASH verification failed!\n");
} }
if (buffer) if (buffer)
@ -275,25 +253,22 @@ void process_verify_list(const verify_item_t list[])
while (list[i].type != VERIFY_TERMINATOR) { while (list[i].type != VERIFY_TERMINATOR) {
switch (list[i].type) { switch (list[i].type) {
case VERIFY_FILE: case VERIFY_FILE:
verified_boot_check_cbfsfile(list[i].name, verified_boot_check_cbfsfile(list[i].name, list[i].data.file.cbfs_type,
list[i].data.file.cbfs_type, list[i].hash_index, NULL, NULL, list[i].pcr);
list[i].hash_index, NULL, NULL,
list[i].pcr);
if (list[i].data.file.related_items) { if (list[i].data.file.related_items) {
printk(BIOS_SPEW, "process related items\n"); printk(BIOS_SPEW, "process related items\n");
process_verify_list((verify_item_t *) process_verify_list(
list[i].data.file.related_items); (verify_item_t *)list[i].data.file.related_items);
} }
break; break;
case VERIFY_BLOCK: case VERIFY_BLOCK:
verified_boot_check_buffer(list[i].name, verified_boot_check_buffer(list[i].name,
(void *) list[i].data.block.start, (void *)list[i].data.block.start,
list[i].data.block.size, list[i].data.block.size,
list[i].hash_index, list[i].pcr); list[i].hash_index, list[i].pcr);
break; break;
default: default:
printk(BIOS_EMERG, "INVALID TYPE IN VERIFY" printk(BIOS_EMERG, "INVALID TYPE IN VERIFY LIST 0x%x\n", list[i].type);
"LIST 0x%x\n", list[i].type);
die("HASH verification failed!\n"); die("HASH verification failed!\n");
} }
i++; i++;
@ -392,9 +367,8 @@ static int process_oprom_list(const verify_item_t list[],
uint32_t viddevid = 0; uint32_t viddevid = 0;
if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) { if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
printk(BIOS_ERR, "Incorrect expansion ROM header " printk(BIOS_ERR, "Incorrect expansion ROM header signature %04x DONT START\n",
"signature %04x DONT START\n", le32_to_cpu(rom_header->signature));
le32_to_cpu(rom_header->signature));
return 0; return 0;
} }
@ -408,22 +382,22 @@ static int process_oprom_list(const verify_item_t list[],
case VERIFY_OPROM: case VERIFY_OPROM:
if (viddevid == list[i].data.oprom.viddev) { if (viddevid == list[i].data.oprom.viddev) {
verified_boot_check_buffer(list[i].name, verified_boot_check_buffer(list[i].name,
(void *) rom_header, (void *)rom_header,
rom_header->size * 512, rom_header->size * 512,
list[i].hash_index, list[i].pcr); list[i].hash_index, list[i].pcr);
if (list[i].data.oprom.related_items) { if (list[i].data.oprom.related_items) {
printk(BIOS_SPEW, "%s: process" printk(BIOS_SPEW, "%s: process related items\n",
" related items\n", __func__); __func__);
process_verify_list((verify_item_t *)list[i].data.oprom.related_items); process_verify_list(
(verify_item_t *)list[i].data.oprom.related_items);
} }
printk(BIOS_SPEW, "%s: option rom can be" printk(BIOS_SPEW, "%s: option rom can be started\n", __func__);
" started\n", __func__);
return 1; return 1;
} }
break; break;
default: default:
printk(BIOS_EMERG, "%s: INVALID TYPE IN OPTION ROM LIST" printk(BIOS_EMERG, "%s: INVALID TYPE IN OPTION ROM LIST 0x%x\n",
"0x%x\n", __func__, list[i].type); __func__, list[i].type);
die("HASH verification failed!\n"); die("HASH verification failed!\n");
} }
i++; i++;