summaryrefslogtreecommitdiff
path: root/src/security/tpm/tspi/tspi.c
diff options
context:
space:
mode:
authorPhilipp Deppenwiese <zaolin@das-labor.org>2018-02-27 19:40:52 +0100
committerMartin Roth <martinroth@google.com>2018-06-04 20:33:07 +0000
commitc07f8fbe6fd13e4245da71574b52b47e9733db84 (patch)
tree12db8b3c40552eab81045c6165538e2d3ba36ce8 /src/security/tpm/tspi/tspi.c
parent961d31bdb3c97e177156ed335d6f2c726d08ab51 (diff)
security/tpm: Unify the coreboot TPM software stack
* Remove 2nd software stack in pc80 drivers directory. * Create TSPI interface for common usage. * Refactor TSS / TIS code base. * Add vendor tss (Cr50) directory. * Change kconfig options for TPM to TPM1. * Add user / board configuration with: * MAINBOARD_HAS_*_TPM # * BUS driver * MAINBOARD_HAS_TPM1 or MAINBOARD_HAS_TPM2 * Add kconfig TPM user selection (e.g. pluggable TPMs) * Fix existing headers and function calls. * Fix vboot for interface usage and antirollback mode. Change-Id: I7ec277e82a3c20c62a0548a1a2b013e6ce8f5b3f Signed-off-by: Philipp Deppenwiese <zaolin@das-labor.org> Reviewed-on: https://review.coreboot.org/24903 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/security/tpm/tspi/tspi.c')
-rw-r--r--src/security/tpm/tspi/tspi.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/security/tpm/tspi/tspi.c b/src/security/tpm/tspi/tspi.c
new file mode 100644
index 0000000000..407e1fa1e0
--- /dev/null
+++ b/src/security/tpm/tspi/tspi.c
@@ -0,0 +1,190 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+ * Copyright 2017 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/cbmem_console.h>
+#include <console/console.h>
+#include <reset.h>
+#include <security/tpm/tspi.h>
+#include <security/tpm/tss.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if IS_ENABLED(CONFIG_TPM1)
+static uint32_t tpm1_invoke_state_machine(void)
+{
+ uint8_t disable;
+ uint8_t deactivated;
+ uint32_t result = TPM_SUCCESS;
+
+ /* Check that the TPM is enabled and activated. */
+ result = tlcl_get_flags(&disable, &deactivated, NULL);
+ if (result != TPM_SUCCESS) {
+ printk(BIOS_ERR, "TPM: Can't read capabilities.\n");
+ return result;
+ }
+
+ if (!!deactivated != IS_ENABLED(CONFIG_TPM_DEACTIVATE)) {
+ printk(BIOS_INFO,
+ "TPM: Unexpected TPM deactivated state. Toggling...\n");
+ result = tlcl_set_deactivated(!deactivated);
+ if (result != TPM_SUCCESS) {
+ printk(BIOS_ERR,
+ "TPM: Can't toggle deactivated state.\n");
+ return result;
+ }
+
+ deactivated = !deactivated;
+ result = TPM_E_MUST_REBOOT;
+ }
+
+ if (disable && !deactivated) {
+ printk(BIOS_INFO, "TPM: disabled (%d). Enabling...\n", disable);
+
+ result = tlcl_set_enable();
+ if (result != TPM_SUCCESS) {
+ printk(BIOS_ERR, "TPM: Can't set enabled state.\n");
+ return result;
+ }
+
+ printk(BIOS_INFO, "TPM: Must reboot to re-enable\n");
+ result = TPM_E_MUST_REBOOT;
+ }
+
+ return result;
+}
+#endif
+
+/*
+ * tpm_setup starts the TPM and establishes the root of trust for the
+ * anti-rollback mechanism. SetupTPM can fail for three reasons. 1 A bug. 2 a
+ * TPM hardware failure. 3 An unexpected TPM state due to some attack. In
+ * general we cannot easily distinguish the kind of failure, so our strategy is
+ * to reboot in recovery mode in all cases. The recovery mode calls SetupTPM
+ * again, which executes (almost) the same sequence of operations. There is a
+ * good chance that, if recovery mode was entered because of a TPM failure, the
+ * failure will repeat itself. (In general this is impossible to guarantee
+ * because we have no way of creating the exact TPM initial state at the
+ * previous boot.) In recovery mode, we ignore the failure and continue, thus
+ * giving the recovery kernel a chance to fix things (that's why we don't set
+ * bGlobalLock). The choice is between a knowingly insecure device and a
+ * bricked device.
+ *
+ * As a side note, observe that we go through considerable hoops to avoid using
+ * the STCLEAR permissions for the index spaces. We do this to avoid writing
+ * to the TPM flashram at every reboot or wake-up, because of concerns about
+ * the durability of the NVRAM.
+ */
+uint32_t tpm_setup(int s3flag)
+{
+ uint32_t result;
+
+ result = tlcl_lib_init();
+ if (result != TPM_SUCCESS) {
+ printk(BIOS_ERR, "TPM: Can't initialize.\n");
+ goto out;
+ }
+
+ /* Handle special init for S3 resume path */
+ if (s3flag) {
+ result = tlcl_resume();
+ if (result == TPM_E_INVALID_POSTINIT)
+ printk(BIOS_INFO, "TPM: Already initialized.\n");
+
+ return TPM_SUCCESS;
+ }
+
+ result = tlcl_startup();
+ if (result != TPM_SUCCESS) {
+ printk(BIOS_ERR, "TPM: Can't run startup command.\n");
+ goto out;
+ }
+
+ result = tlcl_assert_physical_presence();
+ if (result != TPM_SUCCESS) {
+ /*
+ * It is possible that the TPM was delivered with the physical
+ * presence command disabled. This tries enabling it, then
+ * tries asserting PP again.
+ */
+ result = tlcl_physical_presence_cmd_enable();
+ if (result != TPM_SUCCESS) {
+ printk(
+ BIOS_ERR,
+ "TPM: Can't enable physical presence command.\n");
+ goto out;
+ }
+
+ result = tlcl_assert_physical_presence();
+ if (result != TPM_SUCCESS) {
+ printk(BIOS_ERR,
+ "TPM: Can't assert physical presence.\n");
+ goto out;
+ }
+ }
+
+#if IS_ENABLED(CONFIG_TPM1)
+ result = tpm1_invoke_state_machine();
+ if (result != TPM_SUCCESS)
+ return result;
+#endif
+
+out:
+ if (result != TPM_SUCCESS)
+ post_code(POST_TPM_FAILURE);
+ else
+ printk(BIOS_INFO, "TPM: setup succeeded\n");
+
+ return result;
+}
+
+uint32_t tpm_clear_and_reenable(void)
+{
+ uint32_t result;
+
+ printk(BIOS_INFO, "TPM: Clear and re-enable\n");
+ result = tlcl_force_clear();
+ if (result != TPM_SUCCESS) {
+ printk(BIOS_ERR, "TPM: Can't initiate a force clear.\n");
+ return result;
+ }
+
+#if IS_ENABLED(CONFIG_TPM1)
+ result = tlcl_set_enable();
+ if (result != TPM_SUCCESS) {
+ printk(BIOS_ERR, "TPM: Can't set enabled state.\n");
+ return result;
+ }
+
+ result = tlcl_set_deactivated(0);
+ if (result != TPM_SUCCESS) {
+ printk(BIOS_ERR, "TPM: Can't set deactivated state.\n");
+ return result;
+ }
+#endif
+
+ return TPM_SUCCESS;
+}
+
+uint32_t tpm_extend_pcr(int pcr, uint8_t *digest, uint8_t *out_digest)
+{
+ if (!digest)
+ return TPM_E_IOERROR;
+
+ if (out_digest)
+ return tlcl_extend(pcr, digest, out_digest);
+
+ return tlcl_extend(pcr, digest, NULL);
+}