From d88fb36e61beac7b52b6183385de4434895a4995 Mon Sep 17 00:00:00 2001 From: Philipp Deppenwiese Date: Wed, 18 Oct 2017 20:26:18 +0200 Subject: security/tpm: Change TPM naming for different layers. * Rename tlcl* to tss* as tpm software stack layer. * Fix inconsistent naming. Change-Id: I206dd6a32dbd303a6d4d987e424407ebf5c518fa Signed-off-by: Philipp Deppenwiese Reviewed-on: https://review.coreboot.org/22104 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- src/cpu/intel/haswell/romstage.c | 2 +- src/drivers/i2c/tpm/cr50.c | 2 +- src/drivers/i2c/tpm/tis.c | 2 +- src/drivers/i2c/tpm/tis_atmel.c | 2 +- src/drivers/i2c/tpm/tpm.c | 2 +- src/drivers/intel/fsp1_1/romstage.c | 2 +- src/drivers/intel/fsp2_0/memory_init.c | 2 +- src/drivers/pc80/tpm/Makefile.inc | 6 +- src/drivers/pc80/tpm/romstage.c | 2 +- src/drivers/pc80/tpm/tis.c | 992 +++++++++++++++++++++ src/drivers/pc80/tpm/tpm.c | 992 --------------------- src/drivers/spi/tpm/tis.c | 2 +- src/drivers/spi/tpm/tpm.c | 2 +- src/mainboard/asus/kgpe-d16/romstage.c | 2 +- src/mainboard/google/gru/chromeos.c | 2 +- src/mainboard/google/link/romstage.c | 2 +- src/mainboard/google/oak/tpm_tis.c | 2 +- src/mainboard/google/parrot/romstage.c | 2 +- src/mainboard/google/stout/romstage.c | 2 +- src/mainboard/intel/emeraldlake2/romstage.c | 2 +- src/mainboard/lenovo/x201/romstage.c | 2 +- src/mainboard/pcengines/apu2/romstage.c | 2 +- src/mainboard/samsung/lumpy/romstage.c | 2 +- src/mainboard/samsung/stumpy/romstage.c | 2 +- src/northbridge/intel/sandybridge/romstage.c | 2 +- src/security/tpm/Makefile.inc | 16 +- src/security/tpm/tcg-1.2/tlcl.c | 353 -------- src/security/tpm/tcg-1.2/tlcl_internal.h | 65 -- src/security/tpm/tcg-1.2/tlcl_structures.h | 164 ---- src/security/tpm/tcg-1.2/tss.c | 353 ++++++++ src/security/tpm/tcg-1.2/tss_internal.h | 65 ++ src/security/tpm/tcg-1.2/tss_structures.h | 164 ++++ src/security/tpm/tcg-2.0/tpm2_marshaling.c | 559 ------------ src/security/tpm/tcg-2.0/tpm2_marshaling.h | 46 - src/security/tpm/tcg-2.0/tpm2_tlcl.c | 438 --------- src/security/tpm/tcg-2.0/tpm2_tlcl_structures.h | 373 -------- src/security/tpm/tcg-2.0/tss.c | 438 +++++++++ src/security/tpm/tcg-2.0/tss_marshaling.c | 559 ++++++++++++ src/security/tpm/tcg-2.0/tss_marshaling.h | 46 + src/security/tpm/tcg-2.0/tss_structures.h | 373 ++++++++ src/security/tpm/tis.h | 102 +++ src/security/tpm/tlcl.h | 177 ---- src/security/tpm/tpm.h | 102 --- src/security/tpm/tpm_error_messages.h | 255 ------ src/security/tpm/tss.h | 177 ++++ src/security/tpm/tss_error_messages.h | 255 ++++++ src/security/vboot/secdata_mock.c | 2 +- src/security/vboot/secdata_tpm.c | 2 +- src/soc/intel/baytrail/romstage/romstage.c | 2 +- src/soc/intel/braswell/romstage/romstage.c | 2 +- src/soc/intel/broadwell/romstage/romstage.c | 2 +- src/soc/intel/common/tpm_tis.c | 2 +- .../google/chromeos/cr50_enable_update.c | 2 +- src/vendorcode/google/chromeos/tpm2.c | 2 +- 54 files changed, 3565 insertions(+), 3565 deletions(-) create mode 100644 src/drivers/pc80/tpm/tis.c delete mode 100644 src/drivers/pc80/tpm/tpm.c delete mode 100644 src/security/tpm/tcg-1.2/tlcl.c delete mode 100644 src/security/tpm/tcg-1.2/tlcl_internal.h delete mode 100644 src/security/tpm/tcg-1.2/tlcl_structures.h create mode 100644 src/security/tpm/tcg-1.2/tss.c create mode 100644 src/security/tpm/tcg-1.2/tss_internal.h create mode 100644 src/security/tpm/tcg-1.2/tss_structures.h delete mode 100644 src/security/tpm/tcg-2.0/tpm2_marshaling.c delete mode 100644 src/security/tpm/tcg-2.0/tpm2_marshaling.h delete mode 100644 src/security/tpm/tcg-2.0/tpm2_tlcl.c delete mode 100644 src/security/tpm/tcg-2.0/tpm2_tlcl_structures.h create mode 100644 src/security/tpm/tcg-2.0/tss.c create mode 100644 src/security/tpm/tcg-2.0/tss_marshaling.c create mode 100644 src/security/tpm/tcg-2.0/tss_marshaling.h create mode 100644 src/security/tpm/tcg-2.0/tss_structures.h create mode 100644 src/security/tpm/tis.h delete mode 100644 src/security/tpm/tlcl.h delete mode 100644 src/security/tpm/tpm.h delete mode 100644 src/security/tpm/tpm_error_messages.h create mode 100644 src/security/tpm/tss.h create mode 100644 src/security/tpm/tss_error_messages.h (limited to 'src') diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c index ffbfbdfd83..6d9fbc4a0b 100644 --- a/src/cpu/intel/haswell/romstage.c +++ b/src/cpu/intel/haswell/romstage.c @@ -42,7 +42,7 @@ #include "northbridge/intel/haswell/raminit.h" #include "southbridge/intel/lynxpoint/pch.h" #include "southbridge/intel/lynxpoint/me.h" -#include +#include static inline void reset_system(void) { diff --git a/src/drivers/i2c/tpm/cr50.c b/src/drivers/i2c/tpm/cr50.c index 0927d7fc43..96e00379c8 100644 --- a/src/drivers/i2c/tpm/cr50.c +++ b/src/drivers/i2c/tpm/cr50.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include "tpm.h" #define CR50_MAX_BUFSIZE 63 diff --git a/src/drivers/i2c/tpm/tis.c b/src/drivers/i2c/tpm/tis.c index ba5f0e4a10..1893d167d2 100644 --- a/src/drivers/i2c/tpm/tis.c +++ b/src/drivers/i2c/tpm/tis.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include "tpm.h" #include diff --git a/src/drivers/i2c/tpm/tis_atmel.c b/src/drivers/i2c/tpm/tis_atmel.c index d321d24558..2bea13565d 100644 --- a/src/drivers/i2c/tpm/tis_atmel.c +++ b/src/drivers/i2c/tpm/tis_atmel.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #define RECV_TIMEOUT (1 * 1000) /* 1 second */ diff --git a/src/drivers/i2c/tpm/tpm.c b/src/drivers/i2c/tpm/tpm.c index dede671d1b..7d69861586 100644 --- a/src/drivers/i2c/tpm/tpm.c +++ b/src/drivers/i2c/tpm/tpm.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include "tpm.h" /* max. number of iterations after I2C NAK */ diff --git a/src/drivers/intel/fsp1_1/romstage.c b/src/drivers/intel/fsp1_1/romstage.c index 3e96136ec9..69ea7865ea 100644 --- a/src/drivers/intel/fsp1_1/romstage.c +++ b/src/drivers/intel/fsp1_1/romstage.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include asmlinkage void *romstage_main(FSP_INFO_HEADER *fih) diff --git a/src/drivers/intel/fsp2_0/memory_init.c b/src/drivers/intel/fsp2_0/memory_init.c index 18e0a2a97d..8eb1bd54ea 100644 --- a/src/drivers/intel/fsp2_0/memory_init.c +++ b/src/drivers/intel/fsp2_0/memory_init.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/drivers/pc80/tpm/Makefile.inc b/src/drivers/pc80/tpm/Makefile.inc index 0068ff19a6..9d428b5e22 100644 --- a/src/drivers/pc80/tpm/Makefile.inc +++ b/src/drivers/pc80/tpm/Makefile.inc @@ -1,8 +1,8 @@ ifeq ($(CONFIG_ARCH_X86),y) -verstage-$(CONFIG_LPC_TPM) += tpm.c -romstage-$(CONFIG_LPC_TPM) += tpm.c -ramstage-$(CONFIG_LPC_TPM) += tpm.c +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 index 20413d8cf4..b8e4705e87 100644 --- a/src/drivers/pc80/tpm/romstage.c +++ b/src/drivers/pc80/tpm/romstage.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include //#define EXTRA_LOGGING diff --git a/src/drivers/pc80/tpm/tis.c b/src/drivers/pc80/tpm/tis.c new file mode 100644 index 0000000000..9802654ee1 --- /dev/null +++ b/src/drivers/pc80/tpm/tis.c @@ -0,0 +1,992 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 The Chromium OS 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. + */ + +/* + * The code in this file has been heavily based on the article "Writing a TPM + * Device Driver" published on http://ptgmedia.pearsoncmg.com and the + * submission by Stefan Berger on Qemu-devel mailing list. + * + * One principal difference is that in the simplest config the other than 0 + * TPM localities do not get mapped by some devices (for instance, by + * Infineon slb9635), so this driver provides access to locality 0 only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "chip.h" + +#define PREFIX "lpc_tpm: " +/* TCG Physical Presence Interface */ +#define TPM_PPI_UUID "3dddfaa6-361b-4eb4-a424-8d10089d1653" +/* TCG Memory Clear Interface */ +#define TPM_MCI_UUID "376054ed-cc13-4675-901c-4756d7f2d45d" +/* coreboot wrapper for TPM driver (start) */ +#define TPM_DEBUG(fmt, args...) \ + if (IS_ENABLED(CONFIG_DEBUG_TPM)) { \ + printk(BIOS_DEBUG, PREFIX); \ + printk(BIOS_DEBUG, fmt , ##args); \ + } +#define TPM_DEBUG_IO_READ(reg_, val_) \ + TPM_DEBUG("Read reg 0x%x returns 0x%x\n", (reg_), (val_)) +#define TPM_DEBUG_IO_WRITE(reg_, val_) \ + TPM_DEBUG("Write reg 0x%x with 0x%x\n", (reg_), (val_)) +#define printf(x...) printk(BIOS_ERR, x) + +/* coreboot wrapper for TPM driver (end) */ + +/* the macro accepts the locality value, but only locality 0 is operational */ +#define TIS_REG(LOCALITY, REG) \ + (void *)(CONFIG_TPM_TIS_BASE_ADDRESS + (LOCALITY << 12) + REG) + +/* hardware registers' offsets */ +#define TIS_REG_ACCESS 0x0 +#define TIS_REG_INT_ENABLE 0x8 +#define TIS_REG_INT_VECTOR 0xc +#define TIS_REG_INT_STATUS 0x10 +#define TIS_REG_INTF_CAPABILITY 0x14 +#define TIS_REG_STS 0x18 +#define TIS_REG_BURST_COUNT 0x19 +#define TIS_REG_DATA_FIFO 0x24 +#define TIS_REG_DID_VID 0xf00 +#define TIS_REG_RID 0xf04 + +/* Some registers' bit field definitions */ +#define TIS_STS_VALID (1 << 7) /* 0x80 */ +#define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */ +#define TIS_STS_TPM_GO (1 << 5) /* 0x20 */ +#define TIS_STS_DATA_AVAILABLE (1 << 4) /* 0x10 */ +#define TIS_STS_EXPECT (1 << 3) /* 0x08 */ +#define TIS_STS_RESPONSE_RETRY (1 << 1) /* 0x02 */ + +#define TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */ +#define TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */ +#define TIS_ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */ +#define TIS_ACCESS_SEIZE (1 << 3) /* 0x08 */ +#define TIS_ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */ +#define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */ +#define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */ + +/* + * Error value returned if a tpm register does not enter the expected state + * after continuous polling. No actual TPM register reading ever returns ~0, + * so this value is a safe error indication to be mixed with possible status + * register values. + */ +#define TPM_TIMEOUT_ERR (~0) + +/* Error value returned on various TPM driver errors */ +#define TPM_DRIVER_ERR (~0) + + /* 1 second is plenty for anything TPM does.*/ +#define MAX_DELAY_US (1000 * 1000) + +/* + * Structures defined below allow creating descriptions of TPM vendor/device + * ID information for run time discovery. The only device the system knows + * about at this time is Infineon slb9635 + */ +struct device_name { + u16 dev_id; + const char * const dev_name; +}; + +struct vendor_name { + u16 vendor_id; + const char * vendor_name; + const struct device_name* dev_names; +}; + +static const struct device_name atmel_devices[] = { + {0x3204, "AT97SC3204"}, + {0xffff} +}; + +static const struct device_name infineon_devices[] = { + {0x000b, "SLB9635 TT 1.2"}, + {0x001a, "SLB9660 TT 1.2"}, +#if IS_ENABLED(CONFIG_TPM2) + {0x001b, "SLB9670 TT 2.0"}, +#else + {0x001b, "SLB9670 TT 1.2"}, +#endif + {0xffff} +}; + +static const struct device_name nuvoton_devices[] = { + {0x00fe, "NPCT420AA V2"}, + {0xffff} +}; + +static const struct device_name stmicro_devices[] = { + {0x0000, "ST33ZP24" }, + {0xffff} +}; + +static const struct vendor_name vendor_names[] = { + {0x1114, "Atmel", atmel_devices}, + {0x15d1, "Infineon", infineon_devices}, + {0x1050, "Nuvoton", nuvoton_devices}, + {0x104a, "ST Microelectronics", stmicro_devices}, +}; + +/* + * Cached vendor/device ID pair to indicate that the device has been already + * discovered + */ +static u32 vendor_dev_id CAR_GLOBAL; + +static inline u8 tpm_read_status(int locality) +{ + u8 value = read8(TIS_REG(locality, TIS_REG_STS)); + TPM_DEBUG_IO_READ(TIS_REG_STS, value); + return value; +} + +static inline void tpm_write_status(u8 sts, int locality) +{ + TPM_DEBUG_IO_WRITE(TIS_REG_STS, sts); + write8(TIS_REG(locality, TIS_REG_STS), sts); +} + +static inline u8 tpm_read_data(int locality) +{ + u8 value = read8(TIS_REG(locality, TIS_REG_DATA_FIFO)); + TPM_DEBUG_IO_READ(TIS_REG_DATA_FIFO, value); + return value; +} + +static inline void tpm_write_data(u8 data, int locality) +{ + TPM_DEBUG_IO_WRITE(TIS_REG_STS, data); + write8(TIS_REG(locality, TIS_REG_DATA_FIFO), data); +} + +static inline u16 tpm_read_burst_count(int locality) +{ + u16 count; + count = read8(TIS_REG(locality, TIS_REG_BURST_COUNT)); + count |= read8(TIS_REG(locality, TIS_REG_BURST_COUNT + 1)) << 8; + TPM_DEBUG_IO_READ(TIS_REG_BURST_COUNT, count); + return count; +} + +static inline u8 tpm_read_access(int locality) +{ + u8 value = read8(TIS_REG(locality, TIS_REG_ACCESS)); + TPM_DEBUG_IO_READ(TIS_REG_ACCESS, value); + return value; +} + +static inline void tpm_write_access(u8 data, int locality) +{ + TPM_DEBUG_IO_WRITE(TIS_REG_ACCESS, data); + write8(TIS_REG(locality, TIS_REG_ACCESS), data); +} + +static inline u32 tpm_read_did_vid(int locality) +{ + u32 value = read32(TIS_REG(locality, TIS_REG_DID_VID)); + TPM_DEBUG_IO_READ(TIS_REG_DID_VID, value); + return value; +} + +static inline void tpm_write_int_vector(int vector, int locality) +{ + TPM_DEBUG_IO_WRITE(TIS_REG_INT_VECTOR, vector); + write8(TIS_REG(locality, TIS_REG_INT_VECTOR), vector & 0xf); +} + +static inline u8 tpm_read_int_vector(int locality) +{ + u8 value = read8(TIS_REG(locality, TIS_REG_INT_VECTOR)); + TPM_DEBUG_IO_READ(TIS_REG_INT_VECTOR, value); + return value; +} + +static inline void tpm_write_int_polarity(int polarity, int locality) +{ + /* Set polarity and leave all other bits at 0 */ + u32 value = (polarity & 0x3) << 3; + TPM_DEBUG_IO_WRITE(TIS_REG_INT_ENABLE, value); + write32(TIS_REG(locality, TIS_REG_INT_ENABLE), value); +} + +static inline u32 tpm_read_int_polarity(int locality) +{ + /* Get polarity and leave all other bits */ + u32 value = read8(TIS_REG(locality, TIS_REG_INT_ENABLE)); + value = (value >> 3) & 0x3; + TPM_DEBUG_IO_READ(TIS_REG_INT_ENABLE, value); + return value; +} + +/* + * tis_wait_sts() + * + * Wait for at least a second for a status to change its state to match the + * expected state. Normally the transition happens within microseconds. + * + * @locality - locality + * @mask - bitmask for the bitfield(s) to watch + * @expected - value the field(s) are supposed to be set to + * + * Returns 0 on success or TPM_TIMEOUT_ERR on timeout. + */ +static int tis_wait_sts(int locality, u8 mask, u8 expected) +{ + u32 time_us = MAX_DELAY_US; + while (time_us > 0) { + u8 value = tpm_read_status(locality); + if ((value & mask) == expected) + return 0; + udelay(1); /* 1 us */ + time_us--; + } + return TPM_TIMEOUT_ERR; +} + +static inline int tis_wait_ready(int locality) +{ + return tis_wait_sts(locality, TIS_STS_COMMAND_READY, + TIS_STS_COMMAND_READY); +} + +static inline int tis_wait_valid(int locality) +{ + return tis_wait_sts(locality, TIS_STS_VALID, TIS_STS_VALID); +} + +static inline int tis_wait_valid_data(int locality) +{ + const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID; + return tis_wait_sts(locality, has_data, has_data); +} + +static inline int tis_has_valid_data(int locality) +{ + const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID; + return (tpm_read_status(locality) & has_data) == has_data; +} + +static inline int tis_expect_data(int locality) +{ + return !!(tpm_read_status(locality) & TIS_STS_EXPECT); +} + +/* + * tis_wait_access() + * + * Wait for at least a second for a access to change its state to match the + * expected state. Normally the transition happens within microseconds. + * + * @locality - locality + * @mask - bitmask for the bitfield(s) to watch + * @expected - value the field(s) are supposed to be set to + * + * Returns 0 on success or TPM_TIMEOUT_ERR on timeout. + */ +static int tis_wait_access(int locality, u8 mask, u8 expected) +{ + u32 time_us = MAX_DELAY_US; + while (time_us > 0) { + u8 value = tpm_read_access(locality); + if ((value & mask) == expected) + return 0; + udelay(1); /* 1 us */ + time_us--; + } + return TPM_TIMEOUT_ERR; +} + +static inline int tis_wait_dropped_access(int locality) +{ + return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, 0); +} + +static inline int tis_wait_received_access(int locality) +{ + return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, + TIS_ACCESS_ACTIVE_LOCALITY); +} + +static inline int tis_has_access(int locality) +{ + return !!(tpm_read_access(locality) & TIS_ACCESS_ACTIVE_LOCALITY); +} + +static inline void tis_request_access(int locality) +{ + tpm_write_access(TIS_ACCESS_REQUEST_USE, locality); +} + +static inline void tis_drop_access(int locality) +{ + tpm_write_access(TIS_ACCESS_ACTIVE_LOCALITY, locality); +} + +/* + * PC Client Specific TPM Interface Specification section 11.2.12: + * + * Software must be prepared to send two writes of a "1" to command ready + * field: the first to indicate successful read of all the data, thus + * clearing the data from the ReadFIFO and freeing the TPM's resources, + * and the second to indicate to the TPM it is about to send a new command. + * + * In practice not all TPMs behave the same so it is necessary to be + * flexible when trying to set command ready. + * + * Returns 0 on success if the TPM is ready for transactions. + * Returns TPM_TIMEOUT_ERR if the command ready bit does not get set. + */ +static int tis_command_ready(u8 locality) +{ + u32 status; + + /* 1st attempt to set command ready */ + tpm_write_status(TIS_STS_COMMAND_READY, locality); + + /* Wait for response */ + status = tpm_read_status(locality); + + /* Check if command ready is set yet */ + if (status & TIS_STS_COMMAND_READY) + return 0; + + /* 2nd attempt to set command ready */ + tpm_write_status(TIS_STS_COMMAND_READY, locality); + + return tis_wait_ready(locality); +} + +/* + * Probe the TPM device and try determining its manufacturer/device name. + * + * Returns 0 on success (the device is found or was found during an earlier + * invocation) or TPM_DRIVER_ERR if the device is not found. + */ +static u32 tis_probe(void) +{ + const char *device_name = "unknown"; + const char *vendor_name = device_name; + const struct device_name *dev; + u32 didvid; + u16 vid, did; + int i; + + if (car_get_var(vendor_dev_id)) + return 0; /* Already probed. */ + + didvid = tpm_read_did_vid(0); + if (!didvid || (didvid == 0xffffffff)) { + printf("%s: No TPM device found\n", __FUNCTION__); + return TPM_DRIVER_ERR; + } + + car_set_var(vendor_dev_id, didvid); + + vid = didvid & 0xffff; + did = (didvid >> 16) & 0xffff; + for (i = 0; i < ARRAY_SIZE(vendor_names); i++) { + int j = 0; + u16 known_did; + if (vid == vendor_names[i].vendor_id) { + vendor_name = vendor_names[i].vendor_name; + } else { + continue; + } + dev = &vendor_names[i].dev_names[j]; + while ((known_did = dev->dev_id) != 0xffff) { + if (known_did == did) { + device_name = dev->dev_name; + break; + } + j++; + dev = &vendor_names[i].dev_names[j]; + } + break; + } + /* this will have to be converted into debug printout */ + printk(BIOS_INFO, "Found TPM %s by %s\n", device_name, vendor_name); + return 0; +} + +/* + * tis_senddata() + * + * send the passed in data to the TPM device. + * + * @data - address of the data to send, byte by byte + * @len - length of the data to send + * + * Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does + * not accept the entire command). + */ +static u32 tis_senddata(const u8 * const data, u32 len) +{ + u32 offset = 0; + u16 burst = 0; + u32 max_cycles = 0; + u8 locality = 0; + + if (tis_wait_ready(locality)) { + printf("%s:%d - failed to get 'command_ready' status\n", + __FILE__, __LINE__); + return TPM_DRIVER_ERR; + } + burst = tpm_read_burst_count(locality); + + while (1) { + unsigned count; + + /* Wait till the device is ready to accept more data. */ + while (!burst) { + if (max_cycles++ == MAX_DELAY_US) { + printf("%s:%d failed to feed %d bytes of %d\n", + __FILE__, __LINE__, len - offset, len); + return TPM_DRIVER_ERR; + } + udelay(1); + burst = tpm_read_burst_count(locality); + } + + max_cycles = 0; + + /* + * Calculate number of bytes the TPM is ready to accept in one + * shot. + * + * We want to send the last byte outside of the loop (hence + * the -1 below) to make sure that the 'expected' status bit + * changes to zero exactly after the last byte is fed into the + * FIFO. + */ + count = min(burst, len - offset - 1); + while (count--) + tpm_write_data(data[offset++], locality); + + if (tis_wait_valid(locality) || !tis_expect_data(locality)) { + printf("%s:%d TPM command feed overflow\n", + __FILE__, __LINE__); + return TPM_DRIVER_ERR; + } + + burst = tpm_read_burst_count(locality); + if ((offset == (len - 1)) && burst) + /* + * We need to be able to send the last byte to the + * device, so burst size must be nonzero before we + * break out. + */ + break; + } + + /* Send the last byte. */ + tpm_write_data(data[offset++], locality); + + /* + * Verify that TPM does not expect any more data as part of this + * command. + */ + if (tis_wait_valid(locality) || tis_expect_data(locality)) { + printf("%s:%d unexpected TPM status 0x%x\n", + __FILE__, __LINE__, tpm_read_status(locality)); + return TPM_DRIVER_ERR; + } + + /* OK, sitting pretty, let's start the command execution. */ + tpm_write_status(TIS_STS_TPM_GO, locality); + + return 0; +} + +/* + * tis_readresponse() + * + * read the TPM device response after a command was issued. + * + * @buffer - address where to read the response, byte by byte. + * @len - pointer to the size of buffer + * + * On success stores the number of received bytes to len and returns 0. On + * errors (misformatted TPM data or synchronization problems) returns + * TPM_DRIVER_ERR. + */ +static u32 tis_readresponse(u8 *buffer, size_t *len) +{ + u16 burst_count; + u32 offset = 0; + u8 locality = 0; + u32 expected_count = *len; + int max_cycles = 0; + + /* Wait for the TPM to process the command */ + if (tis_wait_valid_data(locality)) { + printf("%s:%d failed processing command\n", __FILE__, __LINE__); + return TPM_DRIVER_ERR; + } + + do { + while ((burst_count = tpm_read_burst_count(locality)) == 0) { + if (max_cycles++ == MAX_DELAY_US) { + printf("%s:%d TPM stuck on read\n", + __FILE__, __LINE__); + return TPM_DRIVER_ERR; + } + udelay(1); + } + + max_cycles = 0; + + while (burst_count-- && (offset < expected_count)) { + buffer[offset++] = tpm_read_data(locality); + if (offset == 6) { + /* + * We got the first six bytes of the reply, + * let's figure out how many bytes to expect + * total - it is stored as a 4 byte number in + * network order, starting with offset 2 into + * the body of the reply. + */ + u32 real_length; + memcpy(&real_length, + buffer + 2, + sizeof(real_length)); + expected_count = be32_to_cpu(real_length); + + if ((expected_count < offset) || + (expected_count > *len)) { + printf("%s:%d bad response size %d\n", + __FILE__, __LINE__, + expected_count); + return TPM_DRIVER_ERR; + } + } + } + + /* Wait for the next portion */ + if (tis_wait_valid(locality)) { + printf("%s:%d failed to read response\n", + __FILE__, __LINE__); + return TPM_DRIVER_ERR; + } + + if (offset == expected_count) + break; /* We got all we need */ + + } while (tis_has_valid_data(locality)); + + /* * Make sure we indeed read all there was. */ + if (tis_has_valid_data(locality)) { + printf("%s:%d wrong receive status: %x %d bytes left\n", + __FILE__, __LINE__, tpm_read_status(locality), + tpm_read_burst_count(locality)); + return TPM_DRIVER_ERR; + } + + /* Tell the TPM that we are done. */ + if (tis_command_ready(locality) == TPM_TIMEOUT_ERR) + return TPM_DRIVER_ERR; + + *len = offset; + return 0; +} + +/* + * tis_init() + * + * Initialize the TPM device. Returns 0 on success or TPM_DRIVER_ERR on + * failure (in case device probing did not succeed). + */ +int tis_init(void) +{ + if (tis_probe()) + return TPM_DRIVER_ERR; + return 0; +} + +/* + * tis_open() + * + * Requests access to locality 0 for the caller. After all commands have been + * completed the caller is supposed to call tis_close(). + * + * Returns 0 on success, TPM_DRIVER_ERR on failure. + */ +int tis_open(void) +{ + u8 locality = 0; /* we use locality zero for everything */ + + if (tis_close()) + return TPM_DRIVER_ERR; + + /* now request access to locality */ + tis_request_access(locality); + + /* did we get a lock? */ + if (tis_wait_received_access(locality)) { + printf("%s:%d - failed to lock locality %d\n", + __FILE__, __LINE__, locality); + return TPM_DRIVER_ERR; + } + + /* Certain TPMs seem to need some delay here or they hang... */ + udelay(10); + + if (tis_command_ready(locality) == TPM_TIMEOUT_ERR) + return TPM_DRIVER_ERR; + + return 0; +} + +/* + * tis_close() + * + * terminate the current session with the TPM by releasing the locked + * locality. Returns 0 on success of TPM_DRIVER_ERR on failure (in case lock + * removal did not succeed). + */ +int tis_close(void) +{ + u8 locality = 0; + if (tis_has_access(locality)) { + tis_drop_access(locality); + if (tis_wait_dropped_access(locality)) { + printf("%s:%d - failed to release locality %d\n", + __FILE__, __LINE__, locality); + return TPM_DRIVER_ERR; + } + } + return 0; +} + +/* + * tis_sendrecv() + * + * Send the requested data to the TPM and then try to get its response + * + * @sendbuf - buffer of the data to send + * @send_size size of the data to send + * @recvbuf - memory to save the response to + * @recv_len - pointer to the size of the response buffer + * + * Returns 0 on success (and places the number of response bytes at recv_len) + * or TPM_DRIVER_ERR on failure. + */ +int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, + uint8_t *recvbuf, size_t *recv_len) +{ + if (tis_senddata(sendbuf, send_size)) { + printf("%s:%d failed sending data to TPM\n", + __FILE__, __LINE__); + return TPM_DRIVER_ERR; + } + + return tis_readresponse(recvbuf, recv_len); +} + +#ifdef __RAMSTAGE__ + +/* + * tis_setup_interrupt() + * + * Set up the interrupt vector and polarity for locality 0 and + * disable all interrupts so they are unused in firmware but can + * be enabled by the OS. + * + * The values used here must match what is passed in the TPM ACPI + * device if ACPI is used on the platform. + * + * @vector - TPM interrupt vector + * @polarity - TPM interrupt polarity + * + * Returns 0 on success, TPM_DRIVER_ERR on failure. + */ +static int tis_setup_interrupt(int vector, int polarity) +{ + u8 locality = 0; + int has_access = tis_has_access(locality); + + /* Open connection and request access if not already granted */ + if (!has_access && tis_open() < 0) + return TPM_DRIVER_ERR; + + /* Set TPM interrupt vector */ + tpm_write_int_vector(vector, locality); + + /* Set TPM interupt polarity and disable interrupts */ + tpm_write_int_polarity(polarity, locality); + + /* Close connection if it was opened */ + if (!has_access && tis_close() < 0) + return TPM_DRIVER_ERR; + + return 0; +} + +static void lpc_tpm_read_resources(struct device *dev) +{ + /* Static 5K memory region specified in Kconfig */ + mmio_resource(dev, 0, CONFIG_TPM_TIS_BASE_ADDRESS >> 10, 0x5000 >> 10); +} + +static void lpc_tpm_set_resources(struct device *dev) +{ + tpm_config_t *config = (tpm_config_t *)dev->chip_info; + struct resource *res; + + for (res = dev->resource_list; res; res = res->next) { + if (!(res->flags & IORESOURCE_ASSIGNED)) + continue; + + if (res->flags & IORESOURCE_IRQ) { + /* Set interrupt vector */ + tis_setup_interrupt((int)res->base, + config->irq_polarity); + } else { + continue; + } + + res->flags |= IORESOURCE_STORED; + report_resource_stored(dev, res, " "); + } +} + +#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) + +static void tpm_ppi_func0_cb(void *arg) +{ + /* Functions 1-8. */ + u8 buf[] = {0xff, 0x01}; + acpigen_write_return_byte_buffer(buf, 2); +} + +static void tpm_ppi_func1_cb(void *arg) +{ + if (IS_ENABLED(CONFIG_TPM2)) + /* Interface version: 2.0 */ + acpigen_write_return_string("2.0"); + else + /* Interface version: 1.2 */ + acpigen_write_return_string("1.2"); +} + +static void tpm_ppi_func2_cb(void *arg) +{ + /* Submit operations: drop on the floor and return success. */ + acpigen_write_return_byte(0); +} + +static void tpm_ppi_func3_cb(void *arg) +{ + /* Pending operation: none. */ + acpigen_emit_byte(RETURN_OP); + acpigen_write_package(2); + acpigen_write_byte(0); + acpigen_write_byte(0); + acpigen_pop_len(); +} +static void tpm_ppi_func4_cb(void *arg) +{ + /* Pre-OS transition method: reboot. */ + acpigen_write_return_byte(2); +} +static void tpm_ppi_func5_cb(void *arg) +{ + /* Operation response: no operation executed. */ + acpigen_emit_byte(RETURN_OP); + acpigen_write_package(3); + acpigen_write_byte(0); + acpigen_write_byte(0); + acpigen_write_byte(0); + acpigen_pop_len(); +} +static void tpm_ppi_func6_cb(void *arg) +{ + /* + * Set preferred user language: deprecated and must return 3 aka + * "not implemented". + */ + acpigen_write_return_byte(3); +} +static void tpm_ppi_func7_cb(void *arg) +{ + /* Submit operations: deny. */ + acpigen_write_return_byte(3); +} +static void tpm_ppi_func8_cb(void *arg) +{ + /* All actions are forbidden. */ + acpigen_write_return_byte(1); +} +static void (*tpm_ppi_callbacks[])(void *) = { + tpm_ppi_func0_cb, + tpm_ppi_func1_cb, + tpm_ppi_func2_cb, + tpm_ppi_func3_cb, + tpm_ppi_func4_cb, + tpm_ppi_func5_cb, + tpm_ppi_func6_cb, + tpm_ppi_func7_cb, + tpm_ppi_func8_cb, +}; + +static void tpm_mci_func0_cb(void *arg) +{ + /* Function 1. */ + acpigen_write_return_singleton_buffer(0x3); +} +static void tpm_mci_func1_cb(void *arg) +{ + /* Just return success. */ + acpigen_write_return_byte(0); +} + +static void (*tpm_mci_callbacks[])(void *) = { + tpm_mci_func0_cb, + tpm_mci_func1_cb, +}; + +static void lpc_tpm_fill_ssdt(struct device *dev) +{ + const char *path = acpi_device_path(dev->bus->dev); + u32 arg; + + if (!path) { + path = "\\_SB_.PCI0.LPCB"; + printk(BIOS_DEBUG, "Using default TPM ACPI path: '%s'\n", path); + } + + /* Device */ + acpigen_write_scope(path); + acpigen_write_device(acpi_device_name(dev)); + + acpigen_write_name("_HID"); + acpigen_emit_eisaid("PNP0C31"); + + acpigen_write_name("_CID"); + acpigen_emit_eisaid("PNP0C31"); + + acpigen_write_name_integer("_UID", 1); + + u32 did_vid = tpm_read_did_vid(0); + if (did_vid > 0 && did_vid < 0xffffffff) + acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON); + else + acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_OFF); + + /* Resources */ + acpigen_write_name("_CRS"); + acpigen_write_resourcetemplate_header(); + acpigen_write_mem32fixed(1, CONFIG_TPM_TIS_BASE_ADDRESS, 0x5000); + acpigen_write_io16(0x2e, 0x2e, 1, 2, 1); + + if (CONFIG_TPM_PIRQ) { + /* + * PIRQ: Update interrupt vector with configured PIRQ + * Active-Low Level-Triggered Shared + */ + struct acpi_irq tpm_irq_a = ACPI_IRQ_LEVEL_LOW(CONFIG_TPM_PIRQ); + acpi_device_write_interrupt(&tpm_irq_a); + } else if (tpm_read_int_vector(0) > 0) { + u8 int_vec = tpm_read_int_vector(0); + u8 int_pol = tpm_read_int_polarity(0); + struct acpi_irq tpm_irq = ACPI_IRQ_LEVEL_LOW(int_vec); + + if (int_pol & 1) + tpm_irq.polarity = ACPI_IRQ_ACTIVE_LOW; + else + tpm_irq.polarity = ACPI_IRQ_ACTIVE_HIGH; + + if (int_pol & 2) + tpm_irq.mode = ACPI_IRQ_EDGE_TRIGGERED; + else + tpm_irq.mode = ACPI_IRQ_LEVEL_TRIGGERED; + + acpi_device_write_interrupt(&tpm_irq); + } + + acpigen_write_resourcetemplate_footer(); + + if (!IS_ENABLED(CONFIG_CHROMEOS)) { + /* + * _DSM method + */ + struct dsm_uuid ids[] = { + /* Physical presence interface. + * This is used to submit commands like "Clear TPM" to + * be run at next reboot provided that user confirms + * them. Spec allows user to cancel all commands and/or + * configure BIOS to reject commands. So we pretend that + * user did just this: cancelled everything. If user + * really wants to clear TPM the only option now is to + * do it manually in payload. + */ + DSM_UUID(TPM_PPI_UUID, &tpm_ppi_callbacks[0], + ARRAY_SIZE(tpm_ppi_callbacks), (void *) &arg), + /* Memory clearing on boot: just a dummy. */ + DSM_UUID(TPM_MCI_UUID, &tpm_mci_callbacks[0], + ARRAY_SIZE(tpm_mci_callbacks), (void *) &arg), + }; + + acpigen_write_dsm_uuid_arr(ids, ARRAY_SIZE(ids)); + } + acpigen_pop_len(); /* Device */ + acpigen_pop_len(); /* Scope */ + + printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev), + dev->chip_ops->name, dev_path(dev)); +} + +static const char *lpc_tpm_acpi_name(const struct device *dev) +{ + return "TPM"; +} +#endif + +static struct device_operations lpc_tpm_ops = { + .read_resources = &lpc_tpm_read_resources, + .set_resources = &lpc_tpm_set_resources, +#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) + .acpi_name = &lpc_tpm_acpi_name, + .acpi_fill_ssdt_generator = &lpc_tpm_fill_ssdt, +#endif +}; + +static struct pnp_info pnp_dev_info[] = { + { .flags = PNP_IRQ0 } +}; + +static void enable_dev(struct device *dev) +{ + pnp_enable_devices(dev, &lpc_tpm_ops, + ARRAY_SIZE(pnp_dev_info), pnp_dev_info); +} + +struct chip_operations drivers_pc80_tpm_ops = { + CHIP_NAME("LPC TPM") + .enable_dev = enable_dev +}; + +#endif /* __RAMSTAGE__ */ diff --git a/src/drivers/pc80/tpm/tpm.c b/src/drivers/pc80/tpm/tpm.c deleted file mode 100644 index 8f1c5df0aa..0000000000 --- a/src/drivers/pc80/tpm/tpm.c +++ /dev/null @@ -1,992 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2011 The Chromium OS 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. - */ - -/* - * The code in this file has been heavily based on the article "Writing a TPM - * Device Driver" published on http://ptgmedia.pearsoncmg.com and the - * submission by Stefan Berger on Qemu-devel mailing list. - * - * One principal difference is that in the simplest config the other than 0 - * TPM localities do not get mapped by some devices (for instance, by - * Infineon slb9635), so this driver provides access to locality 0 only. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "chip.h" - -#define PREFIX "lpc_tpm: " -/* TCG Physical Presence Interface */ -#define TPM_PPI_UUID "3dddfaa6-361b-4eb4-a424-8d10089d1653" -/* TCG Memory Clear Interface */ -#define TPM_MCI_UUID "376054ed-cc13-4675-901c-4756d7f2d45d" -/* coreboot wrapper for TPM driver (start) */ -#define TPM_DEBUG(fmt, args...) \ - if (IS_ENABLED(CONFIG_DEBUG_TPM)) { \ - printk(BIOS_DEBUG, PREFIX); \ - printk(BIOS_DEBUG, fmt , ##args); \ - } -#define TPM_DEBUG_IO_READ(reg_, val_) \ - TPM_DEBUG("Read reg 0x%x returns 0x%x\n", (reg_), (val_)) -#define TPM_DEBUG_IO_WRITE(reg_, val_) \ - TPM_DEBUG("Write reg 0x%x with 0x%x\n", (reg_), (val_)) -#define printf(x...) printk(BIOS_ERR, x) - -/* coreboot wrapper for TPM driver (end) */ - -/* the macro accepts the locality value, but only locality 0 is operational */ -#define TIS_REG(LOCALITY, REG) \ - (void *)(CONFIG_TPM_TIS_BASE_ADDRESS + (LOCALITY << 12) + REG) - -/* hardware registers' offsets */ -#define TIS_REG_ACCESS 0x0 -#define TIS_REG_INT_ENABLE 0x8 -#define TIS_REG_INT_VECTOR 0xc -#define TIS_REG_INT_STATUS 0x10 -#define TIS_REG_INTF_CAPABILITY 0x14 -#define TIS_REG_STS 0x18 -#define TIS_REG_BURST_COUNT 0x19 -#define TIS_REG_DATA_FIFO 0x24 -#define TIS_REG_DID_VID 0xf00 -#define TIS_REG_RID 0xf04 - -/* Some registers' bit field definitions */ -#define TIS_STS_VALID (1 << 7) /* 0x80 */ -#define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */ -#define TIS_STS_TPM_GO (1 << 5) /* 0x20 */ -#define TIS_STS_DATA_AVAILABLE (1 << 4) /* 0x10 */ -#define TIS_STS_EXPECT (1 << 3) /* 0x08 */ -#define TIS_STS_RESPONSE_RETRY (1 << 1) /* 0x02 */ - -#define TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */ -#define TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */ -#define TIS_ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */ -#define TIS_ACCESS_SEIZE (1 << 3) /* 0x08 */ -#define TIS_ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */ -#define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */ -#define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */ - -/* - * Error value returned if a tpm register does not enter the expected state - * after continuous polling. No actual TPM register reading ever returns ~0, - * so this value is a safe error indication to be mixed with possible status - * register values. - */ -#define TPM_TIMEOUT_ERR (~0) - -/* Error value returned on various TPM driver errors */ -#define TPM_DRIVER_ERR (~0) - - /* 1 second is plenty for anything TPM does.*/ -#define MAX_DELAY_US (1000 * 1000) - -/* - * Structures defined below allow creating descriptions of TPM vendor/device - * ID information for run time discovery. The only device the system knows - * about at this time is Infineon slb9635 - */ -struct device_name { - u16 dev_id; - const char * const dev_name; -}; - -struct vendor_name { - u16 vendor_id; - const char * vendor_name; - const struct device_name* dev_names; -}; - -static const struct device_name atmel_devices[] = { - {0x3204, "AT97SC3204"}, - {0xffff} -}; - -static const struct device_name infineon_devices[] = { - {0x000b, "SLB9635 TT 1.2"}, - {0x001a, "SLB9660 TT 1.2"}, -#if IS_ENABLED(CONFIG_TPM2) - {0x001b, "SLB9670 TT 2.0"}, -#else - {0x001b, "SLB9670 TT 1.2"}, -#endif - {0xffff} -}; - -static const struct device_name nuvoton_devices[] = { - {0x00fe, "NPCT420AA V2"}, - {0xffff} -}; - -static const struct device_name stmicro_devices[] = { - {0x0000, "ST33ZP24" }, - {0xffff} -}; - -static const struct vendor_name vendor_names[] = { - {0x1114, "Atmel", atmel_devices}, - {0x15d1, "Infineon", infineon_devices}, - {0x1050, "Nuvoton", nuvoton_devices}, - {0x104a, "ST Microelectronics", stmicro_devices}, -}; - -/* - * Cached vendor/device ID pair to indicate that the device has been already - * discovered - */ -static u32 vendor_dev_id CAR_GLOBAL; - -static inline u8 tpm_read_status(int locality) -{ - u8 value = read8(TIS_REG(locality, TIS_REG_STS)); - TPM_DEBUG_IO_READ(TIS_REG_STS, value); - return value; -} - -static inline void tpm_write_status(u8 sts, int locality) -{ - TPM_DEBUG_IO_WRITE(TIS_REG_STS, sts); - write8(TIS_REG(locality, TIS_REG_STS), sts); -} - -static inline u8 tpm_read_data(int locality) -{ - u8 value = read8(TIS_REG(locality, TIS_REG_DATA_FIFO)); - TPM_DEBUG_IO_READ(TIS_REG_DATA_FIFO, value); - return value; -} - -static inline void tpm_write_data(u8 data, int locality) -{ - TPM_DEBUG_IO_WRITE(TIS_REG_STS, data); - write8(TIS_REG(locality, TIS_REG_DATA_FIFO), data); -} - -static inline u16 tpm_read_burst_count(int locality) -{ - u16 count; - count = read8(TIS_REG(locality, TIS_REG_BURST_COUNT)); - count |= read8(TIS_REG(locality, TIS_REG_BURST_COUNT + 1)) << 8; - TPM_DEBUG_IO_READ(TIS_REG_BURST_COUNT, count); - return count; -} - -static inline u8 tpm_read_access(int locality) -{ - u8 value = read8(TIS_REG(locality, TIS_REG_ACCESS)); - TPM_DEBUG_IO_READ(TIS_REG_ACCESS, value); - return value; -} - -static inline void tpm_write_access(u8 data, int locality) -{ - TPM_DEBUG_IO_WRITE(TIS_REG_ACCESS, data); - write8(TIS_REG(locality, TIS_REG_ACCESS), data); -} - -static inline u32 tpm_read_did_vid(int locality) -{ - u32 value = read32(TIS_REG(locality, TIS_REG_DID_VID)); - TPM_DEBUG_IO_READ(TIS_REG_DID_VID, value); - return value; -} - -static inline void tpm_write_int_vector(int vector, int locality) -{ - TPM_DEBUG_IO_WRITE(TIS_REG_INT_VECTOR, vector); - write8(TIS_REG(locality, TIS_REG_INT_VECTOR), vector & 0xf); -} - -static inline u8 tpm_read_int_vector(int locality) -{ - u8 value = read8(TIS_REG(locality, TIS_REG_INT_VECTOR)); - TPM_DEBUG_IO_READ(TIS_REG_INT_VECTOR, value); - return value; -} - -static inline void tpm_write_int_polarity(int polarity, int locality) -{ - /* Set polarity and leave all other bits at 0 */ - u32 value = (polarity & 0x3) << 3; - TPM_DEBUG_IO_WRITE(TIS_REG_INT_ENABLE, value); - write32(TIS_REG(locality, TIS_REG_INT_ENABLE), value); -} - -static inline u32 tpm_read_int_polarity(int locality) -{ - /* Get polarity and leave all other bits */ - u32 value = read8(TIS_REG(locality, TIS_REG_INT_ENABLE)); - value = (value >> 3) & 0x3; - TPM_DEBUG_IO_READ(TIS_REG_INT_ENABLE, value); - return value; -} - -/* - * tis_wait_sts() - * - * Wait for at least a second for a status to change its state to match the - * expected state. Normally the transition happens within microseconds. - * - * @locality - locality - * @mask - bitmask for the bitfield(s) to watch - * @expected - value the field(s) are supposed to be set to - * - * Returns 0 on success or TPM_TIMEOUT_ERR on timeout. - */ -static int tis_wait_sts(int locality, u8 mask, u8 expected) -{ - u32 time_us = MAX_DELAY_US; - while (time_us > 0) { - u8 value = tpm_read_status(locality); - if ((value & mask) == expected) - return 0; - udelay(1); /* 1 us */ - time_us--; - } - return TPM_TIMEOUT_ERR; -} - -static inline int tis_wait_ready(int locality) -{ - return tis_wait_sts(locality, TIS_STS_COMMAND_READY, - TIS_STS_COMMAND_READY); -} - -static inline int tis_wait_valid(int locality) -{ - return tis_wait_sts(locality, TIS_STS_VALID, TIS_STS_VALID); -} - -static inline int tis_wait_valid_data(int locality) -{ - const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID; - return tis_wait_sts(locality, has_data, has_data); -} - -static inline int tis_has_valid_data(int locality) -{ - const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID; - return (tpm_read_status(locality) & has_data) == has_data; -} - -static inline int tis_expect_data(int locality) -{ - return !!(tpm_read_status(locality) & TIS_STS_EXPECT); -} - -/* - * tis_wait_access() - * - * Wait for at least a second for a access to change its state to match the - * expected state. Normally the transition happens within microseconds. - * - * @locality - locality - * @mask - bitmask for the bitfield(s) to watch - * @expected - value the field(s) are supposed to be set to - * - * Returns 0 on success or TPM_TIMEOUT_ERR on timeout. - */ -static int tis_wait_access(int locality, u8 mask, u8 expected) -{ - u32 time_us = MAX_DELAY_US; - while (time_us > 0) { - u8 value = tpm_read_access(locality); - if ((value & mask) == expected) - return 0; - udelay(1); /* 1 us */ - time_us--; - } - return TPM_TIMEOUT_ERR; -} - -static inline int tis_wait_dropped_access(int locality) -{ - return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, 0); -} - -static inline int tis_wait_received_access(int locality) -{ - return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, - TIS_ACCESS_ACTIVE_LOCALITY); -} - -static inline int tis_has_access(int locality) -{ - return !!(tpm_read_access(locality) & TIS_ACCESS_ACTIVE_LOCALITY); -} - -static inline void tis_request_access(int locality) -{ - tpm_write_access(TIS_ACCESS_REQUEST_USE, locality); -} - -static inline void tis_drop_access(int locality) -{ - tpm_write_access(TIS_ACCESS_ACTIVE_LOCALITY, locality); -} - -/* - * PC Client Specific TPM Interface Specification section 11.2.12: - * - * Software must be prepared to send two writes of a "1" to command ready - * field: the first to indicate successful read of all the data, thus - * clearing the data from the ReadFIFO and freeing the TPM's resources, - * and the second to indicate to the TPM it is about to send a new command. - * - * In practice not all TPMs behave the same so it is necessary to be - * flexible when trying to set command ready. - * - * Returns 0 on success if the TPM is ready for transactions. - * Returns TPM_TIMEOUT_ERR if the command ready bit does not get set. - */ -static int tis_command_ready(u8 locality) -{ - u32 status; - - /* 1st attempt to set command ready */ - tpm_write_status(TIS_STS_COMMAND_READY, locality); - - /* Wait for response */ - status = tpm_read_status(locality); - - /* Check if command ready is set yet */ - if (status & TIS_STS_COMMAND_READY) - return 0; - - /* 2nd attempt to set command ready */ - tpm_write_status(TIS_STS_COMMAND_READY, locality); - - return tis_wait_ready(locality); -} - -/* - * Probe the TPM device and try determining its manufacturer/device name. - * - * Returns 0 on success (the device is found or was found during an earlier - * invocation) or TPM_DRIVER_ERR if the device is not found. - */ -static u32 tis_probe(void) -{ - const char *device_name = "unknown"; - const char *vendor_name = device_name; - const struct device_name *dev; - u32 didvid; - u16 vid, did; - int i; - - if (car_get_var(vendor_dev_id)) - return 0; /* Already probed. */ - - didvid = tpm_read_did_vid(0); - if (!didvid || (didvid == 0xffffffff)) { - printf("%s: No TPM device found\n", __FUNCTION__); - return TPM_DRIVER_ERR; - } - - car_set_var(vendor_dev_id, didvid); - - vid = didvid & 0xffff; - did = (didvid >> 16) & 0xffff; - for (i = 0; i < ARRAY_SIZE(vendor_names); i++) { - int j = 0; - u16 known_did; - if (vid == vendor_names[i].vendor_id) { - vendor_name = vendor_names[i].vendor_name; - } else { - continue; - } - dev = &vendor_names[i].dev_names[j]; - while ((known_did = dev->dev_id) != 0xffff) { - if (known_did == did) { - device_name = dev->dev_name; - break; - } - j++; - dev = &vendor_names[i].dev_names[j]; - } - break; - } - /* this will have to be converted into debug printout */ - printk(BIOS_INFO, "Found TPM %s by %s\n", device_name, vendor_name); - return 0; -} - -/* - * tis_senddata() - * - * send the passed in data to the TPM device. - * - * @data - address of the data to send, byte by byte - * @len - length of the data to send - * - * Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does - * not accept the entire command). - */ -static u32 tis_senddata(const u8 * const data, u32 len) -{ - u32 offset = 0; - u16 burst = 0; - u32 max_cycles = 0; - u8 locality = 0; - - if (tis_wait_ready(locality)) { - printf("%s:%d - failed to get 'command_ready' status\n", - __FILE__, __LINE__); - return TPM_DRIVER_ERR; - } - burst = tpm_read_burst_count(locality); - - while (1) { - unsigned count; - - /* Wait till the device is ready to accept more data. */ - while (!burst) { - if (max_cycles++ == MAX_DELAY_US) { - printf("%s:%d failed to feed %d bytes of %d\n", - __FILE__, __LINE__, len - offset, len); - return TPM_DRIVER_ERR; - } - udelay(1); - burst = tpm_read_burst_count(locality); - } - - max_cycles = 0; - - /* - * Calculate number of bytes the TPM is ready to accept in one - * shot. - * - * We want to send the last byte outside of the loop (hence - * the -1 below) to make sure that the 'expected' status bit - * changes to zero exactly after the last byte is fed into the - * FIFO. - */ - count = min(burst, len - offset - 1); - while (count--) - tpm_write_data(data[offset++], locality); - - if (tis_wait_valid(locality) || !tis_expect_data(locality)) { - printf("%s:%d TPM command feed overflow\n", - __FILE__, __LINE__); - return TPM_DRIVER_ERR; - } - - burst = tpm_read_burst_count(locality); - if ((offset == (len - 1)) && burst) - /* - * We need to be able to send the last byte to the - * device, so burst size must be nonzero before we - * break out. - */ - break; - } - - /* Send the last byte. */ - tpm_write_data(data[offset++], locality); - - /* - * Verify that TPM does not expect any more data as part of this - * command. - */ - if (tis_wait_valid(locality) || tis_expect_data(locality)) { - printf("%s:%d unexpected TPM status 0x%x\n", - __FILE__, __LINE__, tpm_read_status(locality)); - return TPM_DRIVER_ERR; - } - - /* OK, sitting pretty, let's start the command execution. */ - tpm_write_status(TIS_STS_TPM_GO, locality); - - return 0; -} - -/* - * tis_readresponse() - * - * read the TPM device response after a command was issued. - * - * @buffer - address where to read the response, byte by byte. - * @len - pointer to the size of buffer - * - * On success stores the number of received bytes to len and returns 0. On - * errors (misformatted TPM data or synchronization problems) returns - * TPM_DRIVER_ERR. - */ -static u32 tis_readresponse(u8 *buffer, size_t *len) -{ - u16 burst_count; - u32 offset = 0; - u8 locality = 0; - u32 expected_count = *len; - int max_cycles = 0; - - /* Wait for the TPM to process the command */ - if (tis_wait_valid_data(locality)) { - printf("%s:%d failed processing command\n", __FILE__, __LINE__); - return TPM_DRIVER_ERR; - } - - do { - while ((burst_count = tpm_read_burst_count(locality)) == 0) { - if (max_cycles++ == MAX_DELAY_US) { - printf("%s:%d TPM stuck on read\n", - __FILE__, __LINE__); - return TPM_DRIVER_ERR; - } - udelay(1); - } - - max_cycles = 0; - - while (burst_count-- && (offset < expected_count)) { - buffer[offset++] = tpm_read_data(locality); - if (offset == 6) { - /* - * We got the first six bytes of the reply, - * let's figure out how many bytes to expect - * total - it is stored as a 4 byte number in - * network order, starting with offset 2 into - * the body of the reply. - */ - u32 real_length; - memcpy(&real_length, - buffer + 2, - sizeof(real_length)); - expected_count = be32_to_cpu(real_length); - - if ((expected_count < offset) || - (expected_count > *len)) { - printf("%s:%d bad response size %d\n", - __FILE__, __LINE__, - expected_count); - return TPM_DRIVER_ERR; - } - } - } - - /* Wait for the next portion */ - if (tis_wait_valid(locality)) { - printf("%s:%d failed to read response\n", - __FILE__, __LINE__); - return TPM_DRIVER_ERR; - } - - if (offset == expected_count) - break; /* We got all we need */ - - } while (tis_has_valid_data(locality)); - - /* * Make sure we indeed read all there was. */ - if (tis_has_valid_data(locality)) { - printf("%s:%d wrong receive status: %x %d bytes left\n", - __FILE__, __LINE__, tpm_read_status(locality), - tpm_read_burst_count(locality)); - return TPM_DRIVER_ERR; - } - - /* Tell the TPM that we are done. */ - if (tis_command_ready(locality) == TPM_TIMEOUT_ERR) - return TPM_DRIVER_ERR; - - *len = offset; - return 0; -} - -/* - * tis_init() - * - * Initialize the TPM device. Returns 0 on success or TPM_DRIVER_ERR on - * failure (in case device probing did not succeed). - */ -int tis_init(void) -{ - if (tis_probe()) - return TPM_DRIVER_ERR; - return 0; -} - -/* - * tis_open() - * - * Requests access to locality 0 for the caller. After all commands have been - * completed the caller is supposed to call tis_close(). - * - * Returns 0 on success, TPM_DRIVER_ERR on failure. - */ -int tis_open(void) -{ - u8 locality = 0; /* we use locality zero for everything */ - - if (tis_close()) - return TPM_DRIVER_ERR; - - /* now request access to locality */ - tis_request_access(locality); - - /* did we get a lock? */ - if (tis_wait_received_access(locality)) { - printf("%s:%d - failed to lock locality %d\n", - __FILE__, __LINE__, locality); - return TPM_DRIVER_ERR; - } - - /* Certain TPMs seem to need some delay here or they hang... */ - udelay(10); - - if (tis_command_ready(locality) == TPM_TIMEOUT_ERR) - return TPM_DRIVER_ERR; - - return 0; -} - -/* - * tis_close() - * - * terminate the current session with the TPM by releasing the locked - * locality. Returns 0 on success of TPM_DRIVER_ERR on failure (in case lock - * removal did not succeed). - */ -int tis_close(void) -{ - u8 locality = 0; - if (tis_has_access(locality)) { - tis_drop_access(locality); - if (tis_wait_dropped_access(locality)) { - printf("%s:%d - failed to release locality %d\n", - __FILE__, __LINE__, locality); - return TPM_DRIVER_ERR; - } - } - return 0; -} - -/* - * tis_sendrecv() - * - * Send the requested data to the TPM and then try to get its response - * - * @sendbuf - buffer of the data to send - * @send_size size of the data to send - * @recvbuf - memory to save the response to - * @recv_len - pointer to the size of the response buffer - * - * Returns 0 on success (and places the number of response bytes at recv_len) - * or TPM_DRIVER_ERR on failure. - */ -int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, - uint8_t *recvbuf, size_t *recv_len) -{ - if (tis_senddata(sendbuf, send_size)) { - printf("%s:%d failed sending data to TPM\n", - __FILE__, __LINE__); - return TPM_DRIVER_ERR; - } - - return tis_readresponse(recvbuf, recv_len); -} - -#ifdef __RAMSTAGE__ - -/* - * tis_setup_interrupt() - * - * Set up the interrupt vector and polarity for locality 0 and - * disable all interrupts so they are unused in firmware but can - * be enabled by the OS. - * - * The values used here must match what is passed in the TPM ACPI - * device if ACPI is used on the platform. - * - * @vector - TPM interrupt vector - * @polarity - TPM interrupt polarity - * - * Returns 0 on success, TPM_DRIVER_ERR on failure. - */ -static int tis_setup_interrupt(int vector, int polarity) -{ - u8 locality = 0; - int has_access = tis_has_access(locality); - - /* Open connection and request access if not already granted */ - if (!has_access && tis_open() < 0) - return TPM_DRIVER_ERR; - - /* Set TPM interrupt vector */ - tpm_write_int_vector(vector, locality); - - /* Set TPM interupt polarity and disable interrupts */ - tpm_write_int_polarity(polarity, locality); - - /* Close connection if it was opened */ - if (!has_access && tis_close() < 0) - return TPM_DRIVER_ERR; - - return 0; -} - -static void lpc_tpm_read_resources(struct device *dev) -{ - /* Static 5K memory region specified in Kconfig */ - mmio_resource(dev, 0, CONFIG_TPM_TIS_BASE_ADDRESS >> 10, 0x5000 >> 10); -} - -static void lpc_tpm_set_resources(struct device *dev) -{ - tpm_config_t *config = (tpm_config_t *)dev->chip_info; - struct resource *res; - - for (res = dev->resource_list; res; res = res->next) { - if (!(res->flags & IORESOURCE_ASSIGNED)) - continue; - - if (res->flags & IORESOURCE_IRQ) { - /* Set interrupt vector */ - tis_setup_interrupt((int)res->base, - config->irq_polarity); - } else { - continue; - } - - res->flags |= IORESOURCE_STORED; - report_resource_stored(dev, res, " "); - } -} - -#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) - -static void tpm_ppi_func0_cb(void *arg) -{ - /* Functions 1-8. */ - u8 buf[] = {0xff, 0x01}; - acpigen_write_return_byte_buffer(buf, 2); -} - -static void tpm_ppi_func1_cb(void *arg) -{ - if (IS_ENABLED(CONFIG_TPM2)) - /* Interface version: 2.0 */ - acpigen_write_return_string("2.0"); - else - /* Interface version: 1.2 */ - acpigen_write_return_string("1.2"); -} - -static void tpm_ppi_func2_cb(void *arg) -{ - /* Submit operations: drop on the floor and return success. */ - acpigen_write_return_byte(0); -} - -static void tpm_ppi_func3_cb(void *arg) -{ - /* Pending operation: none. */ - acpigen_emit_byte(RETURN_OP); - acpigen_write_package(2); - acpigen_write_byte(0); - acpigen_write_byte(0); - acpigen_pop_len(); -} -static void tpm_ppi_func4_cb(void *arg) -{ - /* Pre-OS transition method: reboot. */ - acpigen_write_return_byte(2); -} -static void tpm_ppi_func5_cb(void *arg) -{ - /* Operation response: no operation executed. */ - acpigen_emit_byte(RETURN_OP); - acpigen_write_package(3); - acpigen_write_byte(0); - acpigen_write_byte(0); - acpigen_write_byte(0); - acpigen_pop_len(); -} -static void tpm_ppi_func6_cb(void *arg) -{ - /* - * Set preferred user language: deprecated and must return 3 aka - * "not implemented". - */ - acpigen_write_return_byte(3); -} -static void tpm_ppi_func7_cb(void *arg) -{ - /* Submit operations: deny. */ - acpigen_write_return_byte(3); -} -static void tpm_ppi_func8_cb(void *arg) -{ - /* All actions are forbidden. */ - acpigen_write_return_byte(1); -} -static void (*tpm_ppi_callbacks[])(void *) = { - tpm_ppi_func0_cb, - tpm_ppi_func1_cb, - tpm_ppi_func2_cb, - tpm_ppi_func3_cb, - tpm_ppi_func4_cb, - tpm_ppi_func5_cb, - tpm_ppi_func6_cb, - tpm_ppi_func7_cb, - tpm_ppi_func8_cb, -}; - -static void tpm_mci_func0_cb(void *arg) -{ - /* Function 1. */ - acpigen_write_return_singleton_buffer(0x3); -} -static void tpm_mci_func1_cb(void *arg) -{ - /* Just return success. */ - acpigen_write_return_byte(0); -} - -static void (*tpm_mci_callbacks[])(void *) = { - tpm_mci_func0_cb, - tpm_mci_func1_cb, -}; - -static void lpc_tpm_fill_ssdt(struct device *dev) -{ - const char *path = acpi_device_path(dev->bus->dev); - u32 arg; - - if (!path) { - path = "\\_SB_.PCI0.LPCB"; - printk(BIOS_DEBUG, "Using default TPM ACPI path: '%s'\n", path); - } - - /* Device */ - acpigen_write_scope(path); - acpigen_write_device(acpi_device_name(dev)); - - acpigen_write_name("_HID"); - acpigen_emit_eisaid("PNP0C31"); - - acpigen_write_name("_CID"); - acpigen_emit_eisaid("PNP0C31"); - - acpigen_write_name_integer("_UID", 1); - - u32 did_vid = tpm_read_did_vid(0); - if (did_vid > 0 && did_vid < 0xffffffff) - acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON); - else - acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_OFF); - - /* Resources */ - acpigen_write_name("_CRS"); - acpigen_write_resourcetemplate_header(); - acpigen_write_mem32fixed(1, CONFIG_TPM_TIS_BASE_ADDRESS, 0x5000); - acpigen_write_io16(0x2e, 0x2e, 1, 2, 1); - - if (CONFIG_TPM_PIRQ) { - /* - * PIRQ: Update interrupt vector with configured PIRQ - * Active-Low Level-Triggered Shared - */ - struct acpi_irq tpm_irq_a = ACPI_IRQ_LEVEL_LOW(CONFIG_TPM_PIRQ); - acpi_device_write_interrupt(&tpm_irq_a); - } else if (tpm_read_int_vector(0) > 0) { - u8 int_vec = tpm_read_int_vector(0); - u8 int_pol = tpm_read_int_polarity(0); - struct acpi_irq tpm_irq = ACPI_IRQ_LEVEL_LOW(int_vec); - - if (int_pol & 1) - tpm_irq.polarity = ACPI_IRQ_ACTIVE_LOW; - else - tpm_irq.polarity = ACPI_IRQ_ACTIVE_HIGH; - - if (int_pol & 2) - tpm_irq.mode = ACPI_IRQ_EDGE_TRIGGERED; - else - tpm_irq.mode = ACPI_IRQ_LEVEL_TRIGGERED; - - acpi_device_write_interrupt(&tpm_irq); - } - - acpigen_write_resourcetemplate_footer(); - - if (!IS_ENABLED(CONFIG_CHROMEOS)) { - /* - * _DSM method - */ - struct dsm_uuid ids[] = { - /* Physical presence interface. - * This is used to submit commands like "Clear TPM" to - * be run at next reboot provided that user confirms - * them. Spec allows user to cancel all commands and/or - * configure BIOS to reject commands. So we pretend that - * user did just this: cancelled everything. If user - * really wants to clear TPM the only option now is to - * do it manually in payload. - */ - DSM_UUID(TPM_PPI_UUID, &tpm_ppi_callbacks[0], - ARRAY_SIZE(tpm_ppi_callbacks), (void *) &arg), - /* Memory clearing on boot: just a dummy. */ - DSM_UUID(TPM_MCI_UUID, &tpm_mci_callbacks[0], - ARRAY_SIZE(tpm_mci_callbacks), (void *) &arg), - }; - - acpigen_write_dsm_uuid_arr(ids, ARRAY_SIZE(ids)); - } - acpigen_pop_len(); /* Device */ - acpigen_pop_len(); /* Scope */ - - printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev), - dev->chip_ops->name, dev_path(dev)); -} - -static const char *lpc_tpm_acpi_name(const struct device *dev) -{ - return "TPM"; -} -#endif - -static struct device_operations lpc_tpm_ops = { - .read_resources = &lpc_tpm_read_resources, - .set_resources = &lpc_tpm_set_resources, -#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES) - .acpi_name = &lpc_tpm_acpi_name, - .acpi_fill_ssdt_generator = &lpc_tpm_fill_ssdt, -#endif -}; - -static struct pnp_info pnp_dev_info[] = { - { .flags = PNP_IRQ0 } -}; - -static void enable_dev(struct device *dev) -{ - pnp_enable_devices(dev, &lpc_tpm_ops, - ARRAY_SIZE(pnp_dev_info), pnp_dev_info); -} - -struct chip_operations drivers_pc80_tpm_ops = { - CHIP_NAME("LPC TPM") - .enable_dev = enable_dev -}; - -#endif /* __RAMSTAGE__ */ diff --git a/src/drivers/spi/tpm/tis.c b/src/drivers/spi/tpm/tis.c index f561a97280..40bf27dee2 100644 --- a/src/drivers/spi/tpm/tis.c +++ b/src/drivers/spi/tpm/tis.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "tpm.h" diff --git a/src/drivers/spi/tpm/tpm.c b/src/drivers/spi/tpm/tpm.c index c7a3ab7749..c0fee46dc7 100644 --- a/src/drivers/spi/tpm/tpm.c +++ b/src/drivers/spi/tpm/tpm.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include "tpm.h" diff --git a/src/mainboard/asus/kgpe-d16/romstage.c b/src/mainboard/asus/kgpe-d16/romstage.c index b52a698f33..89b654f149 100644 --- a/src/mainboard/asus/kgpe-d16/romstage.c +++ b/src/mainboard/asus/kgpe-d16/romstage.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include "resourcemap.c" #include "cpu/amd/quadcore/quadcore.c" diff --git a/src/mainboard/google/gru/chromeos.c b/src/mainboard/google/gru/chromeos.c index 8d0acbbf2d..ff5368a65c 100644 --- a/src/mainboard/google/gru/chromeos.c +++ b/src/mainboard/google/gru/chromeos.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include "board.h" diff --git a/src/mainboard/google/link/romstage.c b/src/mainboard/google/link/romstage.c index e23eced50f..b628e7efe1 100644 --- a/src/mainboard/google/link/romstage.c +++ b/src/mainboard/google/link/romstage.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/mainboard/google/oak/tpm_tis.c b/src/mainboard/google/oak/tpm_tis.c index ba019a6983..303cfc72b4 100644 --- a/src/mainboard/google/oak/tpm_tis.c +++ b/src/mainboard/google/oak/tpm_tis.c @@ -14,7 +14,7 @@ */ #include -#include +#include #include "gpio.h" diff --git a/src/mainboard/google/parrot/romstage.c b/src/mainboard/google/parrot/romstage.c index f34dac0705..2cfefdfbab 100644 --- a/src/mainboard/google/parrot/romstage.c +++ b/src/mainboard/google/parrot/romstage.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include "ec/compal/ene932/ec.h" void pch_enable_lpc(void) diff --git a/src/mainboard/google/stout/romstage.c b/src/mainboard/google/stout/romstage.c index 90313fb848..0710f02e3d 100644 --- a/src/mainboard/google/stout/romstage.c +++ b/src/mainboard/google/stout/romstage.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include "ec.h" diff --git a/src/mainboard/intel/emeraldlake2/romstage.c b/src/mainboard/intel/emeraldlake2/romstage.c index 3827337f94..0759e6252a 100644 --- a/src/mainboard/intel/emeraldlake2/romstage.c +++ b/src/mainboard/intel/emeraldlake2/romstage.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #define SIO_PORT 0x164e diff --git a/src/mainboard/lenovo/x201/romstage.c b/src/mainboard/lenovo/x201/romstage.c index f19f55578f..3c723ab65e 100644 --- a/src/mainboard/lenovo/x201/romstage.c +++ b/src/mainboard/lenovo/x201/romstage.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include "dock.h" #include "arch/early_variables.h" diff --git a/src/mainboard/pcengines/apu2/romstage.c b/src/mainboard/pcengines/apu2/romstage.c index b4b2802ea0..c9984ca8cd 100644 --- a/src/mainboard/pcengines/apu2/romstage.c +++ b/src/mainboard/pcengines/apu2/romstage.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include "gpio_ftns.h" diff --git a/src/mainboard/samsung/lumpy/romstage.c b/src/mainboard/samsung/lumpy/romstage.c index a04d538e80..1fde58ef95 100644 --- a/src/mainboard/samsung/lumpy/romstage.c +++ b/src/mainboard/samsung/lumpy/romstage.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/mainboard/samsung/stumpy/romstage.c b/src/mainboard/samsung/stumpy/romstage.c index 367a4388f4..830e6b6c1c 100644 --- a/src/mainboard/samsung/stumpy/romstage.c +++ b/src/mainboard/samsung/stumpy/romstage.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #if IS_ENABLED(CONFIG_DRIVERS_UART_8250IO) #include #endif diff --git a/src/northbridge/intel/sandybridge/romstage.c b/src/northbridge/intel/sandybridge/romstage.c index 1f31ad611e..4c596539de 100644 --- a/src/northbridge/intel/sandybridge/romstage.c +++ b/src/northbridge/intel/sandybridge/romstage.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include "southbridge/intel/bd82x6x/pch.h" #include diff --git a/src/security/tpm/Makefile.inc b/src/security/tpm/Makefile.inc index 48e70107e0..cfd93c3a76 100644 --- a/src/security/tpm/Makefile.inc +++ b/src/security/tpm/Makefile.inc @@ -1,12 +1,12 @@ -verstage-$(CONFIG_TPM) += tcg-1.2/tlcl.c -verstage-$(CONFIG_TPM2) += tcg-2.0/tpm2_marshaling.c -verstage-$(CONFIG_TPM2) += tcg-2.0/tpm2_tlcl.c +verstage-$(CONFIG_TPM) += tcg-1.2/tss.c +verstage-$(CONFIG_TPM2) += tcg-2.0/tss_marshaling.c +verstage-$(CONFIG_TPM2) += tcg-2.0/tss.c ifeq ($(CONFIG_VBOOT_SEPARATE_VERSTAGE),y) -romstage-$(CONFIG_TPM) += tcg-1.2/tlcl.c -romstage-$(CONFIG_TPM2) += tcg-2.0/tpm2_marshaling.c -romstage-$(CONFIG_TPM2) += tcg-2.0/tpm2_tlcl.c +romstage-$(CONFIG_TPM) += tcg-1.2/tss.c +romstage-$(CONFIG_TPM2) += tcg-2.0/tss_marshaling.c +romstage-$(CONFIG_TPM2) += tcg-2.0/tss.c endif # CONFIG_VBOOT_SEPARATE_VERSTAGE -ramstage-$(CONFIG_TPM2) += tcg-2.0/tpm2_marshaling.c -ramstage-$(CONFIG_TPM2) += tcg-2.0/tpm2_tlcl.c +ramstage-$(CONFIG_TPM2) += tcg-2.0/tss_marshaling.c +ramstage-$(CONFIG_TPM2) += tcg-2.0/tss.c diff --git a/src/security/tpm/tcg-1.2/tlcl.c b/src/security/tpm/tcg-1.2/tlcl.c deleted file mode 100644 index c7fcfcb7d6..0000000000 --- a/src/security/tpm/tcg-1.2/tlcl.c +++ /dev/null @@ -1,353 +0,0 @@ -/* Copyright (c) 2012 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. - */ - -/* A lightweight TPM command library. - * - * The general idea is that TPM commands are array of bytes whose - * fields are mostly compile-time constant. The goal is to build much - * of the commands at compile time (or build time) and change some of - * the fields at run time as needed. The code in - * utility/tlcl_generator.c builds structures containing the commands, - * as well as the offsets of the fields that need to be set at run - * time. - */ - -#include -#include -#include -#include -#include -#include "tlcl_internal.h" -#include "tlcl_structures.h" -#include "../tlcl.h" - -#ifdef FOR_TEST -#include -#define VBDEBUG(format, args...) printf(format, ## args) -#else -#include -#define VBDEBUG(format, args...) printk(BIOS_DEBUG, format, ## args) -#endif - -static int tpm_send_receive(const uint8_t *request, - uint32_t request_length, - uint8_t *response, - uint32_t *response_length) -{ - size_t len = *response_length; - if (tis_sendrecv(request, request_length, response, &len)) - return VB2_ERROR_UNKNOWN; - /* check 64->32bit overflow and (re)check response buffer overflow */ - if (len > *response_length) - return VB2_ERROR_UNKNOWN; - *response_length = len; - return VB2_SUCCESS; -} - -/* Sets the size field of a TPM command. */ -static inline void set_tpm_command_size(uint8_t *buffer, uint32_t size) -{ - to_tpm_uint32(buffer + sizeof(uint16_t), size); -} - -/* Gets the size field of a TPM command. */ -__attribute__((unused)) -static inline int tpm_command_size(const uint8_t *buffer) -{ - uint32_t size; - from_tpm_uint32(buffer + sizeof(uint16_t), &size); - return (int) size; -} - -/* Gets the code field of a TPM command. */ -static inline int tpm_command_code(const uint8_t *buffer) -{ - uint32_t code; - from_tpm_uint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code); - return code; -} - -/* Gets the return code field of a TPM result. */ -static inline int tpm_return_code(const uint8_t *buffer) -{ - return tpm_command_code(buffer); -} - -/* Like TlclSendReceive below, but do not retry if NEEDS_SELFTEST or - * DOING_SELFTEST errors are returned. - */ -static uint32_t tlcl_send_receive_no_retry(const uint8_t *request, - uint8_t *response, int max_length) -{ - uint32_t response_length = max_length; - uint32_t result; - - result = tpm_send_receive(request, tpm_command_size(request), - response, &response_length); - if (result != 0) { - /* Communication with TPM failed, so response is garbage */ - VBDEBUG("TPM: command 0x%x send/receive failed: 0x%x\n", - tpm_command_code(request), result); - return result; - } - /* Otherwise, use the result code from the response */ - result = tpm_return_code(response); - - /* TODO: add paranoia about returned response_length vs. max_length - * (and possibly expected length from the response header). See - * crosbug.com/17017 */ - - VBDEBUG("TPM: command 0x%x returned 0x%x\n", - tpm_command_code(request), result); - -return result; -} - - -/* Sends a TPM command and gets a response. Returns 0 if success or the TPM - * error code if error. Waits for the self test to complete if needed. */ -uint32_t tlcl_send_receive(const uint8_t *request, uint8_t *response, - int max_length) -{ - uint32_t result = tlcl_send_receive_no_retry(request, response, - max_length); - /* 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 = tlcl_continue_self_test(); - if (result != TPM_SUCCESS) - return result; -#if defined(TPM_BLOCKING_CONTINUESELFTEST) || defined(VB_RECOVERY_MODE) - /* Retry only once */ - result = tlcl_send_receive_no_retry(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 = tlcl_send_receive_no_retry(request, response, - max_length); - } while (result == TPM_E_DOING_SELFTEST); -#endif - } - return result; -} - -/* Sends a command and returns the error code. */ -static uint32_t send(const uint8_t *command) -{ - uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; - return tlcl_send_receive(command, response, sizeof(response)); -} - -/* Exported functions. */ - -static uint8_t tlcl_init_done CAR_GLOBAL; - -uint32_t tlcl_lib_init(void) -{ - uint8_t done = car_get_var(tlcl_init_done); - if (done) - return VB2_SUCCESS; - - if (tis_init()) - return VB2_ERROR_UNKNOWN; - if (tis_open()) - return VB2_ERROR_UNKNOWN; - - car_set_var(tlcl_init_done, 1); - - return VB2_SUCCESS; -} - -uint32_t tlcl_startup(void) -{ - VBDEBUG("TPM: Startup\n"); - return send(tpm_startup_cmd.buffer); -} - -uint32_t tlcl_resume(void) -{ - VBDEBUG("TPM: Resume\n"); - return send(tpm_resume_cmd.buffer); -} - -uint32_t tlcl_self_test_full(void) -{ - VBDEBUG("TPM: Self test full\n"); - return send(tpm_selftestfull_cmd.buffer); -} - -uint32_t tlcl_continue_self_test(void) -{ - uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; - VBDEBUG("TPM: Continue self test\n"); - /* Call the No Retry version of SendReceive to avoid recursion. */ - return tlcl_send_receive_no_retry(tpm_continueselftest_cmd.buffer, - response, sizeof(response)); -} - -uint32_t tlcl_define_space(uint32_t index, uint32_t perm, uint32_t size) -{ - struct s_tpm_nv_definespace_cmd cmd; - VBDEBUG("TPM: TlclDefineSpace(0x%x, 0x%x, %d)\n", index, perm, size); - memcpy(&cmd, &tpm_nv_definespace_cmd, sizeof(cmd)); - to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.index, index); - to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.perm, perm); - to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.size, size); - return send(cmd.buffer); -} - -uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length) -{ - struct s_tpm_nv_write_cmd cmd; - uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; - const int total_length = - kTpmRequestHeaderLength + kWriteInfoLength + length; - - VBDEBUG("TPM: tlcl_write(0x%x, %d)\n", index, length); - memcpy(&cmd, &tpm_nv_write_cmd, sizeof(cmd)); - assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); - set_tpm_command_size(cmd.buffer, total_length); - - to_tpm_uint32(cmd.buffer + tpm_nv_write_cmd.index, index); - to_tpm_uint32(cmd.buffer + tpm_nv_write_cmd.length, length); - memcpy(cmd.buffer + tpm_nv_write_cmd.data, data, length); - - return tlcl_send_receive(cmd.buffer, response, sizeof(response)); -} - -uint32_t tlcl_read(uint32_t index, void *data, uint32_t length) -{ - struct s_tpm_nv_read_cmd cmd; - uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; - uint32_t result_length; - uint32_t result; - - VBDEBUG("TPM: tlcl_read(0x%x, %d)\n", index, length); - memcpy(&cmd, &tpm_nv_read_cmd, sizeof(cmd)); - to_tpm_uint32(cmd.buffer + tpm_nv_read_cmd.index, index); - to_tpm_uint32(cmd.buffer + tpm_nv_read_cmd.length, length); - - result = tlcl_send_receive(cmd.buffer, response, sizeof(response)); - if (result == TPM_SUCCESS && length > 0) { - uint8_t *nv_read_cursor = response + kTpmResponseHeaderLength; - from_tpm_uint32(nv_read_cursor, &result_length); - nv_read_cursor += sizeof(uint32_t); - memcpy(data, nv_read_cursor, result_length); - } - - return result; -} - - -uint32_t tlcl_assert_physical_presence(void) -{ - VBDEBUG("TPM: Asserting physical presence\n"); - return send(tpm_ppassert_cmd.buffer); -} - -uint32_t tlcl_physical_presence_cmd_enable(void) -{ - VBDEBUG("TPM: Enable the physical presence command\n"); - return send(tpm_ppenable_cmd.buffer); -} - -uint32_t tlcl_finalize_physical_presence(void) -{ - VBDEBUG("TPM: Enable PP cmd, disable HW pp, and set lifetime lock\n"); - return send(tpm_finalizepp_cmd.buffer); -} - -uint32_t tlcl_set_nv_locked(void) -{ - VBDEBUG("TPM: Set NV locked\n"); - return tlcl_define_space(TPM_NV_INDEX_LOCK, 0, 0); -} - -uint32_t tlcl_force_clear(void) -{ - VBDEBUG("TPM: Force clear\n"); - return send(tpm_forceclear_cmd.buffer); -} - -uint32_t tlcl_set_enable(void) -{ - VBDEBUG("TPM: Enabling TPM\n"); - return send(tpm_physicalenable_cmd.buffer); -} - -uint32_t tlcl_set_deactivated(uint8_t flag) -{ - struct s_tpm_physicalsetdeactivated_cmd cmd; - VBDEBUG("TPM: SetDeactivated(%d)\n", flag); - memcpy(&cmd, &tpm_physicalsetdeactivated_cmd, sizeof(cmd)); - *(cmd.buffer + cmd.deactivated) = flag; - return send(cmd.buffer); -} - -uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags) -{ - uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; - uint32_t size; - uint32_t result = tlcl_send_receive(tpm_getflags_cmd.buffer, response, - sizeof(response)); - if (result != TPM_SUCCESS) - return result; - from_tpm_uint32(response + kTpmResponseHeaderLength, &size); - assert(size == sizeof(TPM_PERMANENT_FLAGS)); - memcpy(pflags, response + kTpmResponseHeaderLength + sizeof(size), - sizeof(TPM_PERMANENT_FLAGS)); - return result; -} - -uint32_t tlcl_get_flags(uint8_t *disable, uint8_t *deactivated, - uint8_t *nvlocked) -{ - TPM_PERMANENT_FLAGS pflags; - uint32_t result = tlcl_get_permanent_flags(&pflags); - if (result == TPM_SUCCESS) { - if (disable) - *disable = pflags.disable; - if (deactivated) - *deactivated = pflags.deactivated; - if (nvlocked) - *nvlocked = pflags.nvLocked; - VBDEBUG("TPM: flags disable=%d, deactivated=%d, nvlocked=%d\n", - pflags.disable, pflags.deactivated, pflags.nvLocked); - } - return result; -} - -uint32_t tlcl_set_global_lock(void) -{ - uint32_t x; - VBDEBUG("TPM: Set global lock\n"); - return tlcl_write(TPM_NV_INDEX0, (uint8_t *) &x, 0); -} - -uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest, - uint8_t *out_digest) -{ - struct s_tpm_extend_cmd cmd; - uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; - uint32_t result; - - memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd)); - to_tpm_uint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num); - memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength); - - result = tlcl_send_receive(cmd.buffer, response, sizeof(response)); - if (result != TPM_SUCCESS) - return result; - - if (out_digest) - memcpy(out_digest, response + kTpmResponseHeaderLength, - kPcrDigestLength); - return result; -} diff --git a/src/security/tpm/tcg-1.2/tlcl_internal.h b/src/security/tpm/tcg-1.2/tlcl_internal.h deleted file mode 100644 index 3648be622a..0000000000 --- a/src/security/tpm/tcg-1.2/tlcl_internal.h +++ /dev/null @@ -1,65 +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. - */ - -#ifndef TPM_LITE_TLCL_INTERNAL_H_ -#define TPM_LITE_TLCL_INTERNAL_H_ - -/* - * These numbers derive from adding the sizes of command fields as shown in the - * TPM commands manual. - */ -#define kTpmRequestHeaderLength 10 -#define kTpmResponseHeaderLength 10 -#define kTpmReadInfoLength 12 -#define kEncAuthLength 20 -#define kPcrDigestLength 20 - - -/* - * Conversion functions. to_tpm_TYPE puts a value of type TYPE into a TPM - * command buffer. from_tpm_TYPE gets a value of type TYPE from a TPM command - * buffer into a variable. - */ -__attribute__((unused)) -static inline void to_tpm_uint32(uint8_t *buffer, uint32_t x) -{ - buffer[0] = (uint8_t)(x >> 24); - buffer[1] = (uint8_t)((x >> 16) & 0xff); - buffer[2] = (uint8_t)((x >> 8) & 0xff); - buffer[3] = (uint8_t)(x & 0xff); -} - -/* - * See comment for above function. - */ -__attribute__((unused)) -static inline void from_tpm_uint32(const uint8_t *buffer, uint32_t *x) -{ - *x = ((buffer[0] << 24) | - (buffer[1] << 16) | - (buffer[2] << 8) | - buffer[3]); -} - -/* - * See comment for above function. - */ -__attribute__((unused)) -static inline void to_tpm_uint16(uint8_t *buffer, uint16_t x) -{ - buffer[0] = (uint8_t)(x >> 8); - buffer[1] = (uint8_t)(x & 0xff); -} - -/* - * See comment for above function. - */ -__attribute__((unused)) -static inline void from_tpm_uint16(const uint8_t *buffer, uint16_t *x) -{ - *x = (buffer[0] << 8) | buffer[1]; -} - -#endif /* TPM_LITE_TLCL_INTERNAL_H_ */ diff --git a/src/security/tpm/tcg-1.2/tlcl_structures.h b/src/security/tpm/tcg-1.2/tlcl_structures.h deleted file mode 100644 index 880864ee50..0000000000 --- a/src/security/tpm/tcg-1.2/tlcl_structures.h +++ /dev/null @@ -1,164 +0,0 @@ -/* 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; diff --git a/src/security/tpm/tcg-1.2/tss.c b/src/security/tpm/tcg-1.2/tss.c new file mode 100644 index 0000000000..e0ffdea433 --- /dev/null +++ b/src/security/tpm/tcg-1.2/tss.c @@ -0,0 +1,353 @@ +/* Copyright (c) 2012 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. + */ + +/* A lightweight TPM command library. + * + * The general idea is that TPM commands are array of bytes whose + * fields are mostly compile-time constant. The goal is to build much + * of the commands at compile time (or build time) and change some of + * the fields at run time as needed. The code in + * utility/tlcl_generator.c builds structures containing the commands, + * as well as the offsets of the fields that need to be set at run + * time. + */ + +#include +#include +#include +#include +#include +#include "tss_internal.h" +#include "tss_structures.h" +#include "../tss.h" + +#ifdef FOR_TEST +#include +#define VBDEBUG(format, args...) printf(format, ## args) +#else +#include +#define VBDEBUG(format, args...) printk(BIOS_DEBUG, format, ## args) +#endif + +static int tpm_send_receive(const uint8_t *request, + uint32_t request_length, + uint8_t *response, + uint32_t *response_length) +{ + size_t len = *response_length; + if (tis_sendrecv(request, request_length, response, &len)) + return VB2_ERROR_UNKNOWN; + /* check 64->32bit overflow and (re)check response buffer overflow */ + if (len > *response_length) + return VB2_ERROR_UNKNOWN; + *response_length = len; + return VB2_SUCCESS; +} + +/* Sets the size field of a TPM command. */ +static inline void set_tpm_command_size(uint8_t *buffer, uint32_t size) +{ + to_tpm_uint32(buffer + sizeof(uint16_t), size); +} + +/* Gets the size field of a TPM command. */ +__attribute__((unused)) +static inline int tpm_command_size(const uint8_t *buffer) +{ + uint32_t size; + from_tpm_uint32(buffer + sizeof(uint16_t), &size); + return (int) size; +} + +/* Gets the code field of a TPM command. */ +static inline int tpm_command_code(const uint8_t *buffer) +{ + uint32_t code; + from_tpm_uint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code); + return code; +} + +/* Gets the return code field of a TPM result. */ +static inline int tpm_return_code(const uint8_t *buffer) +{ + return tpm_command_code(buffer); +} + +/* Like TlclSendReceive below, but do not retry if NEEDS_SELFTEST or + * DOING_SELFTEST errors are returned. + */ +static uint32_t tlcl_send_receive_no_retry(const uint8_t *request, + uint8_t *response, int max_length) +{ + uint32_t response_length = max_length; + uint32_t result; + + result = tpm_send_receive(request, tpm_command_size(request), + response, &response_length); + if (result != 0) { + /* Communication with TPM failed, so response is garbage */ + VBDEBUG("TPM: command 0x%x send/receive failed: 0x%x\n", + tpm_command_code(request), result); + return result; + } + /* Otherwise, use the result code from the response */ + result = tpm_return_code(response); + + /* TODO: add paranoia about returned response_length vs. max_length + * (and possibly expected length from the response header). See + * crosbug.com/17017 */ + + VBDEBUG("TPM: command 0x%x returned 0x%x\n", + tpm_command_code(request), result); + +return result; +} + + +/* Sends a TPM command and gets a response. Returns 0 if success or the TPM + * error code if error. Waits for the self test to complete if needed. */ +uint32_t tlcl_send_receive(const uint8_t *request, uint8_t *response, + int max_length) +{ + uint32_t result = tlcl_send_receive_no_retry(request, response, + max_length); + /* 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 = tlcl_continue_self_test(); + if (result != TPM_SUCCESS) + return result; +#if defined(TPM_BLOCKING_CONTINUESELFTEST) || defined(VB_RECOVERY_MODE) + /* Retry only once */ + result = tlcl_send_receive_no_retry(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 = tlcl_send_receive_no_retry(request, response, + max_length); + } while (result == TPM_E_DOING_SELFTEST); +#endif + } + return result; +} + +/* Sends a command and returns the error code. */ +static uint32_t send(const uint8_t *command) +{ + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + return tlcl_send_receive(command, response, sizeof(response)); +} + +/* Exported functions. */ + +static uint8_t tlcl_init_done CAR_GLOBAL; + +uint32_t tlcl_lib_init(void) +{ + uint8_t done = car_get_var(tlcl_init_done); + if (done) + return VB2_SUCCESS; + + if (tis_init()) + return VB2_ERROR_UNKNOWN; + if (tis_open()) + return VB2_ERROR_UNKNOWN; + + car_set_var(tlcl_init_done, 1); + + return VB2_SUCCESS; +} + +uint32_t tlcl_startup(void) +{ + VBDEBUG("TPM: Startup\n"); + return send(tpm_startup_cmd.buffer); +} + +uint32_t tlcl_resume(void) +{ + VBDEBUG("TPM: Resume\n"); + return send(tpm_resume_cmd.buffer); +} + +uint32_t tlcl_self_test_full(void) +{ + VBDEBUG("TPM: Self test full\n"); + return send(tpm_selftestfull_cmd.buffer); +} + +uint32_t tlcl_continue_self_test(void) +{ + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + VBDEBUG("TPM: Continue self test\n"); + /* Call the No Retry version of SendReceive to avoid recursion. */ + return tlcl_send_receive_no_retry(tpm_continueselftest_cmd.buffer, + response, sizeof(response)); +} + +uint32_t tlcl_define_space(uint32_t index, uint32_t perm, uint32_t size) +{ + struct s_tpm_nv_definespace_cmd cmd; + VBDEBUG("TPM: TlclDefineSpace(0x%x, 0x%x, %d)\n", index, perm, size); + memcpy(&cmd, &tpm_nv_definespace_cmd, sizeof(cmd)); + to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.index, index); + to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.perm, perm); + to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.size, size); + return send(cmd.buffer); +} + +uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length) +{ + struct s_tpm_nv_write_cmd cmd; + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + const int total_length = + kTpmRequestHeaderLength + kWriteInfoLength + length; + + VBDEBUG("TPM: tlcl_write(0x%x, %d)\n", index, length); + memcpy(&cmd, &tpm_nv_write_cmd, sizeof(cmd)); + assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); + set_tpm_command_size(cmd.buffer, total_length); + + to_tpm_uint32(cmd.buffer + tpm_nv_write_cmd.index, index); + to_tpm_uint32(cmd.buffer + tpm_nv_write_cmd.length, length); + memcpy(cmd.buffer + tpm_nv_write_cmd.data, data, length); + + return tlcl_send_receive(cmd.buffer, response, sizeof(response)); +} + +uint32_t tlcl_read(uint32_t index, void *data, uint32_t length) +{ + struct s_tpm_nv_read_cmd cmd; + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t result_length; + uint32_t result; + + VBDEBUG("TPM: tlcl_read(0x%x, %d)\n", index, length); + memcpy(&cmd, &tpm_nv_read_cmd, sizeof(cmd)); + to_tpm_uint32(cmd.buffer + tpm_nv_read_cmd.index, index); + to_tpm_uint32(cmd.buffer + tpm_nv_read_cmd.length, length); + + result = tlcl_send_receive(cmd.buffer, response, sizeof(response)); + if (result == TPM_SUCCESS && length > 0) { + uint8_t *nv_read_cursor = response + kTpmResponseHeaderLength; + from_tpm_uint32(nv_read_cursor, &result_length); + nv_read_cursor += sizeof(uint32_t); + memcpy(data, nv_read_cursor, result_length); + } + + return result; +} + + +uint32_t tlcl_assert_physical_presence(void) +{ + VBDEBUG("TPM: Asserting physical presence\n"); + return send(tpm_ppassert_cmd.buffer); +} + +uint32_t tlcl_physical_presence_cmd_enable(void) +{ + VBDEBUG("TPM: Enable the physical presence command\n"); + return send(tpm_ppenable_cmd.buffer); +} + +uint32_t tlcl_finalize_physical_presence(void) +{ + VBDEBUG("TPM: Enable PP cmd, disable HW pp, and set lifetime lock\n"); + return send(tpm_finalizepp_cmd.buffer); +} + +uint32_t tlcl_set_nv_locked(void) +{ + VBDEBUG("TPM: Set NV locked\n"); + return tlcl_define_space(TPM_NV_INDEX_LOCK, 0, 0); +} + +uint32_t tlcl_force_clear(void) +{ + VBDEBUG("TPM: Force clear\n"); + return send(tpm_forceclear_cmd.buffer); +} + +uint32_t tlcl_set_enable(void) +{ + VBDEBUG("TPM: Enabling TPM\n"); + return send(tpm_physicalenable_cmd.buffer); +} + +uint32_t tlcl_set_deactivated(uint8_t flag) +{ + struct s_tpm_physicalsetdeactivated_cmd cmd; + VBDEBUG("TPM: SetDeactivated(%d)\n", flag); + memcpy(&cmd, &tpm_physicalsetdeactivated_cmd, sizeof(cmd)); + *(cmd.buffer + cmd.deactivated) = flag; + return send(cmd.buffer); +} + +uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags) +{ + uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; + uint32_t size; + uint32_t result = tlcl_send_receive(tpm_getflags_cmd.buffer, response, + sizeof(response)); + if (result != TPM_SUCCESS) + return result; + from_tpm_uint32(response + kTpmResponseHeaderLength, &size); + assert(size == sizeof(TPM_PERMANENT_FLAGS)); + memcpy(pflags, response + kTpmResponseHeaderLength + sizeof(size), + sizeof(TPM_PERMANENT_FLAGS)); + return result; +} + +uint32_t tlcl_get_flags(uint8_t *disable, uint8_t *deactivated, + uint8_t *nvlocked) +{ + TPM_PERMANENT_FLAGS pflags; + uint32_t result = tlcl_get_permanent_flags(&pflags); + if (result == TPM_SUCCESS) { + if (disable) + *disable = pflags.disable; + if (deactivated) + *deactivated = pflags.deactivated; + if (nvlocked) + *nvlocked = pflags.nvLocked; + VBDEBUG("TPM: flags disable=%d, deactivated=%d, nvlocked=%d\n", + pflags.disable, pflags.deactivated, pflags.nvLocked); + } + return result; +} + +uint32_t tlcl_set_global_lock(void) +{ + uint32_t x; + VBDEBUG("TPM: Set global lock\n"); + return tlcl_write(TPM_NV_INDEX0, (uint8_t *) &x, 0); +} + +uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest, + uint8_t *out_digest) +{ + struct s_tpm_extend_cmd cmd; + uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; + uint32_t result; + + memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd)); + to_tpm_uint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num); + memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength); + + result = tlcl_send_receive(cmd.buffer, response, sizeof(response)); + if (result != TPM_SUCCESS) + return result; + + if (out_digest) + memcpy(out_digest, response + kTpmResponseHeaderLength, + kPcrDigestLength); + return result; +} diff --git a/src/security/tpm/tcg-1.2/tss_internal.h b/src/security/tpm/tcg-1.2/tss_internal.h new file mode 100644 index 0000000000..01912bb78e --- /dev/null +++ b/src/security/tpm/tcg-1.2/tss_internal.h @@ -0,0 +1,65 @@ +/* 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. + */ + +#ifndef TCG_TSS_INTERNAL_H_ +#define TCG_TSS_INTERNAL_H_ + +/* + * These numbers derive from adding the sizes of command fields as shown in the + * TPM commands manual. + */ +#define kTpmRequestHeaderLength 10 +#define kTpmResponseHeaderLength 10 +#define kTpmReadInfoLength 12 +#define kEncAuthLength 20 +#define kPcrDigestLength 20 + + +/* + * Conversion functions. to_tpm_TYPE puts a value of type TYPE into a TPM + * command buffer. from_tpm_TYPE gets a value of type TYPE from a TPM command + * buffer into a variable. + */ +__attribute__((unused)) +static inline void to_tpm_uint32(uint8_t *buffer, uint32_t x) +{ + buffer[0] = (uint8_t)(x >> 24); + buffer[1] = (uint8_t)((x >> 16) & 0xff); + buffer[2] = (uint8_t)((x >> 8) & 0xff); + buffer[3] = (uint8_t)(x & 0xff); +} + +/* + * See comment for above function. + */ +__attribute__((unused)) +static inline void from_tpm_uint32(const uint8_t *buffer, uint32_t *x) +{ + *x = ((buffer[0] << 24) | + (buffer[1] << 16) | + (buffer[2] << 8) | + buffer[3]); +} + +/* + * See comment for above function. + */ +__attribute__((unused)) +static inline void to_tpm_uint16(uint8_t *buffer, uint16_t x) +{ + buffer[0] = (uint8_t)(x >> 8); + buffer[1] = (uint8_t)(x & 0xff); +} + +/* + * See comment for above function. + */ +__attribute__((unused)) +static inline void from_tpm_uint16(const uint8_t *buffer, uint16_t *x) +{ + *x = (buffer[0] << 8) | buffer[1]; +} + +#endif /* TCG_TSS_INTERNAL_H_ */ diff --git a/src/security/tpm/tcg-1.2/tss_structures.h b/src/security/tpm/tcg-1.2/tss_structures.h new file mode 100644 index 0000000000..880864ee50 --- /dev/null +++ b/src/security/tpm/tcg-1.2/tss_structures.h @@ -0,0 +1,164 @@ +/* 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; diff --git a/src/security/tpm/tcg-2.0/tpm2_marshaling.c b/src/security/tpm/tcg-2.0/tpm2_marshaling.c deleted file mode 100644 index 3ce09a4f8d..0000000000 --- a/src/security/tpm/tcg-2.0/tpm2_marshaling.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * 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 "tpm2_marshaling.h" - -static uint16_t tpm_tag CAR_GLOBAL; /* Depends on the command type. */ - -#define unmarshal_TPM_CAP(a, b) ibuf_read_be32(a, b) -#define unmarshal_TPM_CC(a, b) ibuf_read_be32(a, b) -#define unmarshal_TPM_PT(a, b) ibuf_read_be32(a, b) -#define unmarshal_TPM_HANDLE(a, b) ibuf_read_be32(a, b) - -#define marshal_TPM_HANDLE(a, b) obuf_write_be32(a, b) -#define marshal_TPMI_ALG_HASH(a, b) obuf_write_be16(a, b) - -static int marshal_startup(struct obuf *ob, struct tpm2_startup *cmd_body) -{ - return obuf_write_be16(ob, cmd_body->startup_type); -} - -static int marshal_get_capability(struct obuf *ob, - struct tpm2_get_capability *cmd_body) -{ - int rc = 0; - - rc |= obuf_write_be32(ob, cmd_body->capability); - rc |= obuf_write_be32(ob, cmd_body->property); - rc |= obuf_write_be32(ob, cmd_body->propertyCount); - - return rc; -} - -static int marshal_TPM2B(struct obuf *ob, TPM2B *data) -{ - int rc = 0; - - rc |= obuf_write_be16(ob, data->size); - rc |= obuf_write(ob, data->buffer, data->size); - - return rc; -} - -static int marshal_TPMA_NV(struct obuf *ob, TPMA_NV *nv) -{ - uint32_t v; - - memcpy(&v, nv, sizeof(v)); - return obuf_write_be32(ob, v); -} - -static int marshal_TPMS_NV_PUBLIC(struct obuf *ob, TPMS_NV_PUBLIC *nvpub) -{ - int rc = 0; - - rc |= marshal_TPM_HANDLE(ob, nvpub->nvIndex); - rc |= marshal_TPMI_ALG_HASH(ob, nvpub->nameAlg); - rc |= marshal_TPMA_NV(ob, &nvpub->attributes); - rc |= marshal_TPM2B(ob, &nvpub->authPolicy.b); - rc |= obuf_write_be16(ob, nvpub->dataSize); - - return rc; -} - -static int marshal_TPMT_HA(struct obuf *ob, TPMT_HA *tpmtha) -{ - int rc = 0; - - rc |= marshal_TPMI_ALG_HASH(ob, tpmtha->hashAlg); - rc |= obuf_write(ob, tpmtha->digest.sha256, - sizeof(tpmtha->digest.sha256)); - - return rc; -} - -static int marshal_TPML_DIGEST_VALUES(struct obuf *ob, - TPML_DIGEST_VALUES *dvalues) -{ - int i; - int rc = 0; - - rc |= obuf_write_be32(ob, dvalues->count); - for (i = 0; i < dvalues->count; i++) - rc |= marshal_TPMT_HA(ob, &dvalues->digests[i]); - - return rc; -} - -static int marshal_session_header(struct obuf *ob, - struct tpm2_session_header *session_header) -{ - int rc = 0; - struct obuf ob_sz; - size_t prev_written; - - /* Snapshot current location to place size of header. */ - if (obuf_splice_current(ob, &ob_sz, sizeof(uint32_t)) < 0) - return -1; - - /* Write a size placeholder. */ - rc |= obuf_write_be32(ob, 0); - - /* Keep track of session header data size by tracking num written. */ - prev_written = obuf_nr_written(ob); - - rc |= obuf_write_be32(ob, session_header->session_handle); - rc |= obuf_write_be16(ob, session_header->nonce_size); - rc |= obuf_write(ob, session_header->nonce, session_header->nonce_size); - rc |= obuf_write_be8(ob, session_header->session_attrs); - rc |= obuf_write_be16(ob, session_header->auth_size); - rc |= obuf_write(ob, session_header->auth, session_header->auth_size); - - /* Fill back in proper size of session header. */ - rc |= obuf_write_be32(&ob_sz, obuf_nr_written(ob) - prev_written); - - return rc; -} - -/* - * Common session header can include one or two handles and an empty - * session_header structure. - */ -static int marshal_common_session_header(struct obuf *ob, - const uint32_t *handles, - size_t handle_count) -{ - size_t i; - struct tpm2_session_header session_header; - int rc = 0; - - car_set_var(tpm_tag, TPM_ST_SESSIONS); - - for (i = 0; i < handle_count; i++) - rc |= marshal_TPM_HANDLE(ob, handles[i]); - - memset(&session_header, 0, sizeof(session_header)); - session_header.session_handle = TPM_RS_PW; - rc |= marshal_session_header(ob, &session_header); - - return rc; -} - -static int marshal_nv_define_space(struct obuf *ob, - struct tpm2_nv_define_space_cmd *nvd_in) -{ - const uint32_t handle[] = { TPM_RH_PLATFORM }; - struct obuf ob_sz; - size_t prev_written; - int rc = 0; - - rc |= marshal_common_session_header(ob, handle, ARRAY_SIZE(handle)); - rc |= marshal_TPM2B(ob, &nvd_in->auth.b); - - /* Snapshot current location to place size field. */ - if (obuf_splice_current(ob, &ob_sz, sizeof(uint16_t)) < 0) - return -1; - - /* Put placeholder for size */ - rc |= obuf_write_be16(ob, 0); - - /* Keep track of nv define space data size by tracking num written. */ - prev_written = obuf_nr_written(ob); - - rc |= marshal_TPMS_NV_PUBLIC(ob, &nvd_in->publicInfo); - rc |= obuf_write_be16(&ob_sz, obuf_nr_written(ob) - prev_written); - - return rc; -} - -static int marshal_nv_write(struct obuf *ob, - struct tpm2_nv_write_cmd *command_body) -{ - int rc = 0; - uint32_t handles[] = { TPM_RH_PLATFORM, command_body->nvIndex }; - - rc |= marshal_common_session_header(ob, handles, ARRAY_SIZE(handles)); - rc |= marshal_TPM2B(ob, &command_body->data.b); - rc |= obuf_write_be16(ob, command_body->offset); - - return rc; -} - -static int marshal_nv_write_lock(struct obuf *ob, - struct tpm2_nv_write_lock_cmd *command_body) -{ - uint32_t handles[] = { TPM_RH_PLATFORM, command_body->nvIndex }; - - return marshal_common_session_header(ob, handles, ARRAY_SIZE(handles)); -} - -static int marshal_pcr_extend(struct obuf *ob, - struct tpm2_pcr_extend_cmd *command_body) -{ - int rc = 0; - uint32_t handles[] = { command_body->pcrHandle }; - - rc |= marshal_common_session_header(ob, handles, ARRAY_SIZE(handles)); - rc |= marshal_TPML_DIGEST_VALUES(ob, &command_body->digests); - - return rc; -} - -static int marshal_nv_read(struct obuf *ob, - struct tpm2_nv_read_cmd *command_body) -{ - int rc = 0; - uint32_t handles[] = { TPM_RH_PLATFORM, command_body->nvIndex }; - - rc |= marshal_common_session_header(ob, handles, ARRAY_SIZE(handles)); - rc |= obuf_write_be16(ob, command_body->size); - rc |= obuf_write_be16(ob, command_body->offset); - - return rc; -} - -/* TPM2_Clear command does not require paramaters. */ -static int marshal_clear(struct obuf *ob) -{ - const uint32_t handle[] = { TPM_RH_PLATFORM }; - - return marshal_common_session_header(ob, handle, ARRAY_SIZE(handle)); -} - -static int marshal_selftest(struct obuf *ob, - struct tpm2_self_test *command_body) -{ - return obuf_write_be8(ob, command_body->yes_no); -} - -static int marshal_hierarchy_control(struct obuf *ob, - struct tpm2_hierarchy_control_cmd *command_body) -{ - int rc = 0; - struct tpm2_session_header session_header; - - car_set_var(tpm_tag, TPM_ST_SESSIONS); - - rc |= marshal_TPM_HANDLE(ob, TPM_RH_PLATFORM); - memset(&session_header, 0, sizeof(session_header)); - session_header.session_handle = TPM_RS_PW; - rc |= marshal_session_header(ob, &session_header); - - rc |= marshal_TPM_HANDLE(ob, command_body->enable); - rc |= obuf_write_be8(ob, command_body->state); - - return rc; -} - -static int marshal_cr50_vendor_command(struct obuf *ob, void *command_body) -{ - int rc = 0; - uint16_t *sub_command = command_body; - - switch (*sub_command) { - case TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS: - rc |= obuf_write_be16(ob, *sub_command); - break; - case TPM2_CR50_SUB_CMD_TURN_UPDATE_ON: - rc |= obuf_write_be16(ob, sub_command[0]); - rc |= obuf_write_be16(ob, sub_command[1]); - break; - default: - /* Unsupported subcommand. */ - printk(BIOS_WARNING, "Unsupported cr50 subcommand: 0x%04x\n", - *sub_command); - rc = -1; - break; - } - return rc; -} - -int tpm_marshal_command(TPM_CC command, void *tpm_command_body, struct obuf *ob) -{ - struct obuf ob_hdr; - const size_t hdr_sz = sizeof(uint16_t) + 2 * sizeof(uint32_t); - int rc = 0; - - car_set_var(tpm_tag, TPM_ST_NO_SESSIONS); - - if (obuf_splice_current(ob, &ob_hdr, hdr_sz) < 0) - return -1; - - /* Write TPM command header with placeholder field values. */ - rc |= obuf_write_be16(ob, 0); - rc |= obuf_write_be32(ob, 0); - rc |= obuf_write_be32(ob, command); - - if (rc != 0) - return rc; - - switch (command) { - case TPM2_Startup: - rc |= marshal_startup(ob, tpm_command_body); - break; - - case TPM2_GetCapability: - rc |= marshal_get_capability(ob, tpm_command_body); - break; - - case TPM2_NV_Read: - rc |= marshal_nv_read(ob, tpm_command_body); - break; - - case TPM2_NV_DefineSpace: - rc |= marshal_nv_define_space(ob, tpm_command_body); - break; - - case TPM2_NV_Write: - rc |= marshal_nv_write(ob, tpm_command_body); - break; - - case TPM2_NV_WriteLock: - rc |= marshal_nv_write_lock(ob, tpm_command_body); - break; - - case TPM2_SelfTest: - rc |= marshal_selftest(ob, tpm_command_body); - break; - - case TPM2_Hierarchy_Control: - rc |= marshal_hierarchy_control(ob, tpm_command_body); - break; - - case TPM2_Clear: - rc |= marshal_clear(ob); - break; - - case TPM2_PCR_Extend: - rc |= marshal_pcr_extend(ob, tpm_command_body); - break; - - case TPM2_CR50_VENDOR_COMMAND: - rc |= marshal_cr50_vendor_command(ob, tpm_command_body); - break; - - default: - printk(BIOS_INFO, "%s:%d:Request to marshal unsupported command %#x\n", - __FILE__, __LINE__, command); - rc = -1; - } - - if (rc != 0) - return rc; - - /* Fix up the command header with known values. */ - rc |= obuf_write_be16(&ob_hdr, car_get_var(tpm_tag)); - rc |= obuf_write_be32(&ob_hdr, obuf_nr_written(ob)); - - return rc; -} - -static int unmarshal_get_capability(struct ibuf *ib, - struct get_cap_response *gcr) -{ - int i; - int rc = 0; - - rc |= ibuf_read_be8(ib, &gcr->more_data); - rc |= unmarshal_TPM_CAP(ib, &gcr->cd.capability); - - if (rc != 0) - return rc; - - switch (gcr->cd.capability) { - case TPM_CAP_TPM_PROPERTIES: - if (ibuf_read_be32(ib, &gcr->cd.data.tpmProperties.count)) - return -1; - if (gcr->cd.data.tpmProperties.count > ARRAY_SIZE - (gcr->cd.data.tpmProperties.tpmProperty)) { - printk(BIOS_INFO, "%s:%s:%d - %d - too many properties\n", - __FILE__, __func__, __LINE__, - gcr->cd.data.tpmProperties.count); - return -1; - } - for (i = 0; i < gcr->cd.data.tpmProperties.count; i++) { - TPMS_TAGGED_PROPERTY *pp; - - pp = gcr->cd.data.tpmProperties.tpmProperty + i; - rc |= unmarshal_TPM_PT(ib, &pp->property); - rc |= ibuf_read_be32(ib, &pp->value); - } - break; - default: - printk(BIOS_ERR, - "%s:%d - unable to unmarshal capability response", - __func__, __LINE__); - printk(BIOS_ERR, " for %d\n", gcr->cd.capability); - rc = -1; - break; - } - - return rc; -} - -static int unmarshal_TPM2B_MAX_NV_BUFFER(struct ibuf *ib, - TPM2B_MAX_NV_BUFFER *nv_buffer) -{ - if (ibuf_read_be16(ib, &nv_buffer->t.size)) - return -1; - - nv_buffer->t.buffer = ibuf_oob_drain(ib, nv_buffer->t.size); - - if (nv_buffer->t.buffer == NULL) { - printk(BIOS_ERR, "%s:%d - " - "size mismatch: expected %d, remaining %zd\n", - __func__, __LINE__, nv_buffer->t.size, - ibuf_remaining(ib)); - return -1; - } - - return 0; -} - -static int unmarshal_nv_read(struct ibuf *ib, struct nv_read_response *nvr) -{ - /* Total size of the parameter field. */ - if (ibuf_read_be32(ib, &nvr->params_size)) - return -1; - - if (unmarshal_TPM2B_MAX_NV_BUFFER(ib, &nvr->buffer)) - return -1; - - if (nvr->params_size != - (nvr->buffer.t.size + sizeof(nvr->buffer.t.size))) { - printk(BIOS_ERR, - "%s:%d - parameter/buffer %d/%d size mismatch", - __func__, __LINE__, nvr->params_size, - nvr->buffer.t.size); - return -1; - } - - /* - * Let's ignore the authorisation section. It should be 5 bytes total, - * just confirm that this is the case and report any discrepancy. - */ - if (ibuf_remaining(ib) != 5) - printk(BIOS_ERR, - "%s:%d - unexpected authorisation seciton size %zd\n", - __func__, __LINE__, ibuf_remaining(ib)); - - ibuf_oob_drain(ib, ibuf_remaining(ib)); - - return 0; -} - -static int unmarshal_vendor_command(struct ibuf *ib, - struct vendor_command_response *vcr) -{ - if (ibuf_read_be16(ib, &vcr->vc_subcommand)) - return -1; - - switch (vcr->vc_subcommand) { - case TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS: - break; - case TPM2_CR50_SUB_CMD_TURN_UPDATE_ON: - return ibuf_read_be8(ib, &vcr->num_restored_headers); - break; - default: - printk(BIOS_ERR, - "%s:%d - unsupported vendor command %#04x!\n", - __func__, __LINE__, vcr->vc_subcommand); - return -1; - } - - return 0; -} - -struct tpm2_response *tpm_unmarshal_response(TPM_CC command, struct ibuf *ib) -{ - static struct tpm2_response tpm2_static_resp CAR_GLOBAL; - struct tpm2_response *tpm2_resp = car_get_var_ptr(&tpm2_static_resp); - int rc = 0; - - rc |= ibuf_read_be16(ib, &tpm2_resp->hdr.tpm_tag); - rc |= ibuf_read_be32(ib, &tpm2_resp->hdr.tpm_size); - rc |= unmarshal_TPM_CC(ib, &tpm2_resp->hdr.tpm_code); - - if (rc != 0) - return NULL; - - if (ibuf_remaining(ib) == 0) { - if (tpm2_resp->hdr.tpm_size != ibuf_nr_read(ib)) - printk(BIOS_ERR, - "%s: size mismatch in response to command %#x\n", - __func__, command); - return tpm2_resp; - } - - switch (command) { - case TPM2_Startup: - break; - - case TPM2_GetCapability: - rc |= unmarshal_get_capability(ib, &tpm2_resp->gc); - break; - - case TPM2_NV_Read: - rc |= unmarshal_nv_read(ib, &tpm2_resp->nvr); - break; - - case TPM2_Hierarchy_Control: - case TPM2_Clear: - case TPM2_NV_DefineSpace: - case TPM2_NV_Write: - case TPM2_NV_WriteLock: - case TPM2_PCR_Extend: - /* Session data included in response can be safely ignored. */ - ibuf_oob_drain(ib, ibuf_remaining(ib)); - break; - - case TPM2_CR50_VENDOR_COMMAND: - rc |= unmarshal_vendor_command(ib, &tpm2_resp->vcr); - break; - - default: - { - size_t i; - size_t sz_left; - const uint8_t *data; - - printk(BIOS_INFO, "%s:%d:" - "Request to unmarshal unexpected command %#x," - " code %#x", - __func__, __LINE__, command, - tpm2_resp->hdr.tpm_code); - - sz_left = ibuf_remaining(ib); - data = ibuf_oob_drain(ib, sz_left); - - for (i = 0; i < sz_left; i++) { - if (!(i % 16)) - printk(BIOS_INFO, "\n"); - printk(BIOS_INFO, "%2.2x ", data[i]); - } - } - printk(BIOS_INFO, "\n"); - return NULL; - } - - if (ibuf_remaining(ib)) { - printk(BIOS_INFO, - "%s:%d got %d bytes back in response to %#x," - " failed to parse (%zd)\n", - __func__, __LINE__, tpm2_resp->hdr.tpm_size, - command, ibuf_remaining(ib)); - return NULL; - } - - /* The entire message have been parsed. */ - return tpm2_resp; -} diff --git a/src/security/tpm/tcg-2.0/tpm2_marshaling.h b/src/security/tpm/tcg-2.0/tpm2_marshaling.h deleted file mode 100644 index 5802044378..0000000000 --- a/src/security/tpm/tcg-2.0/tpm2_marshaling.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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. - */ -#ifndef __SRC_LIB_TPM2_MARSHALING_H -#define __SRC_LIB_TPM2_MARSHALING_H - -#include -#include "tpm2_tlcl_structures.h" - -/* The below functions are used to serialize/deserialize TPM2 commands. */ - -/** - * tpm_marshal_command - * - * Given a structure containing a TPM2 command, serialize the structure for - * sending it to the TPM. - * - * @command: code of the TPM2 command to marshal - * @tpm_command_body: a pointer to the command specific structure - * @ob: output buffer where command is marshaled to - * - * Returns 0 on success or -1 on error. - * - */ -int tpm_marshal_command(TPM_CC command, void *tpm_command_body, - struct obuf *ob); - -/** - * tpm_unmarshal_response - * - * Given a buffer received from the TPM in response to a certain command, - * deserialize the buffer into the expeced response structure. - * - * struct tpm2_response is a union of all possible responses. - * - * @command: code of the TPM2 command for which a response is unmarshaled - * @ib: input buffer containing the serialized response. - * - * Returns a pointer to the deserialized response or NULL in case of - * unmarshaling problems. - */ -struct tpm2_response *tpm_unmarshal_response(TPM_CC command, struct ibuf *ib); - -#endif // __SRC_LIB_TPM2_MARSHALING_H diff --git a/src/security/tpm/tcg-2.0/tpm2_tlcl.c b/src/security/tpm/tcg-2.0/tpm2_tlcl.c deleted file mode 100644 index e111b89ae2..0000000000 --- a/src/security/tpm/tcg-2.0/tpm2_tlcl.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * 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 "tpm2_tlcl_structures.h" -#include "tpm2_marshaling.h" -#include "../tpm.h" -#include "../antirollback.h" - -/* - * This file provides interface between firmware and TPM2 device. The TPM1.2 - * API was copied as is and relevant functions modified to comply with the - * TPM2 specification. - */ - -static void *tpm_process_command(TPM_CC command, void *command_body) -{ - struct obuf ob; - struct ibuf ib; - size_t out_size; - size_t in_size; - const uint8_t *sendb; - /* Command/response buffer. */ - static uint8_t cr_buffer[TPM_BUFFER_SIZE] CAR_GLOBAL; - - uint8_t *cr_buffer_ptr = car_get_var_ptr(cr_buffer); - - obuf_init(&ob, cr_buffer_ptr, sizeof(cr_buffer)); - - if (tpm_marshal_command(command, command_body, &ob) < 0) { - printk(BIOS_ERR, "command %#x\n", command); - return NULL; - } - - sendb = obuf_contents(&ob, &out_size); - - in_size = sizeof(cr_buffer); - if (tis_sendrecv(sendb, out_size, cr_buffer_ptr, &in_size)) { - printk(BIOS_ERR, "tpm transaction failed\n"); - return NULL; - } - - ibuf_init(&ib, cr_buffer_ptr, in_size); - - 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; - struct tpm2_response *response; - - startup.startup_type = type; - response = tpm_process_command(TPM2_Startup, &startup); - - if (response && response->hdr.tpm_code && - (response->hdr.tpm_code != TPM_RC_INITIALIZE)) { - printk(BIOS_INFO, "%s: Startup return code is %x\n", - __func__, response->hdr.tpm_code); - return TPM_E_IOERROR; - } - return TPM_SUCCESS; - -} - -uint32_t tlcl_resume(void) -{ - return tlcl_send_startup(TPM_SU_STATE); -} - -uint32_t tlcl_assert_physical_presence(void) -{ - /* - * Nothing to do on TPM2 for this, use platform hierarchy availability - * instead. - */ - return TPM_SUCCESS; -} - -/* - * The caller will provide the digest in a 32 byte buffer, let's consider it a - * sha256 digest. - */ -uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest, - uint8_t *out_digest) -{ - struct tpm2_pcr_extend_cmd pcr_ext_cmd; - struct tpm2_response *response; - - pcr_ext_cmd.pcrHandle = HR_PCR + pcr_num; - pcr_ext_cmd.digests.count = 1; - pcr_ext_cmd.digests.digests[0].hashAlg = TPM_ALG_SHA256; - memcpy(pcr_ext_cmd.digests.digests[0].digest.sha256, in_digest, - sizeof(pcr_ext_cmd.digests.digests[0].digest.sha256)); - - response = tpm_process_command(TPM2_PCR_Extend, &pcr_ext_cmd); - - printk(BIOS_INFO, "%s: response is %x\n", - __func__, response ? response->hdr.tpm_code : -1); - if (!response || response->hdr.tpm_code) - return TPM_E_IOERROR; - - return TPM_SUCCESS; -} - -uint32_t tlcl_finalize_physical_presence(void) -{ - /* Nothing needs to be done with tpm2. */ - printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__); - return TPM_SUCCESS; -} - -uint32_t tlcl_force_clear(void) -{ - struct tpm2_response *response; - - response = tpm_process_command(TPM2_Clear, NULL); - printk(BIOS_INFO, "%s: response is %x\n", - __func__, response ? response->hdr.tpm_code : -1); - - if (!response || response->hdr.tpm_code) - return TPM_E_IOERROR; - - 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. */ -uint32_t tlcl_lib_init(void) -{ - uint8_t done = car_get_var(tlcl_init_done); - if (done) - return VB2_SUCCESS; - - if (tis_init()) - return VB2_ERROR_UNKNOWN; - if (tis_open()) - return VB2_ERROR_UNKNOWN; - - car_set_var(tlcl_init_done, 1); - - return VB2_SUCCESS; -} - -uint32_t tlcl_physical_presence_cmd_enable(void) -{ - printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__); - return TPM_SUCCESS; -} - -uint32_t tlcl_read(uint32_t index, void *data, uint32_t length) -{ - struct tpm2_nv_read_cmd nv_readc; - struct tpm2_response *response; - - memset(&nv_readc, 0, sizeof(nv_readc)); - - nv_readc.nvIndex = HR_NV_INDEX + index; - nv_readc.size = length; - - response = tpm_process_command(TPM2_NV_Read, &nv_readc); - - /* Need to map tpm error codes into internal values. */ - if (!response) - return TPM_E_READ_FAILURE; - - printk(BIOS_INFO, "%s:%d index %#x return code %x\n", - __FILE__, __LINE__, index, response->hdr.tpm_code); - switch (response->hdr.tpm_code) { - case 0: - break; - - /* Uninitialized, returned if the space hasn't been written. */ - case TPM_RC_NV_UNINITIALIZED: - /* - * Bad index, cr50 specific value, returned if the space - * hasn't been defined. - */ - case TPM_RC_CR50_NV_UNDEFINED: - return TPM_E_BADINDEX; - - default: - return TPM_E_READ_FAILURE; - } - - if (length > response->nvr.buffer.t.size) - return TPM_E_RESPONSE_TOO_LARGE; - - if (length < response->nvr.buffer.t.size) - return TPM_E_READ_EMPTY; - - memcpy(data, response->nvr.buffer.t.buffer, length); - - return TPM_SUCCESS; -} - -uint32_t tlcl_self_test_full(void) -{ - struct tpm2_self_test st; - struct tpm2_response *response; - - st.yes_no = 1; - - response = tpm_process_command(TPM2_SelfTest, &st); - printk(BIOS_INFO, "%s: response is %x\n", - __func__, response ? response->hdr.tpm_code : -1); - 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; - /* TPM Wll reject attempts to write at non-defined index. */ - struct tpm2_nv_write_lock_cmd nv_wl = { - .nvIndex = HR_NV_INDEX + index, - }; - - response = tpm_process_command(TPM2_NV_WriteLock, &nv_wl); - - printk(BIOS_INFO, "%s: response is %x\n", - __func__, response ? response->hdr.tpm_code : -1); - - if (!response || response->hdr.tpm_code) - return TPM_E_IOERROR; - - return TPM_SUCCESS; -} - -uint32_t tlcl_startup(void) -{ - return tlcl_send_startup(TPM_SU_CLEAR); -} - -uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length) -{ - struct tpm2_nv_write_cmd nv_writec; - struct tpm2_response *response; - - memset(&nv_writec, 0, sizeof(nv_writec)); - - nv_writec.nvIndex = HR_NV_INDEX + index; - nv_writec.data.t.size = length; - nv_writec.data.t.buffer = data; - - response = tpm_process_command(TPM2_NV_Write, &nv_writec); - - printk(BIOS_INFO, "%s: response is %x\n", - __func__, response ? response->hdr.tpm_code : -1); - - /* Need to map tpm error codes into internal values. */ - if (!response || response->hdr.tpm_code) - return TPM_E_WRITE_FAILURE; - - return TPM_SUCCESS; -} - -uint32_t tlcl_define_space(uint32_t space_index, size_t space_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)); - - nvds_cmd.publicInfo.dataSize = space_size; - nvds_cmd.publicInfo.nvIndex = HR_NV_INDEX + space_index; - nvds_cmd.publicInfo.nameAlg = TPM_ALG_SHA256; - - /* 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; - } - - response = tpm_process_command(TPM2_NV_DefineSpace, &nvds_cmd); - printk(BIOS_INFO, "%s: response is %x\n", - __func__, response ? response->hdr.tpm_code : -1); - - if (!response) - return TPM_E_NO_DEVICE; - - /* Map TPM2 retrun codes into common vboot represenation. */ - switch (response->hdr.tpm_code) { - case TPM2_RC_SUCCESS: - return TPM_SUCCESS; - case TPM2_RC_NV_DEFINED: - return TPM_E_NV_DEFINED; - default: - return TPM_E_INTERNAL_INCONSISTENCY; - } -} - -uint32_t tlcl_disable_platform_hierarchy(void) -{ - struct tpm2_response *response; - struct tpm2_hierarchy_control_cmd hc = { - .enable = TPM_RH_PLATFORM, - .state = 0, - }; - - response = tpm_process_command(TPM2_Hierarchy_Control, &hc); - - if (!response || response->hdr.tpm_code) - return TPM_E_INTERNAL_INCONSISTENCY; - - 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/tcg-2.0/tpm2_tlcl_structures.h b/src/security/tpm/tcg-2.0/tpm2_tlcl_structures.h deleted file mode 100644 index acd9e74aec..0000000000 --- a/src/security/tpm/tcg-2.0/tpm2_tlcl_structures.h +++ /dev/null @@ -1,373 +0,0 @@ -/* - * 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. - */ - -#ifndef __SRC_LIB_TPM2_TLCL_STRUCTURES_H -#define __SRC_LIB_TPM2_TLCL_STRUCTURES_H - -/* - * This file includes a subset of definitions of TPM protocol version 2.x - * constants and structures needed for functions used in coreboot. - */ -#include -#include -#include - -#include "../tlcl.h" - -/* This should be plenty for what firmware needs. */ -#define TPM_BUFFER_SIZE 256 - -/* 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; -typedef TPM_ALG_ID TPMI_ALG_HASH; -typedef TPM_HANDLE TPMI_DH_PCR; -typedef TPM_HANDLE TPMI_RH_NV_INDEX; -typedef TPM_HANDLE TPMI_RH_ENABLES; -typedef TPM_HANDLE TPMI_SH_AUTH_SESSION; -typedef TPM_HANDLE TPM_RH; - -/* Some hardcoded algorithm values. */ -#define TPM_ALG_HMAC ((TPM_ALG_ID)0x0005) -#define TPM_ALG_NULL ((TPM_ALG_ID)0x0010) -#define TPM_ALG_SHA1 ((TPM_ALG_ID)0x0004) -#define TPM_ALG_SHA256 ((TPM_ALG_ID)0x000b) - -#define SHA256_DIGEST_SIZE 32 - -/* Some hardcoded hierarchies. */ -#define TPM_RH_NULL 0x40000007 -#define TPM_RS_PW 0x40000009 -#define TPM_RH_PLATFORM 0x4000000C - -typedef struct { - uint16_t size; - uint8_t *buffer; -} TPM2B; - -/* Relevant TPM Command's structures. */ -/* Common command/response header. */ -struct tpm_header { - uint16_t tpm_tag; - uint32_t tpm_size; - TPM_CC tpm_code; -} __packed; - -/* TPM command codes. */ -#define TPM2_Hierarchy_Control ((TPM_CC)0x00000121) -#define TPM2_Clear ((TPM_CC)0x00000126) -#define TPM2_NV_DefineSpace ((TPM_CC)0x0000012A) -#define TPM2_NV_Write ((TPM_CC)0x00000137) -#define TPM2_NV_WriteLock ((TPM_CC)0x00000138) -#define TPM2_SelfTest ((TPM_CC)0x00000143) -#define TPM2_Startup ((TPM_CC)0x00000144) -#define TPM2_NV_Read ((TPM_CC)0x0000014E) -#define TPM2_GetCapability ((TPM_CC)0x0000017A) -#define TPM2_PCR_Extend ((TPM_CC)0x00000182) -/* 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 -#define TPM_SU_STATE 1 - -#define TPM_HT_PCR 0x00 -#define TPM_HT_NV_INDEX 0x01 -#define TPM_HT_HMAC_SESSION 0x02 -#define TPM_HT_POLICY_SESSION 0x03 - -#define HR_SHIFT 24 -#define HR_PCR (TPM_HT_PCR << HR_SHIFT) -#define HR_HMAC_SESSION (TPM_HT_HMAC_SESSION << HR_SHIFT) -#define HR_POLICY_SESSION (TPM_HT_POLICY_SESSION << HR_SHIFT) -#define HR_TRANSIENT (TPM_HT_TRANSIENT << HR_SHIFT) -#define HR_PERSISTENT (TPM_HT_PERSISTENT << HR_SHIFT) -#define HR_NV_INDEX (TPM_HT_NV_INDEX << HR_SHIFT) -#define HR_PERMANENT (TPM_HT_PERMANENT << HR_SHIFT) -#define PCR_FIRST (HR_PCR + 0) -#define PCR_LAST (PCR_FIRST + IMPLEMENTATION_PCR-1) -#define HMAC_SESSION_FIRST (HR_HMAC_SESSION + 0) -#define HMAC_SESSION_LAST (HMAC_SESSION_FIRST+MAX_ACTIVE_SESSIONS-1) -#define LOADED_SESSION_FIRST HMAC_SESSION_FIRST -#define LOADED_SESSION_LAST HMAC_SESSION_LAST -#define POLICY_SESSION_FIRST (HR_POLICY_SESSION + 0) -#define POLICY_SESSION_LAST (POLICY_SESSION_FIRST + MAX_ACTIVE_SESSIONS-1) -#define TRANSIENT_FIRST (HR_TRANSIENT + 0) -#define ACTIVE_SESSION_FIRST POLICY_SESSION_FIRST -#define ACTIVE_SESSION_LAST POLICY_SESSION_LAST -#define TRANSIENT_LAST (TRANSIENT_FIRST+MAX_LOADED_OBJECTS-1) -#define PERSISTENT_FIRST (HR_PERSISTENT + 0) -#define PERSISTENT_LAST (PERSISTENT_FIRST + 0x00FFFFFF) -#define PLATFORM_PERSISTENT (PERSISTENT_FIRST + 0x00800000) -#define NV_INDEX_FIRST (HR_NV_INDEX + 0) -#define NV_INDEX_LAST (NV_INDEX_FIRST + 0x00FFFFFF) -#define PERMANENT_FIRST TPM_RH_FIRST -#define PERMANENT_LAST TPM_RH_LAST - -/* Tpm2 command tags. */ -#define TPM_ST_NO_SESSIONS 0x8001 -#define TPM_ST_SESSIONS 0x8002 - -/* Values copied from tpm2/tpm_types.h */ -#define RC_VER1 0x100 -#define TPM_RC_INITIALIZE ((TPM_RC)(RC_VER1 + 0x000)) -#define TPM_RC_NV_UNINITIALIZED ((TPM_RC)(RC_VER1 + 0x04A)) - -/* - * Cr50 returns this code when an attempt is made to read an NV location which - * has not yet been defined. This is an aggregation of various return code - * extensions which may or may not match if a different TPM2 device is - * used. - */ -#define TPM_RC_CR50_NV_UNDEFINED 0x28b - -/* TPM command structures. */ - -struct tpm2_startup { - TPM_SU startup_type; -}; - -/* Various TPM capability types to use when querying the device. */ -typedef uint32_t TPM_CAP; -#define TPM_CAP_TPM_PROPERTIES ((TPM_CAP)0x00000006) - -typedef TPM_HANDLE TPMI_RH_NV_AUTH; -typedef TPM_HANDLE TPMI_RH_NV_INDEX; - -/* TPM Property capability constants. */ -typedef uint32_t TPM_PT; -#define PT_GROUP 0x00000100 -#define PT_VAR (PT_GROUP * 2) -#define TPM_PT_PERMANENT ((TPM_PT)(PT_VAR + 0)) - -/* Structures of payloads of various TPM2 commands. */ -struct tpm2_get_capability { - TPM_CAP capability; - uint32_t property; - uint32_t propertyCount; -}; - -/* get_capability response when PT_PERMANENT is requested. */ -typedef struct { - uint32_t ownerAuthSet : 1; - uint32_t endorsementAuthSet : 1; - uint32_t lockoutAuthSet : 1; - uint32_t reserved3_7 : 5; - uint32_t disableClear : 1; - uint32_t inLockout : 1; - uint32_t tpmGeneratedEPS : 1; - uint32_t reserved11_31 : 21; -} TPMA_PERMANENT; - -typedef struct { - uint32_t TPMA_NV_PPWRITE : 1; - uint32_t TPMA_NV_OWNERWRITE : 1; - uint32_t TPMA_NV_AUTHWRITE : 1; - uint32_t TPMA_NV_POLICYWRITE : 1; - uint32_t TPMA_NV_COUNTER : 1; - uint32_t TPMA_NV_BITS : 1; - uint32_t TPMA_NV_EXTEND : 1; - uint32_t reserved7_9 : 3; - uint32_t TPMA_NV_POLICY_DELETE : 1; - uint32_t TPMA_NV_WRITELOCKED : 1; - uint32_t TPMA_NV_WRITEALL : 1; - uint32_t TPMA_NV_WRITEDEFINE : 1; - uint32_t TPMA_NV_WRITE_STCLEAR : 1; - uint32_t TPMA_NV_GLOBALLOCK : 1; - uint32_t TPMA_NV_PPREAD : 1; - uint32_t TPMA_NV_OWNERREAD : 1; - uint32_t TPMA_NV_AUTHREAD : 1; - uint32_t TPMA_NV_POLICYREAD : 1; - uint32_t reserved20_24 : 5; - uint32_t TPMA_NV_NO_DA : 1; - uint32_t TPMA_NV_ORDERLY : 1; - uint32_t TPMA_NV_CLEAR_STCLEAR : 1; - uint32_t TPMA_NV_READLOCKED : 1; - uint32_t TPMA_NV_WRITTEN : 1; - uint32_t TPMA_NV_PLATFORMCREATE : 1; - uint32_t TPMA_NV_READ_STCLEAR : 1; -} TPMA_NV; - -typedef union { - struct { - uint16_t size; - const uint8_t *buffer; - } t; - TPM2B b; -} TPM2B_DIGEST; - -typedef TPM2B_DIGEST TPM2B_AUTH; -typedef TPM2B_DIGEST TPM2B_NONCE; - -typedef struct { - TPM_PT property; - uint32_t value; -} TPMS_TAGGED_PROPERTY; - -#define MAX_CAP_DATA (TPM_BUFFER_SIZE - sizeof(struct tpm_header) - \ - sizeof(TPMI_YES_NO) - sizeof(TPM_CAP) - sizeof(uint32_t)) -#define MAX_TPM_PROPERTIES (MAX_CAP_DATA/sizeof(TPMS_TAGGED_PROPERTY)) - -/* Somewhat arbitrary, leave enough room for command wrappers. */ -#define MAX_NV_BUFFER_SIZE (TPM_BUFFER_SIZE - sizeof(struct tpm_header) - 50) - -typedef struct { - uint32_t count; - TPMS_TAGGED_PROPERTY tpmProperty[MAX_TPM_PROPERTIES]; -} TPML_TAGGED_TPM_PROPERTY; - -typedef union { - TPML_TAGGED_TPM_PROPERTY tpmProperties; -} TPMU_CAPABILITIES; - -typedef struct { - TPM_CAP capability; - TPMU_CAPABILITIES data; -} TPMS_CAPABILITY_DATA; - -struct get_cap_response { - TPMI_YES_NO more_data; - TPMS_CAPABILITY_DATA cd; -}; - -typedef struct { - TPMI_RH_NV_INDEX nvIndex; - TPMI_ALG_HASH nameAlg; - TPMA_NV attributes; - TPM2B_DIGEST authPolicy; - uint16_t dataSize; -} TPMS_NV_PUBLIC; - -typedef union { - struct { - uint16_t size; - TPMS_NV_PUBLIC nvPublic; - } t; - TPM2B b; -} TPM2B_NV_PUBLIC; - -typedef union { - struct { - uint16_t size; - const uint8_t *buffer; - } t; - TPM2B b; -} TPM2B_MAX_NV_BUFFER; - -/* - * This is a union, but as of now we support just one digest - sha256, so - * there is just one element. - */ -typedef union { - uint8_t sha256[SHA256_DIGEST_SIZE]; -} TPMU_HA; - -typedef struct { - TPMI_ALG_HASH hashAlg; - TPMU_HA digest; -} TPMT_HA; - -typedef struct { - uint32_t count; - TPMT_HA digests[1]; /* Limit max number of hashes to 1. */ -} TPML_DIGEST_VALUES; - -struct nv_read_response { - uint32_t params_size; - TPM2B_MAX_NV_BUFFER buffer; -}; - -struct vendor_command_response { - uint16_t vc_subcommand; - union { - uint8_t num_restored_headers; - }; -}; - -struct tpm2_session_attrs { - uint8_t continueSession : 1; - uint8_t auditExclusive : 1; - uint8_t auditReset : 1; - uint8_t reserved3_4 : 2; - uint8_t decrypt : 1; - uint8_t encrypt : 1; - uint8_t audit : 1; -}; - -/* - * TPM session header for commands requiring session information. Also - * included in the responses to those commands. - */ -struct tpm2_session_header { - uint32_t session_handle; - uint16_t nonce_size; - uint8_t *nonce; - union { - struct tpm2_session_attrs session_attr_bits; - uint8_t session_attrs; - } __packed; - uint16_t auth_size; - uint8_t *auth; -}; - -struct tpm2_response { - struct tpm_header hdr; - union { - struct get_cap_response gc; - struct nv_read_response nvr; - struct tpm2_session_header def_space; - struct vendor_command_response vcr; - }; -}; - -struct tpm2_nv_define_space_cmd { - TPM2B_AUTH auth; - TPMS_NV_PUBLIC publicInfo; -}; - -struct tpm2_nv_write_cmd { - TPMI_RH_NV_INDEX nvIndex; - TPM2B_MAX_NV_BUFFER data; - uint16_t offset; -}; - -struct tpm2_self_test { - TPMI_YES_NO yes_no; -}; - -struct tpm2_nv_read_cmd { - TPMI_RH_NV_INDEX nvIndex; - uint16_t size; - uint16_t offset; -}; - -struct tpm2_nv_write_lock_cmd { - TPMI_RH_NV_INDEX nvIndex; -}; - -struct tpm2_pcr_extend_cmd { - TPMI_DH_PCR pcrHandle; - TPML_DIGEST_VALUES digests; -}; - -struct tpm2_hierarchy_control_cmd { - TPMI_RH_ENABLES enable; - TPMI_YES_NO state; -}; - -#endif // __SRC_LIB_TPM2_TLCL_STRUCTURES_H diff --git a/src/security/tpm/tcg-2.0/tss.c b/src/security/tpm/tcg-2.0/tss.c new file mode 100644 index 0000000000..ae8625c0b2 --- /dev/null +++ b/src/security/tpm/tcg-2.0/tss.c @@ -0,0 +1,438 @@ +/* + * 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 "tss_structures.h" +#include "tss_marshaling.h" +#include "../tis.h" +#include "../antirollback.h" + +/* + * This file provides interface between firmware and TPM2 device. The TPM1.2 + * API was copied as is and relevant functions modified to comply with the + * TPM2 specification. + */ + +static void *tpm_process_command(TPM_CC command, void *command_body) +{ + struct obuf ob; + struct ibuf ib; + size_t out_size; + size_t in_size; + const uint8_t *sendb; + /* Command/response buffer. */ + static uint8_t cr_buffer[TPM_BUFFER_SIZE] CAR_GLOBAL; + + uint8_t *cr_buffer_ptr = car_get_var_ptr(cr_buffer); + + obuf_init(&ob, cr_buffer_ptr, sizeof(cr_buffer)); + + if (tpm_marshal_command(command, command_body, &ob) < 0) { + printk(BIOS_ERR, "command %#x\n", command); + return NULL; + } + + sendb = obuf_contents(&ob, &out_size); + + in_size = sizeof(cr_buffer); + if (tis_sendrecv(sendb, out_size, cr_buffer_ptr, &in_size)) { + printk(BIOS_ERR, "tpm transaction failed\n"); + return NULL; + } + + ibuf_init(&ib, cr_buffer_ptr, in_size); + + 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; + struct tpm2_response *response; + + startup.startup_type = type; + response = tpm_process_command(TPM2_Startup, &startup); + + if (response && response->hdr.tpm_code && + (response->hdr.tpm_code != TPM_RC_INITIALIZE)) { + printk(BIOS_INFO, "%s: Startup return code is %x\n", + __func__, response->hdr.tpm_code); + return TPM_E_IOERROR; + } + return TPM_SUCCESS; + +} + +uint32_t tlcl_resume(void) +{ + return tlcl_send_startup(TPM_SU_STATE); +} + +uint32_t tlcl_assert_physical_presence(void) +{ + /* + * Nothing to do on TPM2 for this, use platform hierarchy availability + * instead. + */ + return TPM_SUCCESS; +} + +/* + * The caller will provide the digest in a 32 byte buffer, let's consider it a + * sha256 digest. + */ +uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest, + uint8_t *out_digest) +{ + struct tpm2_pcr_extend_cmd pcr_ext_cmd; + struct tpm2_response *response; + + pcr_ext_cmd.pcrHandle = HR_PCR + pcr_num; + pcr_ext_cmd.digests.count = 1; + pcr_ext_cmd.digests.digests[0].hashAlg = TPM_ALG_SHA256; + memcpy(pcr_ext_cmd.digests.digests[0].digest.sha256, in_digest, + sizeof(pcr_ext_cmd.digests.digests[0].digest.sha256)); + + response = tpm_process_command(TPM2_PCR_Extend, &pcr_ext_cmd); + + printk(BIOS_INFO, "%s: response is %x\n", + __func__, response ? response->hdr.tpm_code : -1); + if (!response || response->hdr.tpm_code) + return TPM_E_IOERROR; + + return TPM_SUCCESS; +} + +uint32_t tlcl_finalize_physical_presence(void) +{ + /* Nothing needs to be done with tpm2. */ + printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__); + return TPM_SUCCESS; +} + +uint32_t tlcl_force_clear(void) +{ + struct tpm2_response *response; + + response = tpm_process_command(TPM2_Clear, NULL); + printk(BIOS_INFO, "%s: response is %x\n", + __func__, response ? response->hdr.tpm_code : -1); + + if (!response || response->hdr.tpm_code) + return TPM_E_IOERROR; + + 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. */ +uint32_t tlcl_lib_init(void) +{ + uint8_t done = car_get_var(tlcl_init_done); + if (done) + return VB2_SUCCESS; + + if (tis_init()) + return VB2_ERROR_UNKNOWN; + if (tis_open()) + return VB2_ERROR_UNKNOWN; + + car_set_var(tlcl_init_done, 1); + + return VB2_SUCCESS; +} + +uint32_t tlcl_physical_presence_cmd_enable(void) +{ + printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__); + return TPM_SUCCESS; +} + +uint32_t tlcl_read(uint32_t index, void *data, uint32_t length) +{ + struct tpm2_nv_read_cmd nv_readc; + struct tpm2_response *response; + + memset(&nv_readc, 0, sizeof(nv_readc)); + + nv_readc.nvIndex = HR_NV_INDEX + index; + nv_readc.size = length; + + response = tpm_process_command(TPM2_NV_Read, &nv_readc); + + /* Need to map tpm error codes into internal values. */ + if (!response) + return TPM_E_READ_FAILURE; + + printk(BIOS_INFO, "%s:%d index %#x return code %x\n", + __FILE__, __LINE__, index, response->hdr.tpm_code); + switch (response->hdr.tpm_code) { + case 0: + break; + + /* Uninitialized, returned if the space hasn't been written. */ + case TPM_RC_NV_UNINITIALIZED: + /* + * Bad index, cr50 specific value, returned if the space + * hasn't been defined. + */ + case TPM_RC_CR50_NV_UNDEFINED: + return TPM_E_BADINDEX; + + default: + return TPM_E_READ_FAILURE; + } + + if (length > response->nvr.buffer.t.size) + return TPM_E_RESPONSE_TOO_LARGE; + + if (length < response->nvr.buffer.t.size) + return TPM_E_READ_EMPTY; + + memcpy(data, response->nvr.buffer.t.buffer, length); + + return TPM_SUCCESS; +} + +uint32_t tlcl_self_test_full(void) +{ + struct tpm2_self_test st; + struct tpm2_response *response; + + st.yes_no = 1; + + response = tpm_process_command(TPM2_SelfTest, &st); + printk(BIOS_INFO, "%s: response is %x\n", + __func__, response ? response->hdr.tpm_code : -1); + 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; + /* TPM Wll reject attempts to write at non-defined index. */ + struct tpm2_nv_write_lock_cmd nv_wl = { + .nvIndex = HR_NV_INDEX + index, + }; + + response = tpm_process_command(TPM2_NV_WriteLock, &nv_wl); + + printk(BIOS_INFO, "%s: response is %x\n", + __func__, response ? response->hdr.tpm_code : -1); + + if (!response || response->hdr.tpm_code) + return TPM_E_IOERROR; + + return TPM_SUCCESS; +} + +uint32_t tlcl_startup(void) +{ + return tlcl_send_startup(TPM_SU_CLEAR); +} + +uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length) +{ + struct tpm2_nv_write_cmd nv_writec; + struct tpm2_response *response; + + memset(&nv_writec, 0, sizeof(nv_writec)); + + nv_writec.nvIndex = HR_NV_INDEX + index; + nv_writec.data.t.size = length; + nv_writec.data.t.buffer = data; + + response = tpm_process_command(TPM2_NV_Write, &nv_writec); + + printk(BIOS_INFO, "%s: response is %x\n", + __func__, response ? response->hdr.tpm_code : -1); + + /* Need to map tpm error codes into internal values. */ + if (!response || response->hdr.tpm_code) + return TPM_E_WRITE_FAILURE; + + return TPM_SUCCESS; +} + +uint32_t tlcl_define_space(uint32_t space_index, size_t space_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)); + + nvds_cmd.publicInfo.dataSize = space_size; + nvds_cmd.publicInfo.nvIndex = HR_NV_INDEX + space_index; + nvds_cmd.publicInfo.nameAlg = TPM_ALG_SHA256; + + /* 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; + } + + response = tpm_process_command(TPM2_NV_DefineSpace, &nvds_cmd); + printk(BIOS_INFO, "%s: response is %x\n", + __func__, response ? response->hdr.tpm_code : -1); + + if (!response) + return TPM_E_NO_DEVICE; + + /* Map TPM2 retrun codes into common vboot represenation. */ + switch (response->hdr.tpm_code) { + case TPM2_RC_SUCCESS: + return TPM_SUCCESS; + case TPM2_RC_NV_DEFINED: + return TPM_E_NV_DEFINED; + default: + return TPM_E_INTERNAL_INCONSISTENCY; + } +} + +uint32_t tlcl_disable_platform_hierarchy(void) +{ + struct tpm2_response *response; + struct tpm2_hierarchy_control_cmd hc = { + .enable = TPM_RH_PLATFORM, + .state = 0, + }; + + response = tpm_process_command(TPM2_Hierarchy_Control, &hc); + + if (!response || response->hdr.tpm_code) + return TPM_E_INTERNAL_INCONSISTENCY; + + 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/tcg-2.0/tss_marshaling.c b/src/security/tpm/tcg-2.0/tss_marshaling.c new file mode 100644 index 0000000000..b1d666362b --- /dev/null +++ b/src/security/tpm/tcg-2.0/tss_marshaling.c @@ -0,0 +1,559 @@ +/* + * 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 "tss_marshaling.h" + +static uint16_t tpm_tag CAR_GLOBAL; /* Depends on the command type. */ + +#define unmarshal_TPM_CAP(a, b) ibuf_read_be32(a, b) +#define unmarshal_TPM_CC(a, b) ibuf_read_be32(a, b) +#define unmarshal_TPM_PT(a, b) ibuf_read_be32(a, b) +#define unmarshal_TPM_HANDLE(a, b) ibuf_read_be32(a, b) + +#define marshal_TPM_HANDLE(a, b) obuf_write_be32(a, b) +#define marshal_TPMI_ALG_HASH(a, b) obuf_write_be16(a, b) + +static int marshal_startup(struct obuf *ob, struct tpm2_startup *cmd_body) +{ + return obuf_write_be16(ob, cmd_body->startup_type); +} + +static int marshal_get_capability(struct obuf *ob, + struct tpm2_get_capability *cmd_body) +{ + int rc = 0; + + rc |= obuf_write_be32(ob, cmd_body->capability); + rc |= obuf_write_be32(ob, cmd_body->property); + rc |= obuf_write_be32(ob, cmd_body->propertyCount); + + return rc; +} + +static int marshal_TPM2B(struct obuf *ob, TPM2B *data) +{ + int rc = 0; + + rc |= obuf_write_be16(ob, data->size); + rc |= obuf_write(ob, data->buffer, data->size); + + return rc; +} + +static int marshal_TPMA_NV(struct obuf *ob, TPMA_NV *nv) +{ + uint32_t v; + + memcpy(&v, nv, sizeof(v)); + return obuf_write_be32(ob, v); +} + +static int marshal_TPMS_NV_PUBLIC(struct obuf *ob, TPMS_NV_PUBLIC *nvpub) +{ + int rc = 0; + + rc |= marshal_TPM_HANDLE(ob, nvpub->nvIndex); + rc |= marshal_TPMI_ALG_HASH(ob, nvpub->nameAlg); + rc |= marshal_TPMA_NV(ob, &nvpub->attributes); + rc |= marshal_TPM2B(ob, &nvpub->authPolicy.b); + rc |= obuf_write_be16(ob, nvpub->dataSize); + + return rc; +} + +static int marshal_TPMT_HA(struct obuf *ob, TPMT_HA *tpmtha) +{ + int rc = 0; + + rc |= marshal_TPMI_ALG_HASH(ob, tpmtha->hashAlg); + rc |= obuf_write(ob, tpmtha->digest.sha256, + sizeof(tpmtha->digest.sha256)); + + return rc; +} + +static int marshal_TPML_DIGEST_VALUES(struct obuf *ob, + TPML_DIGEST_VALUES *dvalues) +{ + int i; + int rc = 0; + + rc |= obuf_write_be32(ob, dvalues->count); + for (i = 0; i < dvalues->count; i++) + rc |= marshal_TPMT_HA(ob, &dvalues->digests[i]); + + return rc; +} + +static int marshal_session_header(struct obuf *ob, + struct tpm2_session_header *session_header) +{ + int rc = 0; + struct obuf ob_sz; + size_t prev_written; + + /* Snapshot current location to place size of header. */ + if (obuf_splice_current(ob, &ob_sz, sizeof(uint32_t)) < 0) + return -1; + + /* Write a size placeholder. */ + rc |= obuf_write_be32(ob, 0); + + /* Keep track of session header data size by tracking num written. */ + prev_written = obuf_nr_written(ob); + + rc |= obuf_write_be32(ob, session_header->session_handle); + rc |= obuf_write_be16(ob, session_header->nonce_size); + rc |= obuf_write(ob, session_header->nonce, session_header->nonce_size); + rc |= obuf_write_be8(ob, session_header->session_attrs); + rc |= obuf_write_be16(ob, session_header->auth_size); + rc |= obuf_write(ob, session_header->auth, session_header->auth_size); + + /* Fill back in proper size of session header. */ + rc |= obuf_write_be32(&ob_sz, obuf_nr_written(ob) - prev_written); + + return rc; +} + +/* + * Common session header can include one or two handles and an empty + * session_header structure. + */ +static int marshal_common_session_header(struct obuf *ob, + const uint32_t *handles, + size_t handle_count) +{ + size_t i; + struct tpm2_session_header session_header; + int rc = 0; + + car_set_var(tpm_tag, TPM_ST_SESSIONS); + + for (i = 0; i < handle_count; i++) + rc |= marshal_TPM_HANDLE(ob, handles[i]); + + memset(&session_header, 0, sizeof(session_header)); + session_header.session_handle = TPM_RS_PW; + rc |= marshal_session_header(ob, &session_header); + + return rc; +} + +static int marshal_nv_define_space(struct obuf *ob, + struct tpm2_nv_define_space_cmd *nvd_in) +{ + const uint32_t handle[] = { TPM_RH_PLATFORM }; + struct obuf ob_sz; + size_t prev_written; + int rc = 0; + + rc |= marshal_common_session_header(ob, handle, ARRAY_SIZE(handle)); + rc |= marshal_TPM2B(ob, &nvd_in->auth.b); + + /* Snapshot current location to place size field. */ + if (obuf_splice_current(ob, &ob_sz, sizeof(uint16_t)) < 0) + return -1; + + /* Put placeholder for size */ + rc |= obuf_write_be16(ob, 0); + + /* Keep track of nv define space data size by tracking num written. */ + prev_written = obuf_nr_written(ob); + + rc |= marshal_TPMS_NV_PUBLIC(ob, &nvd_in->publicInfo); + rc |= obuf_write_be16(&ob_sz, obuf_nr_written(ob) - prev_written); + + return rc; +} + +static int marshal_nv_write(struct obuf *ob, + struct tpm2_nv_write_cmd *command_body) +{ + int rc = 0; + uint32_t handles[] = { TPM_RH_PLATFORM, command_body->nvIndex }; + + rc |= marshal_common_session_header(ob, handles, ARRAY_SIZE(handles)); + rc |= marshal_TPM2B(ob, &command_body->data.b); + rc |= obuf_write_be16(ob, command_body->offset); + + return rc; +} + +static int marshal_nv_write_lock(struct obuf *ob, + struct tpm2_nv_write_lock_cmd *command_body) +{ + uint32_t handles[] = { TPM_RH_PLATFORM, command_body->nvIndex }; + + return marshal_common_session_header(ob, handles, ARRAY_SIZE(handles)); +} + +static int marshal_pcr_extend(struct obuf *ob, + struct tpm2_pcr_extend_cmd *command_body) +{ + int rc = 0; + uint32_t handles[] = { command_body->pcrHandle }; + + rc |= marshal_common_session_header(ob, handles, ARRAY_SIZE(handles)); + rc |= marshal_TPML_DIGEST_VALUES(ob, &command_body->digests); + + return rc; +} + +static int marshal_nv_read(struct obuf *ob, + struct tpm2_nv_read_cmd *command_body) +{ + int rc = 0; + uint32_t handles[] = { TPM_RH_PLATFORM, command_body->nvIndex }; + + rc |= marshal_common_session_header(ob, handles, ARRAY_SIZE(handles)); + rc |= obuf_write_be16(ob, command_body->size); + rc |= obuf_write_be16(ob, command_body->offset); + + return rc; +} + +/* TPM2_Clear command does not require paramaters. */ +static int marshal_clear(struct obuf *ob) +{ + const uint32_t handle[] = { TPM_RH_PLATFORM }; + + return marshal_common_session_header(ob, handle, ARRAY_SIZE(handle)); +} + +static int marshal_selftest(struct obuf *ob, + struct tpm2_self_test *command_body) +{ + return obuf_write_be8(ob, command_body->yes_no); +} + +static int marshal_hierarchy_control(struct obuf *ob, + struct tpm2_hierarchy_control_cmd *command_body) +{ + int rc = 0; + struct tpm2_session_header session_header; + + car_set_var(tpm_tag, TPM_ST_SESSIONS); + + rc |= marshal_TPM_HANDLE(ob, TPM_RH_PLATFORM); + memset(&session_header, 0, sizeof(session_header)); + session_header.session_handle = TPM_RS_PW; + rc |= marshal_session_header(ob, &session_header); + + rc |= marshal_TPM_HANDLE(ob, command_body->enable); + rc |= obuf_write_be8(ob, command_body->state); + + return rc; +} + +static int marshal_cr50_vendor_command(struct obuf *ob, void *command_body) +{ + int rc = 0; + uint16_t *sub_command = command_body; + + switch (*sub_command) { + case TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS: + rc |= obuf_write_be16(ob, *sub_command); + break; + case TPM2_CR50_SUB_CMD_TURN_UPDATE_ON: + rc |= obuf_write_be16(ob, sub_command[0]); + rc |= obuf_write_be16(ob, sub_command[1]); + break; + default: + /* Unsupported subcommand. */ + printk(BIOS_WARNING, "Unsupported cr50 subcommand: 0x%04x\n", + *sub_command); + rc = -1; + break; + } + return rc; +} + +int tpm_marshal_command(TPM_CC command, void *tpm_command_body, struct obuf *ob) +{ + struct obuf ob_hdr; + const size_t hdr_sz = sizeof(uint16_t) + 2 * sizeof(uint32_t); + int rc = 0; + + car_set_var(tpm_tag, TPM_ST_NO_SESSIONS); + + if (obuf_splice_current(ob, &ob_hdr, hdr_sz) < 0) + return -1; + + /* Write TPM command header with placeholder field values. */ + rc |= obuf_write_be16(ob, 0); + rc |= obuf_write_be32(ob, 0); + rc |= obuf_write_be32(ob, command); + + if (rc != 0) + return rc; + + switch (command) { + case TPM2_Startup: + rc |= marshal_startup(ob, tpm_command_body); + break; + + case TPM2_GetCapability: + rc |= marshal_get_capability(ob, tpm_command_body); + break; + + case TPM2_NV_Read: + rc |= marshal_nv_read(ob, tpm_command_body); + break; + + case TPM2_NV_DefineSpace: + rc |= marshal_nv_define_space(ob, tpm_command_body); + break; + + case TPM2_NV_Write: + rc |= marshal_nv_write(ob, tpm_command_body); + break; + + case TPM2_NV_WriteLock: + rc |= marshal_nv_write_lock(ob, tpm_command_body); + break; + + case TPM2_SelfTest: + rc |= marshal_selftest(ob, tpm_command_body); + break; + + case TPM2_Hierarchy_Control: + rc |= marshal_hierarchy_control(ob, tpm_command_body); + break; + + case TPM2_Clear: + rc |= marshal_clear(ob); + break; + + case TPM2_PCR_Extend: + rc |= marshal_pcr_extend(ob, tpm_command_body); + break; + + case TPM2_CR50_VENDOR_COMMAND: + rc |= marshal_cr50_vendor_command(ob, tpm_command_body); + break; + + default: + printk(BIOS_INFO, "%s:%d:Request to marshal unsupported command %#x\n", + __FILE__, __LINE__, command); + rc = -1; + } + + if (rc != 0) + return rc; + + /* Fix up the command header with known values. */ + rc |= obuf_write_be16(&ob_hdr, car_get_var(tpm_tag)); + rc |= obuf_write_be32(&ob_hdr, obuf_nr_written(ob)); + + return rc; +} + +static int unmarshal_get_capability(struct ibuf *ib, + struct get_cap_response *gcr) +{ + int i; + int rc = 0; + + rc |= ibuf_read_be8(ib, &gcr->more_data); + rc |= unmarshal_TPM_CAP(ib, &gcr->cd.capability); + + if (rc != 0) + return rc; + + switch (gcr->cd.capability) { + case TPM_CAP_TPM_PROPERTIES: + if (ibuf_read_be32(ib, &gcr->cd.data.tpmProperties.count)) + return -1; + if (gcr->cd.data.tpmProperties.count > ARRAY_SIZE + (gcr->cd.data.tpmProperties.tpmProperty)) { + printk(BIOS_INFO, "%s:%s:%d - %d - too many properties\n", + __FILE__, __func__, __LINE__, + gcr->cd.data.tpmProperties.count); + return -1; + } + for (i = 0; i < gcr->cd.data.tpmProperties.count; i++) { + TPMS_TAGGED_PROPERTY *pp; + + pp = gcr->cd.data.tpmProperties.tpmProperty + i; + rc |= unmarshal_TPM_PT(ib, &pp->property); + rc |= ibuf_read_be32(ib, &pp->value); + } + break; + default: + printk(BIOS_ERR, + "%s:%d - unable to unmarshal capability response", + __func__, __LINE__); + printk(BIOS_ERR, " for %d\n", gcr->cd.capability); + rc = -1; + break; + } + + return rc; +} + +static int unmarshal_TPM2B_MAX_NV_BUFFER(struct ibuf *ib, + TPM2B_MAX_NV_BUFFER *nv_buffer) +{ + if (ibuf_read_be16(ib, &nv_buffer->t.size)) + return -1; + + nv_buffer->t.buffer = ibuf_oob_drain(ib, nv_buffer->t.size); + + if (nv_buffer->t.buffer == NULL) { + printk(BIOS_ERR, "%s:%d - " + "size mismatch: expected %d, remaining %zd\n", + __func__, __LINE__, nv_buffer->t.size, + ibuf_remaining(ib)); + return -1; + } + + return 0; +} + +static int unmarshal_nv_read(struct ibuf *ib, struct nv_read_response *nvr) +{ + /* Total size of the parameter field. */ + if (ibuf_read_be32(ib, &nvr->params_size)) + return -1; + + if (unmarshal_TPM2B_MAX_NV_BUFFER(ib, &nvr->buffer)) + return -1; + + if (nvr->params_size != + (nvr->buffer.t.size + sizeof(nvr->buffer.t.size))) { + printk(BIOS_ERR, + "%s:%d - parameter/buffer %d/%d size mismatch", + __func__, __LINE__, nvr->params_size, + nvr->buffer.t.size); + return -1; + } + + /* + * Let's ignore the authorisation section. It should be 5 bytes total, + * just confirm that this is the case and report any discrepancy. + */ + if (ibuf_remaining(ib) != 5) + printk(BIOS_ERR, + "%s:%d - unexpected authorisation seciton size %zd\n", + __func__, __LINE__, ibuf_remaining(ib)); + + ibuf_oob_drain(ib, ibuf_remaining(ib)); + + return 0; +} + +static int unmarshal_vendor_command(struct ibuf *ib, + struct vendor_command_response *vcr) +{ + if (ibuf_read_be16(ib, &vcr->vc_subcommand)) + return -1; + + switch (vcr->vc_subcommand) { + case TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS: + break; + case TPM2_CR50_SUB_CMD_TURN_UPDATE_ON: + return ibuf_read_be8(ib, &vcr->num_restored_headers); + break; + default: + printk(BIOS_ERR, + "%s:%d - unsupported vendor command %#04x!\n", + __func__, __LINE__, vcr->vc_subcommand); + return -1; + } + + return 0; +} + +struct tpm2_response *tpm_unmarshal_response(TPM_CC command, struct ibuf *ib) +{ + static struct tpm2_response tpm2_static_resp CAR_GLOBAL; + struct tpm2_response *tpm2_resp = car_get_var_ptr(&tpm2_static_resp); + int rc = 0; + + rc |= ibuf_read_be16(ib, &tpm2_resp->hdr.tpm_tag); + rc |= ibuf_read_be32(ib, &tpm2_resp->hdr.tpm_size); + rc |= unmarshal_TPM_CC(ib, &tpm2_resp->hdr.tpm_code); + + if (rc != 0) + return NULL; + + if (ibuf_remaining(ib) == 0) { + if (tpm2_resp->hdr.tpm_size != ibuf_nr_read(ib)) + printk(BIOS_ERR, + "%s: size mismatch in response to command %#x\n", + __func__, command); + return tpm2_resp; + } + + switch (command) { + case TPM2_Startup: + break; + + case TPM2_GetCapability: + rc |= unmarshal_get_capability(ib, &tpm2_resp->gc); + break; + + case TPM2_NV_Read: + rc |= unmarshal_nv_read(ib, &tpm2_resp->nvr); + break; + + case TPM2_Hierarchy_Control: + case TPM2_Clear: + case TPM2_NV_DefineSpace: + case TPM2_NV_Write: + case TPM2_NV_WriteLock: + case TPM2_PCR_Extend: + /* Session data included in response can be safely ignored. */ + ibuf_oob_drain(ib, ibuf_remaining(ib)); + break; + + case TPM2_CR50_VENDOR_COMMAND: + rc |= unmarshal_vendor_command(ib, &tpm2_resp->vcr); + break; + + default: + { + size_t i; + size_t sz_left; + const uint8_t *data; + + printk(BIOS_INFO, "%s:%d:" + "Request to unmarshal unexpected command %#x," + " code %#x", + __func__, __LINE__, command, + tpm2_resp->hdr.tpm_code); + + sz_left = ibuf_remaining(ib); + data = ibuf_oob_drain(ib, sz_left); + + for (i = 0; i < sz_left; i++) { + if (!(i % 16)) + printk(BIOS_INFO, "\n"); + printk(BIOS_INFO, "%2.2x ", data[i]); + } + } + printk(BIOS_INFO, "\n"); + return NULL; + } + + if (ibuf_remaining(ib)) { + printk(BIOS_INFO, + "%s:%d got %d bytes back in response to %#x," + " failed to parse (%zd)\n", + __func__, __LINE__, tpm2_resp->hdr.tpm_size, + command, ibuf_remaining(ib)); + return NULL; + } + + /* The entire message have been parsed. */ + return tpm2_resp; +} diff --git a/src/security/tpm/tcg-2.0/tss_marshaling.h b/src/security/tpm/tcg-2.0/tss_marshaling.h new file mode 100644 index 0000000000..d34756d566 --- /dev/null +++ b/src/security/tpm/tcg-2.0/tss_marshaling.h @@ -0,0 +1,46 @@ +/* + * 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. + */ +#ifndef TCG2_TSS_MARSHALING_H_ +#define TCG2_TSS_MARSHALING_H_ + +#include +#include "tss_structures.h" + +/* The below functions are used to serialize/deserialize TPM2 commands. */ + +/** + * tpm_marshal_command + * + * Given a structure containing a TPM2 command, serialize the structure for + * sending it to the TPM. + * + * @command: code of the TPM2 command to marshal + * @tpm_command_body: a pointer to the command specific structure + * @ob: output buffer where command is marshaled to + * + * Returns 0 on success or -1 on error. + * + */ +int tpm_marshal_command(TPM_CC command, void *tpm_command_body, + struct obuf *ob); + +/** + * tpm_unmarshal_response + * + * Given a buffer received from the TPM in response to a certain command, + * deserialize the buffer into the expeced response structure. + * + * struct tpm2_response is a union of all possible responses. + * + * @command: code of the TPM2 command for which a response is unmarshaled + * @ib: input buffer containing the serialized response. + * + * Returns a pointer to the deserialized response or NULL in case of + * unmarshaling problems. + */ +struct tpm2_response *tpm_unmarshal_response(TPM_CC command, struct ibuf *ib); + +#endif // TCG2_TSS_MARSHALING_H_ diff --git a/src/security/tpm/tcg-2.0/tss_structures.h b/src/security/tpm/tcg-2.0/tss_structures.h new file mode 100644 index 0000000000..389f15df4b --- /dev/null +++ b/src/security/tpm/tcg-2.0/tss_structures.h @@ -0,0 +1,373 @@ +/* + * 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. + */ + +#ifndef TCG2_TSS_STRUCTURES_H_ +#define TCG2_TSS_STRUCTURES_H_ + +/* + * This file includes a subset of definitions of TPM protocol version 2.x + * constants and structures needed for functions used in coreboot. + */ +#include +#include +#include + +#include "../tss.h" + +/* This should be plenty for what firmware needs. */ +#define TPM_BUFFER_SIZE 256 + +/* 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; +typedef TPM_ALG_ID TPMI_ALG_HASH; +typedef TPM_HANDLE TPMI_DH_PCR; +typedef TPM_HANDLE TPMI_RH_NV_INDEX; +typedef TPM_HANDLE TPMI_RH_ENABLES; +typedef TPM_HANDLE TPMI_SH_AUTH_SESSION; +typedef TPM_HANDLE TPM_RH; + +/* Some hardcoded algorithm values. */ +#define TPM_ALG_HMAC ((TPM_ALG_ID)0x0005) +#define TPM_ALG_NULL ((TPM_ALG_ID)0x0010) +#define TPM_ALG_SHA1 ((TPM_ALG_ID)0x0004) +#define TPM_ALG_SHA256 ((TPM_ALG_ID)0x000b) + +#define SHA256_DIGEST_SIZE 32 + +/* Some hardcoded hierarchies. */ +#define TPM_RH_NULL 0x40000007 +#define TPM_RS_PW 0x40000009 +#define TPM_RH_PLATFORM 0x4000000C + +typedef struct { + uint16_t size; + uint8_t *buffer; +} TPM2B; + +/* Relevant TPM Command's structures. */ +/* Common command/response header. */ +struct tpm_header { + uint16_t tpm_tag; + uint32_t tpm_size; + TPM_CC tpm_code; +} __packed; + +/* TPM command codes. */ +#define TPM2_Hierarchy_Control ((TPM_CC)0x00000121) +#define TPM2_Clear ((TPM_CC)0x00000126) +#define TPM2_NV_DefineSpace ((TPM_CC)0x0000012A) +#define TPM2_NV_Write ((TPM_CC)0x00000137) +#define TPM2_NV_WriteLock ((TPM_CC)0x00000138) +#define TPM2_SelfTest ((TPM_CC)0x00000143) +#define TPM2_Startup ((TPM_CC)0x00000144) +#define TPM2_NV_Read ((TPM_CC)0x0000014E) +#define TPM2_GetCapability ((TPM_CC)0x0000017A) +#define TPM2_PCR_Extend ((TPM_CC)0x00000182) +/* 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 +#define TPM_SU_STATE 1 + +#define TPM_HT_PCR 0x00 +#define TPM_HT_NV_INDEX 0x01 +#define TPM_HT_HMAC_SESSION 0x02 +#define TPM_HT_POLICY_SESSION 0x03 + +#define HR_SHIFT 24 +#define HR_PCR (TPM_HT_PCR << HR_SHIFT) +#define HR_HMAC_SESSION (TPM_HT_HMAC_SESSION << HR_SHIFT) +#define HR_POLICY_SESSION (TPM_HT_POLICY_SESSION << HR_SHIFT) +#define HR_TRANSIENT (TPM_HT_TRANSIENT << HR_SHIFT) +#define HR_PERSISTENT (TPM_HT_PERSISTENT << HR_SHIFT) +#define HR_NV_INDEX (TPM_HT_NV_INDEX << HR_SHIFT) +#define HR_PERMANENT (TPM_HT_PERMANENT << HR_SHIFT) +#define PCR_FIRST (HR_PCR + 0) +#define PCR_LAST (PCR_FIRST + IMPLEMENTATION_PCR-1) +#define HMAC_SESSION_FIRST (HR_HMAC_SESSION + 0) +#define HMAC_SESSION_LAST (HMAC_SESSION_FIRST+MAX_ACTIVE_SESSIONS-1) +#define LOADED_SESSION_FIRST HMAC_SESSION_FIRST +#define LOADED_SESSION_LAST HMAC_SESSION_LAST +#define POLICY_SESSION_FIRST (HR_POLICY_SESSION + 0) +#define POLICY_SESSION_LAST (POLICY_SESSION_FIRST + MAX_ACTIVE_SESSIONS-1) +#define TRANSIENT_FIRST (HR_TRANSIENT + 0) +#define ACTIVE_SESSION_FIRST POLICY_SESSION_FIRST +#define ACTIVE_SESSION_LAST POLICY_SESSION_LAST +#define TRANSIENT_LAST (TRANSIENT_FIRST+MAX_LOADED_OBJECTS-1) +#define PERSISTENT_FIRST (HR_PERSISTENT + 0) +#define PERSISTENT_LAST (PERSISTENT_FIRST + 0x00FFFFFF) +#define PLATFORM_PERSISTENT (PERSISTENT_FIRST + 0x00800000) +#define NV_INDEX_FIRST (HR_NV_INDEX + 0) +#define NV_INDEX_LAST (NV_INDEX_FIRST + 0x00FFFFFF) +#define PERMANENT_FIRST TPM_RH_FIRST +#define PERMANENT_LAST TPM_RH_LAST + +/* Tpm2 command tags. */ +#define TPM_ST_NO_SESSIONS 0x8001 +#define TPM_ST_SESSIONS 0x8002 + +/* Values copied from tpm2/tpm_types.h */ +#define RC_VER1 0x100 +#define TPM_RC_INITIALIZE ((TPM_RC)(RC_VER1 + 0x000)) +#define TPM_RC_NV_UNINITIALIZED ((TPM_RC)(RC_VER1 + 0x04A)) + +/* + * Cr50 returns this code when an attempt is made to read an NV location which + * has not yet been defined. This is an aggregation of various return code + * extensions which may or may not match if a different TPM2 device is + * used. + */ +#define TPM_RC_CR50_NV_UNDEFINED 0x28b + +/* TPM command structures. */ + +struct tpm2_startup { + TPM_SU startup_type; +}; + +/* Various TPM capability types to use when querying the device. */ +typedef uint32_t TPM_CAP; +#define TPM_CAP_TPM_PROPERTIES ((TPM_CAP)0x00000006) + +typedef TPM_HANDLE TPMI_RH_NV_AUTH; +typedef TPM_HANDLE TPMI_RH_NV_INDEX; + +/* TPM Property capability constants. */ +typedef uint32_t TPM_PT; +#define PT_GROUP 0x00000100 +#define PT_VAR (PT_GROUP * 2) +#define TPM_PT_PERMANENT ((TPM_PT)(PT_VAR + 0)) + +/* Structures of payloads of various TPM2 commands. */ +struct tpm2_get_capability { + TPM_CAP capability; + uint32_t property; + uint32_t propertyCount; +}; + +/* get_capability response when PT_PERMANENT is requested. */ +typedef struct { + uint32_t ownerAuthSet : 1; + uint32_t endorsementAuthSet : 1; + uint32_t lockoutAuthSet : 1; + uint32_t reserved3_7 : 5; + uint32_t disableClear : 1; + uint32_t inLockout : 1; + uint32_t tpmGeneratedEPS : 1; + uint32_t reserved11_31 : 21; +} TPMA_PERMANENT; + +typedef struct { + uint32_t TPMA_NV_PPWRITE : 1; + uint32_t TPMA_NV_OWNERWRITE : 1; + uint32_t TPMA_NV_AUTHWRITE : 1; + uint32_t TPMA_NV_POLICYWRITE : 1; + uint32_t TPMA_NV_COUNTER : 1; + uint32_t TPMA_NV_BITS : 1; + uint32_t TPMA_NV_EXTEND : 1; + uint32_t reserved7_9 : 3; + uint32_t TPMA_NV_POLICY_DELETE : 1; + uint32_t TPMA_NV_WRITELOCKED : 1; + uint32_t TPMA_NV_WRITEALL : 1; + uint32_t TPMA_NV_WRITEDEFINE : 1; + uint32_t TPMA_NV_WRITE_STCLEAR : 1; + uint32_t TPMA_NV_GLOBALLOCK : 1; + uint32_t TPMA_NV_PPREAD : 1; + uint32_t TPMA_NV_OWNERREAD : 1; + uint32_t TPMA_NV_AUTHREAD : 1; + uint32_t TPMA_NV_POLICYREAD : 1; + uint32_t reserved20_24 : 5; + uint32_t TPMA_NV_NO_DA : 1; + uint32_t TPMA_NV_ORDERLY : 1; + uint32_t TPMA_NV_CLEAR_STCLEAR : 1; + uint32_t TPMA_NV_READLOCKED : 1; + uint32_t TPMA_NV_WRITTEN : 1; + uint32_t TPMA_NV_PLATFORMCREATE : 1; + uint32_t TPMA_NV_READ_STCLEAR : 1; +} TPMA_NV; + +typedef union { + struct { + uint16_t size; + const uint8_t *buffer; + } t; + TPM2B b; +} TPM2B_DIGEST; + +typedef TPM2B_DIGEST TPM2B_AUTH; +typedef TPM2B_DIGEST TPM2B_NONCE; + +typedef struct { + TPM_PT property; + uint32_t value; +} TPMS_TAGGED_PROPERTY; + +#define MAX_CAP_DATA (TPM_BUFFER_SIZE - sizeof(struct tpm_header) - \ + sizeof(TPMI_YES_NO) - sizeof(TPM_CAP) - sizeof(uint32_t)) +#define MAX_TPM_PROPERTIES (MAX_CAP_DATA/sizeof(TPMS_TAGGED_PROPERTY)) + +/* Somewhat arbitrary, leave enough room for command wrappers. */ +#define MAX_NV_BUFFER_SIZE (TPM_BUFFER_SIZE - sizeof(struct tpm_header) - 50) + +typedef struct { + uint32_t count; + TPMS_TAGGED_PROPERTY tpmProperty[MAX_TPM_PROPERTIES]; +} TPML_TAGGED_TPM_PROPERTY; + +typedef union { + TPML_TAGGED_TPM_PROPERTY tpmProperties; +} TPMU_CAPABILITIES; + +typedef struct { + TPM_CAP capability; + TPMU_CAPABILITIES data; +} TPMS_CAPABILITY_DATA; + +struct get_cap_response { + TPMI_YES_NO more_data; + TPMS_CAPABILITY_DATA cd; +}; + +typedef struct { + TPMI_RH_NV_INDEX nvIndex; + TPMI_ALG_HASH nameAlg; + TPMA_NV attributes; + TPM2B_DIGEST authPolicy; + uint16_t dataSize; +} TPMS_NV_PUBLIC; + +typedef union { + struct { + uint16_t size; + TPMS_NV_PUBLIC nvPublic; + } t; + TPM2B b; +} TPM2B_NV_PUBLIC; + +typedef union { + struct { + uint16_t size; + const uint8_t *buffer; + } t; + TPM2B b; +} TPM2B_MAX_NV_BUFFER; + +/* + * This is a union, but as of now we support just one digest - sha256, so + * there is just one element. + */ +typedef union { + uint8_t sha256[SHA256_DIGEST_SIZE]; +} TPMU_HA; + +typedef struct { + TPMI_ALG_HASH hashAlg; + TPMU_HA digest; +} TPMT_HA; + +typedef struct { + uint32_t count; + TPMT_HA digests[1]; /* Limit max number of hashes to 1. */ +} TPML_DIGEST_VALUES; + +struct nv_read_response { + uint32_t params_size; + TPM2B_MAX_NV_BUFFER buffer; +}; + +struct vendor_command_response { + uint16_t vc_subcommand; + union { + uint8_t num_restored_headers; + }; +}; + +struct tpm2_session_attrs { + uint8_t continueSession : 1; + uint8_t auditExclusive : 1; + uint8_t auditReset : 1; + uint8_t reserved3_4 : 2; + uint8_t decrypt : 1; + uint8_t encrypt : 1; + uint8_t audit : 1; +}; + +/* + * TPM session header for commands requiring session information. Also + * included in the responses to those commands. + */ +struct tpm2_session_header { + uint32_t session_handle; + uint16_t nonce_size; + uint8_t *nonce; + union { + struct tpm2_session_attrs session_attr_bits; + uint8_t session_attrs; + } __packed; + uint16_t auth_size; + uint8_t *auth; +}; + +struct tpm2_response { + struct tpm_header hdr; + union { + struct get_cap_response gc; + struct nv_read_response nvr; + struct tpm2_session_header def_space; + struct vendor_command_response vcr; + }; +}; + +struct tpm2_nv_define_space_cmd { + TPM2B_AUTH auth; + TPMS_NV_PUBLIC publicInfo; +}; + +struct tpm2_nv_write_cmd { + TPMI_RH_NV_INDEX nvIndex; + TPM2B_MAX_NV_BUFFER data; + uint16_t offset; +}; + +struct tpm2_self_test { + TPMI_YES_NO yes_no; +}; + +struct tpm2_nv_read_cmd { + TPMI_RH_NV_INDEX nvIndex; + uint16_t size; + uint16_t offset; +}; + +struct tpm2_nv_write_lock_cmd { + TPMI_RH_NV_INDEX nvIndex; +}; + +struct tpm2_pcr_extend_cmd { + TPMI_DH_PCR pcrHandle; + TPML_DIGEST_VALUES digests; +}; + +struct tpm2_hierarchy_control_cmd { + TPMI_RH_ENABLES enable; + TPMI_YES_NO state; +}; + +#endif // TCG2_TSS_STRUCTURES_H_ diff --git a/src/security/tpm/tis.h b/src/security/tpm/tis.h new file mode 100644 index 0000000000..6906ce33ec --- /dev/null +++ b/src/security/tpm/tis.h @@ -0,0 +1,102 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2011 Google 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 TIS_H_ +#define TIS_H_ + +#include +#include + +enum tis_access { + TPM_ACCESS_VALID = (1 << 7), + TPM_ACCESS_ACTIVE_LOCALITY = (1 << 5), + TPM_ACCESS_REQUEST_PENDING = (1 << 2), + TPM_ACCESS_REQUEST_USE = (1 << 1), + TPM_ACCESS_ESTABLISHMENT = (1 << 0), +}; + +enum tis_status { + TPM_STS_FAMILY_SHIFT = 26, + TPM_STS_FAMILY_MASK = (0x3 << TPM_STS_FAMILY_SHIFT), + TPM_STS_FAMILY_TPM_2_0 = (1 << TPM_STS_FAMILY_SHIFT), + TPM_STS_FAMILY_TPM_1_2 = (0 << TPM_STS_FAMILY_SHIFT), + TPM_STS_RESET_ESTABLISHMENT = (1 << 25), + TPM_STS_COMMAND_CANCEL = (1 << 24), + TPM_STS_BURST_COUNT_SHIFT = 8, + TPM_STS_BURST_COUNT_MASK = (0xFFFF << TPM_STS_BURST_COUNT_SHIFT), + TPM_STS_VALID = (1 << 7), + TPM_STS_COMMAND_READY = (1 << 6), + TPM_STS_GO = (1 << 5), + TPM_STS_DATA_AVAIL = (1 << 4), + TPM_STS_DATA_EXPECT = (1 << 3), + TPM_STS_SELF_TEST_DONE = (1 << 2), + TPM_STS_RESPONSE_RETRY = (1 << 1), +}; + +/* + * tis_init() + * + * Initialize the TPM device. Returns 0 on success or -1 on + * failure (in case device probing did not succeed). + */ +int tis_init(void); + +/* + * tis_open() + * + * Requests access to locality 0 for the caller. After all commands have been + * completed the caller is supposed to call tis_close(). + * + * Returns 0 on success, -1 on failure. + */ +int tis_open(void); + +/* + * tis_close() + * + * terminate the currect session with the TPM by releasing the locked + * locality. Returns 0 on success of -1 on failure (in case lock + * removal did not succeed). + */ +int tis_close(void); + +/* + * tis_sendrecv() + * + * Send the requested data to the TPM and then try to get its response + * + * @sendbuf - buffer of the data to send + * @send_size size of the data to send + * @recvbuf - memory to save the response to + * @recv_len - pointer to the size of the response buffer + * + * Returns 0 on success (and places the number of response bytes at recv_len) + * or -1 on failure. + */ +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() + * + * Check tpm irq and clear it. + * + * Returns 1 when irq pending or 0 when not. + */ +int tis_plat_irq_status(void); + +#endif /* TIS_H_ */ diff --git a/src/security/tpm/tlcl.h b/src/security/tpm/tlcl.h deleted file mode 100644 index 8dd5d80685..0000000000 --- a/src/security/tpm/tlcl.h +++ /dev/null @@ -1,177 +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. - */ - -/* - * TPM Lightweight Command Library. - * - * A low-level library for interfacing to TPM hardware or an emulator. - */ - -#ifndef TPM_LITE_TLCL_H_ -#define TPM_LITE_TLCL_H_ -#include -#include - -#include "tss_constants.h" - -/*****************************************************************************/ -/* Functions implemented in tlcl.c */ - -/** - * Call this first. Returns 0 if success, nonzero if error. - */ -uint32_t tlcl_lib_init(void); - -/** - * Perform a raw TPM request/response transaction. - */ -uint32_t tlcl_send_receive(const uint8_t *request, uint8_t *response, - int max_length); - -/* Commands */ - -/** - * Send a TPM_Startup(ST_CLEAR). The TPM error code is returned (0 for - * success). - */ -uint32_t tlcl_startup(void); - -/** - * Resume by sending a TPM_Startup(ST_STATE). The TPM error code is returned - * (0 for success). - */ -uint32_t tlcl_resume(void); - -/** - * Run the self test. - * - * Note---this is synchronous. To run this in parallel with other firmware, - * use ContinueSelfTest(). The TPM error code is returned. - */ -uint32_t tlcl_self_test_full(void); - -/** - * Run the self test in the background. - */ -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. - */ -uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length); - -/** - * Read [length] bytes from space at [index] into [data]. The TPM error code - * is returned. - */ -uint32_t tlcl_read(uint32_t index, void *data, uint32_t length); - -/** - * Assert physical presence in software. The TPM error code is returned. - */ -uint32_t tlcl_assert_physical_presence(void); - -/** - * Enable the physical presence command. The TPM error code is returned. - */ -uint32_t tlcl_physical_presence_cmd_enable(void); - -/** - * Finalize the physical presence settings: sofware PP is enabled, hardware PP - * is disabled, and the lifetime lock is set. The TPM error code is returned. - */ -uint32_t tlcl_finalize_physical_presence(void); - -/** - * Set the nvLocked bit. The TPM error code is returned. - */ -uint32_t tlcl_set_nv_locked(void); - -/** - * Issue a ForceClear. The TPM error code is returned. - */ -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. - */ -uint32_t tlcl_set_global_lock(void); - -/** - * Make an NV Ram location read_only. The TPM error code is returned. - */ -uint32_t tlcl_lock_nv_write(uint32_t index); - -/** - * Perform a TPM_Extend. - */ -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 /* TPM_LITE_TLCL_H_ */ diff --git a/src/security/tpm/tpm.h b/src/security/tpm/tpm.h deleted file mode 100644 index 32a44c17eb..0000000000 --- a/src/security/tpm/tpm.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2011 Google 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 TPM_H_ -#define TPM_H_ - -#include -#include - -enum tis_access { - TPM_ACCESS_VALID = (1 << 7), - TPM_ACCESS_ACTIVE_LOCALITY = (1 << 5), - TPM_ACCESS_REQUEST_PENDING = (1 << 2), - TPM_ACCESS_REQUEST_USE = (1 << 1), - TPM_ACCESS_ESTABLISHMENT = (1 << 0), -}; - -enum tis_status { - TPM_STS_FAMILY_SHIFT = 26, - TPM_STS_FAMILY_MASK = (0x3 << TPM_STS_FAMILY_SHIFT), - TPM_STS_FAMILY_TPM_2_0 = (1 << TPM_STS_FAMILY_SHIFT), - TPM_STS_FAMILY_TPM_1_2 = (0 << TPM_STS_FAMILY_SHIFT), - TPM_STS_RESET_ESTABLISHMENT = (1 << 25), - TPM_STS_COMMAND_CANCEL = (1 << 24), - TPM_STS_BURST_COUNT_SHIFT = 8, - TPM_STS_BURST_COUNT_MASK = (0xFFFF << TPM_STS_BURST_COUNT_SHIFT), - TPM_STS_VALID = (1 << 7), - TPM_STS_COMMAND_READY = (1 << 6), - TPM_STS_GO = (1 << 5), - TPM_STS_DATA_AVAIL = (1 << 4), - TPM_STS_DATA_EXPECT = (1 << 3), - TPM_STS_SELF_TEST_DONE = (1 << 2), - TPM_STS_RESPONSE_RETRY = (1 << 1), -}; - -/* - * tis_init() - * - * Initialize the TPM device. Returns 0 on success or -1 on - * failure (in case device probing did not succeed). - */ -int tis_init(void); - -/* - * tis_open() - * - * Requests access to locality 0 for the caller. After all commands have been - * completed the caller is supposed to call tis_close(). - * - * Returns 0 on success, -1 on failure. - */ -int tis_open(void); - -/* - * tis_close() - * - * terminate the currect session with the TPM by releasing the locked - * locality. Returns 0 on success of -1 on failure (in case lock - * removal did not succeed). - */ -int tis_close(void); - -/* - * tis_sendrecv() - * - * Send the requested data to the TPM and then try to get its response - * - * @sendbuf - buffer of the data to send - * @send_size size of the data to send - * @recvbuf - memory to save the response to - * @recv_len - pointer to the size of the response buffer - * - * Returns 0 on success (and places the number of response bytes at recv_len) - * or -1 on failure. - */ -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() - * - * Check tpm irq and clear it. - * - * Returns 1 when irq pending or 0 when not. - */ -int tis_plat_irq_status(void); - -#endif /* TPM_H_ */ diff --git a/src/security/tpm/tpm_error_messages.h b/src/security/tpm/tpm_error_messages.h deleted file mode 100644 index ac7cd4e859..0000000000 --- a/src/security/tpm/tpm_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 TPM_ERROR_MESSAGES_H -#define TPM_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 /* TPM_ERROR_MESSAGES_H */ diff --git a/src/security/tpm/tss.h b/src/security/tpm/tss.h new file mode 100644 index 0000000000..8f3f1cbff5 --- /dev/null +++ b/src/security/tpm/tss.h @@ -0,0 +1,177 @@ +/* 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. + */ + +/* + * TPM Lightweight Command Library. + * + * A low-level library for interfacing to TPM hardware or an emulator. + */ + +#ifndef TSS_H_ +#define TSS_H_ +#include +#include + +#include "tss_constants.h" + +/*****************************************************************************/ +/* Functions implemented in tlcl.c */ + +/** + * Call this first. Returns 0 if success, nonzero if error. + */ +uint32_t tlcl_lib_init(void); + +/** + * Perform a raw TPM request/response transaction. + */ +uint32_t tlcl_send_receive(const uint8_t *request, uint8_t *response, + int max_length); + +/* Commands */ + +/** + * Send a TPM_Startup(ST_CLEAR). The TPM error code is returned (0 for + * success). + */ +uint32_t tlcl_startup(void); + +/** + * Resume by sending a TPM_Startup(ST_STATE). The TPM error code is returned + * (0 for success). + */ +uint32_t tlcl_resume(void); + +/** + * Run the self test. + * + * Note---this is synchronous. To run this in parallel with other firmware, + * use ContinueSelfTest(). The TPM error code is returned. + */ +uint32_t tlcl_self_test_full(void); + +/** + * Run the self test in the background. + */ +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. + */ +uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length); + +/** + * Read [length] bytes from space at [index] into [data]. The TPM error code + * is returned. + */ +uint32_t tlcl_read(uint32_t index, void *data, uint32_t length); + +/** + * Assert physical presence in software. The TPM error code is returned. + */ +uint32_t tlcl_assert_physical_presence(void); + +/** + * Enable the physical presence command. The TPM error code is returned. + */ +uint32_t tlcl_physical_presence_cmd_enable(void); + +/** + * Finalize the physical presence settings: sofware PP is enabled, hardware PP + * is disabled, and the lifetime lock is set. The TPM error code is returned. + */ +uint32_t tlcl_finalize_physical_presence(void); + +/** + * Set the nvLocked bit. The TPM error code is returned. + */ +uint32_t tlcl_set_nv_locked(void); + +/** + * Issue a ForceClear. The TPM error code is returned. + */ +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. + */ +uint32_t tlcl_set_global_lock(void); + +/** + * Make an NV Ram location read_only. The TPM error code is returned. + */ +uint32_t tlcl_lock_nv_write(uint32_t index); + +/** + * Perform a TPM_Extend. + */ +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_ */ diff --git a/src/security/tpm/tss_error_messages.h b/src/security/tpm/tss_error_messages.h new file mode 100644 index 0000000000..d5978609c7 --- /dev/null +++ b/src/security/tpm/tss_error_messages.h @@ -0,0 +1,255 @@ +/* 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/vboot/secdata_mock.c b/src/security/vboot/secdata_mock.c index ff8e98e43f..4ea53558f9 100644 --- a/src/security/vboot/secdata_mock.c +++ b/src/security/vboot/secdata_mock.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr, diff --git a/src/security/vboot/secdata_tpm.c b/src/security/vboot/secdata_tpm.c index 2dc11bd2dc..04162b0578 100644 --- a/src/security/vboot/secdata_tpm.c +++ b/src/security/vboot/secdata_tpm.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/soc/intel/baytrail/romstage/romstage.c b/src/soc/intel/baytrail/romstage/romstage.c index d8e6449dc6..0e8710a903 100644 --- a/src/soc/intel/baytrail/romstage/romstage.c +++ b/src/soc/intel/baytrail/romstage/romstage.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/soc/intel/braswell/romstage/romstage.c b/src/soc/intel/braswell/romstage/romstage.c index 12a15304a2..7cedf90331 100644 --- a/src/soc/intel/braswell/romstage/romstage.c +++ b/src/soc/intel/braswell/romstage/romstage.c @@ -43,7 +43,7 @@ #include #include #include -#include +#include void program_base_addresses(void) { diff --git a/src/soc/intel/broadwell/romstage/romstage.c b/src/soc/intel/broadwell/romstage/romstage.c index fa4c1eac62..4a1e67dded 100644 --- a/src/soc/intel/broadwell/romstage/romstage.c +++ b/src/soc/intel/broadwell/romstage/romstage.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/soc/intel/common/tpm_tis.c b/src/soc/intel/common/tpm_tis.c index f088c0d16a..03089b2528 100644 --- a/src/soc/intel/common/tpm_tis.c +++ b/src/soc/intel/common/tpm_tis.c @@ -14,7 +14,7 @@ */ #include -#include +#include int tis_plat_irq_status(void) { diff --git a/src/vendorcode/google/chromeos/cr50_enable_update.c b/src/vendorcode/google/chromeos/cr50_enable_update.c index d322bbea3a..1d91112dad 100644 --- a/src/vendorcode/google/chromeos/cr50_enable_update.c +++ b/src/vendorcode/google/chromeos/cr50_enable_update.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/vendorcode/google/chromeos/tpm2.c b/src/vendorcode/google/chromeos/tpm2.c index 266cf75f61..d4816e09f9 100644 --- a/src/vendorcode/google/chromeos/tpm2.c +++ b/src/vendorcode/google/chromeos/tpm2.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include static void disable_platform_hierarchy(void *unused) -- cgit v1.2.3