vendorcode/eltan/security: Switch to vb2 vboot library

The eltan verified_boot is using the vboot 2.1 data structures and code,
as well as the fwlib21 build target, they are all deprecated. Refer to
CB:37654 for more information.

The verified_boot code is updated to use the vb2 structures and code and
make sure only public functions are used.

BUG=N/A
TEST=build

Change-Id: I1e1a7bce6110fe35221a4d7a47c1eb7c7074c318
Signed-off-by: Wim Vervoorn <wvervoorn@eltan.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/38590
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Frans Hendriks <fhendriks@eltan.com>
This commit is contained in:
Wim Vervoorn 2020-01-27 15:47:44 +01:00 committed by Patrick Georgi
parent 7a4983d1d2
commit 821004776f
12 changed files with 59 additions and 169 deletions

View File

@ -17,7 +17,6 @@ menu "Verified Boot (vboot)"
config VBOOT_LIB config VBOOT_LIB
bool bool
depends on !VENDORCODE_ELTAN_VBOOT && !VENDORCODE_ELTAN_MBOOT
help help
Build and link the vboot library. Makes the vboot API accessible across Build and link the vboot library. Makes the vboot API accessible across
all coreboot stages, without enabling vboot verification. For verification, all coreboot stages, without enabling vboot verification. For verification,

View File

@ -12,7 +12,6 @@
## GNU General Public License for more details. ## GNU General Public License for more details.
## ##
subdirs-y += lib
subdirs-y += verified_boot subdirs-y += verified_boot
subdirs-y += mboot subdirs-y += mboot

View File

@ -1,26 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2018-2019, Eltan B.V.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __SECURITY_CB_SHA_H__
#define __SECURITY_CB_SHA_H__
#include <2rsa.h>
#include <vb21_common.h>
#include <vb2_api.h>
vb2_error_t cb_sha_little_endian(enum vb2_hash_algorithm hash_alg, const uint8_t *data,
uint32_t len, uint8_t *digest);
#endif

View File

@ -1,60 +0,0 @@
#
# This file is part of the coreboot project.
#
# Copyright (C) 2018-2019 Eltan B.V.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# call with $1 = stage name to create rules for building the library
# for the stage and adding it to the stage's set of object files.
define vendor-security-lib
VEN_SEC_LIB_$(1) = $(obj)/external/ven_sec_lib-$(1)/vboot_fw21.a
VEN_SEC_CFLAGS_$(1) += $$(patsubst -I%,-I$(top)/%,\
$$(patsubst $(src)/%.h,$(top)/$(src)/%.h,\
$$(filter-out -I$(obj), $$(CPPFLAGS_$(1)))))
VEN_SEC_CFLAGS_$(1) += $$(CFLAGS_$(1))
VEN_SEC_CFLAGS_$(1) += $$($(1)-c-ccopts)
VEN_SEC_CFLAGS_$(1) += -I$(abspath $(obj)) -Wno-missing-prototypes
$$(VEN_SEC_LIB_$(1)): $(obj)/config.h
printf " MAKE $(subst $(obj)/,,$(@))\n"
+FIRMWARE_ARCH=$$(ARCHDIR-$$(ARCH-$(1)-y)) \
CC="$$(CC_$(1))" \
CFLAGS="$$(VEN_SEC_CFLAGS_$(1))" VBOOT2="y" \
$(MAKE) -C $(VBOOT_SOURCE) \
BUILD=$$(abspath $$(dir $$(VEN_SEC_LIB_$(1)))) \
V=$(V) \
fwlib21
endef # vendor-security-for-stage
CFLAGS_common += -I3rdparty/vboot/firmware/2lib/include
CFLAGS_common += -I3rdparty/vboot/firmware/lib21/include
ifneq ($(filter y,$(CONFIG_VENDORCODE_ELTAN_VBOOT) $(CONFIG_VENDORCODE_ELTAN_MBOOT)),)
bootblock-y += cb_sha.c
bootblock-y += ../../../../security/vboot/vboot_logic.c
$(eval $(call vendor-security-lib,bootblock))
bootblock-srcs += $(obj)/external/ven_sec_lib-bootblock/vboot_fw21.a
postcar-y += cb_sha.c
$(eval $(call vendor-security-lib,postcar))
postcar-srcs += $(obj)/external/ven_sec_lib-postcar/vboot_fw21.a
ramstage-y += cb_sha.c
$(eval $(call vendor-security-lib,ramstage))
ramstage-srcs += $(obj)/external/ven_sec_lib-ramstage/vboot_fw21.a
romstage-y += cb_sha.c
$(eval $(call vendor-security-lib,romstage))
romstage-srcs += $(obj)/external/ven_sec_lib-romstage/vboot_fw21.a
endif

View File

