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:
parent
eb48bb4fc8
commit
ac4896fbcb
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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++;
|
||||
|
|
Loading…
Reference in New Issue