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/drivers/i2c/tpm/Kconfig | 34 ++--- src/drivers/i2c/tpm/Makefile.inc | 17 ++- src/drivers/intel/fsp1_1/romstage.c | 6 +- src/drivers/intel/fsp2_0/Kconfig | 2 + src/drivers/intel/fsp2_0/memory_init.c | 9 +- src/drivers/pc80/tpm/Kconfig | 37 +---- src/drivers/pc80/tpm/Makefile.inc | 5 - src/drivers/pc80/tpm/romstage.c | 253 --------------------------------- src/drivers/spi/tpm/Kconfig | 8 +- src/drivers/spi/tpm/Makefile.inc | 7 +- 10 files changed, 44 insertions(+), 334 deletions(-) delete mode 100644 src/drivers/pc80/tpm/romstage.c (limited to 'src/drivers') diff --git a/src/drivers/i2c/tpm/Kconfig b/src/drivers/i2c/tpm/Kconfig index db6777e65d..6a27224031 100644 --- a/src/drivers/i2c/tpm/Kconfig +++ b/src/drivers/i2c/tpm/Kconfig @@ -1,32 +1,28 @@ config I2C_TPM - bool "I2C TPM" - depends on TPM || TPM2 + bool + help + I2C TPM driver is enabled! config MAINBOARD_HAS_I2C_TPM_ATMEL bool default n + select I2C_TPM + help + Board has an Atmel I2C TPM support config MAINBOARD_HAS_I2C_TPM_CR50 bool default n + select I2C_TPM + help + Board has a Cr50 I2C TPM support -choice - prompt "I2C TPM Driver" - default I2C_TPM_ATMEL if MAINBOARD_HAS_I2C_TPM_ATMEL - default I2C_TPM_CR50 if MAINBOARD_HAS_I2C_TPM_CR50 - default I2C_TPM_GENERIC if !MAINBOARD_HAS_I2C_TPM_CR50 && !MAINBOARD_HAS_I2C_TPM_ATMEL - depends on I2C_TPM - -config I2C_TPM_GENERIC - bool "Generic I2C TPM Driver" - -config I2C_TPM_ATMEL - bool "ATMEL I2C TPM Driver" - -config I2C_TPM_CR50 - bool "CR50 I2C TPM Driver" - -endchoice +config MAINBOARD_HAS_I2C_TPM_GENERIC + bool + default n + select I2C_TPM + help + Board has a generic I2C TPM support config DRIVER_TIS_DEFAULT bool diff --git a/src/drivers/i2c/tpm/Makefile.inc b/src/drivers/i2c/tpm/Makefile.inc index afcb33bb93..e24a66d6d1 100644 --- a/src/drivers/i2c/tpm/Makefile.inc +++ b/src/drivers/i2c/tpm/Makefile.inc @@ -1,4 +1,3 @@ - ramstage-$(CONFIG_DRIVER_TIS_DEFAULT) += tis.c romstage-$(CONFIG_DRIVER_TIS_DEFAULT) += tis.c verstage-$(CONFIG_DRIVER_TIS_DEFAULT) += tis.c @@ -9,14 +8,14 @@ romstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_ATMEL) += tis_atmel.c verstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_ATMEL) += tis_atmel.c bootblock-$(CONFIG_MAINBOARD_HAS_I2C_TPM_ATMEL) += tis_atmel.c -ramstage-$(CONFIG_I2C_TPM_GENERIC) += tpm.c -romstage-$(CONFIG_I2C_TPM_GENERIC) += tpm.c -verstage-$(CONFIG_I2C_TPM_GENERIC) += tpm.c -bootblock-$(CONFIG_I2C_TPM_GENERIC) += tpm.c +ramstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_GENERIC) += tpm.c +romstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_GENERIC) += tpm.c +verstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_GENERIC) += tpm.c +bootblock-$(CONFIG_MAINBOARD_HAS_I2C_TPM_GENERIC) += tpm.c -ramstage-$(CONFIG_I2C_TPM_CR50) += cr50.c -romstage-$(CONFIG_I2C_TPM_CR50) += cr50.c -verstage-$(CONFIG_I2C_TPM_CR50) += cr50.c -bootblock-$(CONFIG_I2C_TPM_CR50) += cr50.c +ramstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_CR50) += cr50.c +romstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_CR50) += cr50.c +verstage-$(CONFIG_MAINBOARD_HAS_I2C_TPM_CR50) += cr50.c +bootblock-$(CONFIG_MAINBOARD_HAS_I2C_TPM_CR50) += cr50.c ramstage-$(CONFIG_DRIVER_I2C_TPM_ACPI) += chip.c diff --git a/src/drivers/intel/fsp1_1/romstage.c b/src/drivers/intel/fsp1_1/romstage.c index ba08cdc42b..0320bf5724 100644 --- a/src/drivers/intel/fsp1_1/romstage.c +++ b/src/drivers/intel/fsp1_1/romstage.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include asmlinkage void *romstage_main(FSP_INFO_HEADER *fih) @@ -172,9 +172,9 @@ void romstage_common(struct romstage_params *params) * Initialize the TPM, unless the TPM was already initialized * in verstage and used to verify romstage. */ - if (IS_ENABLED(CONFIG_LPC_TPM) && + if ((IS_ENABLED(CONFIG_TPM1) || IS_ENABLED(CONFIG_TPM2)) && !IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) - init_tpm(params->power_state->prev_sleep_state == + tpm_setup(params->power_state->prev_sleep_state == ACPI_S3); } diff --git a/src/drivers/intel/fsp2_0/Kconfig b/src/drivers/intel/fsp2_0/Kconfig index 1ff8aa68ef..f14954463b 100644 --- a/src/drivers/intel/fsp2_0/Kconfig +++ b/src/drivers/intel/fsp2_0/Kconfig @@ -119,6 +119,8 @@ config DISPLAY_FSP_VERSION_INFO config FSP2_0_USES_TPM_MRC_HASH bool + depends on TPM1 || TPM2 + depends on VBOOT default y if HAS_RECOVERY_MRC_CACHE default n select VBOOT_HAS_REC_HASH_SPACE diff --git a/src/drivers/intel/fsp2_0/memory_init.c b/src/drivers/intel/fsp2_0/memory_init.c index 30987ce500..1ca52085a7 100644 --- a/src/drivers/intel/fsp2_0/memory_init.c +++ b/src/drivers/intel/fsp2_0/memory_init.c @@ -12,7 +12,7 @@ */ #include -#include +#include #include #include #include @@ -31,8 +31,7 @@ #include #include #include -#include -#include +#include #include #include @@ -152,9 +151,9 @@ static void do_fsp_post_memory_init(bool s3wake, uint32_t fsp_version) * Initialize the TPM, unless the TPM was already initialized * in verstage and used to verify romstage. */ - if (IS_ENABLED(CONFIG_LPC_TPM) && + if ((IS_ENABLED(CONFIG_TPM1) || IS_ENABLED(CONFIG_TPM2)) && !IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK)) - init_tpm(s3wake); + tpm_setup(s3wake); } static int mrc_cache_verify_tpm_hash(const uint8_t *data, size_t size) diff --git a/src/drivers/pc80/tpm/Kconfig b/src/drivers/pc80/tpm/Kconfig index 879b4a2341..853801b9ab 100644 --- a/src/drivers/pc80/tpm/Kconfig +++ b/src/drivers/pc80/tpm/Kconfig @@ -1,11 +1,8 @@ config LPC_TPM - bool "Enable TPM support" - depends on MAINBOARD_HAS_LPC_TPM + bool default n help - Enable this option to enable LPC TPM support in coreboot. - - If unsure, say N. + LPC TPM driver is enabled! config TPM_TIS_BASE_ADDRESS hex @@ -25,33 +22,9 @@ config TPM_PIRQ This can be used to specify a PIRQ to use instead of SERIRQ, which is needed for SPI TPM interrupt support on x86. -config TPM_INIT_FAILURE_IS_FATAL - bool - default n - depends on LPC_TPM - help - What to do if TPM init failed. If true, force a hard reset, - otherwise just log error message to console. - -config SKIP_TPM_STARTUP_ON_NORMAL_BOOT +config MAINBOARD_HAS_LPC_TPM bool default n - depends on LPC_TPM - help - Skip TPM init on normal boot. Useful if payload does TPM init. - -config TPM_DEACTIVATE - bool "Deactivate TPM" - default n - depends on LPC_TPM - help - Deactivate TPM by issuing deactivate command. - -config TPM_RDRESP_NEED_DELAY - bool "Enable Delay Workaround for TPM" - default n - depends on LPC_TPM + select LPC_TPM help - 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. + Board has LPC TPM support diff --git a/src/drivers/pc80/tpm/Makefile.inc b/src/drivers/pc80/tpm/Makefile.inc index 9d428b5e22..8747374407 100644 --- a/src/drivers/pc80/tpm/Makefile.inc +++ b/src/drivers/pc80/tpm/Makefile.inc @@ -1,8 +1,3 @@ -ifeq ($(CONFIG_ARCH_X86),y) - verstage-$(CONFIG_LPC_TPM) += tis.c romstage-$(CONFIG_LPC_TPM) += tis.c ramstage-$(CONFIG_LPC_TPM) += tis.c -romstage-$(CONFIG_LPC_TPM) += romstage.c - -endif diff --git a/src/drivers/pc80/tpm/romstage.c b/src/drivers/pc80/tpm/romstage.c deleted file mode 100644 index b8e4705e87..0000000000 --- a/src/drivers/pc80/tpm/romstage.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. - * - * 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 - -//#define EXTRA_LOGGING - -#define TPM_LARGE_ENOUGH_COMMAND_SIZE 256 /* saves space in the firmware */ - -#define TPM_SUCCESS ((u32)0x00000000) - -#define TPM_E_IOERROR ((u32)0x0000001f) -#define TPM_E_COMMUNICATION_ERROR ((u32)0x00005004) -#define TPM_E_NON_FATAL ((u32)0x00000800) -#define TPM_E_INVALID_POSTINIT ((u32)0x00000026) - -#define TPM_E_NEEDS_SELFTEST ((u32)(TPM_E_NON_FATAL + 1)) -#define TPM_E_DOING_SELFTEST ((u32)(TPM_E_NON_FATAL + 2)) - -static const struct { - u8 buffer[12]; -} tpm_resume_cmd = { - { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x2 } -}; - -static const struct { - u8 buffer[12]; -} tpm_startup_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1 } -}; - -static const struct { - u8 buffer[12]; -} tpm_deactivate_cmd = { - {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x3 } -}; - -static const struct { - u8 buffer[10]; -} tpm_continueselftest_cmd = { - { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53 } -}; - -static inline void FromTpmUint32(const u8 * buffer, u32 * x) -{ - *x = ((buffer[0] << 24) | - (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]); -} - -static inline int TpmCommandSize(const u8 * buffer) -{ - u32 size; - FromTpmUint32(buffer + sizeof(u16), &size); - return (int)size; -} - -/* Gets the code field of a TPM command. */ -static inline int TpmCommandCode(const u8 * buffer) -{ - u32 code; - FromTpmUint32(buffer + sizeof(u16) + sizeof(u32), &code); - return code; -} - -/* Gets the return code field of a TPM result. */ -static inline int TpmReturnCode(const u8 * buffer) -{ - return TpmCommandCode(buffer); -} - -/* Like TlclSendReceive below, but do not retry if NEEDS_SELFTEST or - * DOING_SELFTEST errors are returned. - */ -static u32 TlclSendReceiveNoRetry(const u8 * request, - u8 * response, int max_length) -{ - size_t response_length = max_length; - u32 result; - -#ifdef EXTRA_LOGGING - printk(BIOS_DEBUG, "TPM: command: %x%x %x%x%x%x %x%x%x%x\n", - request[0], request[1], - request[2], request[3], request[4], request[5], - request[6], request[7], request[8], request[9]); -#endif - - result = TPM_SUCCESS; - if (tis_sendrecv - (request, TpmCommandSize(request), response, &response_length)) - result = TPM_E_IOERROR; - - if (0 != result) { - /* Communication with TPM failed, so response is garbage */ - printk(BIOS_DEBUG, - "TPM: command 0x%x send/receive failed: 0x%x\n", - TpmCommandCode(request), result); - return TPM_E_COMMUNICATION_ERROR; - } - /* Otherwise, use the result code from the response */ - result = TpmReturnCode(response); - -/* TODO: add paranoia about returned response_length vs. max_length - * (and possibly expected length from the response header). See - * crosbug.com/17017 */ - -#ifdef EXTRA_LOGGING - printk(BIOS_DEBUG, "TPM: response: %x%x %x%x%x%x %x%x%x%x\n", - response[0], response[1], - response[2], response[3], response[4], response[5], - response[6], response[7], response[8], response[9]); -#endif - - printk(BIOS_DEBUG, "TPM: command 0x%x returned 0x%x\n", - TpmCommandCode(request), result); - - return result; -} - -static inline u32 TlclContinueSelfTest(void) -{ - u8 response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; - printk(BIOS_DEBUG, "TPM: Continue self test\n"); - /* Call the No Retry version of SendReceive to avoid recursion. */ - return TlclSendReceiveNoRetry(tpm_continueselftest_cmd.buffer, - response, sizeof(response)); -} - -/* Sends a TPM command and gets a response. Returns 0 if success or the TPM - * error code if error. In the firmware, waits for the self test to complete - * if needed. In the host, reports the first error without retries. */ -static u32 TlclSendReceive(const u8 * request, u8 * response, int max_length) -{ - u32 result = TlclSendReceiveNoRetry(request, response, max_length); - /* When compiling for the firmware, hide command failures due to the self - * test not having run or completed. */ - /* If the command fails because the self test has not completed, try it - * again after attempting to ensure that the self test has completed. */ - if (result == TPM_E_NEEDS_SELFTEST || result == TPM_E_DOING_SELFTEST) { - result = TlclContinueSelfTest(); - if (result != TPM_SUCCESS) { - return result; - } -#if defined(TPM_BLOCKING_CONTINUESELFTEST) || defined(VB_RECOVERY_MODE) - /* Retry only once */ - result = TlclSendReceiveNoRetry(request, response, max_length); -#else - /* This needs serious testing. The TPM specification says: - * "iii. The caller MUST wait for the actions of - * TPM_ContinueSelfTest to complete before reissuing the - * command C1." But, if ContinueSelfTest is non-blocking, how - * do we know that the actions have completed other than trying - * again? */ - do { - result = - TlclSendReceiveNoRetry(request, response, - max_length); - } while (result == TPM_E_DOING_SELFTEST); -#endif - } - - return result; -} - -void init_tpm(int s3resume) -{ - u32 result; - u8 response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; - - if (IS_ENABLED(CONFIG_TPM_DEACTIVATE)) { - printk(BIOS_SPEW, "TPM: Deactivate\n"); - result = TlclSendReceive(tpm_deactivate_cmd.buffer, - response, sizeof(response)); - if (result == TPM_SUCCESS) { - printk(BIOS_SPEW, "TPM: OK.\n"); - return; - } - - printk(BIOS_ERR, "TPM: Error code 0x%x.\n", result); - return; - } - - /* Doing TPM startup when we're not coming in on the S3 resume path - * saves us roughly 20ms in boot time only. This does not seem to - * be worth an API change to vboot_reference-firmware right now, so - * let's keep the code around, but just bail out early: - */ - if (s3resume ? CONFIG_NO_TPM_RESUME - : CONFIG_SKIP_TPM_STARTUP_ON_NORMAL_BOOT) - return; - - printk(BIOS_DEBUG, "TPM initialization.\n"); - - printk(BIOS_SPEW, "TPM: Init\n"); - if (tis_init()) - return; - - printk(BIOS_SPEW, "TPM: Open\n"); - if (tis_open()) - return; - - if (s3resume) { - /* S3 Resume */ - printk(BIOS_SPEW, "TPM: Resume\n"); - result = TlclSendReceive(tpm_resume_cmd.buffer, - response, sizeof(response)); - if (result == TPM_E_INVALID_POSTINIT) { - /* We're on a platform where the TPM maintains power - * in S3, so it's already initialized. - */ - printk(BIOS_DEBUG, "TPM: Already initialized.\n"); - tis_close(); - return; - } - } else { - printk(BIOS_SPEW, "TPM: Startup\n"); - result = TlclSendReceive(tpm_startup_cmd.buffer, - response, sizeof(response)); - } - - tis_close(); - - if (result == TPM_SUCCESS) { - printk(BIOS_SPEW, "TPM: OK.\n"); - return; - } - - printk(BIOS_ERR, "TPM: Error code 0x%x.\n", result); - - if (IS_ENABLED(CONFIG_TPM_INIT_FAILURE_IS_FATAL)) { - printk(BIOS_ERR, "Hard reset!\n"); - post_code(POST_TPM_FAILURE); - if (IS_ENABLED(CONFIG_CONSOLE_CBMEM_DUMP_TO_UART)) - cbmem_dump_console(); - hard_reset(); - } -} diff --git a/src/drivers/spi/tpm/Kconfig b/src/drivers/spi/tpm/Kconfig index 9022d00d53..be43e2314d 100644 --- a/src/drivers/spi/tpm/Kconfig +++ b/src/drivers/spi/tpm/Kconfig @@ -1,6 +1,7 @@ config SPI_TPM - bool "SPI TPM" - depends on TPM2 + bool + help + SPI TPM driver is enabled! config DRIVER_TPM_SPI_BUS hex "SPI bus TPM chip is connected to" @@ -15,3 +16,6 @@ config DRIVER_TPM_SPI_CHIP config MAINBOARD_HAS_SPI_TPM_CR50 bool default n + select SPI_TPM + help + Board has SPI TPM support diff --git a/src/drivers/spi/tpm/Makefile.inc b/src/drivers/spi/tpm/Makefile.inc index cc7d715609..fd214c63ca 100644 --- a/src/drivers/spi/tpm/Makefile.inc +++ b/src/drivers/spi/tpm/Makefile.inc @@ -1,9 +1,4 @@ -verstage-$(CONFIG_SPI_TPM) += tis.c tpm.c -romstage-$(CONFIG_SPI_TPM) += tis.c tpm.c -ramstage-$(CONFIG_SPI_TPM) += tis.c tpm.c - -ifneq ($(CONFIG_CHROMEOS),y) bootblock-$(CONFIG_SPI_TPM) += tis.c tpm.c +verstage-$(CONFIG_SPI_TPM) += tis.c tpm.c romstage-$(CONFIG_SPI_TPM) += tis.c tpm.c ramstage-$(CONFIG_SPI_TPM) += tis.c tpm.c -endif -- cgit v1.2.3