summaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-06-23 07:39:49 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-06-23 07:39:49 -0700
commit16b2087efdddd0bf042accdbdcc8eedc21bf9227 (patch)
tree4a17759f672723b585b45bd8f4293402e8d3bacb /drivers/char
parent3eb20a97b315a9fd5fea33c207c51823f22c2b4d (diff)
parent1a58f6115bfb34eabcc7de8a3a9745b219179781 (diff)
downloadlwn-16b2087efdddd0bf042accdbdcc8eedc21bf9227.tar.gz
lwn-16b2087efdddd0bf042accdbdcc8eedc21bf9227.zip
Merge tag 'for-next-tpm-7.2-rc1-fixed' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd
Pull tpm updates from Jarkko Sakkinen: "Only bug fixes" * tag 'for-next-tpm-7.2-rc1-fixed' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd: tpm: fix event_size output in tpm1_binary_bios_measurements_show tpm: tpm_crb_ffa: revert defered_probed when tpm_crb_ffa is built-in tpm: tpm2-sessions: wait for async KPP completion in tpm_buf_append_salt tpm: tpm_tis: Add settle time for some TPMs tpm: tpm_tis: store entire did_vid tpm_crb: Check ACPI_COMPANION() against NULL during probe tpm: tpm_tis_spi: Use wait_woken() in wait_for_tmp_stat() tpm: Initialize name_size_alg for non-NULL name in tpm_buf_append_name() tpm: restore timeout for key creation commands tpm: svsm: constify tpm_chip_ops
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/tpm/eventlog/tpm1.c4
-rw-r--r--drivers/char/tpm/tpm2-cmd.c6
-rw-r--r--drivers/char/tpm/tpm2-sessions.c56
-rw-r--r--drivers/char/tpm/tpm_crb.c6
-rw-r--r--drivers/char/tpm/tpm_crb_ffa.c18
-rw-r--r--drivers/char/tpm/tpm_svsm.c2
-rw-r--r--drivers/char/tpm/tpm_tis_core.c63
-rw-r--r--drivers/char/tpm/tpm_tis_core.h3
8 files changed, 98 insertions, 60 deletions
diff --git a/drivers/char/tpm/eventlog/tpm1.c b/drivers/char/tpm/eventlog/tpm1.c
index e7913b2853d5..0397e3361020 100644
--- a/drivers/char/tpm/eventlog/tpm1.c
+++ b/drivers/char/tpm/eventlog/tpm1.c
@@ -236,12 +236,12 @@ static int tpm1_binary_bios_measurements_show(struct seq_file *m, void *v)
temp_ptr = (char *) &temp_event;
- for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
+ for (i = 0; i < sizeof(struct tcpa_event); i++)
seq_putc(m, temp_ptr[i]);
temp_ptr = (char *) v;
- for (i = (sizeof(struct tcpa_event) - 1);
+ for (i = sizeof(struct tcpa_event);
i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
seq_putc(m, temp_ptr[i]);
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index b11e6fa8b740..52ee350da867 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -71,9 +71,9 @@ static const struct {
{TPM2_CC_HIERARCHY_CHANGE_AUTH, 2000},
{TPM2_CC_GET_CAPABILITY, 750},
{TPM2_CC_NV_READ, 2000},
- {TPM2_CC_CREATE_PRIMARY, 30000},
- {TPM2_CC_CREATE, 30000},
- {TPM2_CC_CREATE_LOADED, 30000},
+ {TPM2_CC_CREATE_PRIMARY, 300000},
+ {TPM2_CC_CREATE, 300000},
+ {TPM2_CC_CREATE_LOADED, 300000},
};
/**
diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
index c4da6fde748f..a1ae5e1829cb 100644
--- a/drivers/char/tpm/tpm2-sessions.c
+++ b/drivers/char/tpm/tpm2-sessions.c
@@ -285,11 +285,14 @@ int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
mso == TPM2_MSO_NVRAM) {
if (!name) {
ret = tpm2_read_public(chip, handle, auth->name[slot]);
- if (ret < 0)
- goto err;
-
- name_size_alg = ret;
+ } else {
+ ret = name_size(name);
}
+
+ if (ret < 0)
+ goto err;
+
+ name_size_alg = ret;
} else {
if (name) {
dev_err(&chip->dev, "handle 0x%08x does not use a name\n",
@@ -489,15 +492,17 @@ static void tpm2_KDFe(u8 z[EC_PT_SZ], const char *str, u8 *pt_u, u8 *pt_v,
sha256_final(&sctx, out);
}
-static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
- struct tpm2_auth *auth)
+static int tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
+ struct tpm2_auth *auth)
{
struct crypto_kpp *kpp;
struct kpp_request *req;
+ DECLARE_CRYPTO_WAIT(wait);
struct scatterlist s[2], d[1];
struct ecdh p = {0};
u8 encoded_key[EC_PT_SZ], *x, *y;
unsigned int buf_len;
+ int rc;
/* secret is two sized points */
tpm_buf_append_u16(buf, (EC_PT_SZ + 2)*2);
@@ -520,14 +525,15 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
kpp = crypto_alloc_kpp("ecdh-nist-p256", CRYPTO_ALG_INTERNAL, 0);
if (IS_ERR(kpp)) {
dev_err(&chip->dev, "crypto ecdh allocation failed\n");
- return;
+ return PTR_ERR(kpp);
}
buf_len = crypto_ecdh_key_len(&p);
if (sizeof(encoded_key) < buf_len) {
dev_err(&chip->dev, "salt buffer too small needs %d\n",
buf_len);
- goto out;
+ rc = -EINVAL;
+ goto err_free_kpp;
}
crypto_ecdh_encode_key(encoded_key, buf_len, &p);
/* this generates a random private key */
@@ -535,11 +541,17 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
/* salt is now the public point of this private key */
req = kpp_request_alloc(kpp, GFP_KERNEL);
- if (!req)
- goto out;
+ if (!req) {
+ rc = -ENOMEM;
+ goto err_free_kpp;
+ }
+ kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ crypto_req_done, &wait);
kpp_request_set_input(req, NULL, 0);
kpp_request_set_output(req, s, EC_PT_SZ*2);
- crypto_kpp_generate_public_key(req);
+ rc = crypto_wait_req(crypto_kpp_generate_public_key(req), &wait);
+ if (rc)
+ goto err_free_req;
/*
* we're not done: now we have to compute the shared secret
* which is our private key multiplied by the tpm_key public
@@ -551,8 +563,9 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
kpp_request_set_input(req, s, EC_PT_SZ*2);
sg_init_one(d, auth->salt, EC_PT_SZ);
kpp_request_set_output(req, d, EC_PT_SZ);
- crypto_kpp_compute_shared_secret(req);
- kpp_request_free(req);
+ rc = crypto_wait_req(crypto_kpp_compute_shared_secret(req), &wait);
+ if (rc)
+ goto err_free_req;
/*
* pass the shared secret through KDFe for salt. Note salt
@@ -562,8 +575,16 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
*/
tpm2_KDFe(auth->salt, "SECRET", x, chip->null_ec_key_x, auth->salt);
- out:
+ kpp_request_free(req);
+ crypto_free_kpp(kpp);
+ return 0;
+
+err_free_req:
+ kpp_request_free(req);
+
+err_free_kpp:
crypto_free_kpp(kpp);
+ return rc;
}
/**
@@ -1018,7 +1039,12 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
tpm_buf_append(&buf, auth->our_nonce, sizeof(auth->our_nonce));
/* append encrypted salt and squirrel away unencrypted in auth */
- tpm_buf_append_salt(&buf, chip, auth);
+ rc = tpm_buf_append_salt(&buf, chip, auth);
+ if (rc) {
+ tpm2_flush_context(chip, null_key);
+ tpm_buf_destroy(&buf);
+ goto out;
+ }
/* session type (HMAC, audit or policy) */
tpm_buf_append_u8(&buf, TPM2_SE_HMAC);
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 7d1377e8e616..ceb4100ba400 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -786,8 +786,8 @@ static int crb_map_pluton(struct device *dev, struct crb_priv *priv,
static int crb_acpi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct acpi_device *device = ACPI_COMPANION(dev);
struct acpi_table_tpm2 *buf;
+ struct acpi_device *device;
struct crb_priv *priv;
struct tpm_chip *chip;
struct tpm2_crb_smc *crb_smc;
@@ -797,6 +797,10 @@ static int crb_acpi_probe(struct platform_device *pdev)
u32 sm;
int rc;
+ device = ACPI_COMPANION(dev);
+ if (!device)
+ return -ENODEV;
+
status = acpi_get_table(ACPI_SIG_TPM2, 1,
(struct acpi_table_header **) &buf);
if (ACPI_FAILURE(status) || buf->header.length < sizeof(*buf)) {
diff --git a/drivers/char/tpm/tpm_crb_ffa.c b/drivers/char/tpm/tpm_crb_ffa.c
index 99f1c1e5644b..025c4d4b17ca 100644
--- a/drivers/char/tpm/tpm_crb_ffa.c
+++ b/drivers/char/tpm/tpm_crb_ffa.c
@@ -177,23 +177,13 @@ static int tpm_crb_ffa_to_linux_errno(int errno)
*/
int tpm_crb_ffa_init(void)
{
- int ret = 0;
-
- if (!IS_MODULE(CONFIG_TCG_ARM_CRB_FFA)) {
- ret = ffa_register(&tpm_crb_ffa_driver);
- if (ret) {
- tpm_crb_ffa = ERR_PTR(-ENODEV);
- return ret;
- }
- }
-
if (!tpm_crb_ffa)
- ret = -ENOENT;
+ return -ENOENT;
if (IS_ERR_VALUE(tpm_crb_ffa))
- ret = -ENODEV;
+ return -ENODEV;
- return ret;
+ return 0;
}
EXPORT_SYMBOL_GPL(tpm_crb_ffa_init);
@@ -405,9 +395,7 @@ static struct ffa_driver tpm_crb_ffa_driver = {
.id_table = tpm_crb_ffa_device_id,
};
-#ifdef MODULE
module_ffa_driver(tpm_crb_ffa_driver);
-#endif
MODULE_AUTHOR("Arm");
MODULE_DESCRIPTION("TPM CRB FFA driver");
diff --git a/drivers/char/tpm/tpm_svsm.c b/drivers/char/tpm/tpm_svsm.c
index f5ba0f64850b..b74d60f687d5 100644
--- a/drivers/char/tpm/tpm_svsm.c
+++ b/drivers/char/tpm/tpm_svsm.c
@@ -49,7 +49,7 @@ static int tpm_svsm_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz,
return svsm_vtpm_cmd_response_parse(priv->buffer, buf, bufsiz);
}
-static struct tpm_class_ops tpm_chip_ops = {
+static const struct tpm_class_ops tpm_chip_ops = {
.flags = TPM_OPS_AUTO_STARTUP,
.send = tpm_svsm_send,
};
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 21d79ad3b164..143ef160820e 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -66,8 +66,8 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
bool check_cancel)
{
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
unsigned long stop;
- long rc;
u8 status;
bool canceled = false;
u8 sts_mask;
@@ -87,23 +87,30 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
/* process status changes with irq support */
if (sts_mask) {
ret = -ETIME;
+ add_wait_queue(queue, &wait);
again:
+ if (wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,
+ &canceled)) {
+ ret = canceled ? -ECANCELED : 0;
+ goto out;
+ }
+
timeout = stop - jiffies;
if ((long)timeout <= 0)
- return -ETIME;
- rc = wait_event_interruptible_timeout(*queue,
- wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,
- &canceled),
- timeout);
- if (rc > 0) {
- if (canceled)
- return -ECANCELED;
- ret = 0;
- }
- if (rc == -ERESTARTSYS && freezing(current)) {
- clear_thread_flag(TIF_SIGPENDING);
- goto again;
+ goto out;
+
+ if (signal_pending(current)) {
+ if (freezing(current)) {
+ clear_thread_flag(TIF_SIGPENDING);
+ goto again;
+ }
+ goto out;
}
+
+ wait_woken(&wait, TASK_INTERRUPTIBLE, timeout);
+ goto again;
+out:
+ remove_wait_queue(queue, &wait);
}
if (ret)
@@ -171,6 +178,9 @@ static int __tpm_tis_relinquish_locality(struct tpm_tis_data *priv, int l)
{
tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
+ if (test_bit(TPM_TIS_SETTLE_AFTER_RELINQUISH, &priv->flags))
+ tpm_msleep(TPM_TIMEOUT);
+
return 0;
}
@@ -792,9 +802,10 @@ out:
static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
{
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+ u16 vendor_id = priv->did_vid;
if (!test_bit(TPM_TIS_DEFAULT_CANCELLATION, &priv->flags)) {
- switch (priv->manufacturer_id) {
+ switch (vendor_id) {
case TPM_VID_WINBOND:
return ((status == TPM_STS_VALID) ||
(status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)));
@@ -1115,7 +1126,8 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
const struct tpm_tis_phy_ops *phy_ops,
acpi_handle acpi_dev_handle)
{
- u32 vendor;
+ u16 vendor_id;
+ u16 device_id;
u32 intfcaps;
u32 intmask;
u32 clkrun_val;
@@ -1148,21 +1160,25 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
dev_set_drvdata(&chip->dev, priv);
- rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor);
+ rc = tpm_tis_read32(priv, TPM_DID_VID(0), &priv->did_vid);
if (rc < 0)
return rc;
- priv->manufacturer_id = vendor;
+ vendor_id = priv->did_vid;
+ device_id = priv->did_vid >> 16;
- if (priv->manufacturer_id == TPM_VID_ATML &&
+ if (vendor_id == TPM_VID_ATML &&
!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
priv->timeout_min = TIS_TIMEOUT_MIN_ATML;
priv->timeout_max = TIS_TIMEOUT_MAX_ATML;
}
- if (priv->manufacturer_id == TPM_VID_IFX)
+ if (vendor_id == TPM_VID_IFX)
set_bit(TPM_TIS_STATUS_VALID_RETRY, &priv->flags);
+ if (vendor_id == TPM_VID_WINBOND && device_id == 0x00FE)
+ set_bit(TPM_TIS_SETTLE_AFTER_RELINQUISH, &priv->flags);
+
if (is_bsw()) {
priv->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR,
ILB_REMAP_SIZE);
@@ -1247,9 +1263,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
if (rc < 0)
goto out_err;
- dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
+ dev_info(dev, "%s TPM (vendor-id 0x%X, device-id 0x%X, rev-id %d)\n",
(chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
- vendor >> 16, rid);
+ vendor_id, device_id, rid);
probe = probe_itpm(chip);
if (probe < 0) {
@@ -1315,6 +1331,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
return 0;
out_err:
+ dev_err(dev, "TPM vid 0x%X, did 0x%X init failed with error %d\n",
+ vendor_id, device_id, rc);
+
if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, false);
diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
index 6c3aa480396b..aa6d78898ef3 100644
--- a/drivers/char/tpm/tpm_tis_core.h
+++ b/drivers/char/tpm/tpm_tis_core.h
@@ -90,11 +90,12 @@ enum tpm_tis_flags {
TPM_TIS_DEFAULT_CANCELLATION = 2,
TPM_TIS_IRQ_TESTED = 3,
TPM_TIS_STATUS_VALID_RETRY = 4,
+ TPM_TIS_SETTLE_AFTER_RELINQUISH = 5,
};
struct tpm_tis_data {
struct tpm_chip *chip;
- u16 manufacturer_id;
+ u32 did_vid;
struct mutex locality_count_mutex;
unsigned int locality_count;
int locality;