security/vboot: Add store/validate methods for AMD VBIOS FMAP cache

Add methods to store and retrieve the hash of the data stored in the
VBIOS cache FMAP region. Add a dedicated index in TPM NVRAM to store
the hash, and methods to calculate/read/write it.

Modeled after mrc_cache_hash_tpm.{c,h}

BUG=b:255812886
TEST=tested with rest of patch train

Change-Id: I030017d3bf956b8593bc09073ad6545b80a5b52b
Signed-off-by: Matt DeVillier <matt.devillier@amd.corp-partner.google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/72401
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
This commit is contained in:
Matt DeVillier 2023-01-23 18:31:27 -06:00 committed by Felix Held
parent e47d9fd3b6
commit 9ce755d05e
6 changed files with 165 additions and 0 deletions

View File

@ -127,6 +127,8 @@ postcar-y += common.c
romstage-$(CONFIG_MRC_SAVE_HASH_IN_TPM) += mrc_cache_hash_tpm.c
ramstage-$(CONFIG_MRC_SAVE_HASH_IN_TPM) += mrc_cache_hash_tpm.c
ramstage-$(CONFIG_SOC_AMD_GFX_CACHE_VBIOS_IN_FMAP) += vbios_cache_hash_tpm.c
ifeq ($(CONFIG_VBOOT_SEPARATE_VERSTAGE),y)
$(eval $(call vboot-for-stage,verstage))

View File

