diff options
| -rw-r--r-- | certs/blacklist.c | 21 | ||||
| -rw-r--r-- | crypto/asymmetric_keys/Kconfig | 2 | ||||
| -rw-r--r-- | crypto/asymmetric_keys/pkcs7_verify.c | 1 | ||||
| -rw-r--r-- | crypto/asymmetric_keys/public_key.c | 24 | ||||
| -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 | ||||
| -rw-r--r-- | include/acpi/actbl3.h | 1 | ||||
| -rw-r--r-- | include/linux/key.h | 8 | ||||
| -rw-r--r-- | include/linux/tpm.h | 1 | ||||
| -rw-r--r-- | security/keys/key.c | 137 | 
19 files changed, 293 insertions, 86 deletions
| diff --git a/certs/blacklist.c b/certs/blacklist.c index 41f10601cc72..675dd7a8f07a 100644 --- a/certs/blacklist.c +++ b/certs/blacklist.c @@ -183,16 +183,19 @@ static int mark_raw_hash_blacklisted(const char *hash)  {  	key_ref_t key; -	key = key_create_or_update(make_key_ref(blacklist_keyring, true), -				   "blacklist", -				   hash, -				   NULL, -				   0, -				   BLACKLIST_KEY_PERM, -				   KEY_ALLOC_NOT_IN_QUOTA | -				   KEY_ALLOC_BUILT_IN); +	key = key_create(make_key_ref(blacklist_keyring, true), +			 "blacklist", +			 hash, +			 NULL, +			 0, +			 BLACKLIST_KEY_PERM, +			 KEY_ALLOC_NOT_IN_QUOTA | +			 KEY_ALLOC_BUILT_IN);  	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 0; diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 3df3fe4ed95f..1ef3b46d6f6e 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -83,6 +83,6 @@ config FIPS_SIGNATURE_SELFTEST  	  for FIPS.  	depends on KEYS  	depends on ASYMMETRIC_KEY_TYPE -	depends on PKCS7_MESSAGE_PARSER +	depends on PKCS7_MESSAGE_PARSER=X509_CERTIFICATE_PARSER  endif # ASYMMETRIC_KEY_TYPE diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index f6321c785714..4fa769c4bcdb 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -485,3 +485,4 @@ int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,  	pkcs7->data_len = datalen;  	return 0;  } +EXPORT_SYMBOL_GPL(pkcs7_supply_detached_data); diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 2f8352e88860..eca5671ad3f2 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -186,8 +186,28 @@ static int software_key_query(const struct kernel_pkey_params *params,  	len = crypto_akcipher_maxsize(tfm);  	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_dec_size = len;  	info->supported_ops = (KEYCTL_SUPPORTS_ENCRYPT | 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,  }; diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h index 7b9571e00cc4..832c6464f063 100644 --- a/include/acpi/actbl3.h +++ b/include/acpi/actbl3.h @@ -443,6 +443,7 @@ struct acpi_tpm2_phy {  #define ACPI_TPM2_RESERVED10                        10  #define ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC       11	/* V1.2 Rev 8 */  #define ACPI_TPM2_RESERVED                          12 +#define ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON        13  /* Optional trailer appears after any start_method subtables */ diff --git a/include/linux/key.h b/include/linux/key.h index d27477faf00d..8dc7f7c3088b 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -386,6 +386,14 @@ extern int wait_for_key_construction(struct key *key, bool intr);  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,  				      const char *type,  				      const char *description, diff --git a/include/linux/tpm.h b/include/linux/tpm.h index dfeb25a0362d..4dc97b9f65fb 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -265,6 +265,7 @@ enum tpm2_startup_types {  enum tpm2_cc_attrs {  	TPM2_CC_ATTR_CHANDLES	= 25,  	TPM2_CC_ATTR_RHANDLE	= 28, +	TPM2_CC_ATTR_VENDOR	= 29,  };  #define TPM_VID_INTEL    0x8086 diff --git a/security/keys/key.c b/security/keys/key.c index c45afdd1dfbb..5c0c7df833f8 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -788,38 +788,18 @@ error:  	goto out;  } -/** - * 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. +/* + * Create or potentially update a key. The combined logic behind + * key_create_or_update() and key_create()   */ -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) +static 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, +					bool allow_update)  {  	struct keyring_index_key index_key = {  		.description	= description, @@ -906,14 +886,23 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,  		goto error_link_end;  	} -	/* if it's possible to update this type of key, search for an existing -	 * key of the same type and description in the destination keyring and -	 * update that instead if possible +	/* if it's requested and possible to update this type of key, search +	 * for an existing key of the same type and description in the +	 * 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); -		if (key_ref) -			goto found_matching_key; +		if (key_ref) { +			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 */ @@ -985,9 +974,83 @@ error:  	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);  /** + * 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_ref: The pointer (plus possession flag) to the key.   * @payload: The data to be used to update the key. | 
