security/vboot: Add measured boot mode
* Introduce a measured boot mode into vboot. * Add hook for stage measurements in prog_loader and cbfs. * Implement and hook-up CRTM in vboot and check for suspend. Change-Id: I339a2f1051e44f36aba9f99828f130592a09355e Signed-off-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com> Signed-off-by: Werner Zeh <werner.zeh@siemens.com> Reviewed-on: https://review.coreboot.org/c/29547 Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
bacd57dfaf
commit
66f9a09916
|
@ -167,6 +167,7 @@ Contents:
|
||||||
* [Code of Conduct](community/code_of_conduct.md)
|
* [Code of Conduct](community/code_of_conduct.md)
|
||||||
* [Community forums](community/forums.md)
|
* [Community forums](community/forums.md)
|
||||||
* [coreboot at conferences](community/conferences.md)
|
* [coreboot at conferences](community/conferences.md)
|
||||||
|
* [Security](security.md)
|
||||||
* [Payloads](payloads.md)
|
* [Payloads](payloads.md)
|
||||||
* [Distributions](distributions.md)
|
* [Distributions](distributions.md)
|
||||||
* [Timestamps](timestamp.md)
|
* [Timestamps](timestamp.md)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Security
|
||||||
|
|
||||||
|
## Google VBoot2 Measured boot extension
|
||||||
|
|
||||||
|
- [Measured Boot](vboot/measured_boot.md)
|
|
@ -0,0 +1,58 @@
|
||||||
|
# Measured Boot
|
||||||
|
coreboot measured boot is implemented as Google Verified Boot extension. This
|
||||||
|
means in order to use it, vboot needs to be available for your platform.
|
||||||
|
|
||||||
|
## IBB/CRTM
|
||||||
|
The "Initial Boot Block" or "Core Root of Trust for Measurement" is the first
|
||||||
|
code block loaded at reset vector and measured by a DRTM solution.
|
||||||
|
In case SRTM mode is active, the IBB measures itself before measuring the next
|
||||||
|
code block. In coreboot, cbfs files which are part of the IBB are identified
|
||||||
|
by a metatdata tag. This makes it possible to have platform specific IBB
|
||||||
|
measurements without hardcoding them.
|
||||||
|
|
||||||
|
## Known Limitations
|
||||||
|
At the moment measuring IBB dynamically and FMAP partitions are not possible but
|
||||||
|
will be added later to the implementation.
|
||||||
|
|
||||||
|
Also SoCs making use of VBOOT_RETURN_FROM_VERSTAGE are not able to use the
|
||||||
|
measured boot extension because of platform constraints.
|
||||||
|
|
||||||
|
## SRTM Mode
|
||||||
|
The "Static Root of Trust for Measurement" is the easiest way doing measurements
|
||||||
|
by measuring code before it is loaded.
|
||||||
|
|
||||||
|
![][srtm]
|
||||||
|
|
||||||
|
[srtm]: srtm.png
|
||||||
|
|
||||||
|
## DRTM Mode
|
||||||
|
The "Dynamic Root of Trust for Measurement" is realised by platform features
|
||||||
|
like Intel TXT or Boot Guard. The features provide a way of loading a signed
|
||||||
|
"Authenticated Code Module" aka signed blob. Most of these features are also
|
||||||
|
a "Trusted Execution Environment", e.g. Intel TXT.
|
||||||
|
|
||||||
|
DRTM gives you the ability of measuring the IBB from a higher Root of Trust
|
||||||
|
instead of doing it yourself without any hardware support.
|
||||||
|
|
||||||
|
## Platform Configuration Register
|
||||||
|
Normally PCR 0-7 are reserved for firmware usage. In coreboot we use just 4 PCR
|
||||||
|
banks in order to store the measurements. coreboot uses the SHA-1 or SHA-256
|
||||||
|
hash algorithm depending on the TPM specification for measurements. PCR-4 to
|
||||||
|
PCR-7 are left empty.
|
||||||
|
|
||||||
|
### PCR-0
|
||||||
|
_Hash:_ SHA1
|
||||||
|
_Description:_ Google VBoot GBB flags.
|
||||||
|
|
||||||
|
### PCR-1
|
||||||
|
_Hash:_ SHA1/SHA256
|
||||||
|
_Description:_ Google VBoot GBB HWID.
|
||||||
|
|
||||||
|
### PCR-2
|
||||||
|
_Hash:_ SHA1/SHA256
|
||||||
|
_Description:_ Core Root of Trust for Measurement which includes all stages,
|
||||||
|
data and blobs.
|
||||||
|
|
||||||
|
### PCR-3
|
||||||
|
_Hash:_ SHA1/SHA256
|
||||||
|
_Description:_ Runtime data like hwinfo.hex or MRC cache.
|
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -4,6 +4,8 @@ romstage-y += romstage.c
|
||||||
romstage-y += tsc_freq.c
|
romstage-y += tsc_freq.c
|
||||||
romstage-y += ../car/romstage.c
|
romstage-y += ../car/romstage.c
|
||||||
|
|
||||||
|
postcar-y += tsc_freq.c
|
||||||
|
|
||||||
ramstage-y += acpi.c
|
ramstage-y += acpi.c
|
||||||
ramstage-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c
|
ramstage-$(CONFIG_CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM) += stage_cache.c
|
||||||
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.c
|
ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.c
|
||||||
|
|
|
@ -12,6 +12,7 @@ subdirs-y += ../common
|
||||||
|
|
||||||
ramstage-y += tsc_freq.c
|
ramstage-y += tsc_freq.c
|
||||||
romstage-y += tsc_freq.c
|
romstage-y += tsc_freq.c
|
||||||
|
postcar-y += tsc_freq.c
|
||||||
smm-$(CONFIG_HAVE_SMI_HANDLER) += tsc_freq.c
|
smm-$(CONFIG_HAVE_SMI_HANDLER) += tsc_freq.c
|
||||||
|
|
||||||
ramstage-y += acpi.c
|
ramstage-y += acpi.c
|
||||||
|
|
|
@ -19,6 +19,7 @@ smm-$(CONFIG_HAVE_SMI_HANDLER) += common.c
|
||||||
|
|
||||||
ramstage-y += tsc_freq.c
|
ramstage-y += tsc_freq.c
|
||||||
romstage-y += tsc_freq.c
|
romstage-y += tsc_freq.c
|
||||||
|
postcar-y += tsc_freq.c
|
||||||
smm-$(CONFIG_HAVE_SMI_HANDLER) += tsc_freq.c
|
smm-$(CONFIG_HAVE_SMI_HANDLER) += tsc_freq.c
|
||||||
|
|
||||||
smm-$(CONFIG_HAVE_SMI_HANDLER) += finalize.c
|
smm-$(CONFIG_HAVE_SMI_HANDLER) += finalize.c
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <timestamp.h>
|
#include <timestamp.h>
|
||||||
#include <fmap.h>
|
#include <fmap.h>
|
||||||
#include "fmap_config.h"
|
#include "fmap_config.h"
|
||||||
|
#include <security/vboot/vboot_crtm.h>
|
||||||
|
|
||||||
#define ERROR(x...) printk(BIOS_ERR, "CBFS: " x)
|
#define ERROR(x...) printk(BIOS_ERR, "CBFS: " x)
|
||||||
#define LOG(x...) printk(BIOS_INFO, "CBFS: " x)
|
#define LOG(x...) printk(BIOS_INFO, "CBFS: " x)
|
||||||
|
@ -59,7 +60,12 @@ int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cbfs_locate(fh, &rdev, name, type);
|
int ret = cbfs_locate(fh, &rdev, name, type);
|
||||||
|
if (!ret)
|
||||||
|
if (vboot_measure_cbfs_hook(fh, name))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size)
|
void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size)
|
||||||
|
@ -79,13 +85,13 @@ void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size)
|
||||||
}
|
}
|
||||||
|
|
||||||
int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name,
|
int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name,
|
||||||
const char *name, uint32_t *type)
|
const char *name, uint32_t *type)
|
||||||
{
|
{
|
||||||
struct region_device rdev;
|
struct region_device rdev;
|
||||||
|
|
||||||
if (fmap_locate_area_as_rdev(region_name, &rdev)) {
|
if (fmap_locate_area_as_rdev(region_name, &rdev)) {
|
||||||
LOG("%s region not found while looking for %s\n",
|
LOG("%s region not found while looking for %s\n",
|
||||||
region_name, name);
|
region_name, name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +113,7 @@ size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset,
|
||||||
|
|
||||||
case CBFS_COMPRESS_LZ4:
|
case CBFS_COMPRESS_LZ4:
|
||||||
if ((ENV_BOOTBLOCK || ENV_VERSTAGE) &&
|
if ((ENV_BOOTBLOCK || ENV_VERSTAGE) &&
|
||||||
!IS_ENABLED(CONFIG_COMPRESS_PRERAM_STAGES))
|
!IS_ENABLED(CONFIG_COMPRESS_PRERAM_STAGES))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Load the compressed image to the end of the available memory
|
/* Load the compressed image to the end of the available memory
|
||||||
|
@ -130,7 +136,7 @@ size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset,
|
||||||
if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_POSTCAR_STAGE))
|
if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_POSTCAR_STAGE))
|
||||||
return 0;
|
return 0;
|
||||||
if ((ENV_ROMSTAGE || ENV_POSTCAR)
|
if ((ENV_ROMSTAGE || ENV_POSTCAR)
|
||||||
&& !IS_ENABLED(CONFIG_COMPRESS_RAMSTAGE))
|
&& !IS_ENABLED(CONFIG_COMPRESS_RAMSTAGE))
|
||||||
return 0;
|
return 0;
|
||||||
void *map = rdev_mmap(rdev, offset, in_size);
|
void *map = rdev_mmap(rdev, offset, in_size);
|
||||||
if (map == NULL)
|
if (map == NULL)
|
||||||
|
@ -157,9 +163,9 @@ static inline int tohex4(unsigned int c)
|
||||||
|
|
||||||
static void tohex16(unsigned int val, char *dest)
|
static void tohex16(unsigned int val, char *dest)
|
||||||
{
|
{
|
||||||
dest[0] = tohex4(val>>12);
|
dest[0] = tohex4(val >> 12);
|
||||||
dest[1] = tohex4((val>>8) & 0xf);
|
dest[1] = tohex4((val >> 8) & 0xf);
|
||||||
dest[2] = tohex4((val>>4) & 0xf);
|
dest[2] = tohex4((val >> 4) & 0xf);
|
||||||
dest[3] = tohex4(val & 0xf);
|
dest[3] = tohex4(val & 0xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,8 +173,8 @@ void *cbfs_boot_map_optionrom(uint16_t vendor, uint16_t device)
|
||||||
{
|
{
|
||||||
char name[17] = "pciXXXX,XXXX.rom";
|
char name[17] = "pciXXXX,XXXX.rom";
|
||||||
|
|
||||||
tohex16(vendor, name+3);
|
tohex16(vendor, name + 3);
|
||||||
tohex16(device, name+8);
|
tohex16(device, name + 8);
|
||||||
|
|
||||||
return cbfs_boot_map_with_leak(name, CBFS_TYPE_OPTIONROM, NULL);
|
return cbfs_boot_map_with_leak(name, CBFS_TYPE_OPTIONROM, NULL);
|
||||||
}
|
}
|
||||||
|
@ -202,8 +208,9 @@ size_t cbfs_boot_load_file(const char *name, void *buf, size_t buf_size,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (cbfsf_decompression_info(&fh, &compression_algo,
|
if (cbfsf_decompression_info(&fh, &compression_algo,
|
||||||
&decompressed_size) < 0
|
&decompressed_size)
|
||||||
|| decompressed_size > buf_size)
|
< 0
|
||||||
|
|| decompressed_size > buf_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return cbfs_load_and_decompress(&fh.data, 0, region_device_sz(&fh.data),
|
return cbfs_load_and_decompress(&fh.data, 0, region_device_sz(&fh.data),
|
||||||
|
@ -249,7 +256,7 @@ int cbfs_prog_stage_load(struct prog *pstage)
|
||||||
/* Hacky way to not load programs over read only media. The stages
|
/* Hacky way to not load programs over read only media. The stages
|
||||||
* that would hit this path initialize themselves. */
|
* that would hit this path initialize themselves. */
|
||||||
if (ENV_VERSTAGE && !IS_ENABLED(CONFIG_NO_XIP_EARLY_STAGES) &&
|
if (ENV_VERSTAGE && !IS_ENABLED(CONFIG_NO_XIP_EARLY_STAGES) &&
|
||||||
IS_ENABLED(CONFIG_BOOT_DEVICE_MEMORY_MAPPED)) {
|
IS_ENABLED(CONFIG_BOOT_DEVICE_MEMORY_MAPPED)) {
|
||||||
void *mapping = rdev_mmap(fh, foffset, fsize);
|
void *mapping = rdev_mmap(fh, foffset, fsize);
|
||||||
rdev_munmap(fh, mapping);
|
rdev_munmap(fh, mapping);
|
||||||
if (mapping == load)
|
if (mapping == load)
|
||||||
|
@ -354,7 +361,7 @@ int cbfs_boot_region_properties(struct cbfs_props *props)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LOG("'%s' located CBFS at [%zx:%zx)\n",
|
LOG("'%s' located CBFS at [%zx:%zx)\n",
|
||||||
ops->name, props->offset, props->offset + props->size);
|
ops->name, props->offset, props->offset + props->size);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,6 @@ static uint32_t tpm_setup_s3_helper(void)
|
||||||
default:
|
default:
|
||||||
printk(BIOS_ERR, "TPM: Resume failed (%#x).\n", result);
|
printk(BIOS_ERR, "TPM: Resume failed (%#x).\n", result);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -215,8 +214,6 @@ uint32_t tpm_extend_pcr(int pcr, uint8_t *digest,
|
||||||
if (result != TPM_SUCCESS)
|
if (result != TPM_SUCCESS)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
tcpa_log_add_table_entry(name, pcr, digest, digest_len);
|
|
||||||
|
|
||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +237,7 @@ uint32_t tpm_measure_region(const struct region_device *rdev, uint8_t pcr,
|
||||||
}
|
}
|
||||||
if (IS_ENABLED(CONFIG_TPM1))
|
if (IS_ENABLED(CONFIG_TPM1))
|
||||||
hash_alg = VB2_HASH_SHA1;
|
hash_alg = VB2_HASH_SHA1;
|
||||||
else /* CONFIG_TPM2 */
|
else /* CONFIG_TPM2 */
|
||||||
hash_alg = VB2_HASH_SHA256;
|
hash_alg = VB2_HASH_SHA256;
|
||||||
|
|
||||||
digest_len = vb2_digest_size(hash_alg);
|
digest_len = vb2_digest_size(hash_alg);
|
||||||
|
@ -258,7 +255,7 @@ uint32_t tpm_measure_region(const struct region_device *rdev, uint8_t pcr,
|
||||||
len = MIN(sizeof(buf), region_device_sz(rdev) - offset);
|
len = MIN(sizeof(buf), region_device_sz(rdev) - offset);
|
||||||
if (rdev_readat(rdev, buf, offset, len) < 0) {
|
if (rdev_readat(rdev, buf, offset, len) < 0) {
|
||||||
printk(BIOS_ERR, "TPM: Not able to read region %s.\n",
|
printk(BIOS_ERR, "TPM: Not able to read region %s.\n",
|
||||||
rname);
|
rname);
|
||||||
return TPM_E_READ_FAILURE;
|
return TPM_E_READ_FAILURE;
|
||||||
}
|
}
|
||||||
if (vb2_digest_extend(&ctx, buf, len)) {
|
if (vb2_digest_extend(&ctx, buf, len)) {
|
||||||
|
|
|
@ -26,6 +26,22 @@ config VBOOT
|
||||||
|
|
||||||
if VBOOT
|
if VBOOT
|
||||||
|
|
||||||
|
config VBOOT_MEASURED_BOOT
|
||||||
|
bool "Enable Measured Boot"
|
||||||
|
default n
|
||||||
|
depends on !VBOOT_MOCK_SECDATA
|
||||||
|
depends on !VBOOT_RETURN_FROM_VERSTAGE
|
||||||
|
help
|
||||||
|
Enables measured boot mode in vboot (experimental)
|
||||||
|
|
||||||
|
config VBOOT_MEASURED_BOOT_RUNTIME_DATA
|
||||||
|
string "Runtime data whitelist"
|
||||||
|
default ""
|
||||||
|
depends on VBOOT_MEASURED_BOOT
|
||||||
|
help
|
||||||
|
Runtime data whitelist of cbfs filenames. Needs to be a comma separated
|
||||||
|
list
|
||||||
|
|
||||||
config VBOOT_SLOTS_RW_A
|
config VBOOT_SLOTS_RW_A
|
||||||
bool "Firmware RO + RW_A"
|
bool "Firmware RO + RW_A"
|
||||||
help
|
help
|
||||||
|
@ -37,7 +53,6 @@ config VBOOT_SLOTS_RW_AB
|
||||||
help
|
help
|
||||||
Have two update partitions beside the RO partition.
|
Have two update partitions beside the RO partition.
|
||||||
|
|
||||||
|
|
||||||
config VBOOT_VBNV_CMOS
|
config VBOOT_VBNV_CMOS
|
||||||
bool
|
bool
|
||||||
default n
|
default n
|
||||||
|
|
|
@ -69,6 +69,13 @@ romstage-y += vboot_common.c
|
||||||
ramstage-y += vboot_common.c
|
ramstage-y += vboot_common.c
|
||||||
postcar-y += vboot_common.c
|
postcar-y += vboot_common.c
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_VBOOT_MEASURED_BOOT),y)
|
||||||
|
verstage-y += vboot_crtm.c
|
||||||
|
romstage-y += vboot_crtm.c
|
||||||
|
ramstage-y += vboot_crtm.c
|
||||||
|
postcar-y += vboot_crtm.c
|
||||||
|
endif
|
||||||
|
|
||||||
bootblock-y += common.c
|
bootblock-y += common.c
|
||||||
verstage-y += vboot_logic.c
|
verstage-y += vboot_logic.c
|
||||||
verstage-y += common.c
|
verstage-y += common.c
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Facebook Inc.
|
||||||
|
*
|
||||||
|
* 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 <console/console.h>
|
||||||
|
#include <fmap.h>
|
||||||
|
#include <security/vboot/vboot_crtm.h>
|
||||||
|
#include <security/vboot/misc.h>
|
||||||
|
|
||||||
|
uint32_t vboot_init_crtm(void)
|
||||||
|
{
|
||||||
|
struct prog bootblock = PROG_INIT(PROG_BOOTBLOCK, "bootblock");
|
||||||
|
struct prog verstage =
|
||||||
|
PROG_INIT(PROG_VERSTAGE, CONFIG_CBFS_PREFIX "/verstage");
|
||||||
|
struct prog romstage =
|
||||||
|
PROG_INIT(PROG_ROMSTAGE, CONFIG_CBFS_PREFIX "/romstage");
|
||||||
|
|
||||||
|
/* measure bootblock from RO */
|
||||||
|
struct cbfsf bootblock_data;
|
||||||
|
struct region_device bootblock_fmap;
|
||||||
|
if (fmap_locate_area_as_rdev("BOOTBLOCK", &bootblock_fmap) == 0) {
|
||||||
|
if (tpm_measure_region(&bootblock_fmap,
|
||||||
|
TPM_CRTM_PCR,
|
||||||
|
prog_name(&bootblock)))
|
||||||
|
return VB2_ERROR_UNKNOWN;
|
||||||
|
} else {
|
||||||
|
if (cbfs_boot_locate(&bootblock_data,
|
||||||
|
prog_name(&bootblock), NULL) == 0) {
|
||||||
|
cbfs_file_data(prog_rdev(&bootblock), &bootblock_data);
|
||||||
|
|
||||||
|
if (tpm_measure_region(prog_rdev(&bootblock),
|
||||||
|
TPM_CRTM_PCR,
|
||||||
|
prog_name(&bootblock)))
|
||||||
|
return VB2_ERROR_UNKNOWN;
|
||||||
|
} else {
|
||||||
|
printk(BIOS_INFO,
|
||||||
|
"VBOOT: Couldn't measure bootblock into CRTM!\n");
|
||||||
|
return VB2_ERROR_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE)) {
|
||||||
|
struct cbfsf romstage_data;
|
||||||
|
/* measure romstage from RO */
|
||||||
|
if (cbfs_boot_locate(&romstage_data,
|
||||||
|
prog_name(&romstage), NULL) == 0) {
|
||||||
|
cbfs_file_data(prog_rdev(&romstage), &romstage_data);
|
||||||
|
|
||||||
|
if (tpm_measure_region(prog_rdev(&romstage),
|
||||||
|
TPM_CRTM_PCR,
|
||||||
|
CONFIG_CBFS_PREFIX "/romstage"))
|
||||||
|
return VB2_ERROR_UNKNOWN;
|
||||||
|
} else {
|
||||||
|
printk(BIOS_INFO,
|
||||||
|
"VBOOT: Couldn't measure %s into CRTM!\n",
|
||||||
|
CONFIG_CBFS_PREFIX "/romstage");
|
||||||
|
return VB2_ERROR_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_VBOOT_SEPARATE_VERSTAGE)) {
|
||||||
|
struct cbfsf verstage_data;
|
||||||
|
/* measure verstage from RO */
|
||||||
|
if (cbfs_boot_locate(&verstage_data,
|
||||||
|
prog_name(&verstage), NULL) == 0) {
|
||||||
|
cbfs_file_data(prog_rdev(&verstage), &verstage_data);
|
||||||
|
|
||||||
|
if (tpm_measure_region(prog_rdev(&verstage),
|
||||||
|
TPM_CRTM_PCR,
|
||||||
|
CONFIG_CBFS_PREFIX "/verstage"))
|
||||||
|
return VB2_ERROR_UNKNOWN;
|
||||||
|
} else {
|
||||||
|
printk(BIOS_INFO,
|
||||||
|
"VBOOT: Couldn't measure %s into CRTM!\n",
|
||||||
|
CONFIG_CBFS_PREFIX "/verstage");
|
||||||
|
return VB2_ERROR_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return VB2_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_runtime_data(const char *name)
|
||||||
|
{
|
||||||
|
const char *whitelist = CONFIG_VBOOT_MEASURED_BOOT_RUNTIME_DATA;
|
||||||
|
size_t whitelist_len = sizeof(CONFIG_VBOOT_MEASURED_BOOT_RUNTIME_DATA) - 1;
|
||||||
|
size_t name_len = strlen(name);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!whitelist_len || !name_len)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (i = 0; (i + name_len) <= whitelist_len; i++) {
|
||||||
|
if (!strcmp(whitelist + i, name))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t vboot_measure_cbfs_hook(struct cbfsf *fh, const char *name)
|
||||||
|
{
|
||||||
|
uint32_t pcr_index;
|
||||||
|
uint32_t cbfs_type;
|
||||||
|
struct region_device rdev;
|
||||||
|
|
||||||
|
if (!vb2_logic_executed())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cbfsf_file_type(fh, &cbfs_type);
|
||||||
|
cbfs_file_data(&rdev, fh);
|
||||||
|
|
||||||
|
switch (cbfs_type) {
|
||||||
|
case CBFS_TYPE_MRC:
|
||||||
|
case CBFS_TYPE_MRC_CACHE:
|
||||||
|
pcr_index = TPM_RUNTIME_DATA_PCR;
|
||||||
|
break;
|
||||||
|
case CBFS_TYPE_STAGE:
|
||||||
|
case CBFS_TYPE_SELF:
|
||||||
|
case CBFS_TYPE_FIT:
|
||||||
|
pcr_index = TPM_CRTM_PCR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (is_runtime_data(name))
|
||||||
|
pcr_index = TPM_RUNTIME_DATA_PCR;
|
||||||
|
else
|
||||||
|
pcr_index = TPM_CRTM_PCR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tpm_measure_region(&rdev, pcr_index,
|
||||||
|
name);
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 Facebook Inc.
|
||||||
|
*
|
||||||
|
* 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_VBOOT_CRTM_H__
|
||||||
|
#define __SECURITY_VBOOT_CRTM_H__
|
||||||
|
|
||||||
|
#include <program_loading.h>
|
||||||
|
#include <security/tpm/tspi.h>
|
||||||
|
#include <types.h>
|
||||||
|
#include <cbfs.h>
|
||||||
|
|
||||||
|
/* CRTM */
|
||||||
|
#define TPM_CRTM_PCR 2
|
||||||
|
|
||||||
|
/* PCR for measuring data which changes during runtime
|
||||||
|
* e.g. CMOS, NVRAM...
|
||||||
|
*/
|
||||||
|
#define TPM_RUNTIME_DATA_PCR 3
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes the Core Root of Trust for Measurements
|
||||||
|
* in coreboot. The initial code in a chain of trust must measure
|
||||||
|
* itself.
|
||||||
|
*
|
||||||
|
* Summary:
|
||||||
|
* + Measures bootblock in CBFS or BOOTBLOCK FMAP partition.
|
||||||
|
* + If vboot starts in romstage, it measures the romstage
|
||||||
|
* in CBFS.
|
||||||
|
* + Measure the verstage if it is compiled as separate
|
||||||
|
* stage.
|
||||||
|
*
|
||||||
|
* Takes the current vboot context as parameter for s3 checks.
|
||||||
|
* returns on success VB2_SUCCESS, else a vboot error.
|
||||||
|
*/
|
||||||
|
uint32_t vboot_init_crtm(void);
|
||||||
|
|
||||||
|
#if (IS_ENABLED(CONFIG_VBOOT_MEASURED_BOOT) && \
|
||||||
|
!ENV_BOOTBLOCK && !ENV_DECOMPRESSOR && !ENV_SMM)
|
||||||
|
/*
|
||||||
|
* Measures cbfs data via hook (cbfs)
|
||||||
|
* fh is the cbfs file handle to measure
|
||||||
|
* return 0 if successful, else an error
|
||||||
|
*/
|
||||||
|
uint32_t vboot_measure_cbfs_hook(struct cbfsf *fh, const char *name);
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define vboot_measure_cbfs_hook(fh, name) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __VBOOT_VBOOT_CRTM_H__ */
|
|
@ -24,6 +24,7 @@
|
||||||
#include <vb2_api.h>
|
#include <vb2_api.h>
|
||||||
#include <security/vboot/misc.h>
|
#include <security/vboot/misc.h>
|
||||||
#include <security/vboot/vbnv.h>
|
#include <security/vboot/vbnv.h>
|
||||||
|
#include <security/vboot/vboot_crtm.h>
|
||||||
|
|
||||||
#include "antirollback.h"
|
#include "antirollback.h"
|
||||||
|
|
||||||
|
@ -86,24 +87,21 @@ int vb2ex_read_resource(struct vb2_context *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No-op stubs that can be overridden by SoCs with hardware crypto support. */
|
/* No-op stubs that can be overridden by SoCs with hardware crypto support. */
|
||||||
__weak
|
__weak int vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg,
|
||||||
int vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg,
|
uint32_t data_size)
|
||||||
uint32_t data_size)
|
|
||||||
{
|
{
|
||||||
return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED;
|
return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
__weak
|
__weak int vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size)
|
||||||
int vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size)
|
|
||||||
{
|
{
|
||||||
BUG(); /* Should never get called if init() returned an error. */
|
BUG(); /* Should never get called if init() returned an error. */
|
||||||
return VB2_ERROR_UNKNOWN;
|
return VB2_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
__weak
|
__weak int vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size)
|
||||||
int vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size)
|
|
||||||
{
|
{
|
||||||
BUG(); /* Should never get called if init() returned an error. */
|
BUG(); /* Should never get called if init() returned an error. */
|
||||||
return VB2_ERROR_UNKNOWN;
|
return VB2_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +247,7 @@ static int hash_body(struct vb2_context *ctx, struct region_device *fw_main)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int locate_firmware(struct vb2_context *ctx,
|
static int locate_firmware(struct vb2_context *ctx,
|
||||||
struct region_device *fw_main)
|
struct region_device *fw_main)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
|
@ -281,7 +279,7 @@ static void save_if_needed(struct vb2_context *ctx)
|
||||||
static uint32_t extend_pcrs(struct vb2_context *ctx)
|
static uint32_t extend_pcrs(struct vb2_context *ctx)
|
||||||
{
|
{
|
||||||
return vboot_extend_pcr(ctx, 0, BOOT_MODE_PCR) ||
|
return vboot_extend_pcr(ctx, 0, BOOT_MODE_PCR) ||
|
||||||
vboot_extend_pcr(ctx, 1, HWID_DIGEST_PCR);
|
vboot_extend_pcr(ctx, 1, HWID_DIGEST_PCR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -309,7 +307,7 @@ void verstage_main(void)
|
||||||
* does verification of memory init and thus must ensure it resumes with
|
* does verification of memory init and thus must ensure it resumes with
|
||||||
* the same slot that it booted from. */
|
* the same slot that it booted from. */
|
||||||
if (IS_ENABLED(CONFIG_RESUME_PATH_SAME_AS_BOOT) &&
|
if (IS_ENABLED(CONFIG_RESUME_PATH_SAME_AS_BOOT) &&
|
||||||
vboot_platform_is_resuming())
|
vboot_platform_is_resuming())
|
||||||
ctx.flags |= VB2_CONTEXT_S3_RESUME;
|
ctx.flags |= VB2_CONTEXT_S3_RESUME;
|
||||||
|
|
||||||
/* Read secdata from TPM. Initialize TPM if secdata not found. We don't
|
/* Read secdata from TPM. Initialize TPM if secdata not found. We don't
|
||||||
|
@ -319,8 +317,15 @@ void verstage_main(void)
|
||||||
antirollback_read_space_firmware(&ctx);
|
antirollback_read_space_firmware(&ctx);
|
||||||
timestamp_add_now(TS_END_TPMINIT);
|
timestamp_add_now(TS_END_TPMINIT);
|
||||||
|
|
||||||
|
/* Enable measured boot mode */
|
||||||
|
if (IS_ENABLED(CONFIG_VBOOT_MEASURED_BOOT) &&
|
||||||
|
!(ctx.flags & VB2_CONTEXT_S3_RESUME)) {
|
||||||
|
if (vboot_init_crtm() != VB2_SUCCESS)
|
||||||
|
die("Initializing measured boot mode failed!");
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_VBOOT_PHYSICAL_DEV_SWITCH) &&
|
if (IS_ENABLED(CONFIG_VBOOT_PHYSICAL_DEV_SWITCH) &&
|
||||||
get_developer_mode_switch())
|
get_developer_mode_switch())
|
||||||
ctx.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE;
|
ctx.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE;
|
||||||
|
|
||||||
if (get_recovery_mode_switch()) {
|
if (get_recovery_mode_switch()) {
|
||||||
|
@ -330,7 +335,7 @@ void verstage_main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_VBOOT_WIPEOUT_SUPPORTED) &&
|
if (IS_ENABLED(CONFIG_VBOOT_WIPEOUT_SUPPORTED) &&
|
||||||
get_wipeout_mode_switch())
|
get_wipeout_mode_switch())
|
||||||
ctx.flags |= VB2_CONTEXT_FORCE_WIPEOUT_MODE;
|
ctx.flags |= VB2_CONTEXT_FORCE_WIPEOUT_MODE;
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_VBOOT_LID_SWITCH) && !get_lid_switch())
|
if (IS_ENABLED(CONFIG_VBOOT_LID_SWITCH) && !get_lid_switch())
|
||||||
|
@ -350,7 +355,7 @@ void verstage_main(void)
|
||||||
if (rv == VB2_ERROR_API_PHASE1_RECOVERY) {
|
if (rv == VB2_ERROR_API_PHASE1_RECOVERY) {
|
||||||
printk(BIOS_INFO, "Recovery requested (%x)\n", rv);
|
printk(BIOS_INFO, "Recovery requested (%x)\n", rv);
|
||||||
save_if_needed(&ctx);
|
save_if_needed(&ctx);
|
||||||
extend_pcrs(&ctx); /* ignore failures */
|
extend_pcrs(&ctx); /* ignore failures */
|
||||||
timestamp_add_now(TS_END_VBOOT);
|
timestamp_add_now(TS_END_VBOOT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@ postcar-y += ramtop.c
|
||||||
postcar-y += sb_util.c
|
postcar-y += sb_util.c
|
||||||
postcar-y += nb_util.c
|
postcar-y += nb_util.c
|
||||||
postcar-$(CONFIG_VBOOT_MEASURED_BOOT) += i2c.c
|
postcar-$(CONFIG_VBOOT_MEASURED_BOOT) += i2c.c
|
||||||
|
postcar-y += tsc_freq.c
|
||||||
|
|
||||||
ramstage-y += BiosCallOuts.c
|
ramstage-y += BiosCallOuts.c
|
||||||
ramstage-y += i2c.c
|
ramstage-y += i2c.c
|
||||||
|
|
|
@ -14,6 +14,7 @@ romstage-y += memmap.c
|
||||||
postcar-y += memmap.c
|
postcar-y += memmap.c
|
||||||
ramstage-y += tsc_freq.c
|
ramstage-y += tsc_freq.c
|
||||||
romstage-y += tsc_freq.c
|
romstage-y += tsc_freq.c
|
||||||
|
postcar-y += tsc_freq.c
|
||||||
smm-y += tsc_freq.c
|
smm-y += tsc_freq.c
|
||||||
ramstage-y += spi.c
|
ramstage-y += spi.c
|
||||||
smm-y += spi.c
|
smm-y += spi.c
|
||||||
|
|
|
@ -16,6 +16,8 @@ romstage-y += memmap.c
|
||||||
romstage-y += pmutil.c
|
romstage-y += pmutil.c
|
||||||
romstage-y += tsc_freq.c
|
romstage-y += tsc_freq.c
|
||||||
|
|
||||||
|
postcar-y += tsc_freq.c
|
||||||
|
|
||||||
ramstage-y += acpi.c
|
ramstage-y += acpi.c
|
||||||
ramstage-y += chip.c
|
ramstage-y += chip.c
|
||||||
ramstage-y += cpu.c
|
ramstage-y += cpu.c
|
||||||
|
|
|
@ -61,6 +61,7 @@ ramstage-y += systemagent.c
|
||||||
ramstage-y += tsc_freq.c
|
ramstage-y += tsc_freq.c
|
||||||
romstage-y += tsc_freq.c
|
romstage-y += tsc_freq.c
|
||||||
smm-y += tsc_freq.c
|
smm-y += tsc_freq.c
|
||||||
|
postcar-y += tsc_freq.c
|
||||||
bootblock-$(CONFIG_USBDEBUG) += usb_debug.c
|
bootblock-$(CONFIG_USBDEBUG) += usb_debug.c
|
||||||
romstage-$(CONFIG_USBDEBUG) += usb_debug.c
|
romstage-$(CONFIG_USBDEBUG) += usb_debug.c
|
||||||
ramstage-$(CONFIG_USBDEBUG) += usb_debug.c
|
ramstage-$(CONFIG_USBDEBUG) += usb_debug.c
|
||||||
|
|
|
@ -32,6 +32,7 @@ ramstage-y += memmap.c
|
||||||
romstage-y += memmap.c
|
romstage-y += memmap.c
|
||||||
ramstage-y += tsc_freq.c
|
ramstage-y += tsc_freq.c
|
||||||
romstage-y += tsc_freq.c
|
romstage-y += tsc_freq.c
|
||||||
|
postcar-y += tsc_freq.c
|
||||||
smm-$(CONFIG_HAVE_SMI_HANDLER) += tsc_freq.c
|
smm-$(CONFIG_HAVE_SMI_HANDLER) += tsc_freq.c
|
||||||
ramstage-y += spi.c
|
ramstage-y += spi.c
|
||||||
smm-$(CONFIG_HAVE_SMI_HANDLER) += spi.c
|
smm-$(CONFIG_HAVE_SMI_HANDLER) += spi.c
|
||||||
|
|
|
@ -24,6 +24,7 @@ ramstage-y += acpi.c
|
||||||
ramstage-y += smbus_common.c
|
ramstage-y += smbus_common.c
|
||||||
ramstage-y += smbus.c
|
ramstage-y += smbus.c
|
||||||
romstage-y += tsc_freq.c
|
romstage-y += tsc_freq.c
|
||||||
|
postcar-y += tsc_freq.c
|
||||||
ramstage-y += smi.c
|
ramstage-y += smi.c
|
||||||
ramstage-y += gpio.c
|
ramstage-y += gpio.c
|
||||||
ramstage-y += iou_complto.c
|
ramstage-y += iou_complto.c
|
||||||
|
|
|
@ -39,7 +39,7 @@ SECTIONS
|
||||||
SRAM_END(0x00120000)
|
SRAM_END(0x00120000)
|
||||||
|
|
||||||
SRAM_L2C_START(0x00200000)
|
SRAM_L2C_START(0x00200000)
|
||||||
OVERLAP_DECOMPRESSOR_ROMSTAGE(0x000201000, 110K)
|
OVERLAP_DECOMPRESSOR_ROMSTAGE(0x000201000, 152K)
|
||||||
BOOTBLOCK(0x00227000, 89K)
|
BOOTBLOCK(0x00227000, 89K)
|
||||||
VERSTAGE(0x0023E000, 114K)
|
VERSTAGE(0x0023E000, 114K)
|
||||||
SRAM_L2C_END(0x00280000)
|
SRAM_L2C_END(0x00280000)
|
||||||
|
|
|
@ -717,7 +717,7 @@ while true ; do
|
||||||
chromeos=true
|
chromeos=true
|
||||||
testclass=chromeos
|
testclass=chromeos
|
||||||
customizing="${customizing}, chrome os"
|
customizing="${customizing}, chrome os"
|
||||||
configoptions="${configoptions}CONFIG_CHROMEOS=y\n"
|
configoptions="${configoptions}CONFIG_CHROMEOS=y\nCONFIG_VBOOT_MEASURED_BOOT=y\n"
|
||||||
;;
|
;;
|
||||||
-X|--xmlfile) shift; XMLFILE=$1; REAL_XMLFILE=$1; shift;;
|
-X|--xmlfile) shift; XMLFILE=$1; REAL_XMLFILE=$1; shift;;
|
||||||
-I|--recursive) shift; recursive=true;;
|
-I|--recursive) shift; recursive=true;;
|
||||||
|
|
Loading…
Reference in New Issue