@ -29,6 +29,7 @@ enum vb2_pcr_digest;
#define MRC_RW_HASH_NV_INDEX 0x100d
#define HASH_NV_SIZE VB2_SHA256_DIGEST_SIZE
#define ENT_ROLLBACK_SPACE_INDEX 0x100e
#define VBIOS_CACHE_NV_INDEX 0x100f
/* Widevine Secure Counter space */
#define WIDEVINE_COUNTER_NV_INDEX(n) (0x3000 + (n))
#define NUM_WIDEVINE_COUNTERS 4
@ -99,4 +100,17 @@ uint32_t antirollback_write_space_mrc_hash(uint32_t index, const uint8_t *data,
*/
uint32_t antirollback_lock_space_mrc_hash(uint32_t index);
/*
* Read VBIOS hash data from TPM.
* @param data pointer to buffer where hash from TPM read into
* @param size size of buffer
*/
uint32_t antirollback_read_space_vbios_hash(uint8_t *data, uint32_t size);
/*
* Write new hash data to VBIOS space in TPM.
* @param data pointer to buffer of hash value to be written
* @param size size of buffer
*/
uint32_t antirollback_write_space_vbios_hash(const uint8_t *data, uint32_t size);
#endif /* ANTIROLLBACK_H_ */

View File

@ -69,3 +69,13 @@ vb2_error_t antirollback_write_space_mrc_hash(uint32_t index, const uint8_t *dat
{
return VB2_SUCCESS;
}
vb2_error_t antirollback_read_space_vbios_hash(uint8_t *data, uint32_t size)
{
return VB2_SUCCESS;
}
vb2_error_t antirollback_write_space_vbios_hash(const uint8_t *data, uint32_t size)
{
return VB2_SUCCESS;
}

View File

@ -481,6 +481,52 @@ uint32_t antirollback_lock_space_mrc_hash(uint32_t index)
return tlcl_lock_nv_write(index);
}
static uint32_t read_space_vbios_hash(uint8_t *data)
{
RETURN_ON_FAILURE(tlcl_read(VBIOS_CACHE_NV_INDEX, data, HASH_NV_SIZE));
return TPM_SUCCESS;
}
uint32_t antirollback_read_space_vbios_hash(uint8_t *data, uint32_t size)
{
if (size != HASH_NV_SIZE) {
VBDEBUG("TPM: Incorrect buffer size for hash idx 0x%x. "
"(Expected=0x%x Actual=0x%x).\n", VBIOS_CACHE_NV_INDEX, HASH_NV_SIZE,
size);
return TPM_E_READ_FAILURE;
}
return read_space_vbios_hash(data);
}
uint32_t antirollback_write_space_vbios_hash(const uint8_t *data, uint32_t size)
{
uint8_t spc_data[HASH_NV_SIZE];
uint32_t rv;
if (size != HASH_NV_SIZE) {
VBDEBUG("TPM: Incorrect buffer size for hash idx 0x%x. "
"(Expected=0x%x Actual=0x%x).\n", VBIOS_CACHE_NV_INDEX, HASH_NV_SIZE,
size);
return TPM_E_WRITE_FAILURE;
}
rv = read_space_vbios_hash(spc_data);
if (rv == TPM_E_BADINDEX) {
/*
* If space is not defined already for hash, define
* new space.
*/
VBDEBUG("TPM: Initializing hash space.\n");
return setup_space("VBIOS Cache Hash", VBIOS_CACHE_NV_INDEX, data, HASH_NV_SIZE,
rw_space_attributes, NULL, 0);
}
if (rv != TPM_SUCCESS)
return rv;
return safe_write(VBIOS_CACHE_NV_INDEX, data, size);
}
#else
/**

View File

@ -0,0 +1,75 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <security/vboot/antirollback.h>
#include <program_loading.h>
#include <vb2_api.h>
#include <security/tpm/tss.h>
#include <security/vboot/misc.h>
#include <security/vboot/vbios_cache_hash_tpm.h>
#include <console/console.h>
#include <string.h>
void vbios_cache_update_hash(const uint8_t *data, size_t size)
{
struct vb2_hash hash;
/* Initialize TPM driver. */
if (tlcl_lib_init() != VB2_SUCCESS) {
printk(BIOS_ERR, "VBIOS_CACHE: TPM driver initialization failed.\n");
return;
}
/* Calculate hash of vbios data. */
if (vb2_hash_calculate(vboot_hwcrypto_allowed(), data, size,
VB2_HASH_SHA256, &hash)) {
printk(BIOS_ERR, "VBIOS_CACHE: SHA-256 calculation failed for data; "
"clearing TPM hash space.\n");
/*
* Since data is being updated in vbios cache, the hash
* currently stored in TPM hash space is no longer
* valid. If we are not able to calculate hash of the
* data being updated, reset all the bits in TPM hash
* space to zero to invalidate it.
*/
memset(hash.raw, 0, VB2_SHA256_DIGEST_SIZE);
}
/* Write hash of data to TPM space. */
if (antirollback_write_space_vbios_hash(hash.sha256, sizeof(hash.sha256))
!= TPM_SUCCESS) {
printk(BIOS_ERR, "VBIOS_CACHE: Could not save hash to TPM.\n");
return;
}
printk(BIOS_INFO, "VBIOS_CACHE: TPM NV idx 0x%x updated successfully.\n",
VBIOS_CACHE_NV_INDEX);
}
enum cb_err vbios_cache_verify_hash(const uint8_t *data, size_t size)
{
struct vb2_hash tpm_hash = { .algo = VB2_HASH_SHA256 };
/* Initialize TPM driver. */
if (tlcl_lib_init() != VB2_SUCCESS) {
printk(BIOS_ERR, "VBIOS_CACHE: TPM driver initialization failed.\n");
return CB_ERR;
}
/* Read hash of VBIOS data saved in TPM. */
if (antirollback_read_space_vbios_hash(tpm_hash.sha256, sizeof(tpm_hash.sha256))
!= TPM_SUCCESS) {
printk(BIOS_ERR, "VBIOS_CACHE: Could not read hash from TPM.\n");
return CB_ERR;
}
/* Calculate hash of data read from VBIOS FMAP CACHE and compare. */
if (vb2_hash_verify(vboot_hwcrypto_allowed(), data, size, &tpm_hash)) {
printk(BIOS_ERR, "VBIOS_CACHE: Hash comparison failed.\n");
return CB_ERR;
}
printk(BIOS_INFO, "VBIOS_CACHE: Hash idx 0x%x comparison successful.\n",
VBIOS_CACHE_NV_INDEX);
return CB_SUCCESS;
}

View File

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _VBIOS_CACHE_HASH_TPM_H_
#define _VBIOS_CACHE_HASH_TPM_H_
#include <types.h>
/*
* Updates vbios cache hash.
*/
void vbios_cache_update_hash(const uint8_t *data, size_t size);
/*
* Verifies vbios cache hash which is stored in FMAP region.
*/
enum cb_err vbios_cache_verify_hash(const uint8_t *data, size_t size);
#endif /* _VBIOS_CACHE_HASH_TPM_H_ */