mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
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
This commit is contained in:
@@ -183,16 +183,19 @@ static int mark_raw_hash_blacklisted(const char *hash)
|
|||||||
{
|
{
|
||||||
key_ref_t key;
|
key_ref_t key;
|
||||||
|
|
||||||
key = key_create_or_update(make_key_ref(blacklist_keyring, true),
|
key = key_create(make_key_ref(blacklist_keyring, true),
|
||||||
"blacklist",
|
"blacklist",
|
||||||
hash,
|
hash,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
BLACKLIST_KEY_PERM,
|
BLACKLIST_KEY_PERM,
|
||||||
KEY_ALLOC_NOT_IN_QUOTA |
|
KEY_ALLOC_NOT_IN_QUOTA |
|
||||||
KEY_ALLOC_BUILT_IN);
|
KEY_ALLOC_BUILT_IN);
|
||||||
if (IS_ERR(key)) {
|
if (IS_ERR(key)) {
|
||||||
pr_err("Problem blacklisting hash (%ld)\n", PTR_ERR(key));
|
if (PTR_ERR(key) == -EEXIST)
|
||||||
|
pr_warn("Duplicate blacklisted hash %s\n", hash);
|
||||||
|
else
|
||||||
|
pr_err("Problem blacklisting hash %s: %pe\n", hash, key);
|
||||||
return PTR_ERR(key);
|
return PTR_ERR(key);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -83,6 +83,6 @@ config FIPS_SIGNATURE_SELFTEST
|
|||||||
for FIPS.
|
for FIPS.
|
||||||
depends on KEYS
|
depends on KEYS
|
||||||
depends on ASYMMETRIC_KEY_TYPE
|
depends on ASYMMETRIC_KEY_TYPE
|
||||||
depends on PKCS7_MESSAGE_PARSER
|
depends on PKCS7_MESSAGE_PARSER=X509_CERTIFICATE_PARSER
|
||||||
|
|
||||||
endif # ASYMMETRIC_KEY_TYPE
|
endif # ASYMMETRIC_KEY_TYPE
|
||||||
|
@@ -485,3 +485,4 @@ int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
|
|||||||
pkcs7->data_len = datalen;
|
pkcs7->data_len = datalen;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pkcs7_supply_detached_data);
|
||||||
|
@@ -186,8 +186,28 @@ static int software_key_query(const struct kernel_pkey_params *params,
|
|||||||
|
|
||||||
len = crypto_akcipher_maxsize(tfm);
|
len = crypto_akcipher_maxsize(tfm);
|
||||||
info->key_size = len * 8;
|
info->key_size = len * 8;
|
||||||
info->max_data_size = len;
|
|
||||||
info->max_sig_size = len;
|
if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) {
|
||||||
|
/*
|
||||||
|
* ECDSA key sizes are much smaller than RSA, and thus could
|
||||||
|
* operate on (hashed) inputs that are larger than key size.
|
||||||
|
* For example SHA384-hashed input used with secp256r1
|
||||||
|
* based keys. Set max_data_size to be at least as large as
|
||||||
|
* the largest supported hash size (SHA512)
|
||||||
|
*/
|
||||||
|
info->max_data_size = 64;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify takes ECDSA-Sig (described in RFC 5480) as input,
|
||||||
|
* which is actually 2 'key_size'-bit integers encoded in
|
||||||
|
* ASN.1. Account for the ASN.1 encoding overhead here.
|
||||||
|
*/
|
||||||
|
info->max_sig_size = 2 * (len + 3) + 2;
|
||||||
|
} else {
|
||||||
|
info->max_data_size = len;
|
||||||
|
info->max_sig_size = len;
|
||||||
|
}
|
||||||
|
|
||||||
info->max_enc_size = len;
|
info->max_enc_size = len;
|
||||||
info->max_dec_size = len;
|
info->max_dec_size = len;
|
||||||
info->supported_ops = (KEYCTL_SUPPORTS_ENCRYPT |
|
info->supported_ops = (KEYCTL_SUPPORTS_ENCRYPT |
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
* Access to the event log extended by the TCG BIOS of PC platform
|
* Access to the event log extended by the TCG BIOS of PC platform
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
@@ -135,7 +136,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* malloc EventLog space */
|
/* 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)
|
if (!log->bios_event_log)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -160,7 +161,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
|
|||||||
return format;
|
return format;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
kfree(log->bios_event_log);
|
devm_kfree(&chip->dev, log->bios_event_log);
|
||||||
log->bios_event_log = NULL;
|
log->bios_event_log = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
* Thiebaud Weksteen <tweek@google.com>
|
* Thiebaud Weksteen <tweek@google.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
#include <linux/efi.h>
|
#include <linux/efi.h>
|
||||||
#include <linux/tpm_eventlog.h>
|
#include <linux/tpm_eventlog.h>
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ int tpm_read_log_efi(struct tpm_chip *chip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* malloc EventLog space */
|
/* 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) {
|
if (!log->bios_event_log) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -76,7 +77,7 @@ int tpm_read_log_efi(struct tpm_chip *chip)
|
|||||||
MEMREMAP_WB);
|
MEMREMAP_WB);
|
||||||
if (!final_tbl) {
|
if (!final_tbl) {
|
||||||
pr_err("Could not map UEFI TPM final log\n");
|
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;
|
ret = -ENOMEM;
|
||||||
goto out;
|
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
|
* Allocate memory for the 'combined log' where we will append the
|
||||||
* 'final events log' to.
|
* 'final events log' to.
|
||||||
*/
|
*/
|
||||||
tmp = krealloc(log->bios_event_log,
|
tmp = devm_krealloc(&chip->dev, log->bios_event_log,
|
||||||
log_size + final_events_log_size,
|
log_size + final_events_log_size,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
kfree(log->bios_event_log);
|
devm_kfree(&chip->dev, log->bios_event_log);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@@ -10,13 +10,44 @@
|
|||||||
* Read the event log created by the firmware on PPC64
|
* Read the event log created by the firmware on PPC64
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/of_reserved_mem.h>
|
||||||
#include <linux/tpm_eventlog.h>
|
#include <linux/tpm_eventlog.h>
|
||||||
|
|
||||||
#include "../tpm.h"
|
#include "../tpm.h"
|
||||||
#include "common.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)
|
int tpm_read_log_of(struct tpm_chip *chip)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
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);
|
sizep = of_get_property(np, "linux,sml-size", NULL);
|
||||||
basep = of_get_property(np, "linux,sml-base", NULL);
|
basep = of_get_property(np, "linux,sml-base", NULL);
|
||||||
if (sizep == NULL && basep == NULL)
|
if (sizep == NULL && basep == NULL)
|
||||||
return -ENODEV;
|
return tpm_read_log_memory_region(chip);
|
||||||
if (sizep == NULL || basep == NULL)
|
if (sizep == NULL || basep == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
@@ -65,7 +96,7 @@ int tpm_read_log_of(struct tpm_chip *chip)
|
|||||||
return -EIO;
|
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)
|
if (!log->bios_event_log)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@@ -101,8 +101,7 @@ static const struct st33zp24_phy_ops i2c_phy_ops = {
|
|||||||
* @return: 0 in case of success.
|
* @return: 0 in case of success.
|
||||||
* -1 in other case.
|
* -1 in other case.
|
||||||
*/
|
*/
|
||||||
static int st33zp24_i2c_probe(struct i2c_client *client,
|
static int st33zp24_i2c_probe(struct i2c_client *client)
|
||||||
const struct i2c_device_id *id)
|
|
||||||
{
|
{
|
||||||
struct st33zp24_i2c_phy *phy;
|
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),
|
.of_match_table = of_match_ptr(of_st33zp24_i2c_match),
|
||||||
.acpi_match_table = ACPI_PTR(st33zp24_i2c_acpi_match),
|
.acpi_match_table = ACPI_PTR(st33zp24_i2c_acpi_match),
|
||||||
},
|
},
|
||||||
.probe = st33zp24_i2c_probe,
|
.probe_new = st33zp24_i2c_probe,
|
||||||
.remove = st33zp24_i2c_remove,
|
.remove = st33zp24_i2c_remove,
|
||||||
.id_table = st33zp24_i2c_id
|
.id_table = st33zp24_i2c_id
|
||||||
};
|
};
|
||||||
|
@@ -267,7 +267,6 @@ static void tpm_dev_release(struct device *dev)
|
|||||||
idr_remove(&dev_nums_idr, chip->dev_num);
|
idr_remove(&dev_nums_idr, chip->dev_num);
|
||||||
mutex_unlock(&idr_lock);
|
mutex_unlock(&idr_lock);
|
||||||
|
|
||||||
kfree(chip->log.bios_event_log);
|
|
||||||
kfree(chip->work_space.context_buf);
|
kfree(chip->work_space.context_buf);
|
||||||
kfree(chip->work_space.session_buf);
|
kfree(chip->work_space.session_buf);
|
||||||
kfree(chip->allocated_banks);
|
kfree(chip->allocated_banks);
|
||||||
|
@@ -777,10 +777,12 @@ out:
|
|||||||
|
|
||||||
int tpm2_find_cc(struct tpm_chip *chip, u32 cc)
|
int tpm2_find_cc(struct tpm_chip *chip, u32 cc)
|
||||||
{
|
{
|
||||||
|
u32 cc_mask;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
cc_mask = 1 << TPM2_CC_ATTR_VENDOR | GENMASK(15, 0);
|
||||||
for (i = 0; i < chip->nr_commands; i++)
|
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 i;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@@ -98,6 +98,8 @@ struct crb_priv {
|
|||||||
u8 __iomem *rsp;
|
u8 __iomem *rsp;
|
||||||
u32 cmd_size;
|
u32 cmd_size;
|
||||||
u32 smc_func_id;
|
u32 smc_func_id;
|
||||||
|
u32 __iomem *pluton_start_addr;
|
||||||
|
u32 __iomem *pluton_reply_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tpm2_crb_smc {
|
struct tpm2_crb_smc {
|
||||||
@@ -108,6 +110,11 @@ struct tpm2_crb_smc {
|
|||||||
u32 smc_func_id;
|
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,
|
static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
|
||||||
unsigned long timeout)
|
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);
|
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
|
* __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)
|
static int __crb_go_idle(struct device *dev, struct crb_priv *priv)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
if ((priv->sm == ACPI_TPM2_START_METHOD) ||
|
if ((priv->sm == ACPI_TPM2_START_METHOD) ||
|
||||||
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
|
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
|
||||||
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC))
|
(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);
|
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,
|
if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req,
|
||||||
CRB_CTRL_REQ_GO_IDLE/* mask */,
|
CRB_CTRL_REQ_GO_IDLE/* mask */,
|
||||||
0, /* value */
|
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)
|
static int __crb_cmd_ready(struct device *dev, struct crb_priv *priv)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
if ((priv->sm == ACPI_TPM2_START_METHOD) ||
|
if ((priv->sm == ACPI_TPM2_START_METHOD) ||
|
||||||
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
|
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
|
||||||
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC))
|
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req);
|
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,
|
if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req,
|
||||||
CRB_CTRL_REQ_CMD_READY /* mask */,
|
CRB_CTRL_REQ_CMD_READY /* mask */,
|
||||||
0, /* value */
|
0, /* value */
|
||||||
@@ -371,6 +410,10 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
|
|||||||
return -E2BIG;
|
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);
|
memcpy_toio(priv->cmd, buf, len);
|
||||||
|
|
||||||
/* Make sure that cmd is populated before issuing start. */
|
/* 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);
|
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)
|
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;
|
return ret;
|
||||||
acpi_dev_free_resource_list(&acpi_resource_list);
|
acpi_dev_free_resource_list(&acpi_resource_list);
|
||||||
|
|
||||||
if (resource_type(iores_array) != IORESOURCE_MEM) {
|
/* Pluton doesn't appear to define ACPI memory regions */
|
||||||
dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n");
|
if (priv->sm != ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON) {
|
||||||
return -EINVAL;
|
if (resource_type(iores_array) != IORESOURCE_MEM) {
|
||||||
} else if (resource_type(iores_array + TPM_CRB_MAX_RESOURCES) ==
|
dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n");
|
||||||
IORESOURCE_MEM) {
|
return -EINVAL;
|
||||||
dev_warn(dev, "TPM2 ACPI table defines too many memory resources\n");
|
} else if (resource_type(iores_array + TPM_CRB_MAX_RESOURCES) ==
|
||||||
memset(iores_array + TPM_CRB_MAX_RESOURCES,
|
IORESOURCE_MEM) {
|
||||||
0, sizeof(*iores_array));
|
dev_warn(dev, "TPM2 ACPI table defines too many memory resources\n");
|
||||||
iores_array[TPM_CRB_MAX_RESOURCES].flags = 0;
|
memset(iores_array + TPM_CRB_MAX_RESOURCES,
|
||||||
|
0, sizeof(*iores_array));
|
||||||
|
iores_array[TPM_CRB_MAX_RESOURCES].flags = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iores = NULL;
|
iores = NULL;
|
||||||
@@ -656,6 +705,22 @@ out_relinquish_locality:
|
|||||||
return ret;
|
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)
|
static int crb_acpi_add(struct acpi_device *device)
|
||||||
{
|
{
|
||||||
struct acpi_table_tpm2 *buf;
|
struct acpi_table_tpm2 *buf;
|
||||||
@@ -663,6 +728,7 @@ static int crb_acpi_add(struct acpi_device *device)
|
|||||||
struct tpm_chip *chip;
|
struct tpm_chip *chip;
|
||||||
struct device *dev = &device->dev;
|
struct device *dev = &device->dev;
|
||||||
struct tpm2_crb_smc *crb_smc;
|
struct tpm2_crb_smc *crb_smc;
|
||||||
|
struct tpm2_crb_pluton *crb_pluton;
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
u32 sm;
|
u32 sm;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -700,6 +766,20 @@ static int crb_acpi_add(struct acpi_device *device)
|
|||||||
priv->smc_func_id = crb_smc->smc_func_id;
|
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->sm = sm;
|
||||||
priv->hid = acpi_device_hid(device);
|
priv->hid = acpi_device_hid(device);
|
||||||
|
|
||||||
|
@@ -146,8 +146,7 @@ static const struct tpm_class_ops i2c_atmel = {
|
|||||||
.req_canceled = i2c_atmel_req_canceled,
|
.req_canceled = i2c_atmel_req_canceled,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int i2c_atmel_probe(struct i2c_client *client,
|
static int i2c_atmel_probe(struct i2c_client *client)
|
||||||
const struct i2c_device_id *id)
|
|
||||||
{
|
{
|
||||||
struct tpm_chip *chip;
|
struct tpm_chip *chip;
|
||||||
struct device *dev = &client->dev;
|
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 = {
|
static struct i2c_driver i2c_atmel_driver = {
|
||||||
.id_table = i2c_atmel_id,
|
.id_table = i2c_atmel_id,
|
||||||
.probe = i2c_atmel_probe,
|
.probe_new = i2c_atmel_probe,
|
||||||
.remove = i2c_atmel_remove,
|
.remove = i2c_atmel_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = I2C_DRIVER_NAME,
|
.name = I2C_DRIVER_NAME,
|
||||||
|
@@ -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 SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
|
||||||
|
|
||||||
static int tpm_tis_i2c_probe(struct i2c_client *client,
|
static int tpm_tis_i2c_probe(struct i2c_client *client)
|
||||||
const struct i2c_device_id *id)
|
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct device *dev = &(client->dev);
|
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 = {
|
static struct i2c_driver tpm_tis_i2c_driver = {
|
||||||
.id_table = tpm_tis_i2c_table,
|
.id_table = tpm_tis_i2c_table,
|
||||||
.probe = tpm_tis_i2c_probe,
|
.probe_new = tpm_tis_i2c_probe,
|
||||||
.remove = tpm_tis_i2c_remove,
|
.remove = tpm_tis_i2c_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "tpm_i2c_infineon",
|
.name = "tpm_i2c_infineon",
|
||||||
|
@@ -522,9 +522,9 @@ static int get_vid(struct i2c_client *client, u32 *res)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i2c_nuvoton_probe(struct i2c_client *client,
|
static int i2c_nuvoton_probe(struct i2c_client *client)
|
||||||
const struct i2c_device_id *id)
|
|
||||||
{
|
{
|
||||||
|
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||||
int rc;
|
int rc;
|
||||||
struct tpm_chip *chip;
|
struct tpm_chip *chip;
|
||||||
struct device *dev = &client->dev;
|
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 = {
|
static struct i2c_driver i2c_nuvoton_driver = {
|
||||||
.id_table = i2c_nuvoton_id,
|
.id_table = i2c_nuvoton_id,
|
||||||
.probe = i2c_nuvoton_probe,
|
.probe_new = i2c_nuvoton_probe,
|
||||||
.remove = i2c_nuvoton_remove,
|
.remove = i2c_nuvoton_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "tpm_i2c_nuvoton",
|
.name = "tpm_i2c_nuvoton",
|
||||||
|
@@ -312,8 +312,7 @@ static const struct tpm_tis_phy_ops tpm_i2c_phy_ops = {
|
|||||||
.verify_crc = tpm_tis_i2c_verify_crc,
|
.verify_crc = tpm_tis_i2c_verify_crc,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int tpm_tis_i2c_probe(struct i2c_client *dev,
|
static int tpm_tis_i2c_probe(struct i2c_client *dev)
|
||||||
const struct i2c_device_id *id)
|
|
||||||
{
|
{
|
||||||
struct tpm_tis_i2c_phy *phy;
|
struct tpm_tis_i2c_phy *phy;
|
||||||
const u8 crc_enable = 1;
|
const u8 crc_enable = 1;
|
||||||
@@ -380,7 +379,7 @@ static struct i2c_driver tpm_tis_i2c_driver = {
|
|||||||
.pm = &tpm_tis_pm,
|
.pm = &tpm_tis_pm,
|
||||||
.of_match_table = of_match_ptr(of_tis_i2c_match),
|
.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,
|
.remove = tpm_tis_i2c_remove,
|
||||||
.id_table = tpm_tis_i2c_id,
|
.id_table = tpm_tis_i2c_id,
|
||||||
};
|
};
|
||||||
|
@@ -443,6 +443,7 @@ struct acpi_tpm2_phy {
|
|||||||
#define ACPI_TPM2_RESERVED10 10
|
#define ACPI_TPM2_RESERVED10 10
|
||||||
#define ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC 11 /* V1.2 Rev 8 */
|
#define ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC 11 /* V1.2 Rev 8 */
|
||||||
#define ACPI_TPM2_RESERVED 12
|
#define ACPI_TPM2_RESERVED 12
|
||||||
|
#define ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON 13
|
||||||
|
|
||||||
/* Optional trailer appears after any start_method subtables */
|
/* Optional trailer appears after any start_method subtables */
|
||||||
|
|
||||||
|
@@ -386,6 +386,14 @@ extern int wait_for_key_construction(struct key *key, bool intr);
|
|||||||
|
|
||||||
extern int key_validate(const struct key *key);
|
extern int key_validate(const struct key *key);
|
||||||
|
|
||||||
|
extern key_ref_t key_create(key_ref_t keyring,
|
||||||
|
const char *type,
|
||||||
|
const char *description,
|
||||||
|
const void *payload,
|
||||||
|
size_t plen,
|
||||||
|
key_perm_t perm,
|
||||||
|
unsigned long flags);
|
||||||
|
|
||||||
extern key_ref_t key_create_or_update(key_ref_t keyring,
|
extern key_ref_t key_create_or_update(key_ref_t keyring,
|
||||||
const char *type,
|
const char *type,
|
||||||
const char *description,
|
const char *description,
|
||||||
|
@@ -265,6 +265,7 @@ enum tpm2_startup_types {
|
|||||||
enum tpm2_cc_attrs {
|
enum tpm2_cc_attrs {
|
||||||
TPM2_CC_ATTR_CHANDLES = 25,
|
TPM2_CC_ATTR_CHANDLES = 25,
|
||||||
TPM2_CC_ATTR_RHANDLE = 28,
|
TPM2_CC_ATTR_RHANDLE = 28,
|
||||||
|
TPM2_CC_ATTR_VENDOR = 29,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TPM_VID_INTEL 0x8086
|
#define TPM_VID_INTEL 0x8086
|
||||||
|
@@ -788,38 +788,18 @@ error:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* key_create_or_update - Update or create and instantiate a key.
|
* Create or potentially update a key. The combined logic behind
|
||||||
* @keyring_ref: A pointer to the destination keyring with possession flag.
|
* key_create_or_update() and key_create()
|
||||||
* @type: The type of key.
|
|
||||||
* @description: The searchable description for the key.
|
|
||||||
* @payload: The data to use to instantiate or update the key.
|
|
||||||
* @plen: The length of @payload.
|
|
||||||
* @perm: The permissions mask for a new key.
|
|
||||||
* @flags: The quota flags for a new key.
|
|
||||||
*
|
|
||||||
* Search the destination keyring for a key of the same description and if one
|
|
||||||
* is found, update it, otherwise create and instantiate a new one and create a
|
|
||||||
* link to it from that keyring.
|
|
||||||
*
|
|
||||||
* If perm is KEY_PERM_UNDEF then an appropriate key permissions mask will be
|
|
||||||
* concocted.
|
|
||||||
*
|
|
||||||
* Returns a pointer to the new key if successful, -ENODEV if the key type
|
|
||||||
* wasn't available, -ENOTDIR if the keyring wasn't a keyring, -EACCES if the
|
|
||||||
* caller isn't permitted to modify the keyring or the LSM did not permit
|
|
||||||
* creation of the key.
|
|
||||||
*
|
|
||||||
* On success, the possession flag from the keyring ref will be tacked on to
|
|
||||||
* the key ref before it is returned.
|
|
||||||
*/
|
*/
|
||||||
key_ref_t key_create_or_update(key_ref_t keyring_ref,
|
static key_ref_t __key_create_or_update(key_ref_t keyring_ref,
|
||||||
const char *type,
|
const char *type,
|
||||||
const char *description,
|
const char *description,
|
||||||
const void *payload,
|
const void *payload,
|
||||||
size_t plen,
|
size_t plen,
|
||||||
key_perm_t perm,
|
key_perm_t perm,
|
||||||
unsigned long flags)
|
unsigned long flags,
|
||||||
|
bool allow_update)
|
||||||
{
|
{
|
||||||
struct keyring_index_key index_key = {
|
struct keyring_index_key index_key = {
|
||||||
.description = description,
|
.description = description,
|
||||||
@@ -906,14 +886,23 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
|
|||||||
goto error_link_end;
|
goto error_link_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if it's possible to update this type of key, search for an existing
|
/* if it's requested and possible to update this type of key, search
|
||||||
* key of the same type and description in the destination keyring and
|
* for an existing key of the same type and description in the
|
||||||
* update that instead if possible
|
* destination keyring and update that instead if possible
|
||||||
*/
|
*/
|
||||||
if (index_key.type->update) {
|
if (allow_update) {
|
||||||
|
if (index_key.type->update) {
|
||||||
|
key_ref = find_key_to_update(keyring_ref, &index_key);
|
||||||
|
if (key_ref)
|
||||||
|
goto found_matching_key;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
key_ref = find_key_to_update(keyring_ref, &index_key);
|
key_ref = find_key_to_update(keyring_ref, &index_key);
|
||||||
if (key_ref)
|
if (key_ref) {
|
||||||
goto found_matching_key;
|
key_ref_put(key_ref);
|
||||||
|
key_ref = ERR_PTR(-EEXIST);
|
||||||
|
goto error_link_end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the client doesn't provide, decide on the permissions we want */
|
/* if the client doesn't provide, decide on the permissions we want */
|
||||||
@@ -985,8 +974,82 @@ error:
|
|||||||
|
|
||||||
goto error_free_prep;
|
goto error_free_prep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* key_create_or_update - Update or create and instantiate a key.
|
||||||
|
* @keyring_ref: A pointer to the destination keyring with possession flag.
|
||||||
|
* @type: The type of key.
|
||||||
|
* @description: The searchable description for the key.
|
||||||
|
* @payload: The data to use to instantiate or update the key.
|
||||||
|
* @plen: The length of @payload.
|
||||||
|
* @perm: The permissions mask for a new key.
|
||||||
|
* @flags: The quota flags for a new key.
|
||||||
|
*
|
||||||
|
* Search the destination keyring for a key of the same description and if one
|
||||||
|
* is found, update it, otherwise create and instantiate a new one and create a
|
||||||
|
* link to it from that keyring.
|
||||||
|
*
|
||||||
|
* If perm is KEY_PERM_UNDEF then an appropriate key permissions mask will be
|
||||||
|
* concocted.
|
||||||
|
*
|
||||||
|
* Returns a pointer to the new key if successful, -ENODEV if the key type
|
||||||
|
* wasn't available, -ENOTDIR if the keyring wasn't a keyring, -EACCES if the
|
||||||
|
* caller isn't permitted to modify the keyring or the LSM did not permit
|
||||||
|
* creation of the key.
|
||||||
|
*
|
||||||
|
* On success, the possession flag from the keyring ref will be tacked on to
|
||||||
|
* the key ref before it is returned.
|
||||||
|
*/
|
||||||
|
key_ref_t key_create_or_update(key_ref_t keyring_ref,
|
||||||
|
const char *type,
|
||||||
|
const char *description,
|
||||||
|
const void *payload,
|
||||||
|
size_t plen,
|
||||||
|
key_perm_t perm,
|
||||||
|
unsigned long flags)
|
||||||
|
{
|
||||||
|
return __key_create_or_update(keyring_ref, type, description, payload,
|
||||||
|
plen, perm, flags, true);
|
||||||
|
}
|
||||||
EXPORT_SYMBOL(key_create_or_update);
|
EXPORT_SYMBOL(key_create_or_update);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* key_create - Create and instantiate a key.
|
||||||
|
* @keyring_ref: A pointer to the destination keyring with possession flag.
|
||||||
|
* @type: The type of key.
|
||||||
|
* @description: The searchable description for the key.
|
||||||
|
* @payload: The data to use to instantiate or update the key.
|
||||||
|
* @plen: The length of @payload.
|
||||||
|
* @perm: The permissions mask for a new key.
|
||||||
|
* @flags: The quota flags for a new key.
|
||||||
|
*
|
||||||
|
* Create and instantiate a new key and link to it from the destination keyring.
|
||||||
|
*
|
||||||
|
* If perm is KEY_PERM_UNDEF then an appropriate key permissions mask will be
|
||||||
|
* concocted.
|
||||||
|
*
|
||||||
|
* Returns a pointer to the new key if successful, -EEXIST if a key with the
|
||||||
|
* same description already exists, -ENODEV if the key type wasn't available,
|
||||||
|
* -ENOTDIR if the keyring wasn't a keyring, -EACCES if the caller isn't
|
||||||
|
* permitted to modify the keyring or the LSM did not permit creation of the
|
||||||
|
* key.
|
||||||
|
*
|
||||||
|
* On success, the possession flag from the keyring ref will be tacked on to
|
||||||
|
* the key ref before it is returned.
|
||||||
|
*/
|
||||||
|
key_ref_t key_create(key_ref_t keyring_ref,
|
||||||
|
const char *type,
|
||||||
|
const char *description,
|
||||||
|
const void *payload,
|
||||||
|
size_t plen,
|
||||||
|
key_perm_t perm,
|
||||||
|
unsigned long flags)
|
||||||
|
{
|
||||||
|
return __key_create_or_update(keyring_ref, type, description, payload,
|
||||||
|
plen, perm, flags, false);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(key_create);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* key_update - Update a key's contents.
|
* key_update - Update a key's contents.
|
||||||
* @key_ref: The pointer (plus possession flag) to the key.
|
* @key_ref: The pointer (plus possession flag) to the key.
|
||||||
|
Reference in New Issue
Block a user