summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/security/vboot/Makefile.inc2
-rw-r--r--src/security/vboot/antirollback.h14
-rw-r--r--src/security/vboot/secdata_mock.c10
-rw-r--r--src/security/vboot/secdata_tpm.c46
-rw-r--r--src/security/vboot/vbios_cache_hash_tpm.c75
-rw-r--r--src/security/vboot/vbios_cache_hash_tpm.h18
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_ */