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
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)

View File

@ -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

View File

@ -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;
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];
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);
if (size != (CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS *
DIGEST_SIZE) + 256) {
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;
}
buffer = cbfs_boot_map_with_leak(RSA_PUBLICKEY_FILE_NAME,
CBFS_TYPE_RAW, &size);
/* prepare work buffer structure */
wb.buf = (uint8_t *)&wb_buffer;
wb.size = sizeof(wb_buffer);
size = DIGEST_SIZE;
if (!vb2_unpack_key_data(&key, buffer, size)) {
printk(BIOS_ERR, "ERROR: Unable to create RSA Public Key !\n");
/* 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;
}
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;
}
/* 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__);
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++;