From c8faabfc6f48009fb0d9ad4203aecfa569e5ff8d Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 24 Jan 2019 16:49:05 +0100 Subject: tpm: add _head suffix to tcg_efi_specid_event and tcg_pcr_event2 TCG defines two structures, TCG_EfiSpecIDEventStruct and TCG_PCR_EVENT2, which contain variable-sized arrays in the middle of the definition. Since these structures are not suitable for type casting, this patch removes structure members after the variable-sized arrays and adds the _head suffix to the structure name, to indicate that the renamed structures do not contain all fields defined by TCG. Lastly, given that variable-sized arrays are now in the last position, and given that the size of the arrays cannot be determined in advance, this patch also sets the size of those arrays to zero and removes the definition of TPM2_ACTIVE_PCR_BANKS. Signed-off-by: Roberto Sassu Reviewed-by: Jarkko Sakkinen Tested-by: Nayna Jain Signed-off-by: Jarkko Sakkinen --- include/linux/tpm_eventlog.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h index 20d9da77fc11..f47342361e87 100644 --- a/include/linux/tpm_eventlog.h +++ b/include/linux/tpm_eventlog.h @@ -8,7 +8,6 @@ #define TCG_EVENT_NAME_LEN_MAX 255 #define MAX_TEXT_EVENT 1000 /* Max event string length */ #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ -#define TPM2_ACTIVE_PCR_BANKS 3 #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x1 #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x2 @@ -82,7 +81,7 @@ struct tcg_efi_specid_event_algs { u16 digest_size; } __packed; -struct tcg_efi_specid_event { +struct tcg_efi_specid_event_head { u8 signature[16]; u32 platform_class; u8 spec_version_minor; @@ -90,9 +89,7 @@ struct tcg_efi_specid_event { u8 spec_errata; u8 uintnsize; u32 num_algs; - struct tcg_efi_specid_event_algs digest_sizes[TPM2_ACTIVE_PCR_BANKS]; - u8 vendor_info_size; - u8 vendor_info[0]; + struct tcg_efi_specid_event_algs digest_sizes[]; } __packed; struct tcg_pcr_event { @@ -113,12 +110,11 @@ struct tpm2_digest { u8 digest[SHA512_DIGEST_SIZE]; } __packed; -struct tcg_pcr_event2 { +struct tcg_pcr_event2_head { u32 pcr_idx; u32 event_type; u32 count; - struct tpm2_digest digests[TPM2_ACTIVE_PCR_BANKS]; - struct tcg_event_field event; + struct tpm2_digest digests[]; } __packed; #endif -- cgit v1.2.3 From 36ce089758b1b55df5854d6b6d74713f609e125d Mon Sep 17 00:00:00 2001 From: Jerry Snitselaar Date: Wed, 30 Jan 2019 15:06:58 -0700 Subject: tpm: don't return bool from update_timeouts Set tpm_chip->timeouts_adjusted directly in the update_timeouts code instead of returning bool. In case of tpm read failing print warning that the read failed and continue on. Signed-off-by: Jerry Snitselaar Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- include/linux/tpm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/tpm.h b/include/linux/tpm.h index b49a55cf775f..13563b8c0c3a 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -41,7 +41,7 @@ struct tpm_class_ops { int (*send) (struct tpm_chip *chip, u8 *buf, size_t len); void (*cancel) (struct tpm_chip *chip); u8 (*status) (struct tpm_chip *chip); - bool (*update_timeouts)(struct tpm_chip *chip, + void (*update_timeouts)(struct tpm_chip *chip, unsigned long *timeout_cap); int (*go_idle)(struct tpm_chip *chip); int (*cmd_ready)(struct tpm_chip *chip); -- cgit v1.2.3 From aa042475938f5818b0c1b6203061e85ad2535dbc Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Wed, 6 Feb 2019 17:24:48 +0100 Subject: tpm: rename and export tpm2_digest and tpm2_algorithms Rename tpm2_* to tpm_* and move the definitions to include/linux/tpm.h so that these can be used by other kernel subsystems (e.g. IMA). Also, set the length of the digest array in tpm_digest to a new constant named TPM_MAX_DIGEST_SIZE, equal to SHA512_DIGEST_SIZE. Signed-off-by: Roberto Sassu Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Acked-by: Mimi Zohar Signed-off-by: Jarkko Sakkinen --- include/linux/tpm.h | 19 +++++++++++++++++++ include/linux/tpm_eventlog.h | 9 ++------- 2 files changed, 21 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 13563b8c0c3a..9fe8c9816cf0 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -22,12 +22,31 @@ #ifndef __LINUX_TPM_H__ #define __LINUX_TPM_H__ +#include + #define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ +#define TPM_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE struct tpm_chip; struct trusted_key_payload; struct trusted_key_options; +enum tpm_algorithms { + TPM_ALG_ERROR = 0x0000, + TPM_ALG_SHA1 = 0x0004, + TPM_ALG_KEYEDHASH = 0x0008, + TPM_ALG_SHA256 = 0x000B, + TPM_ALG_SHA384 = 0x000C, + TPM_ALG_SHA512 = 0x000D, + TPM_ALG_NULL = 0x0010, + TPM_ALG_SM3_256 = 0x0012, +}; + +struct tpm_digest { + u16 alg_id; + u8 digest[TPM_MAX_DIGEST_SIZE]; +} __packed; + enum TPM_OPS_FLAGS { TPM_OPS_AUTO_STARTUP = BIT(0), }; diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h index f47342361e87..81519f163211 100644 --- a/include/linux/tpm_eventlog.h +++ b/include/linux/tpm_eventlog.h @@ -3,7 +3,7 @@ #ifndef __LINUX_TPM_EVENTLOG_H__ #define __LINUX_TPM_EVENTLOG_H__ -#include +#include #define TCG_EVENT_NAME_LEN_MAX 255 #define MAX_TEXT_EVENT 1000 /* Max event string length */ @@ -105,16 +105,11 @@ struct tcg_event_field { u8 event[0]; } __packed; -struct tpm2_digest { - u16 alg_id; - u8 digest[SHA512_DIGEST_SIZE]; -} __packed; - struct tcg_pcr_event2_head { u32 pcr_idx; u32 event_type; u32 count; - struct tpm2_digest digests[]; + struct tpm_digest digests[]; } __packed; #endif -- cgit v1.2.3 From 879b589210a9a0c9f77d301aaf0ddee20f2c5052 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Wed, 6 Feb 2019 17:24:49 +0100 Subject: tpm: retrieve digest size of unknown algorithms with PCR read Currently, the TPM driver retrieves the digest size from a table mapping TPM algorithms identifiers to identifiers defined by the crypto subsystem. If the algorithm is not defined by the latter, the digest size can be retrieved from the output of the PCR read command. The patch modifies the definition of tpm_pcr_read() and tpm2_pcr_read() to pass the desired hash algorithm and obtain the digest size at TPM startup. Algorithms and corresponding digest sizes are stored in the new structure tpm_bank_info, member of tpm_chip, so that the information can be used by other kernel subsystems. tpm_bank_info contains: the TPM algorithm identifier, necessary to generate the event log as defined by Trusted Computing Group (TCG); the digest size, to pad/truncate a digest calculated with a different algorithm; the crypto subsystem identifier, to calculate the digest of event data. This patch also protects against data corruption that could happen in the bus, by checking that the digest size returned by the TPM during a PCR read matches the size of the algorithm passed to tpm2_pcr_read(). For the initial PCR read, when digest sizes are not yet available, this patch ensures that the amount of data copied from the output returned by the TPM does not exceed the size of the array data are copied to. Signed-off-by: Roberto Sassu Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Acked-by: Mimi Zohar Signed-off-by: Jarkko Sakkinen --- include/linux/tpm.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 9fe8c9816cf0..afd022fc9d3d 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -47,6 +47,12 @@ struct tpm_digest { u8 digest[TPM_MAX_DIGEST_SIZE]; } __packed; +struct tpm_bank_info { + u16 alg_id; + u16 digest_size; + u16 crypto_id; +}; + enum TPM_OPS_FLAGS { TPM_OPS_AUTO_STARTUP = BIT(0), }; @@ -72,7 +78,8 @@ struct tpm_class_ops { #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) extern int tpm_is_tpm2(struct tpm_chip *chip); -extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf); +extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, + struct tpm_digest *digest); extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash); extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen); extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max); @@ -89,7 +96,8 @@ static inline int tpm_is_tpm2(struct tpm_chip *chip) return -ENODEV; } -static inline int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) +static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, + struct tpm_digest *digest) { return -ENODEV; } -- cgit v1.2.3 From 901615cb916dc955fb7bda4e34402bf263532e4a Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Wed, 6 Feb 2019 17:24:50 +0100 Subject: tpm: move tpm_chip definition to include/linux/tpm.h The tpm_chip structure contains the list of PCR banks currently allocated in the TPM. When support for crypto agility will be added to the TPM driver, users of the driver have to provide a digest for each allocated bank to tpm_pcr_extend(). With this patch, they can obtain the PCR bank algorithms directly from chip->allocated_banks. Signed-off-by: Roberto Sassu Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- include/linux/tpm.h | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) (limited to 'include') diff --git a/include/linux/tpm.h b/include/linux/tpm.h index afd022fc9d3d..816e686a73ac 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -22,6 +22,10 @@ #ifndef __LINUX_TPM_H__ #define __LINUX_TPM_H__ +#include +#include +#include +#include #include #define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ @@ -75,6 +79,93 @@ struct tpm_class_ops { void (*clk_enable)(struct tpm_chip *chip, bool value); }; +#define TPM_NUM_EVENT_LOG_FILES 3 + +/* Indexes the duration array */ +enum tpm_duration { + TPM_SHORT = 0, + TPM_MEDIUM = 1, + TPM_LONG = 2, + TPM_LONG_LONG = 3, + TPM_UNDEFINED, + TPM_NUM_DURATIONS = TPM_UNDEFINED, +}; + +#define TPM_PPI_VERSION_LEN 3 + +struct tpm_space { + u32 context_tbl[3]; + u8 *context_buf; + u32 session_tbl[3]; + u8 *session_buf; +}; + +struct tpm_bios_log { + void *bios_event_log; + void *bios_event_log_end; +}; + +struct tpm_chip_seqops { + struct tpm_chip *chip; + const struct seq_operations *seqops; +}; + +struct tpm_chip { + struct device dev; + struct device devs; + struct cdev cdev; + struct cdev cdevs; + + /* A driver callback under ops cannot be run unless ops_sem is held + * (sometimes implicitly, eg for the sysfs code). ops becomes null + * when the driver is unregistered, see tpm_try_get_ops. + */ + struct rw_semaphore ops_sem; + const struct tpm_class_ops *ops; + + struct tpm_bios_log log; + struct tpm_chip_seqops bin_log_seqops; + struct tpm_chip_seqops ascii_log_seqops; + + unsigned int flags; + + int dev_num; /* /dev/tpm# */ + unsigned long is_open; /* only one allowed */ + + char hwrng_name[64]; + struct hwrng hwrng; + + struct mutex tpm_mutex; /* tpm is processing */ + + unsigned long timeout_a; /* jiffies */ + unsigned long timeout_b; /* jiffies */ + unsigned long timeout_c; /* jiffies */ + unsigned long timeout_d; /* jiffies */ + bool timeout_adjusted; + unsigned long duration[TPM_NUM_DURATIONS]; /* jiffies */ + bool duration_adjusted; + + struct dentry *bios_dir[TPM_NUM_EVENT_LOG_FILES]; + + const struct attribute_group *groups[3]; + unsigned int groups_cnt; + + u32 nr_allocated_banks; + struct tpm_bank_info *allocated_banks; +#ifdef CONFIG_ACPI + acpi_handle acpi_dev_handle; + char ppi_version[TPM_PPI_VERSION_LEN + 1]; +#endif /* CONFIG_ACPI */ + + struct tpm_space work_space; + u32 last_cc; + u32 nr_commands; + u32 *cc_attrs_tbl; + + /* active locality */ + int locality; +}; + #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) extern int tpm_is_tpm2(struct tpm_chip *chip); -- cgit v1.2.3 From 0b6cf6b97b7ef1fa3c7fefab0cac897a1c4a3400 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Wed, 6 Feb 2019 17:24:52 +0100 Subject: tpm: pass an array of tpm_extend_digest structures to tpm_pcr_extend() Currently, tpm_pcr_extend() accepts as an input only a SHA1 digest. This patch replaces the hash parameter of tpm_pcr_extend() with an array of tpm_digest structures, so that the caller can provide a digest for each PCR bank currently allocated in the TPM. tpm_pcr_extend() will not extend banks for which no digest was provided, as it happened before this patch, but instead it requires that callers provide the full set of digests. Since the number of digests will always be chip->nr_allocated_banks, the count parameter has been removed. Due to the API change, ima_pcr_extend() and pcrlock() have been modified. Since the number of allocated banks is not known in advance, the memory for the digests must be dynamically allocated. To avoid performance degradation and to avoid that a PCR extend is not done due to lack of memory, the array of tpm_digest structures is allocated by the users of the TPM driver at initialization time. Signed-off-by: Roberto Sassu Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Tested-by: Mimi Zohar (on x86 for TPM 1.2 & PTT TPM 2.0) Signed-off-by: Jarkko Sakkinen --- include/linux/tpm.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 816e686a73ac..1b5436b213a2 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -171,7 +171,8 @@ struct tpm_chip { extern int tpm_is_tpm2(struct tpm_chip *chip); extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digest); -extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash); +extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, + struct tpm_digest *digests); extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen); extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max); extern int tpm_seal_trusted(struct tpm_chip *chip, @@ -194,7 +195,7 @@ static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, } static inline int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, - const u8 *hash) + struct tpm_digest *digests) { return -ENODEV; } -- cgit v1.2.3