From c07f8fbe6fd13e4245da71574b52b47e9733db84 Mon Sep 17 00:00:00 2001 From: Philipp Deppenwiese Date: Tue, 27 Feb 2018 19:40:52 +0100 Subject: 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 Reviewed-on: https://review.coreboot.org/24903 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/security/tpm/Kconfig | 97 ++++++---- src/security/tpm/Makefile.inc | 51 +++++- src/security/tpm/antirollback.h | 81 -------- src/security/tpm/tis.h | 2 - src/security/tpm/tspi.h | 44 +++++ src/security/tpm/tspi/tspi.c | 190 +++++++++++++++++++ src/security/tpm/tss.h | 120 ++++++------ src/security/tpm/tss/common/tss_common.h | 23 +++ src/security/tpm/tss/tcg-1.2/tss.c | 3 +- src/security/tpm/tss/tcg-1.2/tss_commands.h | 178 ++++++++++++++++++ src/security/tpm/tss/tcg-1.2/tss_structures.h | 233 +++++++---------------- src/security/tpm/tss/tcg-2.0/tss.c | 147 ++------------- src/security/tpm/tss/tcg-2.0/tss_marshaling.c | 1 + src/security/tpm/tss/tcg-2.0/tss_structures.h | 17 +- src/security/tpm/tss/vendor/cr50/Kconfig | 28 +++ src/security/tpm/tss/vendor/cr50/Makefile.inc | 5 + src/security/tpm/tss/vendor/cr50/cr50.c | 54 ++++++ src/security/tpm/tss/vendor/cr50/cr50.h | 47 +++++ src/security/tpm/tss_constants.h | 100 ---------- src/security/tpm/tss_error_messages.h | 255 -------------------------- src/security/tpm/tss_errors.h | 42 +++++ src/security/vboot/Kconfig | 5 +- src/security/vboot/antirollback.h | 66 +++++++ src/security/vboot/secdata_mock.c | 30 ++- src/security/vboot/secdata_tpm.c | 179 ++++++------------ src/security/vboot/vboot_logic.c | 17 +- 26 files changed, 1012 insertions(+), 1003 deletions(-) delete mode 100644 src/security/tpm/antirollback.h create mode 100644 src/security/tpm/tspi.h create mode 100644 src/security/tpm/tspi/tspi.c create mode 100644 src/security/tpm/tss/common/tss_common.h create mode 100644 src/security/tpm/tss/tcg-1.2/tss_commands.h create mode 100644 src/security/tpm/tss/vendor/cr50/Kconfig create mode 100644 src/security/tpm/tss/vendor/cr50/Makefile.inc create mode 100644 src/security/tpm/tss/vendor/cr50/cr50.c create mode 100644 src/security/tpm/tss/vendor/cr50/cr50.h delete mode 100644 src/security/tpm/tss_constants.h delete mode 100644 src/security/tpm/tss_error_messages.h create mode 100644 src/security/tpm/tss_errors.h create mode 100644 src/security/vboot/antirollback.h (limited to 'src/security') diff --git a/src/security/tpm/Kconfig b/src/security/tpm/Kconfig index 111f91a5c1..e6414d385f 100644 --- a/src/security/tpm/Kconfig +++ b/src/security/tpm/Kconfig @@ -1,6 +1,7 @@ ## This file is part of the coreboot project. ## -## Copyright (C) 2017 Philipp Deppenwiese, Facebook, Inc. +## Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +## Copyright (C) 2018 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 @@ -12,58 +13,84 @@ ## GNU General Public License for more details. ## +source "src/security/tpm/tss/vendor/cr50/Kconfig" + menu "Trusted Platform Module" -config TPM +config TPM1 bool - default n - select LPC_TPM if MAINBOARD_HAS_LPC_TPM - select I2C_TPM if !MAINBOARD_HAS_LPC_TPM && !SPI_TPM - help - Enable this option to enable TPM support in coreboot. - - If unsure, say N. + default y if MAINBOARD_HAS_TPM1 || USER_TPM1 + depends on MAINBOARD_HAS_LPC_TPM || MAINBOARD_HAS_I2C_TPM_GENERIC \ + || MAINBOARD_HAS_I2C_TPM_ATMEL config TPM2 bool - select LPC_TPM if MAINBOARD_HAS_LPC_TPM - select I2C_TPM if !MAINBOARD_HAS_LPC_TPM && !SPI_TPM + default y if MAINBOARD_HAS_TPM2 || USER_TPM2 + depends on MAINBOARD_HAS_I2C_TPM_GENERIC || MAINBOARD_HAS_LPC_TPM \ + || MAINBOARD_HAS_I2C_TPM_ATMEL || MAINBOARD_HAS_I2C_TPM_CR50 \ + || MAINBOARD_HAS_SPI_TPM_CR50 + +config MAINBOARD_HAS_TPM1 + bool + +config MAINBOARD_HAS_TPM2 + bool + +if !MAINBOARD_HAS_TPM1 && !MAINBOARD_HAS_TPM2 + +choice + prompt "Trusted Platform Module" + default USER_NO_TPM + +config USER_NO_TPM + bool "disabled" + +config USER_TPM1 + bool "1.2" + depends on MAINBOARD_HAS_LPC_TPM || MAINBOARD_HAS_I2C_TPM_GENERIC \ + || MAINBOARD_HAS_I2C_TPM_ATMEL help - Enable this option to enable TPM2 support in coreboot. + Enable this option to enable TPM 1.0 - 1.2 support in coreboot. - If unsure, say N. + If unsure, say N. -config DEBUG_TPM - bool "Output verbose TPM debug messages" - default n - depends on TPM || TPM2 +config USER_TPM2 + bool "2.0" + depends on MAINBOARD_HAS_I2C_TPM_GENERIC || MAINBOARD_HAS_LPC_TPM \ + || MAINBOARD_HAS_I2C_TPM_ATMEL || MAINBOARD_HAS_I2C_TPM_CR50 \ + || MAINBOARD_HAS_SPI_TPM_CR50 help - This option enables additional TPM related debug messages. + Enable this option to enable TPM 2.0 support in coreboot. -config MAINBOARD_HAS_TPM_CR50 - bool - default y if MAINBOARD_HAS_SPI_TPM_CR50 || MAINBOARD_HAS_I2C_TPM_CR50 - default n - select MAINBOARD_HAS_TPM2 - select POWER_OFF_ON_CR50_UPDATE if ARCH_X86 + If unsure, say N. -config POWER_OFF_ON_CR50_UPDATE - bool +endchoice + +endif + +config TPM_DEACTIVATE + bool "Deactivate TPM" + default n + depends on !VBOOT + depends on TPM1 help - Power off machine while waiting for CR50 update to take effect. + Deactivate TPM by issuing deactivate command. -config MAINBOARD_HAS_LPC_TPM - bool +config DEBUG_TPM + bool "Output verbose TPM debug messages" default n + select DRIVER_TPM_DISPLAY_TIS_BYTES if I2C_TPM + depends on TPM1 || TPM2 help - Board has TPM support + This option enables additional TPM related debug messages. -config MAINBOARD_HAS_TPM2 - bool +config TPM_RDRESP_NEED_DELAY + bool "Enable Delay Workaround for TPM" default n + depends on LPC_TPM help - There is a TPM device installed on the mainboard, and it is - compliant with version 2 TCG TPM specification. Could be connected - over LPC, SPI or I2C. + Certain TPMs seem to need some delay when reading response + to work around a race-condition-related issue, possibly + caused by ill-programmed TPM firmware. endmenu # Trusted Platform Module (tpm) diff --git a/src/security/tpm/Makefile.inc b/src/security/tpm/Makefile.inc index 2385635f32..9157fec386 100644 --- a/src/security/tpm/Makefile.inc +++ b/src/security/tpm/Makefile.inc @@ -1,14 +1,45 @@ +subdirs-$(CONFIG_TPM_CR50) += tss/vendor/cr50 + ## TSS -verstage-$(CONFIG_TPM) += tss/tcg-1.2/tss.c -verstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss_marshaling.c -verstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss.c +ifeq ($(CONFIG_TPM1),y) + +ramstage-y += tss/tcg-1.2/tss.c +romstage-y += tss/tcg-1.2/tss.c + +verstage-$(CONFIG_VBOOT) += tss/tcg-1.2/tss.c +postcar-$(CONFIG_VBOOT) += tss/tcg-1.2/tss.c + +## TSPI + +ramstage-y += tspi/tspi.c +romstage-y += tspi/tspi.c + +verstage-$(CONFIG_VBOOT) += tspi/tspi.c +postcar-$(CONFIG_VBOOT) += tspi/tspi.c + +endif # CONFIG_TPM1 + +ifeq ($(CONFIG_TPM2),y) + +ramstage-y += tss/tcg-2.0/tss_marshaling.c +ramstage-y += tss/tcg-2.0/tss.c + +romstage-y += tss/tcg-2.0/tss_marshaling.c +romstage-y += tss/tcg-2.0/tss.c + +verstage-$(CONFIG_VBOOT) += tss/tcg-2.0/tss_marshaling.c +verstage-$(CONFIG_VBOOT) += tss/tcg-2.0/tss.c + +postcar-$(CONFIG_VBOOT) += tss/tcg-2.0/tss_marshaling.c +postcar-$(CONFIG_VBOOT) += tss/tcg-2.0/tss.c + +## TSPI + +ramstage-y += tspi/tspi.c +romstage-y += tspi/tspi.c -ifeq ($(CONFIG_VBOOT_SEPARATE_VERSTAGE),y) -romstage-$(CONFIG_TPM) += tss/tcg-1.2/tss.c -romstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss_marshaling.c -romstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss.c -endif # CONFIG_VBOOT_SEPARATE_VERSTAGE +verstage-$(CONFIG_VBOOT) += tspi/tspi.c +postcar-$(CONFIG_VBOOT) += tspi/tspi.c -ramstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss_marshaling.c -ramstage-$(CONFIG_TPM2) += tss/tcg-2.0/tss.c +endif # CONFIG_TPM2 diff --git a/src/security/tpm/antirollback.h b/src/security/tpm/antirollback.h deleted file mode 100644 index d1bc433dcd..0000000000 --- a/src/security/tpm/antirollback.h +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Functions for querying, manipulating and locking rollback indices - * stored in the TPM NVRAM. - */ - -#ifndef ANTIROLLBACK_H_ -#define ANTIROLLBACK_H_ - -#include "tss_constants.h" - -struct vb2_context; -enum vb2_pcr_digest; - -/* TPM NVRAM location indices. */ -#define FIRMWARE_NV_INDEX 0x1007 -#define KERNEL_NV_INDEX 0x1008 -/* 0x1009 used to be used as a backup space. Think of conflicts if you - * want to use 0x1009 for something else. */ -#define BACKUP_NV_INDEX 0x1009 -#define FWMP_NV_INDEX 0x100a -#define REC_HASH_NV_INDEX 0x100b -#define REC_HASH_NV_SIZE VB2_SHA256_DIGEST_SIZE - -/* Structure definitions for TPM spaces */ - -/* Flags for firmware space */ - -/* - * Last boot was developer mode. TPM ownership is cleared when transitioning - * to/from developer mode. - */ -#define FLAG_LAST_BOOT_DEVELOPER 0x01 - -/* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */ - -uint32_t antirollback_read_space_firmware(struct vb2_context *ctx); - -/** - * Write may be called if the versions change. - */ -uint32_t antirollback_write_space_firmware(struct vb2_context *ctx); - -/** - * Lock must be called. - */ -uint32_t antirollback_lock_space_firmware(void); - -/* Read recovery hash data from TPM. */ -uint32_t antirollback_read_space_rec_hash(uint8_t *data, uint32_t size); -/* Write new hash data to recovery space in TPM. */ -uint32_t antirollback_write_space_rec_hash(const uint8_t *data, uint32_t size); -/* Lock down recovery hash space in TPM. */ -uint32_t antirollback_lock_space_rec_hash(void); - -/****************************************************************************/ - -/* - * The following functions are internal apis, listed here for use by unit tests - * only. - */ - -/** - * Ask vboot for a digest and extend a TPM PCR with it. - */ -uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr, - enum vb2_pcr_digest which_digest); - -/** - * Issue a TPM_Clear and reenable/reactivate the TPM. - */ -uint32_t tpm_clear_and_reenable(void); - -/** - * Start the TPM and establish the root of trust for the antirollback mechanism. - */ -uint32_t setup_tpm(struct vb2_context *ctx); - -#endif /* ANTIROLLBACK_H_ */ diff --git a/src/security/tpm/tis.h b/src/security/tpm/tis.h index 6906ce33ec..c410838fc2 100644 --- a/src/security/tpm/tis.h +++ b/src/security/tpm/tis.h @@ -88,8 +88,6 @@ int tis_close(void); int tis_sendrecv(const u8 *sendbuf, size_t send_size, u8 *recvbuf, size_t *recv_len); -void init_tpm(int s3resume); - /* * tis_plat_irq_status() * diff --git a/src/security/tpm/tspi.h b/src/security/tpm/tspi.h new file mode 100644 index 0000000000..fdc9e1c187 --- /dev/null +++ b/src/security/tpm/tspi.h @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Copyright 2018 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. + */ + +#ifndef TSPI_H_ +#define TSPI_H_ + +#include + +/** + * Ask vboot for a digest and extend a TPM PCR with it. + * @param pcr sets the pcr index + * @param digest sets the hash to extend into the tpm + * @param out_digest get extended hash + * @return TPM_SUCCESS on success. If not a tpm error is returned + */ +uint32_t tpm_extend_pcr(int pcr, uint8_t *digest, uint8_t *out_digest); + +/** + * Issue a TPM_Clear and reenable/reactivate the TPM. + * @return TPM_SUCCESS on success. If not a tpm error is returned + */ +uint32_t tpm_clear_and_reenable(void); + +/** + * Start the TPM and establish the root of trust. + * @param s3flag tells the tpm setup if we wake up from a s3 state on x86 + * @return TPM_SUCCESS on success. If not a tpm error is returned + */ +uint32_t tpm_setup(int s3flag); + +#endif /* TSPI_H_ */ 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 +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/src/security/tpm/tss.h b/src/security/tpm/tss.h index 8f3f1cbff5..c053df960e 100644 --- a/src/security/tpm/tss.h +++ b/src/security/tpm/tss.h @@ -11,13 +11,70 @@ #ifndef TSS_H_ #define TSS_H_ + #include #include -#include "tss_constants.h" +#include +#include +#include + +#if IS_ENABLED(CONFIG_TPM1) + +#include + +/** + * Define a space with permission [perm]. [index] is the index for the space, + * [size] the usable data size. The TPM error code is returned. + */ +uint32_t tlcl_define_space(uint32_t index, uint32_t perm, uint32_t size); + +/** + * Issue a PhysicalEnable. The TPM error code is returned. + */ +uint32_t tlcl_set_enable(void); + +/** + * Issue a SetDeactivated. Pass 0 to activate. Returns result code. + */ +uint32_t tlcl_set_deactivated(uint8_t flag); + +/** + * Get flags of interest. Pointers for flags you aren't interested in may + * be NULL. The TPM error code is returned. + */ +uint32_t tlcl_get_flags(uint8_t *disable, uint8_t *deactivated, + uint8_t *nvlocked); + +/** + * Get the entire set of permanent flags. + */ +uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags); + +#endif + +#if IS_ENABLED(CONFIG_TPM2) + +#include + +/* + * Define a TPM2 space. The define space command TPM command used by the tlcl + * layer offers the ability to use custom nv attributes and policies. + */ +uint32_t tlcl_define_space(uint32_t space_index, size_t space_size, + const TPMA_NV nv_attributes, + const uint8_t *nv_policy, size_t nv_policy_size); + +/* + * Makes tpm_process_command available for on top implementations of + * custom tpm standards like cr50 + */ +void *tpm_process_command(TPM_CC command, void *command_body); + +#endif /*****************************************************************************/ -/* Functions implemented in tlcl.c */ +/* Generic Functions implemented in tlcl.c */ /** * Call this first. Returns 0 if success, nonzero if error. @@ -57,23 +114,6 @@ uint32_t tlcl_self_test_full(void); */ uint32_t tlcl_continue_self_test(void); -#if IS_ENABLED(CONFIG_TPM) -/** - * Define a space with permission [perm]. [index] is the index for the space, - * [size] the usable data size. The TPM error code is returned. - */ -uint32_t tlcl_define_space(uint32_t index, uint32_t perm, uint32_t size); - -#elif IS_ENABLED(CONFIG_TPM2) - -/* - * Define a TPM space. The define space command TPM command used by the tlcl - * layer is enforcing the policy which would not allow to delete the created - * space after any PCR0 change from its initial value. - */ -uint32_t tlcl_define_space(uint32_t space_index, size_t space_size); -#endif - /** * Write [length] bytes of [data] to space at [index]. The TPM error code is * returned. @@ -112,23 +152,6 @@ uint32_t tlcl_set_nv_locked(void); */ uint32_t tlcl_force_clear(void); -/** - * Issue a PhysicalEnable. The TPM error code is returned. - */ -uint32_t tlcl_set_enable(void); - -/** - * Issue a SetDeactivated. Pass 0 to activate. Returns result code. - */ -uint32_t tlcl_set_deactivated(uint8_t flag); - -/** - * Get flags of interest. Pointers for flags you aren't interested in may - * be NULL. The TPM error code is returned. - */ -uint32_t tlcl_get_flags(uint8_t *disable, uint8_t *deactivated, - uint8_t *nvlocked); - /** * Set the bGlobalLock flag, which only a reboot can clear. The TPM error * code is returned. @@ -146,32 +169,9 @@ uint32_t tlcl_lock_nv_write(uint32_t index); uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest); -/** - * Get the entire set of permanent flags. - */ -uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags); - /** * Disable platform hierarchy. Specific to TPM2. The TPM error code is returned. */ uint32_t tlcl_disable_platform_hierarchy(void); -/** - * CR50 specific tpm command to enable nvmem commits before internal timeout - * expires. - */ -uint32_t tlcl_cr50_enable_nvcommits(void); - -/** - * CR50 specific tpm command to restore header(s) of the dormant RO/RW - * image(s) and in case there indeed was a dormant image, trigger reboot after - * the timeout milliseconds. Note that timeout of zero means "NO REBOOT", not - * "IMMEDIATE REBOOT". - * - * Return value indicates success or failure of accessing the TPM; in case of - * success the number of restored headers is saved in num_restored_headers. - */ -uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms, - uint8_t *num_restored_headers); - -#endif /* TSS_H_ */ +#endif /* TSS_H_ */ diff --git a/src/security/tpm/tss/common/tss_common.h b/src/security/tpm/tss/common/tss_common.h new file mode 100644 index 0000000000..0cb8d86231 --- /dev/null +++ b/src/security/tpm/tss/common/tss_common.h @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Copyright 2018 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. + */ + +#ifndef TCG_TSS_COMMON_H_ +#define TCG_TSS_COMMON_H_ + +#define TPM_PCR_MINIMUM_DIGEST_SIZE 20 +#define TPM_SUCCESS ((uint32_t)0x00000000) + +#endif /* TCG_TSS_COMMON_H_ */ diff --git a/src/security/tpm/tss/tcg-1.2/tss.c b/src/security/tpm/tss/tcg-1.2/tss.c index 161d29f781..0cb7eaa819 100644 --- a/src/security/tpm/tss/tcg-1.2/tss.c +++ b/src/security/tpm/tss/tcg-1.2/tss.c @@ -20,8 +20,9 @@ #include #include #include + #include "tss_internal.h" -#include "tss_structures.h" +#include "tss_commands.h" #ifdef FOR_TEST #include diff --git a/src/security/tpm/tss/tcg-1.2/tss_commands.h b/src/security/tpm/tss/tcg-1.2/tss_commands.h new file mode 100644 index 0000000000..9d30bfc2a2 --- /dev/null +++ b/src/security/tpm/tss/tcg-1.2/tss_commands.h @@ -0,0 +1,178 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Copyright 2018 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. + */ + +const struct s_tpm_extend_cmd{ + uint8_t buffer[34]; + uint16_t pcrNum; + uint16_t inDigest; +} tpm_extend_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14, }, +10, 14, }; + +const struct s_tpm_get_random_cmd{ + uint8_t buffer[14]; + uint16_t bytesRequested; +} tpm_get_random_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x46, }, +10, }; + +const struct s_tpm_getownership_cmd{ + uint8_t buffer[22]; +} tpm_getownership_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, + 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x11, }, +}; + +const struct s_tpm_getpermissions_cmd{ + uint8_t buffer[22]; + uint16_t index; +} tpm_getpermissions_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, + 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x4, }, +18, }; + +const struct s_tpm_getstclearflags_cmd{ + uint8_t buffer[22]; +} tpm_getstclearflags_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, + 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x9, }, +}; + +const struct s_tpm_getflags_cmd{ + uint8_t buffer[22]; +} tpm_getflags_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, + 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x8, }, +}; + +const struct s_tpm_physicalsetdeactivated_cmd{ + uint8_t buffer[11]; + uint16_t deactivated; +} tpm_physicalsetdeactivated_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72, }, +10, }; + +const struct s_tpm_physicalenable_cmd{ + uint8_t buffer[10]; +} tpm_physicalenable_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f, }, +}; + +const struct s_tpm_physicaldisable_cmd{ + uint8_t buffer[10]; +} tpm_physicaldisable_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70, }, +}; + +const struct s_tpm_forceclear_cmd{ + uint8_t buffer[10]; +} tpm_forceclear_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d, }, +}; + +const struct s_tpm_readpubek_cmd{ + uint8_t buffer[30]; +} tpm_readpubek_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c, }, +}; + +const struct s_tpm_continueselftest_cmd{ + uint8_t buffer[10]; +} tpm_continueselftest_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53, }, +}; + +const struct s_tpm_selftestfull_cmd{ + uint8_t buffer[10]; +} tpm_selftestfull_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, }, +}; + +const struct s_tpm_resume_cmd{ + uint8_t buffer[12]; +} tpm_resume_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x2, }, +}; + +const struct s_tpm_savestate_cmd{ + uint8_t buffer[10]; +} tpm_savestate_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x98, }, +}; + +const struct s_tpm_startup_cmd{ + uint8_t buffer[12]; +} tpm_startup_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1, }, +}; + +const struct s_tpm_finalizepp_cmd{ + uint8_t buffer[12]; +} tpm_finalizepp_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0, }, +}; + +const struct s_tpm_pplock_cmd{ + uint8_t buffer[12]; +} tpm_pplock_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x4, }, +}; + +const struct s_tpm_ppenable_cmd{ + uint8_t buffer[12]; +} tpm_ppenable_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x20, }, +}; + +const struct s_tpm_ppassert_cmd{ + uint8_t buffer[12]; +} tpm_ppassert_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x8, }, +}; + +const struct s_tpm_pcr_read_cmd{ + uint8_t buffer[14]; + uint16_t pcrNum; +} tpm_pcr_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15, }, +10, }; + +const struct s_tpm_nv_read_cmd{ + uint8_t buffer[22]; + uint16_t index; + uint16_t length; +} tpm_nv_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf, }, +10, 18, }; + +const struct s_tpm_nv_write_cmd{ + uint8_t buffer[256]; + uint16_t index; + uint16_t length; + uint16_t data; +} tpm_nv_write_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, }, +10, 18, 22, }; + +const struct s_tpm_nv_definespace_cmd{ + uint8_t buffer[101]; + uint16_t index; + uint16_t perm; + uint16_t size; +} tpm_nv_definespace_cmd = { + {0x0, 0xc1, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0xcc, + 0x0, 0x18, 0, 0, 0, 0, 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x17, + }, + 12, 70, 77, +}; + +const int kWriteInfoLength = 12; +const int kNvDataPublicPermissionsOffset = 60; diff --git a/src/security/tpm/tss/tcg-1.2/tss_structures.h b/src/security/tpm/tss/tcg-1.2/tss_structures.h index 880864ee50..50fa3fbf0c 100644 --- a/src/security/tpm/tss/tcg-1.2/tss_structures.h +++ b/src/security/tpm/tss/tcg-1.2/tss_structures.h @@ -1,164 +1,69 @@ -/* This file is automatically generated */ - -const struct s_tpm_extend_cmd{ - uint8_t buffer[34]; - uint16_t pcrNum; - uint16_t inDigest; -} tpm_extend_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14, }, -10, 14, }; - -const struct s_tpm_get_random_cmd{ - uint8_t buffer[14]; - uint16_t bytesRequested; -} tpm_get_random_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x46, }, -10, }; - -const struct s_tpm_getownership_cmd{ - uint8_t buffer[22]; -} tpm_getownership_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, - 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x11, }, -}; - -const struct s_tpm_getpermissions_cmd{ - uint8_t buffer[22]; - uint16_t index; -} tpm_getpermissions_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, - 0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x4, }, -18, }; - -const struct s_tpm_getstclearflags_cmd{ - uint8_t buffer[22]; -} tpm_getstclearflags_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, - 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x9, }, -}; - -const struct s_tpm_getflags_cmd{ - uint8_t buffer[22]; -} tpm_getflags_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65, - 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x8, }, -}; - -const struct s_tpm_physicalsetdeactivated_cmd{ - uint8_t buffer[11]; - uint16_t deactivated; -} tpm_physicalsetdeactivated_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72, }, -10, }; - -const struct s_tpm_physicalenable_cmd{ - uint8_t buffer[10]; -} tpm_physicalenable_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f, }, -}; - -const struct s_tpm_physicaldisable_cmd{ - uint8_t buffer[10]; -} tpm_physicaldisable_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70, }, -}; - -const struct s_tpm_forceclear_cmd{ - uint8_t buffer[10]; -} tpm_forceclear_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d, }, -}; - -const struct s_tpm_readpubek_cmd{ - uint8_t buffer[30]; -} tpm_readpubek_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c, }, -}; - -const struct s_tpm_continueselftest_cmd{ - uint8_t buffer[10]; -} tpm_continueselftest_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53, }, -}; - -const struct s_tpm_selftestfull_cmd{ - uint8_t buffer[10]; -} tpm_selftestfull_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, }, -}; - -const struct s_tpm_resume_cmd{ - uint8_t buffer[12]; -} tpm_resume_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x2, }, -}; - -const struct s_tpm_savestate_cmd{ - uint8_t buffer[10]; -} tpm_savestate_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x98, }, -}; - -const struct s_tpm_startup_cmd{ - uint8_t buffer[12]; -} tpm_startup_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1, }, -}; - -const struct s_tpm_finalizepp_cmd{ - uint8_t buffer[12]; -} tpm_finalizepp_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0, }, -}; - -const struct s_tpm_pplock_cmd{ - uint8_t buffer[12]; -} tpm_pplock_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x4, }, -}; - -const struct s_tpm_ppenable_cmd{ - uint8_t buffer[12]; -} tpm_ppenable_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x20, }, -}; - -const struct s_tpm_ppassert_cmd{ - uint8_t buffer[12]; -} tpm_ppassert_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x8, }, -}; - -const struct s_tpm_pcr_read_cmd{ - uint8_t buffer[14]; - uint16_t pcrNum; -} tpm_pcr_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15, }, -10, }; - -const struct s_tpm_nv_read_cmd{ - uint8_t buffer[22]; - uint16_t index; - uint16_t length; -} tpm_nv_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf, }, -10, 18, }; - -const struct s_tpm_nv_write_cmd{ - uint8_t buffer[256]; - uint16_t index; - uint16_t length; - uint16_t data; -} tpm_nv_write_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, }, -10, 18, 22, }; - -const struct s_tpm_nv_definespace_cmd{ - uint8_t buffer[101]; - uint16_t index; - uint16_t perm; - uint16_t size; -} tpm_nv_definespace_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0xcc, - 0x0, 0x18, 0, 0, 0, 0, 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0x0, 0x3, 0, 0, 0, 0x1f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0, 0x17, - }, - 12, 70, 77, -}; - -const int kWriteInfoLength = 12; -const int kNvDataPublicPermissionsOffset = 60; +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Some TPM constants and type definitions for standalone compilation for use + * in the firmware + */ +#ifndef TCG1_TSS_STRUCTURES_H_ +#define TCG1_TSS_STRUCTURES_H_ + +#include +#include "../common/tss_common.h" + +#define TPM_MAX_COMMAND_SIZE 4096 +#define TPM_LARGE_ENOUGH_COMMAND_SIZE 256 /* saves space in the firmware */ +#define TPM_PUBEK_SIZE 256 + +#define TPM_NV_INDEX0 ((uint32_t)0x00000000) +#define TPM_NV_INDEX_LOCK ((uint32_t)0xffffffff) +#define TPM_NV_PER_GLOBALLOCK (((uint32_t)1)<<15) +#define TPM_NV_PER_PPWRITE (((uint32_t)1)<<0) +#define TPM_NV_PER_READ_STCLEAR (((uint32_t)1)<<31) +#define TPM_NV_PER_WRITE_STCLEAR (((uint32_t)1)<<14) + +#define TPM_TAG_RQU_COMMAND ((uint16_t) 0xc1) +#define TPM_TAG_RQU_AUTH1_COMMAND ((uint16_t) 0xc2) +#define TPM_TAG_RQU_AUTH2_COMMAND ((uint16_t) 0xc3) + +#define TPM_TAG_RSP_COMMAND ((uint16_t) 0xc4) +#define TPM_TAG_RSP_AUTH1_COMMAND ((uint16_t) 0xc5) +#define TPM_TAG_RSP_AUTH2_COMMAND ((uint16_t) 0xc6) + +typedef uint8_t TSS_BOOL; +typedef uint16_t TPM_STRUCTURE_TAG; + +typedef struct tdTPM_PERMANENT_FLAGS { + TPM_STRUCTURE_TAG tag; + TSS_BOOL disable; + TSS_BOOL ownership; + TSS_BOOL deactivated; + TSS_BOOL readPubek; + TSS_BOOL disableOwnerClear; + TSS_BOOL allowMaintenance; + TSS_BOOL physicalPresenceLifetimeLock; + TSS_BOOL physicalPresenceHWEnable; + TSS_BOOL physicalPresenceCMDEnable; + TSS_BOOL CEKPUsed; + TSS_BOOL TPMpost; + TSS_BOOL TPMpostLock; + TSS_BOOL FIPS; + TSS_BOOL Operator; + TSS_BOOL enableRevokeEK; + TSS_BOOL nvLocked; + TSS_BOOL readSRKPub; + TSS_BOOL tpmEstablished; + TSS_BOOL maintenanceDone; + TSS_BOOL disableFullDALogicInfo; +} TPM_PERMANENT_FLAGS; + +typedef struct tdTPM_STCLEAR_FLAGS { + TPM_STRUCTURE_TAG tag; + TSS_BOOL deactivated; + TSS_BOOL disableForceClear; + TSS_BOOL physicalPresence; + TSS_BOOL physicalPresenceLock; + TSS_BOOL bGlobalLock; +} TPM_STCLEAR_FLAGS; + +#endif /* TCG1_TSS_STRUCTURES_H_ */ diff --git a/src/security/tpm/tss/tcg-2.0/tss.c b/src/security/tpm/tss/tcg-2.0/tss.c index cde9ea2946..7db746f4e1 100644 --- a/src/security/tpm/tss/tcg-2.0/tss.c +++ b/src/security/tpm/tss/tcg-2.0/tss.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include "tss_structures.h" #include "tss_marshaling.h" @@ -21,7 +21,7 @@ * TPM2 specification. */ -static void *tpm_process_command(TPM_CC command, void *command_body) +void *tpm_process_command(TPM_CC command, void *command_body) { struct obuf ob; struct ibuf ib; @@ -53,13 +53,6 @@ static void *tpm_process_command(TPM_CC command, void *command_body) return tpm_unmarshal_response(command, &ib); } - -uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags) -{ - printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__); - return TPM_SUCCESS; -} - static uint32_t tlcl_send_startup(TPM_SU type) { struct tpm2_startup startup; @@ -139,30 +132,6 @@ uint32_t tlcl_force_clear(void) return TPM_SUCCESS; } -uint32_t tlcl_get_flags(uint8_t *disable, uint8_t *deactivated, - uint8_t *nvlocked) -{ - /* - * TPM2 does not map directly into these flags TPM1.2 based firmware - * expects to be able to retrieve. - * - * In any case, if any of these conditions are present, the following - * firmware flow would be interrupted and will have a chance to report - * an error. Let's just hardcode an "All OK" response for now. - */ - - if (disable) - *disable = 0; - - if (nvlocked) - *nvlocked = 1; - - if (deactivated) - *deactivated = 0; - - return TPM_SUCCESS; -} - static uint8_t tlcl_init_done CAR_GLOBAL; /* This function is called directly by vboot, uses vboot return types. */ @@ -247,18 +216,6 @@ uint32_t tlcl_self_test_full(void) return TPM_SUCCESS; } -uint32_t tlcl_set_deactivated(uint8_t flag) -{ - printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__); - return TPM_SUCCESS; -} - -uint32_t tlcl_set_enable(void) -{ - printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__); - return TPM_SUCCESS; -} - uint32_t tlcl_lock_nv_write(uint32_t index) { struct tpm2_response *response; @@ -306,29 +263,12 @@ uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length) return TPM_SUCCESS; } -uint32_t tlcl_define_space(uint32_t space_index, size_t space_size) +uint32_t tlcl_define_space(uint32_t space_index, size_t space_size, + const TPMA_NV nv_attributes, + const uint8_t *nv_policy, size_t nv_policy_size) { struct tpm2_nv_define_space_cmd nvds_cmd; struct tpm2_response *response; - /* - * Different sets of NVRAM space attributes apply to the "ro" spaces, - * i.e. those which should not be possible to delete or modify once - * the RO exits, and the rest of the NVRAM spaces. - */ - const TPMA_NV ro_space_attributes = { - .TPMA_NV_PPWRITE = 1, - .TPMA_NV_AUTHREAD = 1, - .TPMA_NV_PPREAD = 1, - .TPMA_NV_PLATFORMCREATE = 1, - .TPMA_NV_WRITE_STCLEAR = 1, - .TPMA_NV_POLICY_DELETE = 1, - }; - const TPMA_NV default_space_attributes = { - .TPMA_NV_PPWRITE = 1, - .TPMA_NV_AUTHREAD = 1, - .TPMA_NV_PPREAD = 1, - .TPMA_NV_PLATFORMCREATE = 1, - }; /* Prepare the define space command structure. */ memset(&nvds_cmd, 0, sizeof(nvds_cmd)); @@ -336,37 +276,21 @@ uint32_t tlcl_define_space(uint32_t space_index, size_t space_size) nvds_cmd.publicInfo.dataSize = space_size; nvds_cmd.publicInfo.nvIndex = HR_NV_INDEX + space_index; nvds_cmd.publicInfo.nameAlg = TPM_ALG_SHA256; + nvds_cmd.publicInfo.attributes = nv_attributes; - /* RO only NV spaces should be impossible to destroy. */ - if ((space_index == FIRMWARE_NV_INDEX) || - (space_index == REC_HASH_NV_INDEX)) { - /* - * This policy digest was obtained using TPM2_PolicyPCR - * selecting only PCR_0 with a value of all zeros. - */ - const uint8_t pcr0_unchanged_policy[] = { - 0x09, 0x93, 0x3C, 0xCE, 0xEB, 0xB4, 0x41, 0x11, - 0x18, 0x81, 0x1D, 0xD4, 0x47, 0x78, 0x80, 0x08, - 0x88, 0x86, 0x62, 0x2D, 0xD7, 0x79, 0x94, 0x46, - 0x62, 0x26, 0x68, 0x8E, 0xEE, 0xE6, 0x6A, 0xA1 - }; - - nvds_cmd.publicInfo.attributes = ro_space_attributes; - /* - * Use policy digest based on default pcr0 value. This makes - * sure that the space can not be deleted as soon as PCR0 - * value has been extended from default. - */ - nvds_cmd.publicInfo.authPolicy.t.buffer = pcr0_unchanged_policy; - nvds_cmd.publicInfo.authPolicy.t.size = - sizeof(pcr0_unchanged_policy); - } else { - nvds_cmd.publicInfo.attributes = default_space_attributes; + /* + * Use policy digest based on default pcr0 value. This makes + * sure that the space can not be deleted as soon as PCR0 + * value has been extended from default. + */ + if (nv_policy && nv_policy_size) { + nvds_cmd.publicInfo.authPolicy.t.buffer = nv_policy; + nvds_cmd.publicInfo.authPolicy.t.size = nv_policy_size; } response = tpm_process_command(TPM2_NV_DefineSpace, &nvds_cmd); - printk(BIOS_INFO, "%s: response is %x\n", - __func__, response ? response->hdr.tpm_code : -1); + printk(BIOS_INFO, "%s: response is %x\n", __func__, + response ? response->hdr.tpm_code : -1); if (!response) return TPM_E_NO_DEVICE; @@ -397,42 +321,3 @@ uint32_t tlcl_disable_platform_hierarchy(void) return TPM_SUCCESS; } - -uint32_t tlcl_cr50_enable_nvcommits(void) -{ - uint16_t sub_command = TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS; - struct tpm2_response *response; - - printk(BIOS_INFO, "Enabling cr50 nvmem commmits\n"); - - response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &sub_command); - - if (response == NULL || (response && response->hdr.tpm_code)) { - if (response) - printk(BIOS_INFO, "%s: failed %x\n", __func__, - response->hdr.tpm_code); - else - printk(BIOS_INFO, "%s: failed\n", __func__); - return TPM_E_IOERROR; - } - return TPM_SUCCESS; -} - -uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms, - uint8_t *num_restored_headers) -{ - struct tpm2_response *response; - uint16_t command_body[] = { - TPM2_CR50_SUB_CMD_TURN_UPDATE_ON, timeout_ms - }; - - printk(BIOS_INFO, "Checking cr50 for pending updates\n"); - - response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, command_body); - - if (!response || response->hdr.tpm_code) - return TPM_E_INTERNAL_INCONSISTENCY; - - *num_restored_headers = response->vcr.num_restored_headers; - return TPM_SUCCESS; -} diff --git a/src/security/tpm/tss/tcg-2.0/tss_marshaling.c b/src/security/tpm/tss/tcg-2.0/tss_marshaling.c index b1d666362b..86f2231c3f 100644 --- a/src/security/tpm/tss/tcg-2.0/tss_marshaling.c +++ b/src/security/tpm/tss/tcg-2.0/tss_marshaling.c @@ -11,6 +11,7 @@ #include #include "tss_marshaling.h" +#include static uint16_t tpm_tag CAR_GLOBAL; /* Depends on the command type. */ diff --git a/src/security/tpm/tss/tcg-2.0/tss_structures.h b/src/security/tpm/tss/tcg-2.0/tss_structures.h index 962e20ca8f..11fb71484c 100644 --- a/src/security/tpm/tss/tcg-2.0/tss_structures.h +++ b/src/security/tpm/tss/tcg-2.0/tss_structures.h @@ -14,16 +14,18 @@ #include #include #include - -#include +#include "../common/tss_common.h" /* This should be plenty for what firmware needs. */ #define TPM_BUFFER_SIZE 256 +/* Some TPM2 return codes used in this library. */ +#define TPM2_RC_SUCCESS 0 +#define TPM2_RC_NV_DEFINED 0x14c + /* Basic TPM2 types. */ typedef uint16_t TPM_SU; typedef uint16_t TPM_ALG_ID; -typedef uint32_t TPM_CC; typedef uint32_t TPM_HANDLE; typedef uint32_t TPM_RC; typedef uint8_t TPMI_YES_NO; @@ -47,6 +49,8 @@ typedef TPM_HANDLE TPM_RH; #define TPM_RS_PW 0x40000009 #define TPM_RH_PLATFORM 0x4000000C +typedef uint32_t TPM_CC; + typedef struct { uint16_t size; uint8_t *buffer; @@ -74,13 +78,6 @@ struct tpm_header { /* TPM2 specifies vendor commands need to have this bit set. Vendor command space is defined by the lower 16 bits. */ #define TPM_CC_VENDOR_BIT_MASK 0x20000000 -/* FIXME: below is not enough to differentiate between vendors commands - of numerous devices. However, the current tpm2 APIs aren't very amenable - to extending generically because the marshaling code is assuming all - knowledge of all commands. */ -#define TPM2_CR50_VENDOR_COMMAND ((TPM_CC)(TPM_CC_VENDOR_BIT_MASK | 0)) -#define TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS (21) -#define TPM2_CR50_SUB_CMD_TURN_UPDATE_ON (24) /* Startup values. */ #define TPM_SU_CLEAR 0 diff --git a/src/security/tpm/tss/vendor/cr50/Kconfig b/src/security/tpm/tss/vendor/cr50/Kconfig new file mode 100644 index 0000000000..4d40c08da6 --- /dev/null +++ b/src/security/tpm/tss/vendor/cr50/Kconfig @@ -0,0 +1,28 @@ +## This file is part of the coreboot project. +## +## Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +## Copyright (C) 2018 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. +## + +config TPM_CR50 + bool + default y if MAINBOARD_HAS_I2C_TPM_CR50 || MAINBOARD_HAS_SPI_TPM_CR50 + select POWER_OFF_ON_CR50_UPDATE if ARCH_X86 + +if TPM_CR50 + +config POWER_OFF_ON_CR50_UPDATE + bool + help + Power off machine while waiting for CR50 update to take effect. + +endif diff --git a/src/security/tpm/tss/vendor/cr50/Makefile.inc b/src/security/tpm/tss/vendor/cr50/Makefile.inc new file mode 100644 index 0000000000..8bacafd023 --- /dev/null +++ b/src/security/tpm/tss/vendor/cr50/Makefile.inc @@ -0,0 +1,5 @@ +ramstage-y += cr50.c +romstage-y += cr50.c +postcar-y += cr50.c + +verstage-$(CONFIG_VBOOT) += cr50.c diff --git a/src/security/tpm/tss/vendor/cr50/cr50.c b/src/security/tpm/tss/vendor/cr50/cr50.c new file mode 100644 index 0000000000..90f796379c --- /dev/null +++ b/src/security/tpm/tss/vendor/cr50/cr50.c @@ -0,0 +1,54 @@ +/* + * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "../../tcg-2.0/tss_marshaling.h" + +uint32_t tlcl_cr50_enable_nvcommits(void) +{ + uint16_t sub_command = TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS; + struct tpm2_response *response; + + printk(BIOS_INFO, "Enabling cr50 nvmem commmits\n"); + + response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &sub_command); + + if (response == NULL || (response && response->hdr.tpm_code)) { + if (response) + printk(BIOS_INFO, "%s: failed %x\n", __func__, + response->hdr.tpm_code); + else + printk(BIOS_INFO, "%s: failed\n", __func__); + return TPM_E_IOERROR; + } + return TPM_SUCCESS; +} + +uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms, + uint8_t *num_restored_headers) +{ + struct tpm2_response *response; + uint16_t command_body[] = { + TPM2_CR50_SUB_CMD_TURN_UPDATE_ON, timeout_ms + }; + + printk(BIOS_INFO, "Checking cr50 for pending updates\n"); + + response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, command_body); + + if (!response || response->hdr.tpm_code) + return TPM_E_INTERNAL_INCONSISTENCY; + + *num_restored_headers = response->vcr.num_restored_headers; + return TPM_SUCCESS; +} diff --git a/src/security/tpm/tss/vendor/cr50/cr50.h b/src/security/tpm/tss/vendor/cr50/cr50.h new file mode 100644 index 0000000000..9bf3bd5f79 --- /dev/null +++ b/src/security/tpm/tss/vendor/cr50/cr50.h @@ -0,0 +1,47 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Copyright 2018 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. + */ +#ifndef CR50_TSS_STRUCTURES_H_ +#define CR50_TSS_STRUCTURES_H_ + +#include + +/* FIXME: below is not enough to differentiate between vendors commands + of numerous devices. However, the current tpm2 APIs aren't very amenable + to extending generically because the marshaling code is assuming all + knowledge of all commands. */ +#define TPM2_CR50_VENDOR_COMMAND ((TPM_CC)(TPM_CC_VENDOR_BIT_MASK | 0)) +#define TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS (21) +#define TPM2_CR50_SUB_CMD_TURN_UPDATE_ON (24) + +/** + * CR50 specific tpm command to enable nvmem commits before internal timeout + * expires. + */ +uint32_t tlcl_cr50_enable_nvcommits(void); + +/** + * CR50 specific tpm command to restore header(s) of the dormant RO/RW + * image(s) and in case there indeed was a dormant image, trigger reboot after + * the timeout milliseconds. Note that timeout of zero means "NO REBOOT", not + * "IMMEDIATE REBOOT". + * + * Return value indicates success or failure of accessing the TPM; in case of + * success the number of restored headers is saved in num_restored_headers. + */ +uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms, + uint8_t *num_restored_headers); + +#endif /* CR50_TSS_STRUCTURES_H_ */ diff --git a/src/security/tpm/tss_constants.h b/src/security/tpm/tss_constants.h deleted file mode 100644 index 937e553969..0000000000 --- a/src/security/tpm/tss_constants.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Some TPM constants and type definitions for standalone compilation for use - * in the firmware - */ -#ifndef VBOOT_REFERENCE_TSS_CONSTANTS_H_ -#define VBOOT_REFERENCE_TSS_CONSTANTS_H_ -#include - -#define TPM_MAX_COMMAND_SIZE 4096 -#define TPM_LARGE_ENOUGH_COMMAND_SIZE 256 /* saves space in the firmware */ -#define TPM_PUBEK_SIZE 256 -#define TPM_PCR_DIGEST 20 - -#define TPM_E_NON_FATAL 0x800 - -#define TPM_SUCCESS ((uint32_t)0x00000000) - -#define TPM_E_AREA_LOCKED ((uint32_t)0x0000003c) -#define TPM_E_BADINDEX ((uint32_t)0x00000002) -#define TPM_E_BAD_PRESENCE ((uint32_t)0x0000002d) -#define TPM_E_IOERROR ((uint32_t)0x0000001f) -#define TPM_E_INVALID_POSTINIT ((uint32_t)0x00000026) -#define TPM_E_MAXNVWRITES ((uint32_t)0x00000048) -#define TPM_E_OWNER_SET ((uint32_t)0x00000014) - -#define TPM_E_NEEDS_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 1)) -#define TPM_E_DOING_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 2)) - -#define TPM_E_ALREADY_INITIALIZED ((uint32_t)0x00005000) /* vboot local */ -#define TPM_E_INTERNAL_INCONSISTENCY ((uint32_t)0x00005001) /* vboot local */ -#define TPM_E_MUST_REBOOT ((uint32_t)0x00005002) /* vboot local */ -#define TPM_E_CORRUPTED_STATE ((uint32_t)0x00005003) /* vboot local */ -#define TPM_E_COMMUNICATION_ERROR ((uint32_t)0x00005004) /* vboot local */ -#define TPM_E_RESPONSE_TOO_LARGE ((uint32_t)0x00005005) /* vboot local */ -#define TPM_E_NO_DEVICE ((uint32_t)0x00005006) /* vboot local */ -#define TPM_E_INPUT_TOO_SMALL ((uint32_t)0x00005007) /* vboot local */ -#define TPM_E_WRITE_FAILURE ((uint32_t)0x00005008) /* vboot local */ -#define TPM_E_READ_EMPTY ((uint32_t)0x00005009) /* vboot local */ -#define TPM_E_READ_FAILURE ((uint32_t)0x0000500a) /* vboot local */ -#define TPM_E_NV_DEFINED ((uint32_t)0x0000500b) /* vboot local */ - -#define TPM_NV_INDEX0 ((uint32_t)0x00000000) -#define TPM_NV_INDEX_LOCK ((uint32_t)0xffffffff) -#define TPM_NV_PER_GLOBALLOCK (((uint32_t)1)<<15) -#define TPM_NV_PER_PPWRITE (((uint32_t)1)<<0) -#define TPM_NV_PER_READ_STCLEAR (((uint32_t)1)<<31) -#define TPM_NV_PER_WRITE_STCLEAR (((uint32_t)1)<<14) - -#define TPM_TAG_RQU_COMMAND ((uint16_t) 0xc1) -#define TPM_TAG_RQU_AUTH1_COMMAND ((uint16_t) 0xc2) -#define TPM_TAG_RQU_AUTH2_COMMAND ((uint16_t) 0xc3) - -#define TPM_TAG_RSP_COMMAND ((uint16_t) 0xc4) -#define TPM_TAG_RSP_AUTH1_COMMAND ((uint16_t) 0xc5) -#define TPM_TAG_RSP_AUTH2_COMMAND ((uint16_t) 0xc6) - -/* Some TPM2 return codes used in this library. */ -#define TPM2_RC_SUCCESS 0 -#define TPM2_RC_NV_DEFINED 0x14c - -typedef uint8_t TSS_BOOL; -typedef uint16_t TPM_STRUCTURE_TAG; - -typedef struct tdTPM_PERMANENT_FLAGS { - TPM_STRUCTURE_TAG tag; - TSS_BOOL disable; - TSS_BOOL ownership; - TSS_BOOL deactivated; - TSS_BOOL readPubek; - TSS_BOOL disableOwnerClear; - TSS_BOOL allowMaintenance; - TSS_BOOL physicalPresenceLifetimeLock; - TSS_BOOL physicalPresenceHWEnable; - TSS_BOOL physicalPresenceCMDEnable; - TSS_BOOL CEKPUsed; - TSS_BOOL TPMpost; - TSS_BOOL TPMpostLock; - TSS_BOOL FIPS; - TSS_BOOL Operator; - TSS_BOOL enableRevokeEK; - TSS_BOOL nvLocked; - TSS_BOOL readSRKPub; - TSS_BOOL tpmEstablished; - TSS_BOOL maintenanceDone; - TSS_BOOL disableFullDALogicInfo; -} TPM_PERMANENT_FLAGS; - -typedef struct tdTPM_STCLEAR_FLAGS { - TPM_STRUCTURE_TAG tag; - TSS_BOOL deactivated; - TSS_BOOL disableForceClear; - TSS_BOOL physicalPresence; - TSS_BOOL physicalPresenceLock; - TSS_BOOL bGlobalLock; -} TPM_STCLEAR_FLAGS; - -#endif /* VBOOT_REFERENCE_TSS_CONSTANTS_H_ */ diff --git a/src/security/tpm/tss_error_messages.h b/src/security/tpm/tss_error_messages.h deleted file mode 100644 index d5978609c7..0000000000 --- a/src/security/tpm/tss_error_messages.h +++ /dev/null @@ -1,255 +0,0 @@ -/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* TPM error codes. - * - * Copy-pasted and lightly edited from TCG TPM Main Part 2 TPM Structures - * Version 1.2 Level 2 Revision 103 26 October 2006 Draft. - */ - -#ifndef TSS_ERROR_MESSAGES_H_ -#define TSS_ERROR_MESSAGES_H_ - -#define TPM_E_BASE 0x0 -#define TPM_E_NON_FATAL 0x800 - -typedef struct tpm_error_info { - const char *name; - uint32_t code; - const char *description; -} tpm_error_info; - -tpm_error_info tpm_error_table[] = { - {"TPM_AUTHFAIL", TPM_E_BASE + 1, - "Authentication failed"}, - {"TPM_BADINDEX", TPM_E_BASE + 2, - "The index to a PCR, DIR or other register is incorrect"}, - {"TPM_BAD_PARAMETER", TPM_E_BASE + 3, - "One or more parameter is bad"}, - {"TPM_AUDITFAILURE", TPM_E_BASE + 4, - "An operation completed successfully\n\ -but the auditing of that operation failed"}, - {"TPM_CLEAR_DISABLED", TPM_E_BASE + 5, - "The clear disable flag is set and all clear operations now require\n\ -physical access"}, - {"TPM_DEACTIVATED", TPM_E_BASE + 6, - "The TPM is deactivated"}, - {"TPM_DISABLED", TPM_E_BASE + 7, - "The TPM is disabled"}, - {"TPM_DISABLED_CMD", TPM_E_BASE + 8, - "The target command has been disabled"}, - {"TPM_FAIL", TPM_E_BASE + 9, - "The operation failed"}, - {"TPM_BAD_ORDINAL", TPM_E_BASE + 10, - "The ordinal was unknown or inconsistent"}, - {"TPM_INSTALL_DISABLED", TPM_E_BASE + 11, - "The ability to install an owner is disabled"}, - {"TPM_INVALID_KEYHANDLE", TPM_E_BASE + 12, - "The key handle can not be interpreted"}, - {"TPM_KEYNOTFOUND", TPM_E_BASE + 13, - "The key handle points to an invalid key"}, - {"TPM_INAPPROPRIATE_ENC", TPM_E_BASE + 14, - "Unacceptable encryption scheme"}, - {"TPM_MIGRATEFAIL", TPM_E_BASE + 15, - "Migration authorization failed"}, - {"TPM_INVALID_PCR_INFO", TPM_E_BASE + 16, - "PCR information could not be interpreted"}, - {"TPM_NOSPACE", TPM_E_BASE + 17, - "No room to load key"}, - {"TPM_NOSRK", TPM_E_BASE + 18, - "There is no SRK set"}, - {"TPM_NOTSEALED_BLOB", TPM_E_BASE + 19, - "An encrypted blob is invalid or was not created by this TPM"}, - {"TPM_OWNER_SET", TPM_E_BASE + 20, - "There is already an Owner"}, - {"TPM_RESOURCES", TPM_E_BASE + 21, - "The TPM has insufficient internal resources to perform the requested \ -action"}, - {"TPM_SHORTRANDOM", TPM_E_BASE + 22, - "A random string was too short"}, - {"TPM_SIZE", TPM_E_BASE + 23, - "The TPM does not have the space to perform the operation"}, - {"TPM_WRONGPCRVAL", TPM_E_BASE + 24, - "The named PCR value does not match the current PCR value"}, - {"TPM_BAD_PARAM_SIZE", TPM_E_BASE + 25, - "The paramSize argument to the command has the incorrect value"}, - {"TPM_SHA_THREAD", TPM_E_BASE + 26, - "There is no existing SHA-1 thread"}, - {"TPM_SHA_ERROR", TPM_E_BASE + 27, - "The calculation is unable to proceed because the existing SHA-1\n\ -thread has already encountered an error"}, - {"TPM_FAILEDSELFTEST", TPM_E_BASE + 28, - "Self-test has failed and the TPM has shutdown"}, - {"TPM_AUTH2FAIL", TPM_E_BASE + 29, - "The authorization for the second key in a 2 key function\n\ -failed authorization"}, - {"TPM_BADTAG", TPM_E_BASE + 30, - "The tag value sent to for a command is invalid"}, - {"TPM_IOERROR", TPM_E_BASE + 31, - "An IO error occurred transmitting information to the TPM"}, - {"TPM_ENCRYPT_ERROR", TPM_E_BASE + 32, - "The encryption process had a problem"}, - {"TPM_DECRYPT_ERROR", TPM_E_BASE + 33, - "The decryption process did not complete"}, - {"TPM_INVALID_AUTHHANDLE", TPM_E_BASE + 34, - "An invalid handle was used"}, - {"TPM_NO_ENDORSEMENT", TPM_E_BASE + 35, - "The TPM does not a EK installed"}, - {"TPM_INVALID_KEYUSAGE", TPM_E_BASE + 36, - "The usage of a key is not allowed"}, - {"TPM_WRONG_ENTITYTYPE", TPM_E_BASE + 37, - "The submitted entity type is not allowed"}, - {"TPM_INVALID_POSTINIT", TPM_E_BASE + 38, - "The command was received in the wrong sequence relative to TPM_Init\n\ -and a subsequent TPM_Startup"}, - {"TPM_INAPPROPRIATE_SIG", TPM_E_BASE + 39, - "Signed data cannot include additional DER information"}, - {"TPM_BAD_KEY_PROPERTY", TPM_E_BASE + 40, - "The key properties in TPM_KEY_PARMs are not supported by this TPM"}, - {"TPM_BAD_MIGRATION", TPM_E_BASE + 41, - "The migration properties of this key are incorrect"}, - {"TPM_BAD_SCHEME", TPM_E_BASE + 42, - "The signature or encryption scheme for this key is incorrect or not\n\ -permitted in this situation"}, - {"TPM_BAD_DATASIZE", TPM_E_BASE + 43, - "The size of the data (or blob) parameter is bad or inconsistent\n\ -with the referenced key"}, - {"TPM_BAD_MODE", TPM_E_BASE + 44, - "A mode parameter is bad, such as capArea or subCapArea for\n\ -TPM_GetCapability, physicalPresence parameter for TPM_PhysicalPresence,\n\ -or migrationType for, TPM_CreateMigrationBlob"}, - {"TPM_BAD_PRESENCE", TPM_E_BASE + 45, - "Either the physicalPresence or physicalPresenceLock bits\n\ -have the wrong value"}, - {"TPM_BAD_VERSION", TPM_E_BASE + 46, - "The TPM cannot perform this version of the capability"}, - {"TPM_NO_WRAP_TRANSPORT", TPM_E_BASE + 47, - "The TPM does not allow for wrapped transport sessions"}, - {"TPM_AUDITFAIL_UNSUCCESSFUL", TPM_E_BASE + 48, - "TPM audit construction failed and the underlying command\n\ -was returning a failure code also"}, - {"TPM_AUDITFAIL_SUCCESSFUL", TPM_E_BASE + 49, - "TPM audit construction failed and the underlying command\n\ -was returning success"}, - {"TPM_NOTRESETABLE", TPM_E_BASE + 50, - "Attempt to reset a PCR register that does not have the resettable \ -attribute"}, - {"TPM_NOTLOCAL", TPM_E_BASE + 51, - "Attempt to reset a PCR register that requires locality\n\ -and locality modifier not part of command transport"}, - {"TPM_BAD_TYPE", TPM_E_BASE + 52, - "Make identity blob not properly typed"}, - {"TPM_INVALID_RESOURCE", TPM_E_BASE + 53, - "When saving context identified resource type does not match actual \ -resource"}, - {"TPM_NOTFIPS", TPM_E_BASE + 54, - "The TPM is attempting to execute a command only available when in \ -FIPS mode"}, - {"TPM_INVALID_FAMILY", TPM_E_BASE + 55, - "The command is attempting to use an invalid family ID"}, - {"TPM_NO_NV_PERMISSION", TPM_E_BASE + 56, - "The permission to manipulate the NV storage is not available"}, - {"TPM_REQUIRES_SIGN", TPM_E_BASE + 57, - "The operation requires a signed command"}, - {"TPM_KEY_NOTSUPPORTED", TPM_E_BASE + 58, - "Wrong operation to load an NV key"}, - {"TPM_AUTH_CONFLICT", TPM_E_BASE + 59, - "NV_LoadKey blob requires both owner and blob authorization"}, - {"TPM_AREA_LOCKED", TPM_E_BASE + 60, - "The NV area is locked and not writable"}, - {"TPM_BAD_LOCALITY", TPM_E_BASE + 61, - "The locality is incorrect for the attempted operation"}, - {"TPM_READ_ONLY", TPM_E_BASE + 62, - "The NV area is read only and can't be written to"}, - {"TPM_PER_NOWRITE", TPM_E_BASE + 63, - "There is no protection on the write to the NV area"}, - {"TPM_FAMILYCOUNT", TPM_E_BASE + 64, - "The family count value does not match"}, - {"TPM_WRITE_LOCKED", TPM_E_BASE + 65, - "The NV area has already been written to"}, - {"TPM_BAD_ATTRIBUTES", TPM_E_BASE + 66, - "The NV area attributes conflict"}, - {"TPM_INVALID_STRUCTURE", TPM_E_BASE + 67, - "The structure tag and version are invalid or inconsistent"}, - {"TPM_KEY_OWNER_CONTROL", TPM_E_BASE + 68, - "The key is under control of the TPM Owner and can only be evicted\n\ -by the TPM Owner"}, - {"TPM_BAD_COUNTER", TPM_E_BASE + 69, - "The counter handle is incorrect"}, - {"TPM_NOT_FULLWRITE", TPM_E_BASE + 70, - "The write is not a complete write of the area"}, - {"TPM_CONTEXT_GAP", TPM_E_BASE + 71, - "The gap between saved context counts is too large"}, - {"TPM_MAXNVWRITES", TPM_E_BASE + 72, - "The maximum number of NV writes without an owner has been exceeded"}, - {"TPM_NOOPERATOR", TPM_E_BASE + 73, - "No operator AuthData value is set"}, - {"TPM_RESOURCEMISSING", TPM_E_BASE + 74, - "The resource pointed to by context is not loaded"}, - {"TPM_DELEGATE_LOCK", TPM_E_BASE + 75, - "The delegate administration is locked"}, - {"TPM_DELEGATE_FAMILY", TPM_E_BASE + 76, - "Attempt to manage a family other then the delegated family"}, - {"TPM_DELEGATE_ADMIN", TPM_E_BASE + 77, - "Delegation table management not enabled"}, - {"TPM_TRANSPORT_NOTEXCLUSIVE", TPM_E_BASE + 78, - "There was a command executed outside of an exclusive transport \ -session"}, - {"TPM_OWNER_CONTROL", TPM_E_BASE + 79, - "Attempt to context save a owner evict controlled key"}, - {"TPM_DAA_RESOURCES", TPM_E_BASE + 80, - "The DAA command has no resources available to execute the command"}, - {"TPM_DAA_INPUT_DATA0", TPM_E_BASE + 81, - "The consistency check on DAA parameter inputData0 has failed"}, - {"TPM_DAA_INPUT_DATA1", TPM_E_BASE + 82, - "The consistency check on DAA parameter inputData1 has failed"}, - {"TPM_DAA_ISSUER_SETTINGS", TPM_E_BASE + 83, - "The consistency check on DAA_issuerSettings has failed"}, - {"TPM_DAA_TPM_SETTINGS", TPM_E_BASE + 84, - "The consistency check on DAA_tpmSpecific has failed"}, - {"TPM_DAA_STAGE", TPM_E_BASE + 85, - "The atomic process indicated by the submitted DAA command is not\n\ -the expected process"}, - {"TPM_DAA_ISSUER_VALIDITY", TPM_E_BASE + 86, - "The issuer's validity check has detected an inconsistency"}, - {"TPM_DAA_WRONG_W", TPM_E_BASE + 87, - "The consistency check on w has failed"}, - {"TPM_BAD_HANDLE", TPM_E_BASE + 88, - "The handle is incorrect"}, - {"TPM_BAD_DELEGATE", TPM_E_BASE + 89, - "Delegation is not correct"}, - {"TPM_BADCONTEXT", TPM_E_BASE + 90, - "The context blob is invalid"}, - {"TPM_TOOMANYCONTEXTS", TPM_E_BASE + 91, - "Too many contexts held by the TPM"}, - {"TPM_MA_TICKET_SIGNATURE", TPM_E_BASE + 92, - "Migration authority signature validation failure"}, - {"TPM_MA_DESTINATION", TPM_E_BASE + 93, - "Migration destination not authenticated"}, - {"TPM_MA_SOURCE", TPM_E_BASE + 94, - "Migration source incorrect"}, - {"TPM_MA_AUTHORITY", TPM_E_BASE + 95, - "Incorrect migration authority"}, - {"TPM_PERMANENTEK", TPM_E_BASE + 97, - "Attempt to revoke the EK and the EK is not revocable"}, - {"TPM_BAD_SIGNATURE", TPM_E_BASE + 98, - "Bad signature of CMK ticket"}, - {"TPM_NOCONTEXTSPACE", TPM_E_BASE + 99, - "There is no room in the context list for additional contexts"}, - {"TPM_RETRY", TPM_E_BASE + TPM_E_NON_FATAL, - "The TPM is too busy to respond to the command immediately, but\n\ -the command could be resubmitted at a later time. The TPM MAY\n\ -return TPM_RETRY for any command at any time"}, - {"TPM_NEEDS_SELFTEST", TPM_E_BASE + TPM_E_NON_FATAL + 1, - "TPM_ContinueSelfTest has not been run"}, - {"TPM_DOING_SELFTEST", TPM_E_BASE + TPM_E_NON_FATAL + 2, - "The TPM is currently executing the actions of TPM_ContinueSelfTest\n\ -because the ordinal required resources that have not been tested"}, - {"TPM_DEFEND_LOCK_RUNNING", TPM_E_BASE + TPM_E_NON_FATAL + 3, - "The TPM is defending against dictionary attacks and is in some\n\ -time-out period"}, -}; - -#endif /* TSS_ERROR_MESSAGES_H_ */ diff --git a/src/security/tpm/tss_errors.h b/src/security/tpm/tss_errors.h new file mode 100644 index 0000000000..e2f1486315 --- /dev/null +++ b/src/security/tpm/tss_errors.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* TPM error codes. + * + * Copy-pasted and lightly edited from TCG TPM Main Part 2 TPM Structures + * Version 1.2 Level 2 Revision 103 26 October 2006 Draft. + */ + +#ifndef TSS_ERRORS_H_ +#define TSS_ERRORS_H_ + +#define TPM_E_BASE 0x0 +#define TPM_E_NON_FATAL 0x800 + +#define TPM_E_AREA_LOCKED ((uint32_t)0x0000003c) +#define TPM_E_BADINDEX ((uint32_t)0x00000002) +#define TPM_E_BAD_PRESENCE ((uint32_t)0x0000002d) +#define TPM_E_IOERROR ((uint32_t)0x0000001f) +#define TPM_E_INVALID_POSTINIT ((uint32_t)0x00000026) +#define TPM_E_MAXNVWRITES ((uint32_t)0x00000048) +#define TPM_E_OWNER_SET ((uint32_t)0x00000014) + +#define TPM_E_NEEDS_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 1)) +#define TPM_E_DOING_SELFTEST ((uint32_t)(TPM_E_NON_FATAL + 2)) + +#define TPM_E_ALREADY_INITIALIZED ((uint32_t)0x00005000) /* vboot local */ +#define TPM_E_INTERNAL_INCONSISTENCY ((uint32_t)0x00005001) /* vboot local */ +#define TPM_E_MUST_REBOOT ((uint32_t)0x00005002) /* vboot local */ +#define TPM_E_CORRUPTED_STATE ((uint32_t)0x00005003) /* vboot local */ +#define TPM_E_COMMUNICATION_ERROR ((uint32_t)0x00005004) /* vboot local */ +#define TPM_E_RESPONSE_TOO_LARGE ((uint32_t)0x00005005) /* vboot local */ +#define TPM_E_NO_DEVICE ((uint32_t)0x00005006) /* vboot local */ +#define TPM_E_INPUT_TOO_SMALL ((uint32_t)0x00005007) /* vboot local */ +#define TPM_E_WRITE_FAILURE ((uint32_t)0x00005008) /* vboot local */ +#define TPM_E_READ_EMPTY ((uint32_t)0x00005009) /* vboot local */ +#define TPM_E_READ_FAILURE ((uint32_t)0x0000500a) /* vboot local */ +#define TPM_E_NV_DEFINED ((uint32_t)0x0000500b) /* vboot local */ + +#endif /* TSS_ERRORS_H_ */ diff --git a/src/security/vboot/Kconfig b/src/security/vboot/Kconfig index 0139d25599..e13101b6be 100644 --- a/src/security/vboot/Kconfig +++ b/src/security/vboot/Kconfig @@ -17,10 +17,7 @@ menu "Verified Boot (vboot)" config VBOOT bool "Verify firmware with vboot." default n - select TPM if !MAINBOARD_HAS_TPM2 && !VBOOT_MOCK_SECDATA - select TPM2 if MAINBOARD_HAS_TPM2 && !VBOOT_MOCK_SECDATA - select TPM_INIT_FAILURE_IS_FATAL if PC80_SYSTEM && LPC_TPM - select SKIP_TPM_STARTUP_ON_NORMAL_BOOT if PC80_SYSTEM && LPC_TPM + select VBOOT_MOCK_SECDATA if !TPM1 && !TPM2 depends on HAVE_HARD_RESET help Enabling VBOOT will use vboot to verify the components of the firmware diff --git a/src/security/vboot/antirollback.h b/src/security/vboot/antirollback.h new file mode 100644 index 0000000000..be42f009e7 --- /dev/null +++ b/src/security/vboot/antirollback.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Functions for querying, manipulating and locking rollback indices + * stored in the TPM NVRAM. + */ + +#ifndef ANTIROLLBACK_H_ +#define ANTIROLLBACK_H_ + +#include +#include + +struct vb2_context; +enum vb2_pcr_digest; + +/* TPM NVRAM location indices. */ +#define FIRMWARE_NV_INDEX 0x1007 +#define KERNEL_NV_INDEX 0x1008 +/* 0x1009 used to be used as a backup space. Think of conflicts if you + * want to use 0x1009 for something else. */ +#define BACKUP_NV_INDEX 0x1009 +#define FWMP_NV_INDEX 0x100a +#define REC_HASH_NV_INDEX 0x100b +#define REC_HASH_NV_SIZE VB2_SHA256_DIGEST_SIZE + +/* Structure definitions for TPM spaces */ + +/* Flags for firmware space */ + +/* + * Last boot was developer mode. TPM ownership is cleared when transitioning + * to/from developer mode. + */ +#define FLAG_LAST_BOOT_DEVELOPER 0x01 + +/* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */ + +uint32_t antirollback_read_space_firmware(struct vb2_context *ctx); + +/** + * Write may be called if the versions change. + */ +uint32_t antirollback_write_space_firmware(struct vb2_context *ctx); + +/** + * Lock must be called. + */ +uint32_t antirollback_lock_space_firmware(void); + +/* Read recovery hash data from TPM. */ +uint32_t antirollback_read_space_rec_hash(uint8_t *data, uint32_t size); +/* Write new hash data to recovery space in TPM. */ +uint32_t antirollback_write_space_rec_hash(const uint8_t *data, uint32_t size); +/* Lock down recovery hash space in TPM. */ +uint32_t antirollback_lock_space_rec_hash(void); + +/* Start of the root of trust */ +uint32_t vboot_setup_tpm(struct vb2_context *ctx); + +/* vboot_extend_pcr function for vb2 context */ +uint32_t vboot_extend_pcr(struct vb2_context *ctx, int pcr, + enum vb2_pcr_digest which_digest); + +#endif /* ANTIROLLBACK_H_ */ diff --git a/src/security/vboot/secdata_mock.c b/src/security/vboot/secdata_mock.c index 4ea53558f9..3075d335f6 100644 --- a/src/security/vboot/secdata_mock.c +++ b/src/security/vboot/secdata_mock.c @@ -32,54 +32,50 @@ * stored in the TPM NVRAM. */ -#include #include -#include +#include #include -uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr, - enum vb2_pcr_digest which_digest) +#include "antirollback.h" + +int vb2ex_tpm_clear_owner(struct vb2_context *ctx) { - return TPM_SUCCESS; + return VB2_SUCCESS; } -uint32_t tpm_clear_and_reenable(void) +uint32_t vboot_extend_pcr(struct vb2_context *ctx, int pcr, + enum vb2_pcr_digest which_digest) { - return TPM_SUCCESS; + return VB2_SUCCESS; } uint32_t antirollback_read_space_firmware(struct vb2_context *ctx) { vb2api_secdata_create(ctx); - return TPM_SUCCESS; + return VB2_SUCCESS; } uint32_t antirollback_write_space_firmware(struct vb2_context *ctx) { - return TPM_SUCCESS; + return VB2_SUCCESS; } uint32_t antirollback_lock_space_firmware() { - return TPM_SUCCESS; + return VB2_SUCCESS; } uint32_t antirollback_lock_space_rec_hash(void) { - return TPM_SUCCESS; + return VB2_SUCCESS; } uint32_t antirollback_read_space_rec_hash(uint8_t *data, uint32_t size) { - return TPM_SUCCESS; + return VB2_SUCCESS; } uint32_t antirollback_write_space_rec_hash(const uint8_t *data, uint32_t size) -{ - return TPM_SUCCESS; -} - -uint32_t tlcl_lib_init(void) { return VB2_SUCCESS; } diff --git a/src/security/vboot/secdata_tpm.c b/src/security/vboot/secdata_tpm.c index a757f02f98..57c107bc3a 100644 --- a/src/security/vboot/secdata_tpm.c +++ b/src/security/vboot/secdata_tpm.c @@ -32,10 +32,10 @@ * stored in the TPM NVRAM. */ -#include +#include #include #include -#include +#include #include #include @@ -64,7 +64,7 @@ static uint32_t safe_write(uint32_t index, const void *data, uint32_t length); -uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr, +uint32_t vboot_extend_pcr(struct vb2_context *ctx, int pcr, enum vb2_pcr_digest which_digest) { uint8_t buffer[VB2_PCR_DIGEST_RECOMMENDED_SIZE]; @@ -74,10 +74,10 @@ uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr, rv = vb2api_get_pcr_digest(ctx, which_digest, buffer, &size); if (rv != VB2_SUCCESS) return rv; - if (size < TPM_PCR_DIGEST) + if (size < TPM_PCR_MINIMUM_DIGEST_SIZE) return VB2_ERROR_UNKNOWN; - return tlcl_extend(pcr, buffer, NULL); + return tpm_extend_pcr(pcr, buffer, NULL); } static uint32_t read_space_firmware(struct vb2_context *ctx) @@ -158,6 +158,35 @@ static const uint8_t secdata_kernel[] = { static const uint8_t rec_hash_data[REC_HASH_NV_SIZE] = { }; #if IS_ENABLED(CONFIG_TPM2) +/* + * Different sets of NVRAM space attributes apply to the "ro" spaces, + * i.e. those which should not be possible to delete or modify once + * the RO exits, and the rest of the NVRAM spaces. + */ +const static TPMA_NV ro_space_attributes = { + .TPMA_NV_PPWRITE = 1, + .TPMA_NV_AUTHREAD = 1, + .TPMA_NV_PPREAD = 1, + .TPMA_NV_PLATFORMCREATE = 1, + .TPMA_NV_WRITE_STCLEAR = 1, + .TPMA_NV_POLICY_DELETE = 1, +}; + +const static TPMA_NV rw_space_attributes = { + .TPMA_NV_PPWRITE = 1, + .TPMA_NV_AUTHREAD = 1, + .TPMA_NV_PPREAD = 1, + .TPMA_NV_PLATFORMCREATE = 1, +}; + +/* + * This policy digest was obtained using TPM2_PolicyPCR + * selecting only PCR_0 with a value of all zeros. + */ +const static uint8_t pcr0_unchanged_policy[] = { + 0x09, 0x93, 0x3C, 0xCE, 0xEB, 0xB4, 0x41, 0x11, 0x18, 0x81, 0x1D, + 0xD4, 0x47, 0x78, 0x80, 0x08, 0x88, 0x86, 0x62, 0x2D, 0xD7, 0x79, + 0x94, 0x46, 0x62, 0x26, 0x68, 0x8E, 0xEE, 0xE6, 0x6A, 0xA1}; /* Nothing special in the TPM2 path yet. */ static uint32_t safe_write(uint32_t index, const void *data, uint32_t length) @@ -166,11 +195,13 @@ static uint32_t safe_write(uint32_t index, const void *data, uint32_t length) } static uint32_t set_space(const char *name, uint32_t index, const void *data, - uint32_t length) + uint32_t length, const TPMA_NV nv_attributes, + const uint8_t *nv_policy, size_t nv_policy_size) { uint32_t rv; - rv = tlcl_define_space(index, length); + rv = tlcl_define_space(index, length, nv_attributes, nv_policy, + nv_policy_size); if (rv == TPM_E_NV_DEFINED) { /* * Continue with writing: it may be defined, but not written @@ -193,19 +224,22 @@ static uint32_t set_space(const char *name, uint32_t index, const void *data, static uint32_t set_firmware_space(const void *firmware_blob) { return set_space("firmware", FIRMWARE_NV_INDEX, firmware_blob, - VB2_SECDATA_SIZE); + VB2_SECDATA_SIZE, ro_space_attributes, + pcr0_unchanged_policy, sizeof(pcr0_unchanged_policy)); } static uint32_t set_kernel_space(const void *kernel_blob) { return set_space("kernel", KERNEL_NV_INDEX, kernel_blob, - sizeof(secdata_kernel)); + sizeof(secdata_kernel), rw_space_attributes, NULL, 0); } static uint32_t set_rec_hash_space(const uint8_t *data) { return set_space("MRC Hash", REC_HASH_NV_INDEX, data, - REC_HASH_NV_SIZE); + REC_HASH_NV_SIZE, + ro_space_attributes, pcr0_unchanged_policy, + sizeof(pcr0_unchanged_policy)); } static uint32_t _factory_initialize_tpm(struct vb2_context *ctx) @@ -228,13 +262,6 @@ static uint32_t _factory_initialize_tpm(struct vb2_context *ctx) return TPM_SUCCESS; } -uint32_t tpm_clear_and_reenable(void) -{ - VBDEBUG("TPM: Clear and re-enable\n"); - RETURN_ON_FAILURE(tlcl_force_clear()); - return TPM_SUCCESS; -} - uint32_t antirollback_lock_space_firmware(void) { return tlcl_lock_nv_write(FIRMWARE_NV_INDEX); @@ -247,16 +274,6 @@ uint32_t antirollback_lock_space_rec_hash(void) #else -uint32_t tpm_clear_and_reenable(void) -{ - VBDEBUG("TPM: Clear and re-enable\n"); - RETURN_ON_FAILURE(tlcl_force_clear()); - RETURN_ON_FAILURE(tlcl_set_enable()); - RETURN_ON_FAILURE(tlcl_set_deactivated(0)); - - return TPM_SUCCESS; -} - /** * 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 @@ -416,110 +433,22 @@ static uint32_t factory_initialize_tpm(struct vb2_context *ctx) return TPM_SUCCESS; } -/* - * SetupTPM 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 setup_tpm(struct vb2_context *ctx) +uint32_t vboot_setup_tpm(struct vb2_context *ctx) { - uint8_t disable; - uint8_t deactivated; uint32_t result; - RETURN_ON_FAILURE(tlcl_lib_init()); - - /* Handle special init for S3 resume path */ - if (ctx->flags & VB2_CONTEXT_S3_RESUME) { - result = tlcl_resume(); - if (result == TPM_E_INVALID_POSTINIT) - printk(BIOS_DEBUG, "TPM: Already initialized.\n"); - return TPM_SUCCESS; - } - - if (IS_ENABLED(CONFIG_VBOOT_SOFT_REBOOT_WORKAROUND)) { - result = tlcl_startup(); - if (result == TPM_E_INVALID_POSTINIT) { - /* - * Some prototype hardware doesn't reset the TPM on a CPU - * reset. We do a hard reset to get around this. - */ - VBDEBUG("TPM: soft reset detected\n"); - ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT; - return TPM_E_MUST_REBOOT; - } else if (result != TPM_SUCCESS) { - VBDEBUG("TPM: tlcl_startup returned %08x\n", result); - return result; - } - } else - RETURN_ON_FAILURE(tlcl_startup()); - - /* - * Some TPMs start the self test automatically at power on. In that case - * we don't need to call ContinueSelfTest. On some (other) TPMs, - * continue_self_test may block. In that case, we definitely don't want - * to call it here. For TPMs in the intersection of these two sets, we - * are screwed. (In other words: TPMs that require manually starting the - * self-test AND block will have poor performance until we split - * tlcl_send_receive() into send() and receive(), and have a state - * machine to control setup.) - * - * This comment is likely to become obsolete in the near future, so - * don't trust it. It may have not been updated. - */ -#ifdef TPM_MANUAL_SELFTEST -#ifdef TPM_BLOCKING_CONTINUESELFTEST -#warning "lousy TPM!" -#endif - RETURN_ON_FAILURE(tlcl_continue_self_test()); -#endif - 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. - */ - RETURN_ON_FAILURE(tlcl_physical_presence_cmd_enable()); - RETURN_ON_FAILURE(tlcl_assert_physical_presence()); - } - - /* Check that the TPM is enabled and activated. */ - RETURN_ON_FAILURE(tlcl_get_flags(&disable, &deactivated, NULL)); - if (disable || deactivated) { - VBDEBUG("TPM: disabled (%d) or deactivated (%d). Fixing...\n", - disable, deactivated); - RETURN_ON_FAILURE(tlcl_set_enable()); - RETURN_ON_FAILURE(tlcl_set_deactivated(0)); - VBDEBUG("TPM: Must reboot to re-enable\n"); + result = tpm_setup(ctx->flags & VB2_CONTEXT_S3_RESUME); + if (result == TPM_E_MUST_REBOOT) ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT; - return TPM_E_MUST_REBOOT; - } - VBDEBUG("TPM: SetupTPM() succeeded\n"); - return TPM_SUCCESS; + return result; } uint32_t antirollback_read_space_firmware(struct vb2_context *ctx) { uint32_t rv; - rv = setup_tpm(ctx); + rv = vboot_setup_tpm(ctx); if (rv) return rv; @@ -585,3 +514,13 @@ uint32_t antirollback_write_space_rec_hash(const uint8_t *data, uint32_t size) return write_secdata(REC_HASH_NV_INDEX, data, size); } + +int vb2ex_tpm_clear_owner(struct vb2_context *ctx) +{ + uint32_t rv; + printk(BIOS_INFO, "Clearing TPM owner\n"); + rv = tpm_clear_and_reenable(); + if (rv) + return VB2_ERROR_EX_TPM_CLEAR_OWNER; + return VB2_SUCCESS; +} diff --git a/src/security/vboot/vboot_logic.c b/src/security/vboot/vboot_logic.c index 2600f84945..9710ae2e7c 100644 --- a/src/security/vboot/vboot_logic.c +++ b/src/security/vboot/vboot_logic.c @@ -13,7 +13,6 @@ * GNU General Public License for more details. */ -#include #include #include #include @@ -27,6 +26,8 @@ #include #include +#include "antirollback.h" + /* The max hash size to expect is for SHA512. */ #define VBOOT_MAX_HASH_SIZE VB2_SHA512_DIGEST_SIZE @@ -53,16 +54,6 @@ void vb2ex_printf(const char *func, const char *fmt, ...) return; } -int vb2ex_tpm_clear_owner(struct vb2_context *ctx) -{ - uint32_t rv; - printk(BIOS_INFO, "Clearing TPM owner\n"); - rv = tpm_clear_and_reenable(); - if (rv) - return VB2_ERROR_EX_TPM_CLEAR_OWNER; - return VB2_SUCCESS; -} - int vb2ex_read_resource(struct vb2_context *ctx, enum vb2_resource_index index, uint32_t offset, @@ -290,8 +281,8 @@ static void save_if_needed(struct vb2_context *ctx) static uint32_t extend_pcrs(struct vb2_context *ctx) { - return tpm_extend_pcr(ctx, 0, BOOT_MODE_PCR) || - tpm_extend_pcr(ctx, 1, HWID_DIGEST_PCR); + return vboot_extend_pcr(ctx, 0, BOOT_MODE_PCR) || + vboot_extend_pcr(ctx, 1, HWID_DIGEST_PCR); } /** -- cgit v1.2.3