diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-20 22:02:05 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-20 22:02:05 +0300 |
commit | 219ac97a486c1ad9c110cb96ebdad7ba068236fb (patch) | |
tree | 18f2d661c6902e6838ddd3b1a4c905d5860d504f /drivers | |
parent | 69adb0bcb833963050d82e645b6a1a0747662490 (diff) | |
parent | 85b93bbd1c9768d09adebbe9f33bab0d4ec94404 (diff) | |
download | linux-219ac97a486c1ad9c110cb96ebdad7ba068236fb.tar.xz |
Merge tag 'tpm-v6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd
Pull tpm updates from Jarkko Sakkinen:
"In additon to bug fixes, these are noteworthy changes:
- In TPM I2C drivers, migrate from probe() to probe_new() (a new
driver model in I2C).
- TPM CRB: Pluton support
- Add duplicate hash detection to the blacklist keyring in order to
give more meaningful klog output than e.g. [1]"
Link: https://askubuntu.com/questions/1436856/ubuntu-22-10-blacklist-problem-blacklisting-hash-13-message-on-boot [1]
* tag 'tpm-v6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd:
tpm: add vendor flag to command code validation
tpm: Add reserved memory event log
tpm: Use managed allocation for bios event log
tpm: tis_i2c: Convert to i2c's .probe_new()
tpm: tpm_i2c_nuvoton: Convert to i2c's .probe_new()
tpm: tpm_i2c_infineon: Convert to i2c's .probe_new()
tpm: tpm_i2c_atmel: Convert to i2c's .probe_new()
tpm: st33zp24: Convert to i2c's .probe_new()
KEYS: asymmetric: Fix ECDSA use via keyctl uapi
certs: don't try to update blacklist keys
KEYS: Add new function key_create()
certs: make blacklisted hash available in klog
tpm_crb: Add support for CRB devices based on Pluton
crypto: certs: fix FIPS selftest dependency
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/tpm/eventlog/acpi.c | 5 | ||||
-rw-r--r-- | drivers/char/tpm/eventlog/efi.c | 13 | ||||
-rw-r--r-- | drivers/char/tpm/eventlog/of.c | 35 | ||||
-rw-r--r-- | drivers/char/tpm/st33zp24/i2c.c | 5 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-chip.c | 1 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 4 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 100 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_i2c_atmel.c | 5 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_i2c_infineon.c | 5 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_i2c_nuvoton.c | 6 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis_i2c.c | 5 |
11 files changed, 147 insertions, 37 deletions
diff --git a/drivers/char/tpm/eventlog/acpi.c b/drivers/char/tpm/eventlog/acpi.c index 0913d3eb8d51..40360e599bc3 100644 --- a/drivers/char/tpm/eventlog/acpi.c +++ b/drivers/char/tpm/eventlog/acpi.c @@ -14,6 +14,7 @@ * Access to the event log extended by the TCG BIOS of PC platform */ +#include <linux/device.h> #include <linux/seq_file.h> #include <linux/fs.h> #include <linux/security.h> @@ -135,7 +136,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip) } /* malloc EventLog space */ - log->bios_event_log = kmalloc(len, GFP_KERNEL); + log->bios_event_log = devm_kmalloc(&chip->dev, len, GFP_KERNEL); if (!log->bios_event_log) return -ENOMEM; @@ -160,7 +161,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip) return format; err: - kfree(log->bios_event_log); + devm_kfree(&chip->dev, log->bios_event_log); log->bios_event_log = NULL; return ret; } diff --git a/drivers/char/tpm/eventlog/efi.c b/drivers/char/tpm/eventlog/efi.c index e6cb9d525e30..4e9d7c2bf32e 100644 --- a/drivers/char/tpm/eventlog/efi.c +++ b/drivers/char/tpm/eventlog/efi.c @@ -6,6 +6,7 @@ * Thiebaud Weksteen <tweek@google.com> */ +#include <linux/device.h> #include <linux/efi.h> #include <linux/tpm_eventlog.h> @@ -55,7 +56,7 @@ int tpm_read_log_efi(struct tpm_chip *chip) } /* malloc EventLog space */ - log->bios_event_log = kmemdup(log_tbl->log, log_size, GFP_KERNEL); + log->bios_event_log = devm_kmemdup(&chip->dev, log_tbl->log, log_size, GFP_KERNEL); if (!log->bios_event_log) { ret = -ENOMEM; goto out; @@ -76,7 +77,7 @@ int tpm_read_log_efi(struct tpm_chip *chip) MEMREMAP_WB); if (!final_tbl) { pr_err("Could not map UEFI TPM final log\n"); - kfree(log->bios_event_log); + devm_kfree(&chip->dev, log->bios_event_log); ret = -ENOMEM; goto out; } @@ -91,11 +92,11 @@ int tpm_read_log_efi(struct tpm_chip *chip) * Allocate memory for the 'combined log' where we will append the * 'final events log' to. */ - tmp = krealloc(log->bios_event_log, - log_size + final_events_log_size, - GFP_KERNEL); + tmp = devm_krealloc(&chip->dev, log->bios_event_log, + log_size + final_events_log_size, + GFP_KERNEL); if (!tmp) { - kfree(log->bios_event_log); + devm_kfree(&chip->dev, log->bios_event_log); ret = -ENOMEM; goto out; } diff --git a/drivers/char/tpm/eventlog/of.c b/drivers/char/tpm/eventlog/of.c index a9ce66d09a75..930fe43d5daf 100644 --- a/drivers/char/tpm/eventlog/of.c +++ b/drivers/char/tpm/eventlog/of.c @@ -10,13 +10,44 @@ * Read the event log created by the firmware on PPC64 */ +#include <linux/device.h> #include <linux/slab.h> +#include <linux/io.h> +#include <linux/ioport.h> #include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_reserved_mem.h> #include <linux/tpm_eventlog.h> #include "../tpm.h" #include "common.h" +static int tpm_read_log_memory_region(struct tpm_chip *chip) +{ + struct device_node *node; + struct resource res; + int rc; + + node = of_parse_phandle(chip->dev.parent->of_node, "memory-region", 0); + if (!node) + return -ENODEV; + + rc = of_address_to_resource(node, 0, &res); + of_node_put(node); + if (rc) + return rc; + + chip->log.bios_event_log = devm_memremap(&chip->dev, res.start, resource_size(&res), + MEMREMAP_WB); + if (IS_ERR(chip->log.bios_event_log)) + return -ENOMEM; + + chip->log.bios_event_log_end = chip->log.bios_event_log + resource_size(&res); + + return chip->flags & TPM_CHIP_FLAG_TPM2 ? EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 : + EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; +} + int tpm_read_log_of(struct tpm_chip *chip) { struct device_node *np; @@ -38,7 +69,7 @@ int tpm_read_log_of(struct tpm_chip *chip) sizep = of_get_property(np, "linux,sml-size", NULL); basep = of_get_property(np, "linux,sml-base", NULL); if (sizep == NULL && basep == NULL) - return -ENODEV; + return tpm_read_log_memory_region(chip); if (sizep == NULL || basep == NULL) return -EIO; @@ -65,7 +96,7 @@ int tpm_read_log_of(struct tpm_chip *chip) return -EIO; } - log->bios_event_log = kmemdup(__va(base), size, GFP_KERNEL); + log->bios_event_log = devm_kmemdup(&chip->dev, __va(base), size, GFP_KERNEL); if (!log->bios_event_log) return -ENOMEM; diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c index 8156bb2af78c..c4d0b744e3cc 100644 --- a/drivers/char/tpm/st33zp24/i2c.c +++ b/drivers/char/tpm/st33zp24/i2c.c @@ -101,8 +101,7 @@ static const struct st33zp24_phy_ops i2c_phy_ops = { * @return: 0 in case of success. * -1 in other case. */ -static int st33zp24_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int st33zp24_i2c_probe(struct i2c_client *client) { struct st33zp24_i2c_phy *phy; @@ -161,7 +160,7 @@ static struct i2c_driver st33zp24_i2c_driver = { .of_match_table = of_match_ptr(of_st33zp24_i2c_match), .acpi_match_table = ACPI_PTR(st33zp24_i2c_acpi_match), }, - .probe = st33zp24_i2c_probe, + .probe_new = st33zp24_i2c_probe, .remove = st33zp24_i2c_remove, .id_table = st33zp24_i2c_id }; diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 741d8f3e8fb3..b99f55f2d4fd 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -267,7 +267,6 @@ static void tpm_dev_release(struct device *dev) idr_remove(&dev_nums_idr, chip->dev_num); mutex_unlock(&idr_lock); - kfree(chip->log.bios_event_log); kfree(chip->work_space.context_buf); kfree(chip->work_space.session_buf); kfree(chip->allocated_banks); diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 65d03867e114..93545be190a5 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -777,10 +777,12 @@ out: int tpm2_find_cc(struct tpm_chip *chip, u32 cc) { + u32 cc_mask; int i; + cc_mask = 1 << TPM2_CC_ATTR_VENDOR | GENMASK(15, 0); for (i = 0; i < chip->nr_commands; i++) - if (cc == (chip->cc_attrs_tbl[i] & GENMASK(15, 0))) + if (cc == (chip->cc_attrs_tbl[i] & cc_mask)) return i; return -1; diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 7e9da671a0e8..d43a0d7b97a8 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -98,6 +98,8 @@ struct crb_priv { u8 __iomem *rsp; u32 cmd_size; u32 smc_func_id; + u32 __iomem *pluton_start_addr; + u32 __iomem *pluton_reply_addr; }; struct tpm2_crb_smc { @@ -108,6 +110,11 @@ struct tpm2_crb_smc { u32 smc_func_id; }; +struct tpm2_crb_pluton { + u64 start_addr; + u64 reply_addr; +}; + static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, unsigned long timeout) { @@ -127,6 +134,25 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, return ((ioread32(reg) & mask) == value); } +static int crb_try_pluton_doorbell(struct crb_priv *priv, bool wait_for_complete) +{ + if (priv->sm != ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) + return 0; + + if (!crb_wait_for_reg_32(priv->pluton_reply_addr, ~0, 1, TPM2_TIMEOUT_C)) + return -ETIME; + + iowrite32(1, priv->pluton_start_addr); + if (wait_for_complete == false) + return 0; + + if (!crb_wait_for_reg_32(priv->pluton_start_addr, + 0xffffffff, 0, 200)) + return -ETIME; + + return 0; +} + /** * __crb_go_idle - request tpm crb device to go the idle state * @@ -145,6 +171,8 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, */ static int __crb_go_idle(struct device *dev, struct crb_priv *priv) { + int rc; + if ((priv->sm == ACPI_TPM2_START_METHOD) || (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) @@ -152,6 +180,10 @@ static int __crb_go_idle(struct device *dev, struct crb_priv *priv) iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); + rc = crb_try_pluton_doorbell(priv, true); + if (rc) + return rc; + if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req, CRB_CTRL_REQ_GO_IDLE/* mask */, 0, /* value */ @@ -188,12 +220,19 @@ static int crb_go_idle(struct tpm_chip *chip) */ static int __crb_cmd_ready(struct device *dev, struct crb_priv *priv) { + int rc; + if ((priv->sm == ACPI_TPM2_START_METHOD) || (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) return 0; iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); + + rc = crb_try_pluton_doorbell(priv, true); + if (rc) + return rc; + if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req, CRB_CTRL_REQ_CMD_READY /* mask */, 0, /* value */ @@ -371,6 +410,10 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) return -E2BIG; } + /* Seems to be necessary for every command */ + if (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) + __crb_cmd_ready(&chip->dev, priv); + memcpy_toio(priv->cmd, buf, len); /* Make sure that cmd is populated before issuing start. */ @@ -394,7 +437,10 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id); } - return rc; + if (rc) + return rc; + + return crb_try_pluton_doorbell(priv, false); } static void crb_cancel(struct tpm_chip *chip) @@ -524,15 +570,18 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, return ret; acpi_dev_free_resource_list(&acpi_resource_list); - if (resource_type(iores_array) != IORESOURCE_MEM) { - dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n"); - return -EINVAL; - } else if (resource_type(iores_array + TPM_CRB_MAX_RESOURCES) == - IORESOURCE_MEM) { - dev_warn(dev, "TPM2 ACPI table defines too many memory resources\n"); - memset(iores_array + TPM_CRB_MAX_RESOURCES, - 0, sizeof(*iores_array)); - iores_array[TPM_CRB_MAX_RESOURCES].flags = 0; + /* Pluton doesn't appear to define ACPI memory regions */ + if (priv->sm != ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) { + if (resource_type(iores_array) != IORESOURCE_MEM) { + dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n"); + return -EINVAL; + } else if (resource_type(iores_array + TPM_CRB_MAX_RESOURCES) == + IORESOURCE_MEM) { + dev_warn(dev, "TPM2 ACPI table defines too many memory resources\n"); + memset(iores_array + TPM_CRB_MAX_RESOURCES, + 0, sizeof(*iores_array)); + iores_array[TPM_CRB_MAX_RESOURCES].flags = 0; + } } iores = NULL; @@ -656,6 +705,22 @@ out_relinquish_locality: return ret; } +static int crb_map_pluton(struct device *dev, struct crb_priv *priv, + struct acpi_table_tpm2 *buf, struct tpm2_crb_pluton *crb_pluton) +{ + priv->pluton_start_addr = crb_map_res(dev, NULL, NULL, + crb_pluton->start_addr, 4); + if (IS_ERR(priv->pluton_start_addr)) + return PTR_ERR(priv->pluton_start_addr); + + priv->pluton_reply_addr = crb_map_res(dev, NULL, NULL, + crb_pluton->reply_addr, 4); + if (IS_ERR(priv->pluton_reply_addr)) + return PTR_ERR(priv->pluton_reply_addr); + + return 0; +} + static int crb_acpi_add(struct acpi_device *device) { struct acpi_table_tpm2 *buf; @@ -663,6 +728,7 @@ static int crb_acpi_add(struct acpi_device *device) struct tpm_chip *chip; struct device *dev = &device->dev; struct tpm2_crb_smc *crb_smc; + struct tpm2_crb_pluton *crb_pluton; acpi_status status; u32 sm; int rc; @@ -700,6 +766,20 @@ static int crb_acpi_add(struct acpi_device *device) priv->smc_func_id = crb_smc->smc_func_id; } + if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) { + if (buf->header.length < (sizeof(*buf) + sizeof(*crb_pluton))) { + dev_err(dev, + FW_BUG "TPM2 ACPI table has wrong size %u for start method type %d\n", + buf->header.length, + ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON); + return -EINVAL; + } + crb_pluton = ACPI_ADD_PTR(struct tpm2_crb_pluton, buf, sizeof(*buf)); + rc = crb_map_pluton(dev, priv, buf, crb_pluton); + if (rc) + return rc; + } + priv->sm = sm; priv->hid = acpi_device_hid(device); diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c index 4be3677c1463..8f77154e0550 100644 --- a/drivers/char/tpm/tpm_i2c_atmel.c +++ b/drivers/char/tpm/tpm_i2c_atmel.c @@ -146,8 +146,7 @@ static const struct tpm_class_ops i2c_atmel = { .req_canceled = i2c_atmel_req_canceled, }; -static int i2c_atmel_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int i2c_atmel_probe(struct i2c_client *client) { struct tpm_chip *chip; struct device *dev = &client->dev; @@ -204,7 +203,7 @@ static SIMPLE_DEV_PM_OPS(i2c_atmel_pm_ops, tpm_pm_suspend, tpm_pm_resume); static struct i2c_driver i2c_atmel_driver = { .id_table = i2c_atmel_id, - .probe = i2c_atmel_probe, + .probe_new = i2c_atmel_probe, .remove = i2c_atmel_remove, .driver = { .name = I2C_DRIVER_NAME, diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index fd3c3661e646..7cdaff52a96d 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -681,8 +681,7 @@ MODULE_DEVICE_TABLE(of, tpm_tis_i2c_of_match); static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume); -static int tpm_tis_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int tpm_tis_i2c_probe(struct i2c_client *client) { int rc; struct device *dev = &(client->dev); @@ -717,7 +716,7 @@ static void tpm_tis_i2c_remove(struct i2c_client *client) static struct i2c_driver tpm_tis_i2c_driver = { .id_table = tpm_tis_i2c_table, - .probe = tpm_tis_i2c_probe, + .probe_new = tpm_tis_i2c_probe, .remove = tpm_tis_i2c_remove, .driver = { .name = "tpm_i2c_infineon", diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index 95c37350cc8e..a026e98add50 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c @@ -522,9 +522,9 @@ static int get_vid(struct i2c_client *client, u32 *res) return 0; } -static int i2c_nuvoton_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int i2c_nuvoton_probe(struct i2c_client *client) { + const struct i2c_device_id *id = i2c_client_get_device_id(client); int rc; struct tpm_chip *chip; struct device *dev = &client->dev; @@ -650,7 +650,7 @@ static SIMPLE_DEV_PM_OPS(i2c_nuvoton_pm_ops, tpm_pm_suspend, tpm_pm_resume); static struct i2c_driver i2c_nuvoton_driver = { .id_table = i2c_nuvoton_id, - .probe = i2c_nuvoton_probe, + .probe_new = i2c_nuvoton_probe, .remove = i2c_nuvoton_remove, .driver = { .name = "tpm_i2c_nuvoton", diff --git a/drivers/char/tpm/tpm_tis_i2c.c b/drivers/char/tpm/tpm_tis_i2c.c index f3a7251c8e38..c8c34adc14c0 100644 --- a/drivers/char/tpm/tpm_tis_i2c.c +++ b/drivers/char/tpm/tpm_tis_i2c.c @@ -312,8 +312,7 @@ static const struct tpm_tis_phy_ops tpm_i2c_phy_ops = { .verify_crc = tpm_tis_i2c_verify_crc, }; -static int tpm_tis_i2c_probe(struct i2c_client *dev, - const struct i2c_device_id *id) +static int tpm_tis_i2c_probe(struct i2c_client *dev) { struct tpm_tis_i2c_phy *phy; const u8 crc_enable = 1; @@ -380,7 +379,7 @@ static struct i2c_driver tpm_tis_i2c_driver = { .pm = &tpm_tis_pm, .of_match_table = of_match_ptr(of_tis_i2c_match), }, - .probe = tpm_tis_i2c_probe, + .probe_new = tpm_tis_i2c_probe, .remove = tpm_tis_i2c_remove, .id_table = tpm_tis_i2c_id, }; |