@ -1,38 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2019 Eltan B.V.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <cb_sha.h>
vb2_error_t cb_sha_little_endian(enum vb2_hash_algorithm hash_alg, const uint8_t *data,
uint32_t len, uint8_t *digest)
{
int i;
int rv;
uint32_t digest_size = vb2_digest_size(hash_alg);
uint8_t result[VB2_MAX_DIGEST_SIZE];
if (!digest_size)
return VB2_ERROR_SHA_INIT_ALGORITHM;
rv = vb2_digest_buffer(data, len, hash_alg, (uint8_t *)&result, digest_size);
if (rv)
return rv;
for (i = 0; i < digest_size; ++i) {
/* use little endian */
digest[digest_size - i - 1] = result[i];
}
return rv;
}

View File

@ -17,6 +17,7 @@ menu "Measured Boot (mboot)"
config VENDORCODE_ELTAN_MBOOT config VENDORCODE_ELTAN_MBOOT
bool "Measure firmware with mboot." bool "Measure firmware with mboot."
default n default n
select VBOOT_LIB
help help
Enabling MBOOT will use mboot to measure the components of the firmware Enabling MBOOT will use mboot to measure the components of the firmware
(stages, payload, etc). (stages, payload, etc).

View File

@ -142,8 +142,8 @@ int mboot_hash_extend_log(uint64_t flags, uint8_t *hashData, uint32_t hashDataLe
/* The hash is provided as data */ /* The hash is provided as data */
memcpy(digest->digest.sha256, (void *)hashData, hashDataLen); memcpy(digest->digest.sha256, (void *)hashData, hashDataLen);
} else { } else {
if (cb_sha_little_endian(VB2_HASH_SHA256, hashData, hashDataLen, if (vb2_digest_buffer(hashData, hashDataLen, VB2_HASH_SHA256, digest->digest.sha256,
digest->digest.sha256)) VB2_SHA256_DIGEST_SIZE))
return TPM_E_IOERROR; return TPM_E_IOERROR;
} }

View File

@ -20,7 +20,6 @@
#include <arch/io.h> #include <arch/io.h>
#include <arch/acpi.h> #include <arch/acpi.h>
#include <string.h> #include <string.h>
#include <cb_sha.h>
#include <console/console.h> #include <console/console.h>
#include <cbfs.h> #include <cbfs.h>
#include <lib.h> #include <lib.h>

View File

@ -18,6 +18,7 @@ config VENDORCODE_ELTAN_VBOOT
bool "Enable Verified Boot" bool "Enable Verified Boot"
depends on !VBOOT depends on !VBOOT
default n default n
select VBOOT_LIB
config VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST config VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST
bool "Enable Signed Manifest" bool "Enable Signed Manifest"
@ -57,11 +58,10 @@ config VENDORCODE_ELTAN_VBOOT_KEY_LOCATION
config VENDORCODE_ELTAN_VBOOT_KEY_FILE config VENDORCODE_ELTAN_VBOOT_KEY_FILE
string "Verified boot Key File" string "Verified boot Key File"
depends on VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST depends on VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST
default "3rdparty/eltan/verified_boot/Keys/key.vbpubk2" default "3rdparty/eltan/verified_boot/Keys/key.vbpubk"
config VENDORCODE_ELTAN_VBOOT_KEY_SIZE config VENDORCODE_ELTAN_VBOOT_KEY_SIZE
int int
default 610 if VENDORCODE_ELTAN_VBOOT_USE_SHA512 default 552
default 576
endmenu # Verified Boot (verified_boot) endmenu # Verified Boot (verified_boot)

View File

