Attention is currently required from: Lance Zhao, Michał Żygowski, Christian Walter, Tim Wawrzynczak, Julius Werner, Krystian Hebel, Yu-Ping Wu.

Sergii Dmytruk would like Michał Żygowski, Julius Werner and Krystian Hebel to review this change.

View Change

security/tpm: replace CONFIG(TPMx) checks with runtime check

Change-Id: Id9cc25aad8d1d7bfad12b7a92059b1b3641bbfa9
Ticket: https://ticket.coreboot.org/issues/433
Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
---
M src/acpi/acpi.c
M src/drivers/crb/tis.c
M src/drivers/pc80/tpm/tis.c
M src/drivers/tpm/ppi.c
M src/security/tpm/tspi/crtm.h
M src/security/tpm/tspi/tspi.c
M src/security/tpm/tss.h
M src/security/tpm/tss/tss.c
M src/security/vboot/secdata_tpm.c
M src/security/vboot/tpm_common.c
M src/vendorcode/google/chromeos/cse_board_reset.c
M src/vendorcode/google/chromeos/tpm2.c
12 files changed, 108 insertions(+), 65 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/61/69161/1
diff --git a/src/acpi/acpi.c b/src/acpi/acpi.c
index e211558..8f6019c 100644
--- a/src/acpi/acpi.c
+++ b/src/acpi/acpi.c
@@ -26,6 +26,7 @@
#include <device/mmio.h>
#include <device/pci.h>
#include <pc80/mc146818rtc.h>
+#include <security/tpm/tss.h>
#include <string.h>
#include <types.h>
#include <version.h>
@@ -1781,7 +1782,7 @@
acpi_add_table(rsdp, mcfg);
}

- if (CONFIG(TPM1)) {
+ if (tlcl_get_family() == 1) {
printk(BIOS_DEBUG, "ACPI: * TCPA\n");
tcpa = (acpi_tcpa_t *) current;
acpi_create_tcpa(tcpa);
@@ -1792,7 +1793,7 @@
}
}

