diff options
-rw-r--r-- | src/security/vboot/Makefile.inc | 2 | ||||
-rw-r--r-- | src/security/vboot/antirollback.h | 14 | ||||
-rw-r--r-- | src/security/vboot/secdata_mock.c | 10 | ||||
-rw-r--r-- | src/security/vboot/secdata_tpm.c | 46 | ||||
-rw-r--r-- | src/security/vboot/vbios_cache_hash_tpm.c | 75 | ||||
-rw-r--r-- | src/security/vboot/vbios_cache_hash_tpm.h | 18 |
6 files changed, 165 insertions, 0 deletions
diff --git a/src/security/vboot/Makefile.inc b/src/security/vboot/Makefile.inc index f6103bbf8e..52d6de39f6 100644 --- a/src/security/vboot/Makefile.inc +++ b/src/security/vboot/Makefile.inc @@ -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)) diff --git a/src/security/vboot/antirollback.h b/src/security/vboot/antirollback.h index 10a9e21e37..ab7c43aac9 100644 --- a/src/security/vboot/antirollback.h +++ b/src/security/vboot/antirollback.h @@ -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_ */ diff --git a/src/security/vboot/secdata_mock.c b/src/security/vboot/secdata_mock.c index 57aed61a71..9d8c13d2ef 100644 --- a/src/security/vboot/secdata_mock.c +++ b/src/security/vboot/secdata_mock.c @@ -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; +} diff --git a/src/security/vboot/secdata_tpm.c b/src/security/vboot/secdata_tpm.c index 844b28de6e..45851a09f4 100644 --- a/src/security/vboot/secdata_tpm.c +++ b/src/security/vboot/secdata_tpm.c @@ -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 /** diff --git a/src/security/vboot/vbios_cache_hash_tpm.c b/src/security/vboot/vbios_cache_hash_tpm.c new file mode 100644 index 0000000000..aa54f19e4c --- /dev/null +++ b/src/security/vboot/vbios_cache_hash_tpm.c @@ -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; +} diff --git a/src/security/vboot/vbios_cache_hash_tpm.h b/src/security/vboot/vbios_cache_hash_tpm.h new file mode 100644 index 0000000000..166fcaaeac --- /dev/null +++ b/src/security/vboot/vbios_cache_hash_tpm.h @@ -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_ */ |