From 06e93279ca77ce2820723427f118a22dd0b35f0f Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Wed, 3 May 2017 18:19:09 +0200 Subject: tpm: move endianness conversion of TPM_TAG_RQU_COMMAND to tpm_input_header In the long term, TPM 1.2 functions in the driver interface will be modified to use tpm_buf_init(). However, tag and ordinals cannot be passed directly to tpm_buf_init(), because this function performs CPU native to big-endian conversion of these arguments. Since TPM_TAG_RQU_COMMAND and TPM_ORD_ are already converted, passing them to the function will undo the previous conversion. This patch moves the conversion of TPM_TAG_RQU_COMMAND from the tpm.h header file in the driver directory to the tpm_input_header declarations in the driver interface and tpm-sysfs.c. Signed-off-by: Roberto Sassu Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm-interface.c | 14 +++++++------- drivers/char/tpm/tpm-sysfs.c | 2 +- drivers/char/tpm/tpm.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 158c1db83f05..a60d57d214a6 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -544,7 +544,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, #define TPM_ORD_GET_RANDOM cpu_to_be32(70) static const struct tpm_input_header tpm_getcap_header = { - .tag = TPM_TAG_RQU_COMMAND, + .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(22), .ordinal = TPM_ORD_GET_CAP }; @@ -586,7 +586,7 @@ EXPORT_SYMBOL_GPL(tpm_getcap); #define TPM_ST_STATE cpu_to_be16(2) #define TPM_ST_DEACTIVATED cpu_to_be16(3) static const struct tpm_input_header tpm_startup_header = { - .tag = TPM_TAG_RQU_COMMAND, + .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(12), .ordinal = TPM_ORD_STARTUP }; @@ -737,7 +737,7 @@ EXPORT_SYMBOL_GPL(tpm_get_timeouts); #define CONTINUE_SELFTEST_RESULT_SIZE 10 static const struct tpm_input_header continue_selftest_header = { - .tag = TPM_TAG_RQU_COMMAND, + .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(10), .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), }; @@ -764,7 +764,7 @@ static int tpm_continue_selftest(struct tpm_chip *chip) #define READ_PCR_RESULT_SIZE 30 #define READ_PCR_RESULT_BODY_SIZE 20 static const struct tpm_input_header pcrread_header = { - .tag = TPM_TAG_RQU_COMMAND, + .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(14), .ordinal = TPM_ORDINAL_PCRREAD }; @@ -842,7 +842,7 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read); #define EXTEND_PCR_RESULT_SIZE 34 #define EXTEND_PCR_RESULT_BODY_SIZE 20 static const struct tpm_input_header pcrextend_header = { - .tag = TPM_TAG_RQU_COMMAND, + .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(34), .ordinal = TPM_ORD_PCR_EXTEND }; @@ -1064,7 +1064,7 @@ EXPORT_SYMBOL_GPL(wait_for_tpm_stat); #define SAVESTATE_RESULT_SIZE 10 static const struct tpm_input_header savestate_header = { - .tag = TPM_TAG_RQU_COMMAND, + .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(10), .ordinal = TPM_ORD_SAVESTATE }; @@ -1149,7 +1149,7 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume); #define TPM_GETRANDOM_RESULT_SIZE 18 static const struct tpm_input_header tpm_getrandom_header = { - .tag = TPM_TAG_RQU_COMMAND, + .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(14), .ordinal = TPM_ORD_GET_RANDOM }; diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 55405dbe43fa..b99fe66ca1b1 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c @@ -24,7 +24,7 @@ #define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256) #define TPM_ORD_READPUBEK cpu_to_be32(124) static const struct tpm_input_header tpm_readpubek_header = { - .tag = TPM_TAG_RQU_COMMAND, + .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(30), .ordinal = TPM_ORD_READPUBEK }; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 4b4c8dee3096..e81d8c7acb39 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -247,7 +247,7 @@ struct tpm_output_header { __be32 return_code; } __packed; -#define TPM_TAG_RQU_COMMAND cpu_to_be16(193) +#define TPM_TAG_RQU_COMMAND 193 struct stclear_flags_t { __be16 tag; -- cgit v1.2.3 From a69faebf4d3e98c6a7a656c26b09bc532edfed08 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Wed, 3 May 2017 18:19:10 +0200 Subject: tpm: move endianness conversion of ordinals to tpm_input_header Move CPU native value to big-endian conversion of ordinals to the tpm_input_header declarations. With the previous and this patch it will now be possible to modify TPM 1.2 functions to use tpm_buf_init(), which expects CPU native value for the tag and ordinal arguments. Signed-off-by: Roberto Sassu Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm-interface.c | 24 ++++++++++++------------ drivers/char/tpm/tpm-sysfs.c | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index a60d57d214a6..7966d8d82d38 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -540,13 +540,13 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, #define TPM_DIGEST_SIZE 20 #define TPM_RET_CODE_IDX 6 #define TPM_INTERNAL_RESULT_SIZE 200 -#define TPM_ORD_GET_CAP cpu_to_be32(101) -#define TPM_ORD_GET_RANDOM cpu_to_be32(70) +#define TPM_ORD_GET_CAP 101 +#define TPM_ORD_GET_RANDOM 70 static const struct tpm_input_header tpm_getcap_header = { .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(22), - .ordinal = TPM_ORD_GET_CAP + .ordinal = cpu_to_be32(TPM_ORD_GET_CAP) }; ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, @@ -581,14 +581,14 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, } EXPORT_SYMBOL_GPL(tpm_getcap); -#define TPM_ORD_STARTUP cpu_to_be32(153) +#define TPM_ORD_STARTUP 153 #define TPM_ST_CLEAR cpu_to_be16(1) #define TPM_ST_STATE cpu_to_be16(2) #define TPM_ST_DEACTIVATED cpu_to_be16(3) static const struct tpm_input_header tpm_startup_header = { .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(12), - .ordinal = TPM_ORD_STARTUP + .ordinal = cpu_to_be32(TPM_ORD_STARTUP) }; static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) @@ -760,13 +760,13 @@ static int tpm_continue_selftest(struct tpm_chip *chip) return rc; } -#define TPM_ORDINAL_PCRREAD cpu_to_be32(21) +#define TPM_ORDINAL_PCRREAD 21 #define READ_PCR_RESULT_SIZE 30 #define READ_PCR_RESULT_BODY_SIZE 20 static const struct tpm_input_header pcrread_header = { .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(14), - .ordinal = TPM_ORDINAL_PCRREAD + .ordinal = cpu_to_be32(TPM_ORDINAL_PCRREAD) }; int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) @@ -838,13 +838,13 @@ int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) } EXPORT_SYMBOL_GPL(tpm_pcr_read); -#define TPM_ORD_PCR_EXTEND cpu_to_be32(20) +#define TPM_ORD_PCR_EXTEND 20 #define EXTEND_PCR_RESULT_SIZE 34 #define EXTEND_PCR_RESULT_BODY_SIZE 20 static const struct tpm_input_header pcrextend_header = { .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(34), - .ordinal = TPM_ORD_PCR_EXTEND + .ordinal = cpu_to_be32(TPM_ORD_PCR_EXTEND) }; /** @@ -1060,13 +1060,13 @@ again: } EXPORT_SYMBOL_GPL(wait_for_tpm_stat); -#define TPM_ORD_SAVESTATE cpu_to_be32(152) +#define TPM_ORD_SAVESTATE 152 #define SAVESTATE_RESULT_SIZE 10 static const struct tpm_input_header savestate_header = { .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(10), - .ordinal = TPM_ORD_SAVESTATE + .ordinal = cpu_to_be32(TPM_ORD_SAVESTATE) }; /* @@ -1151,7 +1151,7 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume); static const struct tpm_input_header tpm_getrandom_header = { .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(14), - .ordinal = TPM_ORD_GET_RANDOM + .ordinal = cpu_to_be32(TPM_ORD_GET_RANDOM) }; /** diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index b99fe66ca1b1..4bd0997cfa2d 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c @@ -22,11 +22,11 @@ #define READ_PUBEK_RESULT_SIZE 314 #define READ_PUBEK_RESULT_MIN_BODY_SIZE (28 + 256) -#define TPM_ORD_READPUBEK cpu_to_be32(124) +#define TPM_ORD_READPUBEK 124 static const struct tpm_input_header tpm_readpubek_header = { .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), .length = cpu_to_be32(30), - .ordinal = TPM_ORD_READPUBEK + .ordinal = cpu_to_be32(TPM_ORD_READPUBEK) }; static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, char *buf) -- cgit v1.2.3 From 175d5b2a570cc0f79a23dbaf86e35e660f6f544f Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 4 May 2017 13:16:47 +0200 Subject: tpm: move TPM 1.2 code of tpm_pcr_extend() to tpm1_pcr_extend() In preparation of the modifications to tpm_pcr_extend(), which will allow callers to supply a digest for each PCR bank of a TPM 2.0, the TPM 1.2 specific code has been moved to tpm1_pcr_extend(). tpm1_pcr_extend() uses tpm_buf_init() to prepare the command buffer, which offers protection against buffer overflow. It is called by tpm_pcr_extend() and tpm_pm_suspend(). Signed-off-by: Roberto Sassu Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm-interface.c | 41 +++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 7966d8d82d38..4ed08ab4d2a8 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -847,6 +847,25 @@ static const struct tpm_input_header pcrextend_header = { .ordinal = cpu_to_be32(TPM_ORD_PCR_EXTEND) }; +static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash, + char *log_msg) +{ + struct tpm_buf buf; + int rc; + + rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND); + if (rc) + return rc; + + tpm_buf_append_u32(&buf, pcr_idx); + tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE); + + rc = tpm_transmit_cmd(chip, NULL, buf.data, EXTEND_PCR_RESULT_SIZE, + EXTEND_PCR_RESULT_BODY_SIZE, 0, log_msg); + tpm_buf_destroy(&buf); + return rc; +} + /** * tpm_pcr_extend - extend pcr value with hash * @chip_num: tpm idx # or AN& @@ -859,7 +878,6 @@ static const struct tpm_input_header pcrextend_header = { */ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) { - struct tpm_cmd_t cmd; int rc; struct tpm_chip *chip; struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)]; @@ -885,13 +903,8 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) return rc; } - cmd.header.in = pcrextend_header; - cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); - memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); - rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE, - EXTEND_PCR_RESULT_BODY_SIZE, 0, - "attempting extend a PCR value"); - + rc = tpm1_pcr_extend(chip, pcr_idx, hash, + "attempting extend a PCR value"); tpm_put_ops(chip); return rc; } @@ -1090,15 +1103,9 @@ int tpm_pm_suspend(struct device *dev) } /* for buggy tpm, flush pcrs with extend to selected dummy */ - if (tpm_suspend_pcr) { - cmd.header.in = pcrextend_header; - cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); - memcpy(cmd.params.pcrextend_in.hash, dummy_hash, - TPM_DIGEST_SIZE); - rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE, - EXTEND_PCR_RESULT_BODY_SIZE, 0, - "extending dummy pcr before suspend"); - } + if (tpm_suspend_pcr) + rc = tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash, + "extending dummy pcr before suspend"); /* now do the actual savestate */ for (try = 0; try < TPM_RETRY; try++) { -- cgit v1.2.3 From d27f81f061bbde627ac4fbd735114f9ea2c63615 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Thu, 4 May 2017 09:53:23 -0600 Subject: tpm_tis: Fix IRQ autoprobing when using platform_device The test was backwards, triggering IRQ autoprobing if the firmware did not specify an IRQ, instead of triggering it only when the module force parameter was specified. Since autoprobing is not enabled on !x86 and the platform device is currently only used on !x86, or with force, this has gone unnoticed. Fixes: 00194826e6be ("tpm_tis: Clean up the force=1 module parameter") Signed-off-by: Jason Gunthorpe Reviewed-by: Jarkko Sakkinen Tested-by: Jerry Snitselaar (with TPM 2.0) Tested-by: Jarkko Sakkinen (with TPM 1.2) Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_tis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index c7e1384f1b08..56ce2bb19166 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -336,7 +336,7 @@ static int tpm_tis_plat_probe(struct platform_device *pdev) if (res) { tpm_info.irq = res->start; } else { - if (pdev == force_pdev) + if (pdev != force_pdev) tpm_info.irq = -1; else /* When forcing auto probe the IRQ */ -- cgit v1.2.3 From fc0e132229a7ef5a8096e2876463403df0767b1b Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Thu, 4 May 2017 09:53:24 -0600 Subject: tpm_tis: Use platform_get_irq Replace the open coded IORESOURCE_IRQ with platform_get_irq, which supports more cases. Fixes: 00194826e6be ("tpm_tis: Clean up the force=1 module parameter") Signed-off-by: Jason Gunthorpe Reviewed-by: Jarkko Sakkinen Tested-by: Jerry Snitselaar (with TPM 2.0) Tested-by: Jarkko Sakkinen (with TPM 1.2) Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_tis.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 56ce2bb19166..1807b284326b 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -332,10 +332,8 @@ static int tpm_tis_plat_probe(struct platform_device *pdev) } tpm_info.res = *res; - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res) { - tpm_info.irq = res->start; - } else { + tpm_info.irq = platform_get_irq(pdev, 0); + if (tpm_info.irq <= 0) { if (pdev != force_pdev) tpm_info.irq = -1; else -- cgit v1.2.3 From 4cb586a188d468e05649575f0689dd2bf8c122e6 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Thu, 4 May 2017 09:53:25 -0600 Subject: tpm_tis: Consolidate the platform and acpi probe flow Now that the platform device was merged for OF support we can use the platform device to match ACPI devices as well and run everything through tpm_tis_init. pnp_acpi_device is replaced with ACPI_COMPANION, and ACPI_HANDLE is pushed further down. platform_get_resource is used instead of acpi_dev_get_resources. The itpm global module parameter is no longer changed during itpm detection, instead the phy specific bit is set directly. Signed-off-by: Jason Gunthorpe Reviewed-by: Jarkko Sakkinen Tested-by: Jerry Snitselaar (with TPM 2.0) Tested-by: Jarkko Sakkinen (with TPM 1.2) Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_tis.c | 167 +++++++++++++++------------------------------ 1 file changed, 54 insertions(+), 113 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 1807b284326b..b14d4aa97af8 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -80,6 +80,8 @@ static int has_hid(struct acpi_device *dev, const char *hid) static inline int is_itpm(struct acpi_device *dev) { + if (!dev) + return 0; return has_hid(dev, "INTC0102"); } #else @@ -89,6 +91,47 @@ static inline int is_itpm(struct acpi_device *dev) } #endif +#if defined(CONFIG_ACPI) +#define DEVICE_IS_TPM2 1 + +static const struct acpi_device_id tpm_acpi_tbl[] = { + {"MSFT0101", DEVICE_IS_TPM2}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, tpm_acpi_tbl); + +static int check_acpi_tpm2(struct device *dev) +{ + const struct acpi_device_id *aid = acpi_match_device(tpm_acpi_tbl, dev); + struct acpi_table_tpm2 *tbl; + acpi_status st; + + if (!aid || aid->driver_data != DEVICE_IS_TPM2) + return 0; + + /* If the ACPI TPM2 signature is matched then a global ACPI_SIG_TPM2 + * table is mandatory + */ + st = + acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **)&tbl); + if (ACPI_FAILURE(st) || tbl->header.length < sizeof(*tbl)) { + dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n"); + return -EINVAL; + } + + /* The tpm2_crb driver handles this device */ + if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED) + return -ENODEV; + + return 0; +} +#else +static int check_acpi_tpm2(struct device *dev) +{ + return 0; +} +#endif + static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result) { @@ -141,11 +184,15 @@ static const struct tpm_tis_phy_ops tpm_tcg = { .write32 = tpm_tcg_write32, }; -static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, - acpi_handle acpi_dev_handle) +static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info) { struct tpm_tis_tcg_phy *phy; int irq = -1; + int rc; + + rc = check_acpi_tpm2(dev); + if (rc) + return rc; phy = devm_kzalloc(dev, sizeof(struct tpm_tis_tcg_phy), GFP_KERNEL); if (phy == NULL) @@ -158,11 +205,11 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, if (interrupts) irq = tpm_info->irq; - if (itpm) + if (itpm || is_itpm(ACPI_COMPANION(dev))) phy->priv.flags |= TPM_TIS_ITPM_WORKAROUND; return tpm_tis_core_init(dev, &phy->priv, irq, &tpm_tcg, - acpi_dev_handle); + ACPI_HANDLE(dev)); } static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); @@ -171,7 +218,6 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, const struct pnp_device_id *pnp_id) { struct tpm_info tpm_info = {}; - acpi_handle acpi_dev_handle = NULL; struct resource *res; res = pnp_get_resource(pnp_dev, IORESOURCE_MEM, 0); @@ -184,14 +230,7 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, else tpm_info.irq = -1; - if (pnp_acpi_device(pnp_dev)) { - if (is_itpm(pnp_acpi_device(pnp_dev))) - itpm = true; - - acpi_dev_handle = ACPI_HANDLE(&pnp_dev->dev); - } - - return tpm_tis_init(&pnp_dev->dev, &tpm_info, acpi_dev_handle); + return tpm_tis_init(&pnp_dev->dev, &tpm_info); } static struct pnp_device_id tpm_pnp_tbl[] = { @@ -231,93 +270,6 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); -#ifdef CONFIG_ACPI -static int tpm_check_resource(struct acpi_resource *ares, void *data) -{ - struct tpm_info *tpm_info = (struct tpm_info *) data; - struct resource res; - - if (acpi_dev_resource_interrupt(ares, 0, &res)) - tpm_info->irq = res.start; - else if (acpi_dev_resource_memory(ares, &res)) { - tpm_info->res = res; - tpm_info->res.name = NULL; - } - - return 1; -} - -static int tpm_tis_acpi_init(struct acpi_device *acpi_dev) -{ - struct acpi_table_tpm2 *tbl; - acpi_status st; - struct list_head resources; - struct tpm_info tpm_info = {}; - int ret; - - st = acpi_get_table(ACPI_SIG_TPM2, 1, - (struct acpi_table_header **) &tbl); - if (ACPI_FAILURE(st) || tbl->header.length < sizeof(*tbl)) { - dev_err(&acpi_dev->dev, - FW_BUG "failed to get TPM2 ACPI table\n"); - return -EINVAL; - } - - if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED) - return -ENODEV; - - INIT_LIST_HEAD(&resources); - tpm_info.irq = -1; - ret = acpi_dev_get_resources(acpi_dev, &resources, tpm_check_resource, - &tpm_info); - if (ret < 0) - return ret; - - acpi_dev_free_resource_list(&resources); - - if (resource_type(&tpm_info.res) != IORESOURCE_MEM) { - dev_err(&acpi_dev->dev, - FW_BUG "TPM2 ACPI table does not define a memory resource\n"); - return -EINVAL; - } - - if (is_itpm(acpi_dev)) - itpm = true; - - return tpm_tis_init(&acpi_dev->dev, &tpm_info, acpi_dev->handle); -} - -static int tpm_tis_acpi_remove(struct acpi_device *dev) -{ - struct tpm_chip *chip = dev_get_drvdata(&dev->dev); - - tpm_chip_unregister(chip); - tpm_tis_remove(chip); - - return 0; -} - -static struct acpi_device_id tpm_acpi_tbl[] = { - {"MSFT0101", 0}, /* TPM 2.0 */ - /* Add new here */ - {"", 0}, /* User Specified */ - {"", 0} /* Terminator */ -}; -MODULE_DEVICE_TABLE(acpi, tpm_acpi_tbl); - -static struct acpi_driver tis_acpi_driver = { - .name = "tpm_tis", - .ids = tpm_acpi_tbl, - .ops = { - .add = tpm_tis_acpi_init, - .remove = tpm_tis_acpi_remove, - }, - .drv = { - .pm = &tpm_tis_pm, - }, -}; -#endif - static struct platform_device *force_pdev; static int tpm_tis_plat_probe(struct platform_device *pdev) @@ -341,7 +293,7 @@ static int tpm_tis_plat_probe(struct platform_device *pdev) tpm_info.irq = 0; } - return tpm_tis_init(&pdev->dev, &tpm_info, NULL); + return tpm_tis_init(&pdev->dev, &tpm_info); } static int tpm_tis_plat_remove(struct platform_device *pdev) @@ -369,6 +321,7 @@ static struct platform_driver tis_drv = { .name = "tpm_tis", .pm = &tpm_tis_pm, .of_match_table = of_match_ptr(tis_of_platform_match), + .acpi_match_table = ACPI_PTR(tpm_acpi_tbl), }, }; @@ -411,11 +364,6 @@ static int __init init_tis(void) if (rc) goto err_platform; -#ifdef CONFIG_ACPI - rc = acpi_bus_register_driver(&tis_acpi_driver); - if (rc) - goto err_acpi; -#endif if (IS_ENABLED(CONFIG_PNP)) { rc = pnp_register_driver(&tis_pnp_driver); @@ -426,10 +374,6 @@ static int __init init_tis(void) return 0; err_pnp: -#ifdef CONFIG_ACPI - acpi_bus_unregister_driver(&tis_acpi_driver); -err_acpi: -#endif platform_driver_unregister(&tis_drv); err_platform: if (force_pdev) @@ -441,9 +385,6 @@ err_force: static void __exit cleanup_tis(void) { pnp_unregister_driver(&tis_pnp_driver); -#ifdef CONFIG_ACPI - acpi_bus_unregister_driver(&tis_acpi_driver); -#endif platform_driver_unregister(&tis_drv); if (force_pdev) -- cgit v1.2.3 From d8c3eab5cb92f37ca8576fc641fa4bfd8a0c8b00 Mon Sep 17 00:00:00 2001 From: Bryan Freed Date: Mon, 22 May 2017 11:20:11 +0200 Subject: tpm: Apply a sane minimum adapterlimit value for retransmission. When the I2C Infineon part is attached to an I2C adapter that imposes a size limitation, large requests will fail with -EOPNOTSUPP. Retry them with a sane minimum size without re-issuing the 0x05 command as this appears to occasionally put the TPM in a bad state. Signed-off-by: Bryan Freed [rework the patch to adapt to the feedback received] Signed-off-by: Enric Balletbo i Serra Acked-by: Andrew Lunn Reviewed-by: Jarkko Sakkinen Reviewed-by: Andrew Lunn Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_i2c_infineon.c | 76 +++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 20 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index dc47fa222a26..79d6bbb58e39 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -70,6 +70,7 @@ struct tpm_inf_dev { u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ struct tpm_chip *chip; enum i2c_chip_type chip_type; + unsigned int adapterlimit; }; static struct tpm_inf_dev tpm_dev; @@ -111,6 +112,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) int rc = 0; int count; + unsigned int msglen = len; /* Lock the adapter for the duration of the whole sequence. */ if (!tpm_dev.client->adapter->algo->master_xfer) @@ -131,27 +133,61 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); } } else { - /* slb9635 protocol should work in all cases */ - for (count = 0; count < MAX_COUNT; count++) { - rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); - if (rc > 0) - break; /* break here to skip sleep */ - - usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); - } - - if (rc <= 0) - goto out; - - /* After the TPM has successfully received the register address - * it needs some time, thus we're sleeping here again, before - * retrieving the data + /* Expect to send one command message and one data message, but + * support looping over each or both if necessary. */ - for (count = 0; count < MAX_COUNT; count++) { - usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); - rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1); - if (rc > 0) - break; + while (len > 0) { + /* slb9635 protocol should work in all cases */ + for (count = 0; count < MAX_COUNT; count++) { + rc = __i2c_transfer(tpm_dev.client->adapter, + &msg1, 1); + if (rc > 0) + break; /* break here to skip sleep */ + + usleep_range(SLEEP_DURATION_LOW, + SLEEP_DURATION_HI); + } + + if (rc <= 0) + goto out; + + /* After the TPM has successfully received the register + * address it needs some time, thus we're sleeping here + * again, before retrieving the data + */ + for (count = 0; count < MAX_COUNT; count++) { + if (tpm_dev.adapterlimit) { + msglen = min_t(unsigned int, + tpm_dev.adapterlimit, + len); + msg2.len = msglen; + } + usleep_range(SLEEP_DURATION_LOW, + SLEEP_DURATION_HI); + rc = __i2c_transfer(tpm_dev.client->adapter, + &msg2, 1); + if (rc > 0) { + /* Since len is unsigned, make doubly + * sure we do not underflow it. + */ + if (msglen > len) + len = 0; + else + len -= msglen; + msg2.buf += msglen; + break; + } + /* If the I2C adapter rejected the request (e.g + * when the quirk read_max_len < len) fall back + * to a sane minimum value and try again. + */ + if (rc == -EOPNOTSUPP) + tpm_dev.adapterlimit = + I2C_SMBUS_BLOCK_MAX; + } + + if (rc <= 0) + goto out; } } -- cgit v1.2.3 From 124bdcf4a697f9672d1150de60c5ea489bcad201 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Sun, 7 May 2017 20:50:02 +0300 Subject: tpm: fix byte order related arithmetic inconsistency in tpm_getcap() You should not do arithmetic with __be32 or __le32 types because sometimes it results incorrect results. Calculations must be done only with integers that are in in the CPU byte order. This commit migrates tpm_getcap() to struct tpm_buf in order to sort out these issues. Signed-off-by: Jarkko Sakkinen Reviewed-by: Jason Gunthorpe --- drivers/char/tpm/tpm-interface.c | 30 ++++++++++++++++-------------- drivers/char/tpm/tpm.h | 13 ------------- 2 files changed, 16 insertions(+), 27 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 4ed08ab4d2a8..be5415923886 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -552,31 +552,33 @@ static const struct tpm_input_header tpm_getcap_header = { ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, const char *desc, size_t min_cap_length) { - struct tpm_cmd_t tpm_cmd; + struct tpm_buf buf; int rc; - tpm_cmd.header.in = tpm_getcap_header; + rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP); + if (rc) + return rc; + if (subcap_id == TPM_CAP_VERSION_1_1 || subcap_id == TPM_CAP_VERSION_1_2) { - tpm_cmd.params.getcap_in.cap = cpu_to_be32(subcap_id); - /*subcap field not necessary */ - tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0); - tpm_cmd.header.in.length -= cpu_to_be32(sizeof(__be32)); + tpm_buf_append_u32(&buf, subcap_id); + tpm_buf_append_u32(&buf, 0); } else { if (subcap_id == TPM_CAP_FLAG_PERM || subcap_id == TPM_CAP_FLAG_VOL) - tpm_cmd.params.getcap_in.cap = - cpu_to_be32(TPM_CAP_FLAG); + tpm_buf_append_u32(&buf, TPM_CAP_FLAG); else - tpm_cmd.params.getcap_in.cap = - cpu_to_be32(TPM_CAP_PROP); - tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); - tpm_cmd.params.getcap_in.subcap = cpu_to_be32(subcap_id); + tpm_buf_append_u32(&buf, TPM_CAP_PROP); + + tpm_buf_append_u32(&buf, 4); + tpm_buf_append_u32(&buf, subcap_id); } - rc = tpm_transmit_cmd(chip, NULL, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, min_cap_length, 0, desc); if (!rc) - *cap = tpm_cmd.params.getcap_out.cap; + *cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4]; + + tpm_buf_destroy(&buf); return rc; } EXPORT_SYMBOL_GPL(tpm_getcap); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index e81d8c7acb39..dd1173427fb2 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -339,17 +339,6 @@ enum tpm_sub_capabilities { TPM_CAP_PROP_TIS_DURATION = 0x120, }; -struct tpm_getcap_params_in { - __be32 cap; - __be32 subcap_size; - __be32 subcap; -} __packed; - -struct tpm_getcap_params_out { - __be32 cap_size; - cap_t cap; -} __packed; - struct tpm_readpubek_params_out { u8 algorithm[4]; u8 encscheme[2]; @@ -399,10 +388,8 @@ struct tpm_startup_in { } __packed; typedef union { - struct tpm_getcap_params_out getcap_out; struct tpm_readpubek_params_out readpubek_out; u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; - struct tpm_getcap_params_in getcap_in; struct tpm_pcrread_in pcrread_in; struct tpm_pcrread_out pcrread_out; struct tpm_pcrextend_in pcrextend_in; -- cgit v1.2.3 From 30bbafe3e0d4be1b0570dc620bc362ca2f516160 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Wed, 24 May 2017 14:29:16 -0700 Subject: tpm, tpm_infineon: remove useless snprintf() calls The memory copy from rodata to stack is useless. Signed-off-by: Jarkko Sakkinen Reviewed-by: Peter Huewe --- drivers/char/tpm/tpm_infineon.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index e3cf9f3545c5..3b1b9f9322d5 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -397,7 +397,7 @@ static int tpm_inf_pnp_probe(struct pnp_dev *dev, int vendorid[2]; int version[2]; int productid[2]; - char chipname[20]; + const char *chipname; struct tpm_chip *chip; /* read IO-ports through PnP */ @@ -488,13 +488,13 @@ static int tpm_inf_pnp_probe(struct pnp_dev *dev, switch ((productid[0] << 8) | productid[1]) { case 6: - snprintf(chipname, sizeof(chipname), " (SLD 9630 TT 1.1)"); + chipname = " (SLD 9630 TT 1.1)"; break; case 11: - snprintf(chipname, sizeof(chipname), " (SLB 9635 TT 1.2)"); + chipname = " (SLB 9635 TT 1.2)"; break; default: - snprintf(chipname, sizeof(chipname), " (unknown chip)"); + chipname = " (unknown chip)"; break; } -- cgit v1.2.3 From 8816188f060a791e08eacfeba3d28343b931872b Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Wed, 24 May 2017 15:26:08 -0700 Subject: tpm: remove struct tpm_pcrextend_in Removed struct tpm_pcrextend_in as it is not used for anything anymore. Signed-off-by: Jarkko Sakkinen Reviewed-by: Peter Huewe --- drivers/char/tpm/tpm.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index dd1173427fb2..af05c1403c6e 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -363,11 +363,6 @@ struct tpm_pcrread_in { __be32 pcr_idx; } __packed; -struct tpm_pcrextend_in { - __be32 pcr_idx; - u8 hash[TPM_DIGEST_SIZE]; -} __packed; - /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18 * bytes, but 128 is still a relatively large number of random bytes and * anything much bigger causes users of struct tpm_cmd_t to start getting @@ -392,7 +387,6 @@ typedef union { u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; struct tpm_pcrread_in pcrread_in; struct tpm_pcrread_out pcrread_out; - struct tpm_pcrextend_in pcrextend_in; struct tpm_getrandom_in getrandom_in; struct tpm_getrandom_out getrandom_out; struct tpm_startup_in startup_in; -- cgit v1.2.3 From 5e9fefd26b47205e423b23c3f0a41b068c84fa1d Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 25 May 2017 07:43:05 +0200 Subject: tpm, tpmrm: Mark tpmrm_write as static sparse complains that tpmrm_write can be made static, and since it is right we make it static. Signed-off-by: Peter Huewe Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpmrm-dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpmrm-dev.c b/drivers/char/tpm/tpmrm-dev.c index c636e7fdd1f5..1a0e97a5da5a 100644 --- a/drivers/char/tpm/tpmrm-dev.c +++ b/drivers/char/tpm/tpmrm-dev.c @@ -45,7 +45,7 @@ static int tpmrm_release(struct inode *inode, struct file *file) return 0; } -ssize_t tpmrm_write(struct file *file, const char __user *buf, +static ssize_t tpmrm_write(struct file *file, const char __user *buf, size_t size, loff_t *off) { struct file_priv *fpriv = file->private_data; -- cgit v1.2.3 From 402149c6470d9562fe6891e0165df7f5f6bff7a7 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 25 May 2017 18:29:13 -0400 Subject: tpm: vtpm_proxy: Suppress error logging when in closed state Suppress the error logging when the core TPM driver sends commands to the VTPM proxy driver and -EPIPE is returned in case the VTPM proxy driver is 'closed' (closed anonymous file descriptor). This error code is only returned by the send function and by tpm_transmit when the VTPM proxy driver is being used. Signed-off-by: Stefan Berger Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm-interface.c | 5 +++-- drivers/char/tpm/tpm2-cmd.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index be5415923886..a965a9f0e5d2 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -429,8 +429,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, rc = chip->ops->send(chip, (u8 *) buf, count); if (rc < 0) { - dev_err(&chip->dev, - "tpm_transmit: tpm_send: error %d\n", rc); + if (rc != -EPIPE) + dev_err(&chip->dev, + "%s: tpm_send: error %d\n", __func__, rc); goto out; } diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 3ee6883f26c1..3a9964326279 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -840,7 +840,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) /* In places where shutdown command is sent there's no much we can do * except print the error code on a system failure. */ - if (rc < 0) + if (rc < 0 && rc != -EPIPE) dev_warn(&chip->dev, "transmit returned %d while stopping the TPM", rc); } -- cgit v1.2.3 From 85ab3bf305b96e5f4c83b23a0b7e11d90144eb18 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Wed, 24 May 2017 17:39:39 -0400 Subject: tpm: Introduce flag TPM_TRANSMIT_RAW Introduce the flag TPM_TRANSMIT_RAW that allows us to transmit a command without recursing into the requesting of locality. Signed-off-by: Stefan Berger Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm-interface.c | 3 ++- drivers/char/tpm/tpm.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index a965a9f0e5d2..8ef5e1723efb 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -416,7 +416,8 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; - if (need_locality && chip->ops->request_locality) { + if (!(flags & TPM_TRANSMIT_RAW) && + need_locality && chip->ops->request_locality) { rc = chip->ops->request_locality(chip, 0); if (rc < 0) goto out_no_locality; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index af05c1403c6e..1df0521138d3 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -506,6 +506,7 @@ extern struct idr dev_nums_idr; enum tpm_transmit_flags { TPM_TRANSMIT_UNLOCKED = BIT(0), + TPM_TRANSMIT_RAW = BIT(1), }; ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, -- cgit v1.2.3 From be4c9acfe2976b6e024d15656254d2eb207b83a8 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Wed, 24 May 2017 17:39:40 -0400 Subject: tpm: vtpm_proxy: Implement request_locality function. Implement the request_locality function. To set the locality on the backend we define vendor-specific TPM 1.2 and TPM 2 ordinals and send a command to the backend to set the locality for the next commands. To avoid recursing into requesting the locality, we set the TPM_TRANSMIT_RAW flag when calling tpm_transmit_cmd. To avoid recursing into TPM 2 space related commands, we set the space parameter to NULL. Signed-off-by: Stefan Berger Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm-interface.c | 1 + drivers/char/tpm/tpm_vtpm_proxy.c | 36 ++++++++++++++++++++++++++++++++++++ include/uapi/linux/vtpm_proxy.h | 4 ++++ 3 files changed, 41 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 8ef5e1723efb..d2b4df6d9894 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -538,6 +538,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, return 0; } +EXPORT_SYMBOL_GPL(tpm_transmit_cmd); #define TPM_DIGEST_SIZE 20 #define TPM_RET_CODE_IDX 6 diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c index 751059d2140a..66024bf92097 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -371,6 +371,41 @@ static bool vtpm_proxy_tpm_req_canceled(struct tpm_chip *chip, u8 status) return ret; } +static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) +{ + struct tpm_buf buf; + int rc; + const struct tpm_output_header *header; + + if (chip->flags & TPM_CHIP_FLAG_TPM2) + rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, + TPM2_CC_SET_LOCALITY); + else + rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, + TPM_ORD_SET_LOCALITY); + if (rc) + return rc; + tpm_buf_append_u8(&buf, locality); + + rc = tpm_transmit_cmd(chip, NULL, buf.data, tpm_buf_length(&buf), 0, + TPM_TRANSMIT_UNLOCKED | TPM_TRANSMIT_RAW, + "attempting to set locality"); + if (rc < 0) { + locality = rc; + goto out; + } + + header = (const struct tpm_output_header *)buf.data; + rc = be32_to_cpu(header->return_code); + if (rc) + locality = -1; + +out: + tpm_buf_destroy(&buf); + + return locality; +} + static const struct tpm_class_ops vtpm_proxy_tpm_ops = { .flags = TPM_OPS_AUTO_STARTUP, .recv = vtpm_proxy_tpm_op_recv, @@ -380,6 +415,7 @@ static const struct tpm_class_ops vtpm_proxy_tpm_ops = { .req_complete_mask = VTPM_PROXY_REQ_COMPLETE_FLAG, .req_complete_val = VTPM_PROXY_REQ_COMPLETE_FLAG, .req_canceled = vtpm_proxy_tpm_req_canceled, + .request_locality = vtpm_proxy_request_locality, }; /* diff --git a/include/uapi/linux/vtpm_proxy.h b/include/uapi/linux/vtpm_proxy.h index a69e991eb080..58ac73cd38fe 100644 --- a/include/uapi/linux/vtpm_proxy.h +++ b/include/uapi/linux/vtpm_proxy.h @@ -46,4 +46,8 @@ struct vtpm_proxy_new_dev { #define VTPM_PROXY_IOC_NEW_DEV _IOWR(0xa1, 0x00, struct vtpm_proxy_new_dev) +/* vendor specific commands to set locality */ +#define TPM2_CC_SET_LOCALITY 0x20001000 +#define TPM_ORD_SET_LOCALITY 0x20001000 + #endif /* _UAPI_LINUX_VTPM_PROXY_H */ -- cgit v1.2.3 From d8b5d94538eb1cb18be36048b0ddb9bd2e80a252 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Wed, 24 May 2017 17:39:41 -0400 Subject: tpm: vtpm_proxy: Prevent userspace from sending driver command To prevent userspace from sending the TPM driver command to set the locality, we need to check every command that is sent from user space. To distinguish user space commands from internally sent commands we introduce an additional state flag STATE_DRIVER_COMMAND that is set while the driver sends this command. Similar to the TPM 2 space commands we return an error code when this command is detected. Signed-off-by: Stefan Berger Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_vtpm_proxy.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c index 66024bf92097..1d877cc9af97 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -43,6 +43,7 @@ struct proxy_dev { #define STATE_OPENED_FLAG BIT(0) #define STATE_WAIT_RESPONSE_FLAG BIT(1) /* waiting for emulator response */ #define STATE_REGISTERED_FLAG BIT(2) +#define STATE_DRIVER_COMMAND BIT(3) /* sending a driver specific command */ size_t req_len; /* length of queued TPM request */ size_t resp_len; /* length of queued TPM response */ @@ -299,6 +300,28 @@ out: return len; } +static int vtpm_proxy_is_driver_command(struct tpm_chip *chip, + u8 *buf, size_t count) +{ + struct tpm_input_header *hdr = (struct tpm_input_header *)buf; + + if (count < sizeof(struct tpm_input_header)) + return 0; + + if (chip->flags & TPM_CHIP_FLAG_TPM2) { + switch (be32_to_cpu(hdr->ordinal)) { + case TPM2_CC_SET_LOCALITY: + return 1; + } + } else { + switch (be32_to_cpu(hdr->ordinal)) { + case TPM_ORD_SET_LOCALITY: + return 1; + } + } + return 0; +} + /* * Called when core TPM driver forwards TPM requests to 'server side'. * @@ -321,6 +344,10 @@ static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count) return -EIO; } + if (!(proxy_dev->state & STATE_DRIVER_COMMAND) && + vtpm_proxy_is_driver_command(chip, buf, count)) + return -EFAULT; + mutex_lock(&proxy_dev->buf_lock); if (!(proxy_dev->state & STATE_OPENED_FLAG)) { @@ -376,6 +403,7 @@ static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) struct tpm_buf buf; int rc; const struct tpm_output_header *header; + struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); if (chip->flags & TPM_CHIP_FLAG_TPM2) rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, @@ -387,9 +415,14 @@ static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) return rc; tpm_buf_append_u8(&buf, locality); + proxy_dev->state |= STATE_DRIVER_COMMAND; + rc = tpm_transmit_cmd(chip, NULL, buf.data, tpm_buf_length(&buf), 0, TPM_TRANSMIT_UNLOCKED | TPM_TRANSMIT_RAW, "attempting to set locality"); + + proxy_dev->state &= ~STATE_DRIVER_COMMAND; + if (rc < 0) { locality = rc; goto out; -- cgit v1.2.3 From 23c3beae581f7cee193c078093a4696040dd380a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 12 Jun 2017 18:44:16 +0300 Subject: tpm/st33zp24: Switch to devm_acpi_dev_add_driver_gpios() Switch to use managed variant of acpi_dev_add_driver_gpios() to simplify error path and fix potentially wrong assignment if ->probe() fails. Signed-off-by: Andy Shevchenko Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen (compilation) Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/st33zp24/i2c.c | 3 +-- drivers/char/tpm/st33zp24/spi.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c index 1b10e38f214e..be5d1abd3e8e 100644 --- a/drivers/char/tpm/st33zp24/i2c.c +++ b/drivers/char/tpm/st33zp24/i2c.c @@ -127,7 +127,7 @@ static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client) struct device *dev = &client->dev; int ret; - ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), acpi_st33zp24_gpios); + ret = devm_acpi_dev_add_driver_gpios(dev, acpi_st33zp24_gpios); if (ret) return ret; @@ -285,7 +285,6 @@ static int st33zp24_i2c_remove(struct i2c_client *client) if (ret) return ret; - acpi_dev_remove_driver_gpios(ACPI_COMPANION(&client->dev)); return 0; } diff --git a/drivers/char/tpm/st33zp24/spi.c b/drivers/char/tpm/st33zp24/spi.c index c69d15198f84..0fc4f20b5f83 100644 --- a/drivers/char/tpm/st33zp24/spi.c +++ b/drivers/char/tpm/st33zp24/spi.c @@ -246,7 +246,7 @@ static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev) struct device *dev = &spi_dev->dev; int ret; - ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), acpi_st33zp24_gpios); + ret = devm_acpi_dev_add_driver_gpios(dev, acpi_st33zp24_gpios); if (ret) return ret; @@ -402,7 +402,6 @@ static int st33zp24_spi_remove(struct spi_device *dev) if (ret) return ret; - acpi_dev_remove_driver_gpios(ACPI_COMPANION(&dev->dev)); return 0; } -- cgit v1.2.3 From e4b0852798bc15ed1a3ed6768ef2c4d2a1cb7599 Mon Sep 17 00:00:00 2001 From: Gustavo A. R. Silva Date: Tue, 13 Jun 2017 14:55:42 -0500 Subject: tpm/tpm_atmel: remove unnecessary NULL check Remove unnecessary NULL check. Pointer _chip_ cannot be NULL in this instance. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen (compilation) Signed-off-by: Jarkko Sakkinen --- drivers/char/tpm/tpm_atmel.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 0d322ab11faa..66a14526aaf4 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c @@ -144,13 +144,11 @@ static void atml_plat_remove(void) struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev); - if (chip) { - tpm_chip_unregister(chip); - if (priv->have_region) - atmel_release_region(priv->base, priv->region_size); - atmel_put_base_addr(priv->iobase); - platform_device_unregister(pdev); - } + tpm_chip_unregister(chip); + if (priv->have_region) + atmel_release_region(priv->base, priv->region_size); + atmel_put_base_addr(priv->iobase); + platform_device_unregister(pdev); } static SIMPLE_DEV_PM_OPS(tpm_atml_pm, tpm_pm_suspend, tpm_pm_resume); -- cgit v1.2.3