@ -17,6 +17,7 @@ ifneq ($(filter y,$(CONFIG_VENDORCODE_ELTAN_VBOOT) $(CONFIG_VENDORCODE_ELTAN_MBO
CPPFLAGS_common += -I$(src)/security/vboot CPPFLAGS_common += -I$(src)/security/vboot
bootblock-y += ../../../../security/vboot/vboot_logic.c
bootblock-y += vboot_check.c bootblock-y += vboot_check.c
postcar-y += vboot_check.c postcar-y += vboot_check.c
romstage-y += vboot_check.c romstage-y += vboot_check.c

View File

@ -13,6 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#define NEED_VB20_INTERNALS
#include <boot_device.h> #include <boot_device.h>
#include <bootmem.h> #include <bootmem.h>
#include <cbfs.h> #include <cbfs.h>
@ -32,12 +35,17 @@
int verified_boot_check_manifest(void) int verified_boot_check_manifest(void)
{ {
uint8_t *buffer; uint8_t *buffer;
uint8_t sig_buffer[1024]; /* used to build vb21_signature */ struct vb2_context *ctx;
size_t size = 0; struct vb2_kernel_preamble *pre;
struct vb2_public_key key; static struct vb2_shared_data *sd;
struct vb2_workbuf wb; size_t size;
struct vb21_signature *vb2_sig_hdr = (struct vb21_signature *)sig_buffer; uint8_t wb_buffer[2800];
uint8_t wb_buffer[1024];
if (vb2api_init(&wb_buffer, sizeof(wb_buffer), &ctx)) {
goto fail;
}
sd = vb2_get_sd(ctx);
buffer = cbfs_boot_map_with_leak(RSA_PUBLICKEY_FILE_NAME, CBFS_TYPE_RAW, &size); buffer = cbfs_boot_map_with_leak(RSA_PUBLICKEY_FILE_NAME, CBFS_TYPE_RAW, &size);
if (!buffer || !size) { if (!buffer || !size) {
@ -46,48 +54,61 @@ int verified_boot_check_manifest(void)
} }
if ((size != CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_SIZE) || if ((size != CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_SIZE) ||
(buffer != (void *)CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_LOCATION)) { (buffer != (void *)CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_LOCATION)) {
printk(BIOS_ERR, "ERROR: Illegal public key!\n"); printk(BIOS_ERR, "ERROR: Illegal public key!\n");
goto fail; goto fail;
} }
if (vb21_unpack_key(&key, buffer, size)) { /*
printk(BIOS_ERR, "ERROR: Invalid public key!\n"); * Check if all items will fit into workbuffer:
* vb2_shared data, Public Key, Preamble data
*/
if ((sd->workbuf_used + size + sizeof(struct vb2_kernel_preamble) +
((CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS * DIGEST_SIZE) + (2048/8))) >
sizeof(wb_buffer)) {
printk(BIOS_ERR, "ERROR: Work buffer too small\n");
goto fail; goto fail;
} }
/* Add public key */
sd->data_key_offset = sd->workbuf_used;
sd->data_key_size = size;
sd->workbuf_used += sd->data_key_size;
memcpy((void *)((void *)sd + (long)sd->data_key_offset), (uint8_t *)buffer, size);
/* Fill preamble area */
sd->preamble_size = sizeof(struct vb2_kernel_preamble);
sd->preamble_offset = sd->data_key_offset + sd->data_key_size;
sd->workbuf_used += sd->preamble_size;
pre = (struct vb2_kernel_preamble *)((void *)sd + (long)sd->preamble_offset);
pre->flags = VB2_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO;
/* Fill body_signature (vb2_structure). RSA2048 key is used */
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 * DIGEST_SIZE) + (2048/8))) {
vb2_rsa_sig_size(VB2_SIG_RSA2048)) {
printk(BIOS_ERR, "ERROR: Incorrect manifest size!\n"); printk(BIOS_ERR, "ERROR: Incorrect manifest size!\n");
goto fail; goto fail;
} }
pre->body_signature.data_size = CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS *
/* prepare work buffer structure */ DIGEST_SIZE;
wb.buf = (uint8_t *)&wb_buffer; pre->body_signature.sig_offset = sizeof(struct vb2_signature) +
wb.size = sizeof(wb_buffer); pre->body_signature.data_size;
pre->body_signature.sig_size = size - pre->body_signature.data_size;
/* Build vb2_sig_hdr buffer */ sd->workbuf_used += size;
vb2_sig_hdr->sig_offset = sizeof(struct vb21_signature) + memcpy((void *)((void *)&pre->body_signature + (long)sizeof(struct vb2_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); (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)) { if (vb2api_verify_kernel_data(ctx, (void *)CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC,
printk(BIOS_ERR, "ERROR: Signature verification failed for hash table\n"); pre->body_signature.data_size))
goto fail; goto fail;
}
printk(BIOS_INFO, "%s: Successfully verified hash_table signature.\n", __func__); printk(BIOS_INFO, "%s: Successfully verified hash_table signature.\n", __func__);
return 0; return 0;
fail: fail:
die("HASH table verification failed!\n"); die("ERROR: HASH table verification failed!\n");
return -1; return -1;
} }
@ -131,20 +152,14 @@ static void verified_boot_check_buffer(const char *name, void *start, size_t siz
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;
vb2_error_t status; vb2_error_t status;
printk(BIOS_DEBUG, "%s: %s HASH verification buffer %p size %d\n", __func__, name, printk(BIOS_DEBUG, "%s: %s HASH verification buffer %p size %d\n", __func__, name,
start, (int)size); start, (int)size);
if (start && size) { if (start && size) {
if (CONFIG(VENDORCODE_ELTAN_VBOOT_USE_SHA512))
hash_algorithm = VB2_HASH_SHA512;
else
hash_algorithm = VB2_HASH_SHA256;
status = cb_sha_little_endian(hash_algorithm, (const uint8_t *)start, size, status = vb2_digest_buffer((const uint8_t *)start, size, HASH_ALG, digest, DIGEST_SIZE);
digest);
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))) || status) { sizeof(digest) * hash_index), digest, sizeof(digest))) || status) {

View File

@ -23,7 +23,7 @@
#include <lib.h> #include <lib.h>
#include CONFIG_VENDORCODE_ELTAN_VBOOT_MANIFEST #include CONFIG_VENDORCODE_ELTAN_VBOOT_MANIFEST
#include <console/console.h> #include <console/console.h>
#include <cb_sha.h> #include <vb2_sha.h>
#include <string.h> #include <string.h>
#include <program_loading.h> #include <program_loading.h>
#include <mboot.h> #include <mboot.h>