- if (CONFIG(TPM2)) {
+ if (tlcl_get_family() == 2) {
printk(BIOS_DEBUG, "ACPI: * TPM2\n");
tpm2 = (acpi_tpm2_t *) current;
acpi_create_tpm2(tpm2);
diff --git a/src/drivers/crb/tis.c b/src/drivers/crb/tis.c
index 1955466..812947d 100644
--- a/src/drivers/crb/tis.c
+++ b/src/drivers/crb/tis.c
@@ -140,6 +140,9 @@
uint32_t fw_ver1, fw_ver2;
uint8_t major_spec_ver, minor_spec_ver;

+ if (tlcl_get_family() == 1)
+ return get_smbios_data(dev, handle, current);
+
tpm2_get_info(&info);

/* If any of these have invalid values, assume TPM not present or disabled */
diff --git a/src/drivers/pc80/tpm/tis.c b/src/drivers/pc80/tpm/tis.c
index e4cd05b..937de43 100644
--- a/src/drivers/pc80/tpm/tis.c
+++ b/src/drivers/pc80/tpm/tis.c
@@ -20,6 +20,7 @@
#include <device/device.h>
#include <console/console.h>
#include <security/tpm/tis.h>
+#include <security/tpm/tss.h>
#include <device/pnp.h>
#include <drivers/tpm/tpm_ppi.h>
#include <timer.h>
@@ -803,7 +804,7 @@
acpigen_write_scope(path);
acpigen_write_device(acpi_device_name(dev));

- if (CONFIG(TPM2)) {
+ if (tlcl_get_family() == 2) {
acpigen_write_name_string("_HID", "MSFT0101");
acpigen_write_name_string("_CID", "MSFT0101");
} else {
diff --git a/src/drivers/tpm/ppi.c b/src/drivers/tpm/ppi.c
index 3e74314..fdbdd8e 100644
--- a/src/drivers/tpm/ppi.c
+++ b/src/drivers/tpm/ppi.c
@@ -5,6 +5,7 @@
#include <acpi/acpi_device.h>
#include <cbmem.h>
#include <console/console.h>
+#include <security/tpm/tss.h>

#include "tpm_ppi.h"

@@ -62,7 +63,7 @@
acpigen_write_store();
acpigen_emit_namestring("^FSUP");
acpigen_emit_byte(LOCAL2_OP);
- acpigen_emit_byte(CONFIG(TPM1) ? ONE_OP : ZERO_OP);
+ acpigen_emit_byte(tlcl_get_family() == 1 ? ONE_OP : ZERO_OP);
acpigen_emit_byte(LOCAL1_OP);
acpigen_write_if_lequal_op_int(LOCAL1_OP, 0);

@@ -84,7 +85,7 @@
acpigen_write_store();
acpigen_emit_namestring("^FSUP");
acpigen_emit_byte(LOCAL2_OP);
- acpigen_emit_byte(CONFIG(TPM1) ? ZERO_OP : ONE_OP);
+ acpigen_emit_byte(tlcl_get_family() == 1 ? ZERO_OP : ONE_OP);
acpigen_emit_byte(LOCAL1_OP);

acpigen_write_if_lequal_op_int(LOCAL1_OP, 1);
@@ -114,7 +115,7 @@
*/
static void tpm_ppi_func1_cb(void *arg)
{
- if (CONFIG(TPM2))
+ if (tlcl_get_family() == 2)
/* Interface version: 1.3 */
acpigen_write_return_string("1.3");
else
@@ -410,7 +411,7 @@
acpigen_write_store();
acpigen_emit_namestring("^FSUP");
acpigen_emit_byte(LOCAL2_OP);
- acpigen_emit_byte(CONFIG(TPM1) ? ONE_OP : ZERO_OP);
+ acpigen_emit_byte(tlcl_get_family() == 1 ? ONE_OP : ZERO_OP);
acpigen_emit_byte(LOCAL1_OP);
acpigen_write_if_lequal_op_int(LOCAL1_OP, 0);
acpigen_write_return_byte(0); /* Not implemented */
@@ -418,7 +419,7 @@

// FIXME: Only advertise supported functions

- if (CONFIG(TPM1)) {
+ if (tlcl_get_family() == 1) {
/*
* Some functions do not require PP depending on configuration.
* Those aren't listed here, so the 'required PP' is always set for those.
@@ -434,7 +435,7 @@
acpigen_write_return_integer(PPI8_RET_ALLOWED);
acpigen_pop_len(); /* Pop : If */
}
- } else if (CONFIG(TPM2)) {
+ } else if (tlcl_get_family() == 2) {
/*
* Some functions do not require PP depending on configuration.
* Those aren't listed here, so the 'required PP' is always set for those.
@@ -574,7 +575,7 @@
bool found = false;
/* Fill in defaults, the TPM command executor may overwrite this list */
memset(ppib->func, 0, sizeof(ppib->func));
- if (CONFIG(TPM1)) {
+ if (tlcl_get_family() == 1) {
for (size_t i = 0; i < ARRAY_SIZE(tpm1_funcs); i++) {
ppib->func[tpm1_funcs[i]] = 1;
if (ppib->pprq == tpm1_funcs[i])
@@ -716,7 +717,7 @@
tpm_ppi->tag = LB_TAG_TPM_PPI_HANDOFF;
tpm_ppi->size = sizeof(*tpm_ppi);
tpm_ppi->ppi_address = (uintptr_t)ppib;
- tpm_ppi->tpm_version = CONFIG(TPM1) ? LB_TPM_VERSION_TPM_VERSION_1_2 :
+ tpm_ppi->tpm_version = tlcl_get_family() == 1 ? LB_TPM_VERSION_TPM_VERSION_1_2 :
LB_TPM_VERSION_TPM_VERSION_2;

tpm_ppi->ppi_version = BCD(1, 3);
diff --git a/src/security/tpm/tspi/crtm.h b/src/security/tpm/tspi/crtm.h
index bd5bc57..951c250 100644
--- a/src/security/tpm/tspi/crtm.h
+++ b/src/security/tpm/tspi/crtm.h
@@ -16,7 +16,7 @@
*/
#define TPM_RUNTIME_DATA_PCR 3

-#define TPM_MEASURE_ALGO (CONFIG(TPM1) ? VB2_HASH_SHA1 : VB2_HASH_SHA256)
+#define TPM_MEASURE_ALGO (tlcl_get_family() == 1 ? VB2_HASH_SHA1 : VB2_HASH_SHA256)

/**
* Measure digests cached in TCPA log entries into PCRs
diff --git a/src/security/tpm/tspi/tspi.c b/src/security/tpm/tspi/tspi.c
index 525522b..d6e0534 100644
--- a/src/security/tpm/tspi/tspi.c
+++ b/src/security/tpm/tspi/tspi.c
@@ -16,6 +16,9 @@
uint8_t deactivated;
uint32_t result = TPM_SUCCESS;

+ if (tlcl_get_family() != 1)
+ return result;
+
/* Check that the TPM is enabled and activated. */
result = tlcl12_get_flags(&disabled, &deactivated, NULL);
if (result != TPM_SUCCESS) {
@@ -200,19 +203,19 @@
return result;
}

-#if CONFIG(TPM1)
- result = tlcl12_set_enable();
- if (result != TPM_SUCCESS) {
- printk(BIOS_ERR, "TPM: Can't set enabled state.\n");
- return result;
- }
+ if (tlcl_get_family() == 1) {
+ result = tlcl12_set_enable();
+ if (result != TPM_SUCCESS) {
+ printk(BIOS_ERR, "TPM: Can't set enabled state.\n");
+ return result;
+ }

- result = tlcl12_set_deactivated(0);
- if (result != TPM_SUCCESS) {
- printk(BIOS_ERR, "TPM: Can't set deactivated state.\n");
- return result;
+ result = tlcl12_set_deactivated(0);
+ if (result != TPM_SUCCESS) {
+ printk(BIOS_ERR, "TPM: Can't set deactivated state.\n");
+ return result;
+ }
}
-#endif

return TPM_SUCCESS;
}
diff --git a/src/security/tpm/tss.h b/src/security/tpm/tss.h
index 9d6e55a..dc910b9 100644
--- a/src/security/tpm/tss.h
+++ b/src/security/tpm/tss.h
@@ -137,6 +137,11 @@
*/
uint32_t tlcl_lib_init(void);

+/**
+ * Query active TPM family. Returns 0 if uninitialized and 1 or 2 otherwise.
+ */
+int tlcl_get_family(void);
+
/* Commands */

/**
diff --git a/src/security/tpm/tss/tss.c b/src/security/tpm/tss/tss.c
index 36ea575..381c45b1 100644
--- a/src/security/tpm/tss/tss.c
+++ b/src/security/tpm/tss/tss.c
@@ -48,6 +48,11 @@
return VB2_ERROR_UNKNOWN;
}

+int tlcl_get_family(void)
+{
+ return tpm_family;
+}
+
uint32_t tlcl_startup(void)
{
#if CONFIG(TPM1)
diff --git a/src/security/vboot/secdata_tpm.c b/src/security/vboot/secdata_tpm.c
index ad2d812..9c84ecf 100644
--- a/src/security/vboot/secdata_tpm.c
+++ b/src/security/vboot/secdata_tpm.c
@@ -38,7 +38,7 @@

uint32_t antirollback_read_space_kernel(struct vb2_context *ctx)
{
- if (!CONFIG(TPM2)) {
+ if (tlcl_get_family() != 2) {
/*
* Before reading the kernel space, verify its permissions. If
* the kernel space has the wrong permission, we give up. This
@@ -233,12 +233,6 @@
return rv;
}

-/* Nothing special in the TPM2 path yet. */
-static uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
-{
- return tlcl_write(index, data, length);
-}
-
static uint32_t setup_space(const char *name, uint32_t index, const void *data,
uint32_t length, const TPMA_NV nv_attributes,
const uint8_t *nv_policy, size_t nv_policy_size)
@@ -381,7 +375,7 @@
return TPM_SUCCESS;
}

-static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
+static uint32_t _factory_initialize_tpm2(struct vb2_context *ctx)
{
RETURN_ON_FAILURE(tlcl_force_clear());

@@ -431,11 +425,6 @@
return TPM_SUCCESS;
}

-uint32_t antirollback_lock_space_firmware(void)
-{
- return tlcl_lock_nv_write(FIRMWARE_NV_INDEX);
-}
-
uint32_t antirollback_read_space_mrc_hash(uint32_t index, uint8_t *data, uint32_t size)
{
if (size != HASH_NV_SIZE) {
@@ -480,25 +469,7 @@
return tlcl_lock_nv_write(index);
}

-#else
-
-/**
- * Like tlcl_write(), but checks for write errors due to hitting the 64-write
- * limit and clears the TPM when that happens. This can only happen when the
- * TPM is unowned, so it is OK to clear it (and we really have no choice).
- * This is not expected to happen frequently, but it could happen.
- */
-
-static uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
-{
- uint32_t result = tlcl_write(index, data, length);
- if (result == TPM_E_MAXNVWRITES) {
- RETURN_ON_FAILURE(tpm_clear_and_reenable());
- return tlcl_write(index, data, length);
- } else {
- return result;
- }
-}
+#endif /* CONFIG(TPM2) */

/**
* Similarly to safe_write(), this ensures we don't fail a DefineSpace because
@@ -517,7 +488,7 @@
}
}

-static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
+static uint32_t _factory_initialize_tpm1(struct vb2_context *ctx)
{
TPM_PERMANENT_FLAGS pflags;
uint32_t result;
@@ -575,12 +546,44 @@
return TPM_SUCCESS;
}

-uint32_t antirollback_lock_space_firmware(void)
+#endif /* CONFIG(TPM1) */
+
+static uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
{
- return tlcl_set_global_lock();
+ uint32_t result;
+
+ if (tlcl_get_family() == 2)
+ /* Nothing special in the TPM2 path yet. */
+ return tlcl_write(index, data, length);
+
+ /**
+ * Like tlcl_write(), but checks for write errors due to hitting the 64-write
+ * limit and clears the TPM when that happens. This can only happen when the
+ * TPM is unowned, so it is OK to clear it (and we really have no choice).
+ * This is not expected to happen frequently, but it could happen.
+ */
+ result = tlcl_write(index, data, length);
+ if (result == TPM_E_MAXNVWRITES) {
+ RETURN_ON_FAILURE(tpm_clear_and_reenable());
+ return tlcl_write(index, data, length);
+ } else {
+ return result;
+ }
}

-#endif
+static uint32_t _factory_initialize_tpm(struct vb2_context *ctx)
+{
+ if (tlcl_get_family() == 2)
+ return _factory_initialize_tpm2(ctx);
+ return _factory_initialize_tpm1(ctx);
+}
+
+uint32_t antirollback_lock_space_firmware(void)
+{
+ if (tlcl_get_family() == 2)
+ return tlcl_lock_nv_write(FIRMWARE_NV_INDEX);
+ return tlcl_set_global_lock();
+}

/**
* Perform one-time initializations.
diff --git a/src/security/vboot/tpm_common.c b/src/security/vboot/tpm_common.c
index e67cc01..a757477 100644
--- a/src/security/vboot/tpm_common.c
+++ b/src/security/vboot/tpm_common.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <security/tpm/tspi.h>
+#include <security/tpm/tss.h>
#include <security/vboot/tpm_common.h>
#include <vb2_api.h>
#include <vb2_sha.h>
@@ -45,7 +46,7 @@
*/
_Static_assert(sizeof(buffer) >= VB2_SHA256_DIGEST_SIZE,
"Buffer needs to be able to fit at least a SHA256");
- enum vb2_hash_algorithm algo = CONFIG(TPM1) ? VB2_HASH_SHA1 : VB2_HASH_SHA256;
+ enum vb2_hash_algorithm algo = tlcl_get_family() == 1 ? VB2_HASH_SHA1 : VB2_HASH_SHA256;

switch (which_digest) {
/* SHA1 of (devmode|recmode|keyblock) bits */
diff --git a/src/vendorcode/google/chromeos/cse_board_reset.c b/src/vendorcode/google/chromeos/cse_board_reset.c
index 08db7e2..9b6f878 100644
--- a/src/vendorcode/google/chromeos/cse_board_reset.c
+++ b/src/vendorcode/google/chromeos/cse_board_reset.c
@@ -16,6 +16,11 @@
int ret;
struct cr50_firmware_version version;

+ /*
+ * Assuming that if particular TPM implementation is enabled at compile
+ * time, it's the one being used. This isn't generic code, so can
+ * probably get away with it.
+ */
if (CONFIG(TPM2) && CONFIG(TPM_GOOGLE_CR50)) {
/* Initialize TPM and get the cr50 firmware version. */
ret = tlcl_lib_init();
@@ -27,11 +32,11 @@
cr50_get_firmware_version(&version);

/*
- * Cr50 firmware versions 0.[3|4].20 or newer support strap
- * config 0xe where PLTRST from AP is connected to cr50's
- * PLTRST# signal. So return immediately and trigger a global
- * reset.
- */
+ * Cr50 firmware versions 0.[3|4].20 or newer support strap
+ * config 0xe where PLTRST from AP is connected to cr50's
+ * PLTRST# signal. So return immediately and trigger a global
+ * reset.
+ */
if (version.epoch != 0 || version.major > 4 ||
(version.major >= 3 && version.minor >= 20))
return;
diff --git a/src/vendorcode/google/chromeos/tpm2.c b/src/vendorcode/google/chromeos/tpm2.c
index 98fd815..4020155 100644
--- a/src/vendorcode/google/chromeos/tpm2.c
+++ b/src/vendorcode/google/chromeos/tpm2.c
@@ -22,6 +22,10 @@
return;
}

+ /* In case both families are enabled, but TPM1 is in use. */
+ if (tlcl_get_family() != 2)
+ return;
+
ret = tlcl_disable_platform_hierarchy();
if (ret != TPM_SUCCESS)
printk(BIOS_ERR, "Platform hierarchy disablement failed: %x\n",

To view, visit change 69161. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Id9cc25aad8d1d7bfad12b7a92059b1b3641bbfa9
Gerrit-Change-Number: 69161
Gerrit-PatchSet: 1
Gerrit-Owner: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
Gerrit-Reviewer: Christian Walter <christian.walter@9elements.com>
Gerrit-Reviewer: Julius Werner <jwerner@chromium.org>
Gerrit-Reviewer: Krystian Hebel <krystian.hebel@3mdeb.com>
Gerrit-Reviewer: Lance Zhao
Gerrit-Reviewer: Michał Żygowski <michal.zygowski@3mdeb.com>
Gerrit-Reviewer: Tim Wawrzynczak <inforichland@gmail.com>
Gerrit-Reviewer: Yu-Ping Wu <yupingso@google.com>
Gerrit-Attention: Lance Zhao
Gerrit-Attention: Michał Żygowski <michal.zygowski@3mdeb.com>
Gerrit-Attention: Christian Walter <christian.walter@9elements.com>
Gerrit-Attention: Tim Wawrzynczak <inforichland@gmail.com>
Gerrit-Attention: Julius Werner <jwerner@chromium.org>
Gerrit-Attention: Krystian Hebel <krystian.hebel@3mdeb.com>
Gerrit-Attention: Yu-Ping Wu <yupingso@google.com>
Gerrit-MessageType: newchange