diff options
| -rw-r--r-- | drivers/char/tpm/Makefile | 16 | ||||
| -rw-r--r-- | drivers/char/tpm/st33zp24/st33zp24.c | 2 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm-chip.c | 11 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm-dev-common.c | 52 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm-dev.h | 5 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm-interface.c | 832 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm-sysfs.c | 52 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm.h | 97 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm1-cmd.c | 781 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 308 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm2-space.c | 2 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_i2c_nuvoton.c | 11 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_ibmvtpm.c | 6 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_tis_core.c | 10 | ||||
| -rw-r--r-- | include/linux/tpm.h | 11 | ||||
| -rw-r--r-- | security/integrity/ima/ima_crypto.c | 5 | 
16 files changed, 1133 insertions, 1068 deletions
| diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 4e9c33ca1f8f..a01c4cab902a 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -3,9 +3,19 @@  # Makefile for the kernel tpm device drivers.  #  obj-$(CONFIG_TCG_TPM) += tpm.o -tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \ -	 tpm-dev-common.o tpmrm-dev.o eventlog/common.o eventlog/tpm1.o \ -	 eventlog/tpm2.o tpm2-space.o +tpm-y := tpm-chip.o +tpm-y += tpm-dev-common.o +tpm-y += tpm-dev.o +tpm-y += tpm-interface.o +tpm-y += tpm1-cmd.o +tpm-y += tpm2-cmd.o +tpm-y += tpmrm-dev.o +tpm-y += tpm2-space.o +tpm-y += tpm-sysfs.o +tpm-y += eventlog/common.o +tpm-y += eventlog/tpm1.o +tpm-y += eventlog/tpm2.o +  tpm-$(CONFIG_ACPI) += tpm_ppi.o eventlog/acpi.o  tpm-$(CONFIG_EFI) += eventlog/efi.o  tpm-$(CONFIG_OF) += eventlog/of.o diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c index abd675bec88c..64dc560859f2 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.c +++ b/drivers/char/tpm/st33zp24/st33zp24.c @@ -649,7 +649,7 @@ int st33zp24_pm_resume(struct device *dev)  	} else {  		ret = tpm_pm_resume(dev);  		if (!ret) -			tpm_do_selftest(chip); +			tpm1_do_selftest(chip);  	}  	return ret;  } /* st33zp24_pm_resume() */ diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 46caadca916a..32db84683c40 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -451,14 +451,9 @@ int tpm_chip_register(struct tpm_chip *chip)  {  	int rc; -	if (chip->ops->flags & TPM_OPS_AUTO_STARTUP) { -		if (chip->flags & TPM_CHIP_FLAG_TPM2) -			rc = tpm2_auto_startup(chip); -		else -			rc = tpm1_auto_startup(chip); -		if (rc) -			return rc; -	} +	rc = tpm_auto_startup(chip); +	if (rc) +		return rc;  	tpm_sysfs_add_device(chip); diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c index 99b5133a9d05..5eecad233ea1 100644 --- a/drivers/char/tpm/tpm-dev-common.c +++ b/drivers/char/tpm/tpm-dev-common.c @@ -40,7 +40,7 @@ static void tpm_async_work(struct work_struct *work)  	tpm_put_ops(priv->chip);  	if (ret > 0) { -		priv->data_pending = ret; +		priv->response_length = ret;  		mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));  	}  	mutex_unlock(&priv->buffer_mutex); @@ -63,7 +63,8 @@ static void tpm_timeout_work(struct work_struct *work)  					      timeout_work);  	mutex_lock(&priv->buffer_mutex); -	priv->data_pending = 0; +	priv->response_read = true; +	priv->response_length = 0;  	memset(priv->data_buffer, 0, sizeof(priv->data_buffer));  	mutex_unlock(&priv->buffer_mutex);  	wake_up_interruptible(&priv->async_wait); @@ -74,6 +75,7 @@ void tpm_common_open(struct file *file, struct tpm_chip *chip,  {  	priv->chip = chip;  	priv->space = space; +	priv->response_read = true;  	mutex_init(&priv->buffer_mutex);  	timer_setup(&priv->user_read_timer, user_reader_timeout, 0); @@ -90,22 +92,35 @@ ssize_t tpm_common_read(struct file *file, char __user *buf,  	ssize_t ret_size = 0;  	int rc; -	del_singleshot_timer_sync(&priv->user_read_timer); -	flush_work(&priv->timeout_work);  	mutex_lock(&priv->buffer_mutex); -	if (priv->data_pending) { -		ret_size = min_t(ssize_t, size, priv->data_pending); -		if (ret_size > 0) { -			rc = copy_to_user(buf, priv->data_buffer, ret_size); -			memset(priv->data_buffer, 0, priv->data_pending); -			if (rc) -				ret_size = -EFAULT; +	if (priv->response_length) { +		priv->response_read = true; + +		ret_size = min_t(ssize_t, size, priv->response_length); +		if (!ret_size) { +			priv->response_length = 0; +			goto out;  		} -		priv->data_pending = 0; +		rc = copy_to_user(buf, priv->data_buffer + *off, ret_size); +		if (rc) { +			memset(priv->data_buffer, 0, TPM_BUFSIZE); +			priv->response_length = 0; +			ret_size = -EFAULT; +		} else { +			memset(priv->data_buffer + *off, 0, ret_size); +			priv->response_length -= ret_size; +			*off += ret_size; +		}  	} +out: +	if (!priv->response_length) { +		*off = 0; +		del_singleshot_timer_sync(&priv->user_read_timer); +		flush_work(&priv->timeout_work); +	}  	mutex_unlock(&priv->buffer_mutex);  	return ret_size;  } @@ -125,7 +140,8 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,  	 * tpm_read or a user_read_timer timeout. This also prevents split  	 * buffered writes from blocking here.  	 */ -	if (priv->data_pending != 0 || priv->command_enqueued) { +	if ((!priv->response_read && priv->response_length) || +	    priv->command_enqueued) {  		ret = -EBUSY;  		goto out;  	} @@ -150,6 +166,10 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,  		goto out;  	} +	priv->response_length = 0; +	priv->response_read = false; +	*off = 0; +  	/*  	 * If in nonblocking mode schedule an async job to send  	 * the command return the size. @@ -168,7 +188,7 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,  	tpm_put_ops(priv->chip);  	if (ret > 0) { -		priv->data_pending = ret; +		priv->response_length = ret;  		mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));  		ret = size;  	} @@ -184,7 +204,7 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait)  	poll_wait(file, &priv->async_wait, wait); -	if (priv->data_pending) +	if (!priv->response_read || priv->response_length)  		mask = EPOLLIN | EPOLLRDNORM;  	else  		mask = EPOLLOUT | EPOLLWRNORM; @@ -201,7 +221,7 @@ void tpm_common_release(struct file *file, struct file_priv *priv)  	del_singleshot_timer_sync(&priv->user_read_timer);  	flush_work(&priv->timeout_work);  	file->private_data = NULL; -	priv->data_pending = 0; +	priv->response_length = 0;  }  int __init tpm_dev_common_init(void) diff --git a/drivers/char/tpm/tpm-dev.h b/drivers/char/tpm/tpm-dev.h index a126b575cb8c..1089fc0bb290 100644 --- a/drivers/char/tpm/tpm-dev.h +++ b/drivers/char/tpm/tpm-dev.h @@ -9,14 +9,13 @@ struct file_priv {  	struct tpm_chip *chip;  	struct tpm_space *space; -	/* Holds the amount of data passed or an error code from async op */ -	ssize_t data_pending;  	struct mutex buffer_mutex; -  	struct timer_list user_read_timer;      /* user needs to claim result */  	struct work_struct timeout_work;  	struct work_struct async_work;  	wait_queue_head_t async_wait; +	size_t response_length; +	bool response_read;  	bool command_enqueued;  	u8 data_buffer[TPM_BUFSIZE]; diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 129f640424b7..d9439f9abe78 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -33,297 +33,32 @@  #include "tpm.h" -#define TPM_MAX_ORDINAL 243 -#define TSC_MAX_ORDINAL 12 -#define TPM_PROTECTED_COMMAND 0x00 -#define TPM_CONNECTION_COMMAND 0x40 -  /*   * Bug workaround - some TPM's don't flush the most   * recently changed pcr on suspend, so force the flush   * with an extend to the selected _unused_ non-volatile pcr.   */ -static int tpm_suspend_pcr; +static u32 tpm_suspend_pcr;  module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);  MODULE_PARM_DESC(suspend_pcr,  		 "PCR to use for dummy writes to facilitate flush on suspend."); -/* - * Array with one entry per ordinal defining the maximum amount - * of time the chip could take to return the result.  The ordinal - * designation of short, medium or long is defined in a table in - * TCG Specification TPM Main Part 2 TPM Structures Section 17. The - * values of the SHORT, MEDIUM, and LONG durations are retrieved - * from the chip during initialization with a call to tpm_get_timeouts. - */ -static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { -	TPM_UNDEFINED,		/* 0 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 5 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 10 */ -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_LONG, -	TPM_LONG, -	TPM_MEDIUM,		/* 15 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_LONG, -	TPM_SHORT,		/* 20 */ -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_SHORT,		/* 25 */ -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_SHORT, -	TPM_SHORT, -	TPM_MEDIUM,		/* 30 */ -	TPM_LONG, -	TPM_MEDIUM, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT,		/* 35 */ -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_MEDIUM,		/* 40 */ -	TPM_LONG, -	TPM_MEDIUM, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT,		/* 45 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_LONG, -	TPM_MEDIUM,		/* 50 */ -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 55 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_MEDIUM,		/* 60 */ -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_SHORT, -	TPM_SHORT, -	TPM_MEDIUM,		/* 65 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 70 */ -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 75 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_LONG,		/* 80 */ -	TPM_UNDEFINED, -	TPM_MEDIUM, -	TPM_LONG, -	TPM_SHORT, -	TPM_UNDEFINED,		/* 85 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 90 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED,		/* 95 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_MEDIUM,		/* 100 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 105 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 110 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT,		/* 115 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_LONG,		/* 120 */ -	TPM_LONG, -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_SHORT, -	TPM_SHORT,		/* 125 */ -	TPM_SHORT, -	TPM_LONG, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT,		/* 130 */ -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_UNDEFINED,		/* 135 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 140 */ -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 145 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 150 */ -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED,		/* 155 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 160 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 165 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_LONG,		/* 170 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 175 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_MEDIUM,		/* 180 */ -	TPM_SHORT, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_MEDIUM,		/* 185 */ -	TPM_SHORT, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 190 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 195 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 200 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT, -	TPM_SHORT,		/* 205 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_MEDIUM,		/* 210 */ -	TPM_UNDEFINED, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_MEDIUM, -	TPM_UNDEFINED,		/* 215 */ -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT, -	TPM_SHORT,		/* 220 */ -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_SHORT, -	TPM_UNDEFINED,		/* 225 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 230 */ -	TPM_LONG, -	TPM_MEDIUM, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED,		/* 235 */ -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_UNDEFINED, -	TPM_SHORT,		/* 240 */ -	TPM_UNDEFINED, -	TPM_MEDIUM, -}; - -/* - * Returns max number of jiffies to wait +/** + * tpm_calc_ordinal_duration() - calculate the maximum command duration + * @chip:    TPM chip to use. + * @ordinal: TPM command ordinal. + * + * The function returns the maximum amount of time the chip could take + * to return the result for a particular ordinal in jiffies. + * + * Return: A maximal duration time for an ordinal in jiffies.   */ -unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, -					   u32 ordinal) +unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)  { -	int duration_idx = TPM_UNDEFINED; -	int duration = 0; - -	/* -	 * We only have a duration table for protected commands, where the upper -	 * 16 bits are 0. For the few other ordinals the fallback will be used. -	 */ -	if (ordinal < TPM_MAX_ORDINAL) -		duration_idx = tpm_ordinal_duration[ordinal]; - -	if (duration_idx != TPM_UNDEFINED) -		duration = chip->duration[duration_idx]; -	if (duration <= 0) -		return 2 * 60 * HZ; +	if (chip->flags & TPM_CHIP_FLAG_TPM2) +		return tpm2_calc_ordinal_duration(chip, ordinal);  	else -		return duration; +		return tpm1_calc_ordinal_duration(chip, ordinal);  }  EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); @@ -477,13 +212,15 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip,  	if (need_locality) {  		rc = tpm_request_locality(chip, flags); -		if (rc < 0) -			goto out_no_locality; +		if (rc < 0) { +			need_locality = false; +			goto out_locality; +		}  	}  	rc = tpm_cmd_ready(chip, flags);  	if (rc) -		goto out; +		goto out_locality;  	rc = tpm2_prepare_space(chip, space, ordinal, buf);  	if (rc) @@ -500,10 +237,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip,  	if (chip->flags & TPM_CHIP_FLAG_IRQ)  		goto out_recv; -	if (chip->flags & TPM_CHIP_FLAG_TPM2) -		stop = jiffies + tpm2_calc_ordinal_duration(chip, ordinal); -	else -		stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); +	stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);  	do {  		u8 status = chip->ops->status(chip);  		if ((status & chip->ops->req_complete_mask) == @@ -547,14 +281,13 @@ out_recv:  		dev_err(&chip->dev, "tpm2_commit_space: error %d\n", rc);  out: -	rc = tpm_go_idle(chip, flags); -	if (rc) -		goto out; +	/* may fail but do not override previous error value in rc */ +	tpm_go_idle(chip, flags); +out_locality:  	if (need_locality)  		tpm_relinquish_locality(chip, flags); -out_no_locality:  	if (chip->ops->clk_enable != NULL)  		chip->ops->clk_enable(chip, false); @@ -677,277 +410,18 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,  }  EXPORT_SYMBOL_GPL(tpm_transmit_cmd); -#define TPM_ORD_STARTUP 153 -#define TPM_ST_CLEAR 1 - -/** - * tpm_startup - turn on the TPM - * @chip: TPM chip to use - * - * Normally the firmware should start the TPM. This function is provided as a - * workaround if this does not happen. A legal case for this could be for - * example when a TPM emulator is used. - * - * Return: same as tpm_transmit_cmd() - */ -int tpm_startup(struct tpm_chip *chip) -{ -	struct tpm_buf buf; -	int rc; - -	dev_info(&chip->dev, "starting up the TPM manually\n"); - -	if (chip->flags & TPM_CHIP_FLAG_TPM2) { -		rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP); -		if (rc < 0) -			return rc; - -		tpm_buf_append_u16(&buf, TPM2_SU_CLEAR); -	} else { -		rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP); -		if (rc < 0) -			return rc; - -		tpm_buf_append_u16(&buf, TPM_ST_CLEAR); -	} - -	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, -			      "attempting to start the TPM"); - -	tpm_buf_destroy(&buf); -	return rc; -} - -#define TPM_DIGEST_SIZE 20 -#define TPM_RET_CODE_IDX 6 -#define TPM_INTERNAL_RESULT_SIZE 200 -#define TPM_ORD_GET_CAP 101 -#define TPM_ORD_GET_RANDOM 70 - -static const struct tpm_input_header tpm_getcap_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(22), -	.ordinal = cpu_to_be32(TPM_ORD_GET_CAP) -}; - -ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, -		   const char *desc, size_t min_cap_length) -{ -	struct tpm_buf buf; -	int rc; - -	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP); -	if (rc) -		return rc; - -	if (subcap_id == TPM_CAP_VERSION_1_1 || -	    subcap_id == TPM_CAP_VERSION_1_2) { -		tpm_buf_append_u32(&buf, subcap_id); -		tpm_buf_append_u32(&buf, 0); -	} else { -		if (subcap_id == TPM_CAP_FLAG_PERM || -		    subcap_id == TPM_CAP_FLAG_VOL) -			tpm_buf_append_u32(&buf, TPM_CAP_FLAG); -		else -			tpm_buf_append_u32(&buf, TPM_CAP_PROP); - -		tpm_buf_append_u32(&buf, 4); -		tpm_buf_append_u32(&buf, subcap_id); -	} -	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, -			      min_cap_length, 0, desc); -	if (!rc) -		*cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4]; - -	tpm_buf_destroy(&buf); -	return rc; -} -EXPORT_SYMBOL_GPL(tpm_getcap); -  int tpm_get_timeouts(struct tpm_chip *chip)  { -	cap_t cap; -	unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4]; -	ssize_t rc; -  	if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS)  		return 0; -	if (chip->flags & TPM_CHIP_FLAG_TPM2) { -		/* Fixed timeouts for TPM2 */ -		chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); -		chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B); -		chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C); -		chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D); -		chip->duration[TPM_SHORT] = -		    msecs_to_jiffies(TPM2_DURATION_SHORT); -		chip->duration[TPM_MEDIUM] = -		    msecs_to_jiffies(TPM2_DURATION_MEDIUM); -		chip->duration[TPM_LONG] = -		    msecs_to_jiffies(TPM2_DURATION_LONG); -		chip->duration[TPM_LONG_LONG] = -		    msecs_to_jiffies(TPM2_DURATION_LONG_LONG); - -		chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; -		return 0; -	} - -	rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL, -			sizeof(cap.timeout)); -	if (rc == TPM_ERR_INVALID_POSTINIT) { -		if (tpm_startup(chip)) -			return rc; - -		rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, -				"attempting to determine the timeouts", -				sizeof(cap.timeout)); -	} - -	if (rc) { -		dev_err(&chip->dev, -			"A TPM error (%zd) occurred attempting to determine the timeouts\n", -			rc); -		return rc; -	} - -	timeout_old[0] = jiffies_to_usecs(chip->timeout_a); -	timeout_old[1] = jiffies_to_usecs(chip->timeout_b); -	timeout_old[2] = jiffies_to_usecs(chip->timeout_c); -	timeout_old[3] = jiffies_to_usecs(chip->timeout_d); -	timeout_chip[0] = be32_to_cpu(cap.timeout.a); -	timeout_chip[1] = be32_to_cpu(cap.timeout.b); -	timeout_chip[2] = be32_to_cpu(cap.timeout.c); -	timeout_chip[3] = be32_to_cpu(cap.timeout.d); -	memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff)); - -	/* -	 * Provide ability for vendor overrides of timeout values in case -	 * of misreporting. -	 */ -	if (chip->ops->update_timeouts != NULL) -		chip->timeout_adjusted = -			chip->ops->update_timeouts(chip, timeout_eff); - -	if (!chip->timeout_adjusted) { -		/* Restore default if chip reported 0 */ -		int i; - -		for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) { -			if (timeout_eff[i]) -				continue; - -			timeout_eff[i] = timeout_old[i]; -			chip->timeout_adjusted = true; -		} - -		if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) { -			/* timeouts in msec rather usec */ -			for (i = 0; i != ARRAY_SIZE(timeout_eff); i++) -				timeout_eff[i] *= 1000; -			chip->timeout_adjusted = true; -		} -	} - -	/* Report adjusted timeouts */ -	if (chip->timeout_adjusted) { -		dev_info(&chip->dev, -			 HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", -			 timeout_chip[0], timeout_eff[0], -			 timeout_chip[1], timeout_eff[1], -			 timeout_chip[2], timeout_eff[2], -			 timeout_chip[3], timeout_eff[3]); -	} - -	chip->timeout_a = usecs_to_jiffies(timeout_eff[0]); -	chip->timeout_b = usecs_to_jiffies(timeout_eff[1]); -	chip->timeout_c = usecs_to_jiffies(timeout_eff[2]); -	chip->timeout_d = usecs_to_jiffies(timeout_eff[3]); - -	rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap, -			"attempting to determine the durations", -			sizeof(cap.duration)); -	if (rc) -		return rc; - -	chip->duration[TPM_SHORT] = -		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_short)); -	chip->duration[TPM_MEDIUM] = -		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium)); -	chip->duration[TPM_LONG] = -		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long)); -	chip->duration[TPM_LONG_LONG] = 0; /* not used under 1.2 */ - -	/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above -	 * value wrong and apparently reports msecs rather than usecs. So we -	 * fix up the resulting too-small TPM_SHORT value to make things work. -	 * We also scale the TPM_MEDIUM and -_LONG values by 1000. -	 */ -	if (chip->duration[TPM_SHORT] < (HZ / 100)) { -		chip->duration[TPM_SHORT] = HZ; -		chip->duration[TPM_MEDIUM] *= 1000; -		chip->duration[TPM_LONG] *= 1000; -		chip->duration_adjusted = true; -		dev_info(&chip->dev, "Adjusting TPM timeout parameters."); -	} - -	chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; -	return 0; +	if (chip->flags & TPM_CHIP_FLAG_TPM2) +		return tpm2_get_timeouts(chip); +	else +		return tpm1_get_timeouts(chip);  }  EXPORT_SYMBOL_GPL(tpm_get_timeouts); -#define TPM_ORD_CONTINUE_SELFTEST 83 -#define CONTINUE_SELFTEST_RESULT_SIZE 10 - -static const struct tpm_input_header continue_selftest_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(10), -	.ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), -}; - -/** - * tpm_continue_selftest -- run TPM's selftest - * @chip: TPM chip to use - * - * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing - * a TPM error code. - */ -static int tpm_continue_selftest(struct tpm_chip *chip) -{ -	int rc; -	struct tpm_cmd_t cmd; - -	cmd.header.in = continue_selftest_header; -	rc = tpm_transmit_cmd(chip, NULL, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, -			      0, 0, "continue selftest"); -	return rc; -} - -#define TPM_ORDINAL_PCRREAD 21 -#define READ_PCR_RESULT_SIZE 30 -#define READ_PCR_RESULT_BODY_SIZE 20 -static const struct tpm_input_header pcrread_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(14), -	.ordinal = cpu_to_be32(TPM_ORDINAL_PCRREAD) -}; - -int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) -{ -	int rc; -	struct tpm_cmd_t cmd; - -	cmd.header.in = pcrread_header; -	cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); -	rc = tpm_transmit_cmd(chip, NULL, &cmd, READ_PCR_RESULT_SIZE, -			      READ_PCR_RESULT_BODY_SIZE, 0, -			      "attempting to read a pcr value"); - -	if (rc == 0) -		memcpy(res_buf, cmd.params.pcrread_out.pcr_result, -		       TPM_DIGEST_SIZE); -	return rc; -} -  /**   * tpm_is_tpm2 - do we a have a TPM2 chip?   * @chip:	a &struct tpm_chip instance, %NULL for the default chip @@ -981,50 +455,24 @@ EXPORT_SYMBOL_GPL(tpm_is_tpm2);   *   * Return: same as with tpm_transmit_cmd()   */ -int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) +int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf)  {  	int rc;  	chip = tpm_find_get_ops(chip);  	if (!chip)  		return -ENODEV; +  	if (chip->flags & TPM_CHIP_FLAG_TPM2)  		rc = tpm2_pcr_read(chip, pcr_idx, res_buf);  	else -		rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf); +		rc = tpm1_pcr_read(chip, pcr_idx, res_buf); +  	tpm_put_ops(chip);  	return rc;  }  EXPORT_SYMBOL_GPL(tpm_pcr_read); -#define TPM_ORD_PCR_EXTEND 20 -#define EXTEND_PCR_RESULT_SIZE 34 -#define EXTEND_PCR_RESULT_BODY_SIZE 20 -static const struct tpm_input_header pcrextend_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(34), -	.ordinal = cpu_to_be32(TPM_ORD_PCR_EXTEND) -}; - -static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash, -			   char *log_msg) -{ -	struct tpm_buf buf; -	int rc; - -	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND); -	if (rc) -		return rc; - -	tpm_buf_append_u32(&buf, pcr_idx); -	tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE); - -	rc = tpm_transmit_cmd(chip, NULL, buf.data, EXTEND_PCR_RESULT_SIZE, -			      EXTEND_PCR_RESULT_BODY_SIZE, 0, log_msg); -	tpm_buf_destroy(&buf); -	return rc; -} -  /**   * tpm_pcr_extend - extend a PCR value in SHA1 bank.   * @chip:	a &struct tpm_chip instance, %NULL for the default chip @@ -1037,7 +485,7 @@ static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,   *   * Return: same as with tpm_transmit_cmd()   */ -int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) +int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash)  {  	int rc;  	struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)]; @@ -1071,97 +519,6 @@ int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)  EXPORT_SYMBOL_GPL(tpm_pcr_extend);  /** - * tpm_do_selftest - have the TPM continue its selftest and wait until it - *                   can receive further commands - * @chip: TPM chip to use - * - * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing - * a TPM error code. - */ -int tpm_do_selftest(struct tpm_chip *chip) -{ -	int rc; -	unsigned int loops; -	unsigned int delay_msec = 100; -	unsigned long duration; -	u8 dummy[TPM_DIGEST_SIZE]; - -	duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST); - -	loops = jiffies_to_msecs(duration) / delay_msec; - -	rc = tpm_continue_selftest(chip); -	if (rc == TPM_ERR_INVALID_POSTINIT) { -		chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; -		dev_info(&chip->dev, "TPM not ready (%d)\n", rc); -	} -	/* This may fail if there was no TPM driver during a suspend/resume -	 * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) -	 */ -	if (rc) -		return rc; - -	do { -		/* Attempt to read a PCR value */ -		rc = tpm_pcr_read_dev(chip, 0, dummy); - -		/* Some buggy TPMs will not respond to tpm_tis_ready() for -		 * around 300ms while the self test is ongoing, keep trying -		 * until the self test duration expires. */ -		if (rc == -ETIME) { -			dev_info( -			    &chip->dev, HW_ERR -			    "TPM command timed out during continue self test"); -			tpm_msleep(delay_msec); -			continue; -		} - -		if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { -			dev_info(&chip->dev, -				 "TPM is disabled/deactivated (0x%X)\n", rc); -			/* TPM is disabled and/or deactivated; driver can -			 * proceed and TPM does handle commands for -			 * suspend/resume correctly -			 */ -			return 0; -		} -		if (rc != TPM_WARN_DOING_SELFTEST) -			return rc; -		tpm_msleep(delay_msec); -	} while (--loops > 0); - -	return rc; -} -EXPORT_SYMBOL_GPL(tpm_do_selftest); - -/** - * tpm1_auto_startup - Perform the standard automatic TPM initialization - *                     sequence - * @chip: TPM chip to use - * - * Returns 0 on success, < 0 in case of fatal error. - */ -int tpm1_auto_startup(struct tpm_chip *chip) -{ -	int rc; - -	rc = tpm_get_timeouts(chip); -	if (rc) -		goto out; -	rc = tpm_do_selftest(chip); -	if (rc) { -		dev_err(&chip->dev, "TPM self test failed\n"); -		goto out; -	} - -	return rc; -out: -	if (rc > 0) -		rc = -ENODEV; -	return rc; -} - -/**   * tpm_send - send a TPM command   * @chip:	a &struct tpm_chip instance, %NULL for the default chip   * @cmd:	a TPM command buffer @@ -1184,14 +541,20 @@ int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)  }  EXPORT_SYMBOL_GPL(tpm_send); -#define TPM_ORD_SAVESTATE 152 -#define SAVESTATE_RESULT_SIZE 10 +int tpm_auto_startup(struct tpm_chip *chip) +{ +	int rc; -static const struct tpm_input_header savestate_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(10), -	.ordinal = cpu_to_be32(TPM_ORD_SAVESTATE) -}; +	if (!(chip->ops->flags & TPM_OPS_AUTO_STARTUP)) +		return 0; + +	if (chip->flags & TPM_CHIP_FLAG_TPM2) +		rc = tpm2_auto_startup(chip); +	else +		rc = tpm1_auto_startup(chip); + +	return rc; +}  /*   * We are about to suspend. Save the TPM state @@ -1200,54 +563,18 @@ static const struct tpm_input_header savestate_header = {  int tpm_pm_suspend(struct device *dev)  {  	struct tpm_chip *chip = dev_get_drvdata(dev); -	struct tpm_cmd_t cmd; -	int rc, try; +	int rc = 0; -	u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; - -	if (chip == NULL) +	if (!chip)  		return -ENODEV;  	if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)  		return 0; -	if (chip->flags & TPM_CHIP_FLAG_TPM2) { +	if (chip->flags & TPM_CHIP_FLAG_TPM2)  		tpm2_shutdown(chip, TPM2_SU_STATE); -		return 0; -	} - -	/* for buggy tpm, flush pcrs with extend to selected dummy */ -	if (tpm_suspend_pcr) -		rc = tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash, -				     "extending dummy pcr before suspend"); - -	/* now do the actual savestate */ -	for (try = 0; try < TPM_RETRY; try++) { -		cmd.header.in = savestate_header; -		rc = tpm_transmit_cmd(chip, NULL, &cmd, SAVESTATE_RESULT_SIZE, -				      0, 0, NULL); - -		/* -		 * If the TPM indicates that it is too busy to respond to -		 * this command then retry before giving up.  It can take -		 * several seconds for this TPM to be ready. -		 * -		 * This can happen if the TPM has already been sent the -		 * SaveState command before the driver has loaded.  TCG 1.2 -		 * specification states that any communication after SaveState -		 * may cause the TPM to invalidate previously saved state. -		 */ -		if (rc != TPM_WARN_RETRY) -			break; -		tpm_msleep(TPM_TIMEOUT_RETRY); -	} - -	if (rc) -		dev_err(&chip->dev, -			"Error (%d) sending savestate before suspend\n", rc); -	else if (try > 0) -		dev_warn(&chip->dev, "TPM savestate took %dms\n", -			 try * TPM_TIMEOUT_RETRY); +	else +		rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);  	return rc;  } @@ -1268,75 +595,32 @@ int tpm_pm_resume(struct device *dev)  }  EXPORT_SYMBOL_GPL(tpm_pm_resume); -#define TPM_GETRANDOM_RESULT_SIZE	18 -static const struct tpm_input_header tpm_getrandom_header = { -	.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), -	.length = cpu_to_be32(14), -	.ordinal = cpu_to_be32(TPM_ORD_GET_RANDOM) -}; -  /**   * tpm_get_random() - get random bytes from the TPM's RNG   * @chip:	a &struct tpm_chip instance, %NULL for the default chip   * @out:	destination buffer for the random bytes   * @max:	the max number of bytes to write to @out   * - * Return: same as with tpm_transmit_cmd() + * Return: number of random bytes read or a negative error value.   */  int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)  { -	struct tpm_cmd_t tpm_cmd; -	u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA), rlength; -	int err, total = 0, retries = 5; -	u8 *dest = out; +	int rc; -	if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) +	if (!out || max > TPM_MAX_RNG_DATA)  		return -EINVAL;  	chip = tpm_find_get_ops(chip);  	if (!chip)  		return -ENODEV; -	if (chip->flags & TPM_CHIP_FLAG_TPM2) { -		err = tpm2_get_random(chip, out, max); -		tpm_put_ops(chip); -		return err; -	} - -	do { -		tpm_cmd.header.in = tpm_getrandom_header; -		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); - -		err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, -				       TPM_GETRANDOM_RESULT_SIZE + num_bytes, -				       offsetof(struct tpm_getrandom_out, -						rng_data), -				       0, "attempting get random"); -		if (err) -			break; - -		recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len); -		if (recd > num_bytes) { -			total = -EFAULT; -			break; -		} - -		rlength = be32_to_cpu(tpm_cmd.header.out.length); -		if (rlength < TPM_HEADER_SIZE + -			      offsetof(struct tpm_getrandom_out, rng_data) + -			      recd) { -			total = -EFAULT; -			break; -		} -		memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd); - -		dest += recd; -		total += recd; -		num_bytes -= recd; -	} while (retries-- && total < max); +	if (chip->flags & TPM_CHIP_FLAG_TPM2) +		rc = tpm2_get_random(chip, out, max); +	else +		rc = tpm1_get_random(chip, out, max);  	tpm_put_ops(chip); -	return total ? total : -EIO; +	return rc;  }  EXPORT_SYMBOL_GPL(tpm_get_random); diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 83a77a445538..b88e08ec2c59 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c @@ -102,19 +102,19 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,  	cap_t cap;  	u8 digest[TPM_DIGEST_SIZE];  	ssize_t rc; -	int i, j, num_pcrs; +	u32 i, j, num_pcrs;  	char *str = buf;  	struct tpm_chip *chip = to_tpm_chip(dev); -	rc = tpm_getcap(chip, TPM_CAP_PROP_PCR, &cap, -			"attempting to determine the number of PCRS", -			sizeof(cap.num_pcrs)); +	rc = tpm1_getcap(chip, TPM_CAP_PROP_PCR, &cap, +			 "attempting to determine the number of PCRS", +			 sizeof(cap.num_pcrs));  	if (rc)  		return 0;  	num_pcrs = be32_to_cpu(cap.num_pcrs);  	for (i = 0; i < num_pcrs; i++) { -		rc = tpm_pcr_read_dev(chip, i, digest); +		rc = tpm1_pcr_read(chip, i, digest);  		if (rc)  			break;  		str += sprintf(str, "PCR-%02d: ", i); @@ -132,9 +132,9 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,  	cap_t cap;  	ssize_t rc; -	rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, -			"attempting to determine the permanent enabled state", -			sizeof(cap.perm_flags)); +	rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, +			 "attempting to determine the permanent enabled state", +			 sizeof(cap.perm_flags));  	if (rc)  		return 0; @@ -149,9 +149,9 @@ static ssize_t active_show(struct device *dev, struct device_attribute *attr,  	cap_t cap;  	ssize_t rc; -	rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, -			"attempting to determine the permanent active state", -			sizeof(cap.perm_flags)); +	rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, +			 "attempting to determine the permanent active state", +			 sizeof(cap.perm_flags));  	if (rc)  		return 0; @@ -166,9 +166,9 @@ static ssize_t owned_show(struct device *dev, struct device_attribute *attr,  	cap_t cap;  	ssize_t rc; -	rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap, -			"attempting to determine the owner state", -			sizeof(cap.owned)); +	rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap, +			 "attempting to determine the owner state", +			 sizeof(cap.owned));  	if (rc)  		return 0; @@ -183,9 +183,9 @@ static ssize_t temp_deactivated_show(struct device *dev,  	cap_t cap;  	ssize_t rc; -	rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap, -			"attempting to determine the temporary state", -			sizeof(cap.stclear_flags)); +	rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap, +			 "attempting to determine the temporary state", +			 sizeof(cap.stclear_flags));  	if (rc)  		return 0; @@ -202,18 +202,18 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,  	ssize_t rc;  	char *str = buf; -	rc = tpm_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap, -			"attempting to determine the manufacturer", -			sizeof(cap.manufacturer_id)); +	rc = tpm1_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap, +			 "attempting to determine the manufacturer", +			 sizeof(cap.manufacturer_id));  	if (rc)  		return 0;  	str += sprintf(str, "Manufacturer: 0x%x\n",  		       be32_to_cpu(cap.manufacturer_id));  	/* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */ -	rc = tpm_getcap(chip, TPM_CAP_VERSION_1_2, &cap, -			"attempting to determine the 1.2 version", -			sizeof(cap.tpm_version_1_2)); +	rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_2, &cap, +			 "attempting to determine the 1.2 version", +			 sizeof(cap.tpm_version_1_2));  	if (!rc) {  		str += sprintf(str,  			       "TCG version: %d.%d\nFirmware version: %d.%d\n", @@ -223,9 +223,9 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,  			       cap.tpm_version_1_2.revMinor);  	} else {  		/* Otherwise just use TPM_STRUCT_VER */ -		rc = tpm_getcap(chip, TPM_CAP_VERSION_1_1, &cap, -				"attempting to determine the 1.1 version", -				sizeof(cap.tpm_version)); +		rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap, +				 "attempting to determine the 1.1 version", +				 sizeof(cap.tpm_version));  		if (rc)  			return 0;  		str += sprintf(str, diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index f20dc8ece348..f27d1f38a93d 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -134,22 +134,31 @@ enum tpm2_algorithms {  };  enum tpm2_command_codes { -	TPM2_CC_FIRST		= 0x011F, -	TPM2_CC_CREATE_PRIMARY  = 0x0131, -	TPM2_CC_SELF_TEST	= 0x0143, -	TPM2_CC_STARTUP		= 0x0144, -	TPM2_CC_SHUTDOWN	= 0x0145, -	TPM2_CC_CREATE		= 0x0153, -	TPM2_CC_LOAD		= 0x0157, -	TPM2_CC_UNSEAL		= 0x015E, -	TPM2_CC_CONTEXT_LOAD	= 0x0161, -	TPM2_CC_CONTEXT_SAVE	= 0x0162, -	TPM2_CC_FLUSH_CONTEXT	= 0x0165, -	TPM2_CC_GET_CAPABILITY	= 0x017A, -	TPM2_CC_GET_RANDOM	= 0x017B, -	TPM2_CC_PCR_READ	= 0x017E, -	TPM2_CC_PCR_EXTEND	= 0x0182, -	TPM2_CC_LAST		= 0x018F, +	TPM2_CC_FIRST		        = 0x011F, +	TPM2_CC_HIERARCHY_CONTROL       = 0x0121, +	TPM2_CC_HIERARCHY_CHANGE_AUTH   = 0x0129, +	TPM2_CC_CREATE_PRIMARY          = 0x0131, +	TPM2_CC_SEQUENCE_COMPLETE       = 0x013E, +	TPM2_CC_SELF_TEST	        = 0x0143, +	TPM2_CC_STARTUP		        = 0x0144, +	TPM2_CC_SHUTDOWN	        = 0x0145, +	TPM2_CC_NV_READ                 = 0x014E, +	TPM2_CC_CREATE		        = 0x0153, +	TPM2_CC_LOAD		        = 0x0157, +	TPM2_CC_SEQUENCE_UPDATE         = 0x015C, +	TPM2_CC_UNSEAL		        = 0x015E, +	TPM2_CC_CONTEXT_LOAD	        = 0x0161, +	TPM2_CC_CONTEXT_SAVE	        = 0x0162, +	TPM2_CC_FLUSH_CONTEXT	        = 0x0165, +	TPM2_CC_VERIFY_SIGNATURE        = 0x0177, +	TPM2_CC_GET_CAPABILITY	        = 0x017A, +	TPM2_CC_GET_RANDOM	        = 0x017B, +	TPM2_CC_PCR_READ	        = 0x017E, +	TPM2_CC_PCR_EXTEND	        = 0x0182, +	TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185, +	TPM2_CC_HASH_SEQUENCE_START     = 0x0186, +	TPM2_CC_CREATE_LOADED           = 0x0191, +	TPM2_CC_LAST		        = 0x0193, /* Spec 1.36 */  };  enum tpm2_permanent_handles { @@ -368,18 +377,6 @@ enum tpm_sub_capabilities {  	TPM_CAP_PROP_TIS_DURATION = 0x120,  }; -typedef union { -	struct	tpm_input_header in; -	struct	tpm_output_header out; -} tpm_cmd_header; - -struct tpm_pcrread_out { -	u8	pcr_result[TPM_DIGEST_SIZE]; -} __packed; - -struct tpm_pcrread_in { -	__be32	pcr_idx; -} __packed;  /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18   * bytes, but 128 is still a relatively large number of random bytes and @@ -387,28 +384,6 @@ struct tpm_pcrread_in {   * compiler warnings about stack frame size. */  #define TPM_MAX_RNG_DATA	128 -struct tpm_getrandom_out { -	__be32 rng_data_len; -	u8     rng_data[TPM_MAX_RNG_DATA]; -} __packed; - -struct tpm_getrandom_in { -	__be32 num_bytes; -} __packed; - -typedef union { -	struct	tpm_pcrread_in	pcrread_in; -	struct	tpm_pcrread_out	pcrread_out; -	struct	tpm_getrandom_in getrandom_in; -	struct	tpm_getrandom_out getrandom_out; -} tpm_cmd_params; - -struct tpm_cmd_t { -	tpm_cmd_header	header; -	tpm_cmd_params	params; -} __packed; - -  /* A string buffer type for constructing TPM commands. This is based on the   * ideas of string buffer code in security/keys/trusted.h but is heap based   * in order to keep the stack usage minimal. @@ -531,12 +506,20 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,  			 void *buf, size_t bufsiz,  			 size_t min_rsp_body_length, unsigned int flags,  			 const char *desc); -int tpm_startup(struct tpm_chip *chip); -ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, -		   const char *desc, size_t min_cap_length);  int tpm_get_timeouts(struct tpm_chip *); +int tpm_auto_startup(struct tpm_chip *chip); + +int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr);  int tpm1_auto_startup(struct tpm_chip *chip); -int tpm_do_selftest(struct tpm_chip *chip); +int tpm1_do_selftest(struct tpm_chip *chip); +int tpm1_get_timeouts(struct tpm_chip *chip); +unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); +int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash, +		    const char *log_msg); +int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf); +ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, +		    const char *desc, size_t min_cap_length); +int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max);  unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);  int tpm_pm_suspend(struct device *dev);  int tpm_pm_resume(struct device *dev); @@ -560,7 +543,6 @@ void tpm_chip_unregister(struct tpm_chip *chip);  void tpm_sysfs_add_device(struct tpm_chip *chip); -int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);  #ifdef CONFIG_ACPI  extern void tpm_add_ppi(struct tpm_chip *chip); @@ -575,8 +557,9 @@ static inline u32 tpm2_rc_value(u32 rc)  	return (rc & BIT(7)) ? rc & 0xff : rc;  } -int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); -int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, +int tpm2_get_timeouts(struct tpm_chip *chip); +int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf); +int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, u32 count,  		    struct tpm2_digest *digests);  int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max);  void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c new file mode 100644 index 000000000000..6f306338953b --- /dev/null +++ b/drivers/char/tpm/tpm1-cmd.c @@ -0,0 +1,781 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2004 IBM Corporation + * Copyright (C) 2014 Intel Corporation + * + * Authors: + * Leendert van Doorn <leendert@watson.ibm.com> + * Dave Safford <safford@watson.ibm.com> + * Reiner Sailer <sailer@watson.ibm.com> + * Kylene Hall <kjhall@us.ibm.com> + * + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + */ + +#include <linux/poll.h> +#include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/spinlock.h> +#include <linux/freezer.h> +#include <linux/tpm_eventlog.h> + +#include "tpm.h" + +#define TPM_MAX_ORDINAL 243 + +/* + * Array with one entry per ordinal defining the maximum amount + * of time the chip could take to return the result.  The ordinal + * designation of short, medium or long is defined in a table in + * TCG Specification TPM Main Part 2 TPM Structures Section 17. The + * values of the SHORT, MEDIUM, and LONG durations are retrieved + * from the chip during initialization with a call to tpm_get_timeouts. + */ +static const u8 tpm1_ordinal_duration[TPM_MAX_ORDINAL] = { +	TPM_UNDEFINED,		/* 0 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED,		/* 5 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT,		/* 10 */ +	TPM_SHORT, +	TPM_MEDIUM, +	TPM_LONG, +	TPM_LONG, +	TPM_MEDIUM,		/* 15 */ +	TPM_SHORT, +	TPM_SHORT, +	TPM_MEDIUM, +	TPM_LONG, +	TPM_SHORT,		/* 20 */ +	TPM_SHORT, +	TPM_MEDIUM, +	TPM_MEDIUM, +	TPM_MEDIUM, +	TPM_SHORT,		/* 25 */ +	TPM_SHORT, +	TPM_MEDIUM, +	TPM_SHORT, +	TPM_SHORT, +	TPM_MEDIUM,		/* 30 */ +	TPM_LONG, +	TPM_MEDIUM, +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT,		/* 35 */ +	TPM_MEDIUM, +	TPM_MEDIUM, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_MEDIUM,		/* 40 */ +	TPM_LONG, +	TPM_MEDIUM, +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT,		/* 45 */ +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT, +	TPM_LONG, +	TPM_MEDIUM,		/* 50 */ +	TPM_MEDIUM, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED,		/* 55 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_MEDIUM,		/* 60 */ +	TPM_MEDIUM, +	TPM_MEDIUM, +	TPM_SHORT, +	TPM_SHORT, +	TPM_MEDIUM,		/* 65 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT,		/* 70 */ +	TPM_SHORT, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED,		/* 75 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_LONG,		/* 80 */ +	TPM_UNDEFINED, +	TPM_MEDIUM, +	TPM_LONG, +	TPM_SHORT, +	TPM_UNDEFINED,		/* 85 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT,		/* 90 */ +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT, +	TPM_UNDEFINED,		/* 95 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_MEDIUM,		/* 100 */ +	TPM_SHORT, +	TPM_SHORT, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED,		/* 105 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT,		/* 110 */ +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT,		/* 115 */ +	TPM_SHORT, +	TPM_SHORT, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_LONG,		/* 120 */ +	TPM_LONG, +	TPM_MEDIUM, +	TPM_UNDEFINED, +	TPM_SHORT, +	TPM_SHORT,		/* 125 */ +	TPM_SHORT, +	TPM_LONG, +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT,		/* 130 */ +	TPM_MEDIUM, +	TPM_UNDEFINED, +	TPM_SHORT, +	TPM_MEDIUM, +	TPM_UNDEFINED,		/* 135 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT,		/* 140 */ +	TPM_SHORT, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED,		/* 145 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT,		/* 150 */ +	TPM_MEDIUM, +	TPM_MEDIUM, +	TPM_SHORT, +	TPM_SHORT, +	TPM_UNDEFINED,		/* 155 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT,		/* 160 */ +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT, +	TPM_UNDEFINED, +	TPM_UNDEFINED,		/* 165 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_LONG,		/* 170 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED,		/* 175 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_MEDIUM,		/* 180 */ +	TPM_SHORT, +	TPM_MEDIUM, +	TPM_MEDIUM, +	TPM_MEDIUM, +	TPM_MEDIUM,		/* 185 */ +	TPM_SHORT, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED,		/* 190 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED,		/* 195 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT,		/* 200 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT, +	TPM_SHORT,		/* 205 */ +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT, +	TPM_MEDIUM,		/* 210 */ +	TPM_UNDEFINED, +	TPM_MEDIUM, +	TPM_MEDIUM, +	TPM_MEDIUM, +	TPM_UNDEFINED,		/* 215 */ +	TPM_MEDIUM, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT, +	TPM_SHORT,		/* 220 */ +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT, +	TPM_SHORT, +	TPM_UNDEFINED,		/* 225 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT,		/* 230 */ +	TPM_LONG, +	TPM_MEDIUM, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED,		/* 235 */ +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_UNDEFINED, +	TPM_SHORT,		/* 240 */ +	TPM_UNDEFINED, +	TPM_MEDIUM, +}; + +/** + * tpm1_calc_ordinal_duration() - calculate the maximum command duration + * @chip:    TPM chip to use. + * @ordinal: TPM command ordinal. + * + * The function returns the maximum amount of time the chip could take + * to return the result for a particular ordinal in jiffies. + * + * Return: A maximal duration time for an ordinal in jiffies. + */ +unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) +{ +	int duration_idx = TPM_UNDEFINED; +	int duration = 0; + +	/* +	 * We only have a duration table for protected commands, where the upper +	 * 16 bits are 0. For the few other ordinals the fallback will be used. +	 */ +	if (ordinal < TPM_MAX_ORDINAL) +		duration_idx = tpm1_ordinal_duration[ordinal]; + +	if (duration_idx != TPM_UNDEFINED) +		duration = chip->duration[duration_idx]; +	if (duration <= 0) +		return 2 * 60 * HZ; +	else +		return duration; +} + +#define TPM_ORD_STARTUP 153 +#define TPM_ST_CLEAR 1 + +/** + * tpm_startup() - turn on the TPM + * @chip: TPM chip to use + * + * Normally the firmware should start the TPM. This function is provided as a + * workaround if this does not happen. A legal case for this could be for + * example when a TPM emulator is used. + * + * Return: same as tpm_transmit_cmd() + */ +static int tpm1_startup(struct tpm_chip *chip) +{ +	struct tpm_buf buf; +	int rc; + +	dev_info(&chip->dev, "starting up the TPM manually\n"); + +	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP); +	if (rc < 0) +		return rc; + +	tpm_buf_append_u16(&buf, TPM_ST_CLEAR); + +	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, +			      "attempting to start the TPM"); + +	tpm_buf_destroy(&buf); + +	return rc; +} + +int tpm1_get_timeouts(struct tpm_chip *chip) +{ +	cap_t cap; +	unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4]; +	ssize_t rc; + +	rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL, +			 sizeof(cap.timeout)); +	if (rc == TPM_ERR_INVALID_POSTINIT) { +		if (tpm1_startup(chip)) +			return rc; + +		rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, +				 "attempting to determine the timeouts", +				 sizeof(cap.timeout)); +	} + +	if (rc) { +		dev_err(&chip->dev, "A TPM error (%zd) occurred attempting to determine the timeouts\n", +			rc); +		return rc; +	} + +	timeout_old[0] = jiffies_to_usecs(chip->timeout_a); +	timeout_old[1] = jiffies_to_usecs(chip->timeout_b); +	timeout_old[2] = jiffies_to_usecs(chip->timeout_c); +	timeout_old[3] = jiffies_to_usecs(chip->timeout_d); +	timeout_chip[0] = be32_to_cpu(cap.timeout.a); +	timeout_chip[1] = be32_to_cpu(cap.timeout.b); +	timeout_chip[2] = be32_to_cpu(cap.timeout.c); +	timeout_chip[3] = be32_to_cpu(cap.timeout.d); +	memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff)); + +	/* +	 * Provide ability for vendor overrides of timeout values in case +	 * of misreporting. +	 */ +	if (chip->ops->update_timeouts) +		chip->timeout_adjusted = +			chip->ops->update_timeouts(chip, timeout_eff); + +	if (!chip->timeout_adjusted) { +		/* Restore default if chip reported 0 */ +		unsigned int i; + +		for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) { +			if (timeout_eff[i]) +				continue; + +			timeout_eff[i] = timeout_old[i]; +			chip->timeout_adjusted = true; +		} + +		if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) { +			/* timeouts in msec rather usec */ +			for (i = 0; i != ARRAY_SIZE(timeout_eff); i++) +				timeout_eff[i] *= 1000; +			chip->timeout_adjusted = true; +		} +	} + +	/* Report adjusted timeouts */ +	if (chip->timeout_adjusted) { +		dev_info(&chip->dev, HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", +			 timeout_chip[0], timeout_eff[0], +			 timeout_chip[1], timeout_eff[1], +			 timeout_chip[2], timeout_eff[2], +			 timeout_chip[3], timeout_eff[3]); +	} + +	chip->timeout_a = usecs_to_jiffies(timeout_eff[0]); +	chip->timeout_b = usecs_to_jiffies(timeout_eff[1]); +	chip->timeout_c = usecs_to_jiffies(timeout_eff[2]); +	chip->timeout_d = usecs_to_jiffies(timeout_eff[3]); + +	rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap, +			 "attempting to determine the durations", +			  sizeof(cap.duration)); +	if (rc) +		return rc; + +	chip->duration[TPM_SHORT] = +		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_short)); +	chip->duration[TPM_MEDIUM] = +		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium)); +	chip->duration[TPM_LONG] = +		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long)); +	chip->duration[TPM_LONG_LONG] = 0; /* not used under 1.2 */ + +	/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above +	 * value wrong and apparently reports msecs rather than usecs. So we +	 * fix up the resulting too-small TPM_SHORT value to make things work. +	 * We also scale the TPM_MEDIUM and -_LONG values by 1000. +	 */ +	if (chip->duration[TPM_SHORT] < (HZ / 100)) { +		chip->duration[TPM_SHORT] = HZ; +		chip->duration[TPM_MEDIUM] *= 1000; +		chip->duration[TPM_LONG] *= 1000; +		chip->duration_adjusted = true; +		dev_info(&chip->dev, "Adjusting TPM timeout parameters."); +	} + +	chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; +	return 0; +} + +#define TPM_ORD_PCR_EXTEND 20 +int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash, +		    const char *log_msg) +{ +	struct tpm_buf buf; +	int rc; + +	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND); +	if (rc) +		return rc; + +	tpm_buf_append_u32(&buf, pcr_idx); +	tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE); + +	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, +			      TPM_DIGEST_SIZE, 0, log_msg); + +	tpm_buf_destroy(&buf); +	return rc; +} + +#define TPM_ORD_GET_CAP 101 +ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, +		    const char *desc, size_t min_cap_length) +{ +	struct tpm_buf buf; +	int rc; + +	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP); +	if (rc) +		return rc; + +	if (subcap_id == TPM_CAP_VERSION_1_1 || +	    subcap_id == TPM_CAP_VERSION_1_2) { +		tpm_buf_append_u32(&buf, subcap_id); +		tpm_buf_append_u32(&buf, 0); +	} else { +		if (subcap_id == TPM_CAP_FLAG_PERM || +		    subcap_id == TPM_CAP_FLAG_VOL) +			tpm_buf_append_u32(&buf, TPM_CAP_FLAG); +		else +			tpm_buf_append_u32(&buf, TPM_CAP_PROP); + +		tpm_buf_append_u32(&buf, 4); +		tpm_buf_append_u32(&buf, subcap_id); +	} +	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, +			      min_cap_length, 0, desc); +	if (!rc) +		*cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4]; + +	tpm_buf_destroy(&buf); +	return rc; +} +EXPORT_SYMBOL_GPL(tpm1_getcap); + +#define TPM_ORD_GET_RANDOM 70 +struct tpm1_get_random_out { +	__be32 rng_data_len; +	u8 rng_data[TPM_MAX_RNG_DATA]; +} __packed; + +/** + * tpm1_get_random() - get random bytes from the TPM's RNG + * @chip:	a &struct tpm_chip instance + * @dest:	destination buffer for the random bytes + * @max:	the maximum number of bytes to write to @dest + * + * Return: + * *  number of bytes read + * * -errno or a TPM return code otherwise + */ +int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max) +{ +	struct tpm1_get_random_out *out; +	u32 num_bytes =  min_t(u32, max, TPM_MAX_RNG_DATA); +	struct tpm_buf buf; +	u32 total = 0; +	int retries = 5; +	u32 recd; +	int rc; + +	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); +	if (rc) +		return rc; + +	do { +		tpm_buf_append_u32(&buf, num_bytes); + +		rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, +				      sizeof(out->rng_data_len), 0, +				      "attempting get random"); +		if (rc) +			goto out; + +		out = (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE]; + +		recd = be32_to_cpu(out->rng_data_len); +		if (recd > num_bytes) { +			rc = -EFAULT; +			goto out; +		} + +		if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + +					   sizeof(out->rng_data_len) + recd) { +			rc = -EFAULT; +			goto out; +		} +		memcpy(dest, out->rng_data, recd); + +		dest += recd; +		total += recd; +		num_bytes -= recd; + +		tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); +	} while (retries-- && total < max); + +	rc = total ? (int)total : -EIO; +out: +	tpm_buf_destroy(&buf); +	return rc; +} + +#define TPM_ORD_PCRREAD 21 +int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) +{ +	struct tpm_buf buf; +	int rc; + +	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCRREAD); +	if (rc) +		return rc; + +	tpm_buf_append_u32(&buf, pcr_idx); + +	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, +			      TPM_DIGEST_SIZE, 0, +			      "attempting to read a pcr value"); +	if (rc) +		goto out; + +	if (tpm_buf_length(&buf) < TPM_DIGEST_SIZE) { +		rc = -EFAULT; +		goto out; +	} + +	memcpy(res_buf, &buf.data[TPM_HEADER_SIZE], TPM_DIGEST_SIZE); + +out: +	tpm_buf_destroy(&buf); +	return rc; +} + +#define TPM_ORD_CONTINUE_SELFTEST 83 +/** + * tpm_continue_selftest() - run TPM's selftest + * @chip: TPM chip to use + * + * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing + * a TPM error code. + */ +static int tpm1_continue_selftest(struct tpm_chip *chip) +{ +	struct tpm_buf buf; +	int rc; + +	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST); +	if (rc) +		return rc; + +	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, +			      0, 0, "continue selftest"); + +	tpm_buf_destroy(&buf); + +	return rc; +} + +/** + * tpm1_do_selftest - have the TPM continue its selftest and wait until it + *                   can receive further commands + * @chip: TPM chip to use + * + * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing + * a TPM error code. + */ +int tpm1_do_selftest(struct tpm_chip *chip) +{ +	int rc; +	unsigned int loops; +	unsigned int delay_msec = 100; +	unsigned long duration; +	u8 dummy[TPM_DIGEST_SIZE]; + +	duration = tpm1_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST); + +	loops = jiffies_to_msecs(duration) / delay_msec; + +	rc = tpm1_continue_selftest(chip); +	if (rc == TPM_ERR_INVALID_POSTINIT) { +		chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; +		dev_info(&chip->dev, "TPM not ready (%d)\n", rc); +	} +	/* This may fail if there was no TPM driver during a suspend/resume +	 * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) +	 */ +	if (rc) +		return rc; + +	do { +		/* Attempt to read a PCR value */ +		rc = tpm1_pcr_read(chip, 0, dummy); + +		/* Some buggy TPMs will not respond to tpm_tis_ready() for +		 * around 300ms while the self test is ongoing, keep trying +		 * until the self test duration expires. +		 */ +		if (rc == -ETIME) { +			dev_info(&chip->dev, HW_ERR "TPM command timed out during continue self test"); +			tpm_msleep(delay_msec); +			continue; +		} + +		if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { +			dev_info(&chip->dev, "TPM is disabled/deactivated (0x%X)\n", +				 rc); +			/* TPM is disabled and/or deactivated; driver can +			 * proceed and TPM does handle commands for +			 * suspend/resume correctly +			 */ +			return 0; +		} +		if (rc != TPM_WARN_DOING_SELFTEST) +			return rc; +		tpm_msleep(delay_msec); +	} while (--loops > 0); + +	return rc; +} +EXPORT_SYMBOL_GPL(tpm1_do_selftest); + +/** + * tpm1_auto_startup - Perform the standard automatic TPM initialization + *                     sequence + * @chip: TPM chip to use + * + * Returns 0 on success, < 0 in case of fatal error. + */ +int tpm1_auto_startup(struct tpm_chip *chip) +{ +	int rc; + +	rc = tpm1_get_timeouts(chip); +	if (rc) +		goto out; +	rc = tpm1_do_selftest(chip); +	if (rc) { +		dev_err(&chip->dev, "TPM self test failed\n"); +		goto out; +	} + +	return rc; +out: +	if (rc > 0) +		rc = -ENODEV; +	return rc; +} + +#define TPM_ORD_SAVESTATE 152 + +/** + * tpm1_pm_suspend() - pm suspend handler + * @chip: TPM chip to use. + * @tpm_suspend_pcr: flush pcr for buggy TPM chips. + * + * The functions saves the TPM state to be restored on resume. + * + * Return: + * * 0 on success, + * * < 0 on error. + */ +int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr) +{ +	u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; +	struct tpm_buf buf; +	unsigned int try; +	int rc; + + +	/* for buggy tpm, flush pcrs with extend to selected dummy */ +	if (tpm_suspend_pcr) +		rc = tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash, +				     "extending dummy pcr before suspend"); + +	rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); +	if (rc) +		return rc; +	/* now do the actual savestate */ +	for (try = 0; try < TPM_RETRY; try++) { +		rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, +				      0, 0, NULL); + +		/* +		 * If the TPM indicates that it is too busy to respond to +		 * this command then retry before giving up.  It can take +		 * several seconds for this TPM to be ready. +		 * +		 * This can happen if the TPM has already been sent the +		 * SaveState command before the driver has loaded.  TCG 1.2 +		 * specification states that any communication after SaveState +		 * may cause the TPM to invalidate previously saved state. +		 */ +		if (rc != TPM_WARN_RETRY) +			break; +		tpm_msleep(TPM_TIMEOUT_RETRY); + +		tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); +	} + +	if (rc) +		dev_err(&chip->dev, "Error (%d) sending savestate before suspend\n", +			rc); +	else if (try > 0) +		dev_warn(&chip->dev, "TPM savestate took %dms\n", +			 try * TPM_TIMEOUT_RETRY); + +	tpm_buf_destroy(&buf); + +	return rc; +} + diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 3acf4fd4e5a5..a6bec13afa69 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -40,129 +40,121 @@ static struct tpm2_hash tpm2_hash_map[] = {  	{HASH_ALGO_SM3_256, TPM2_ALG_SM3_256},  }; -/* - * Array with one entry per ordinal defining the maximum amount - * of time the chip could take to return the result. The values - * of the SHORT, MEDIUM, and LONG durations are taken from the - * PC Client Profile (PTP) specification. - * LONG_LONG is for commands that generates keys which empirically - * takes longer time on some systems. +int tpm2_get_timeouts(struct tpm_chip *chip) +{ +	/* Fixed timeouts for TPM2 */ +	chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); +	chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B); +	chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C); +	chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D); + +	/* PTP spec timeouts */ +	chip->duration[TPM_SHORT] = msecs_to_jiffies(TPM2_DURATION_SHORT); +	chip->duration[TPM_MEDIUM] = msecs_to_jiffies(TPM2_DURATION_MEDIUM); +	chip->duration[TPM_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG); + +	/* Key creation commands long timeouts */ +	chip->duration[TPM_LONG_LONG] = +		msecs_to_jiffies(TPM2_DURATION_LONG_LONG); + +	chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; + +	return 0; +} + +/** + * tpm2_ordinal_duration_index() - returns an index to the chip duration table + * @ordinal: TPM command ordinal. + * + * The function returns an index to the chip duration table + * (enum tpm_duration), that describes the maximum amount of + * time the chip could take to return the result for a  particular ordinal. + * + * The values of the MEDIUM, and LONG durations are taken + * from the PC Client Profile (PTP) specification (750, 2000 msec) + * + * LONG_LONG is for commands that generates keys which empirically takes + * a longer time on some systems. + * + * Return: + * * TPM_MEDIUM + * * TPM_LONG + * * TPM_LONG_LONG + * * TPM_UNDEFINED   */ -static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = { -	TPM_UNDEFINED,		/* 11F */ -	TPM_UNDEFINED,		/* 120 */ -	TPM_LONG,		/* 121 */ -	TPM_UNDEFINED,		/* 122 */ -	TPM_UNDEFINED,		/* 123 */ -	TPM_UNDEFINED,		/* 124 */ -	TPM_UNDEFINED,		/* 125 */ -	TPM_UNDEFINED,		/* 126 */ -	TPM_UNDEFINED,		/* 127 */ -	TPM_UNDEFINED,		/* 128 */ -	TPM_LONG,		/* 129 */ -	TPM_UNDEFINED,		/* 12a */ -	TPM_UNDEFINED,		/* 12b */ -	TPM_UNDEFINED,		/* 12c */ -	TPM_UNDEFINED,		/* 12d */ -	TPM_UNDEFINED,		/* 12e */ -	TPM_UNDEFINED,		/* 12f */ -	TPM_UNDEFINED,		/* 130 */ -	TPM_LONG_LONG,		/* 131 */ -	TPM_UNDEFINED,		/* 132 */ -	TPM_UNDEFINED,		/* 133 */ -	TPM_UNDEFINED,		/* 134 */ -	TPM_UNDEFINED,		/* 135 */ -	TPM_UNDEFINED,		/* 136 */ -	TPM_UNDEFINED,		/* 137 */ -	TPM_UNDEFINED,		/* 138 */ -	TPM_UNDEFINED,		/* 139 */ -	TPM_UNDEFINED,		/* 13a */ -	TPM_UNDEFINED,		/* 13b */ -	TPM_UNDEFINED,		/* 13c */ -	TPM_UNDEFINED,		/* 13d */ -	TPM_MEDIUM,		/* 13e */ -	TPM_UNDEFINED,		/* 13f */ -	TPM_UNDEFINED,		/* 140 */ -	TPM_UNDEFINED,		/* 141 */ -	TPM_UNDEFINED,		/* 142 */ -	TPM_LONG,		/* 143 */ -	TPM_MEDIUM,		/* 144 */ -	TPM_UNDEFINED,		/* 145 */ -	TPM_UNDEFINED,		/* 146 */ -	TPM_UNDEFINED,		/* 147 */ -	TPM_UNDEFINED,		/* 148 */ -	TPM_UNDEFINED,		/* 149 */ -	TPM_UNDEFINED,		/* 14a */ -	TPM_UNDEFINED,		/* 14b */ -	TPM_UNDEFINED,		/* 14c */ -	TPM_UNDEFINED,		/* 14d */ -	TPM_LONG,		/* 14e */ -	TPM_UNDEFINED,		/* 14f */ -	TPM_UNDEFINED,		/* 150 */ -	TPM_UNDEFINED,		/* 151 */ -	TPM_UNDEFINED,		/* 152 */ -	TPM_LONG_LONG,		/* 153 */ -	TPM_UNDEFINED,		/* 154 */ -	TPM_UNDEFINED,		/* 155 */ -	TPM_UNDEFINED,		/* 156 */ -	TPM_UNDEFINED,		/* 157 */ -	TPM_UNDEFINED,		/* 158 */ -	TPM_UNDEFINED,		/* 159 */ -	TPM_UNDEFINED,		/* 15a */ -	TPM_UNDEFINED,		/* 15b */ -	TPM_MEDIUM,		/* 15c */ -	TPM_UNDEFINED,		/* 15d */ -	TPM_UNDEFINED,		/* 15e */ -	TPM_UNDEFINED,		/* 15f */ -	TPM_UNDEFINED,		/* 160 */ -	TPM_UNDEFINED,		/* 161 */ -	TPM_UNDEFINED,		/* 162 */ -	TPM_UNDEFINED,		/* 163 */ -	TPM_UNDEFINED,		/* 164 */ -	TPM_UNDEFINED,		/* 165 */ -	TPM_UNDEFINED,		/* 166 */ -	TPM_UNDEFINED,		/* 167 */ -	TPM_UNDEFINED,		/* 168 */ -	TPM_UNDEFINED,		/* 169 */ -	TPM_UNDEFINED,		/* 16a */ -	TPM_UNDEFINED,		/* 16b */ -	TPM_UNDEFINED,		/* 16c */ -	TPM_UNDEFINED,		/* 16d */ -	TPM_UNDEFINED,		/* 16e */ -	TPM_UNDEFINED,		/* 16f */ -	TPM_UNDEFINED,		/* 170 */ -	TPM_UNDEFINED,		/* 171 */ -	TPM_UNDEFINED,		/* 172 */ -	TPM_UNDEFINED,		/* 173 */ -	TPM_UNDEFINED,		/* 174 */ -	TPM_UNDEFINED,		/* 175 */ -	TPM_UNDEFINED,		/* 176 */ -	TPM_LONG,		/* 177 */ -	TPM_UNDEFINED,		/* 178 */ -	TPM_UNDEFINED,		/* 179 */ -	TPM_MEDIUM,		/* 17a */ -	TPM_LONG,		/* 17b */ -	TPM_UNDEFINED,		/* 17c */ -	TPM_UNDEFINED,		/* 17d */ -	TPM_UNDEFINED,		/* 17e */ -	TPM_UNDEFINED,		/* 17f */ -	TPM_UNDEFINED,		/* 180 */ -	TPM_UNDEFINED,		/* 181 */ -	TPM_MEDIUM,		/* 182 */ -	TPM_UNDEFINED,		/* 183 */ -	TPM_UNDEFINED,		/* 184 */ -	TPM_MEDIUM,		/* 185 */ -	TPM_MEDIUM,		/* 186 */ -	TPM_UNDEFINED,		/* 187 */ -	TPM_UNDEFINED,		/* 188 */ -	TPM_UNDEFINED,		/* 189 */ -	TPM_UNDEFINED,		/* 18a */ -	TPM_UNDEFINED,		/* 18b */ -	TPM_UNDEFINED,		/* 18c */ -	TPM_UNDEFINED,		/* 18d */ -	TPM_UNDEFINED,		/* 18e */ -	TPM_UNDEFINED		/* 18f */ -}; +static u8 tpm2_ordinal_duration_index(u32 ordinal) +{ +	switch (ordinal) { +	/* Startup */ +	case TPM2_CC_STARTUP:                 /* 144 */ +		return TPM_MEDIUM; + +	case TPM2_CC_SELF_TEST:               /* 143 */ +		return TPM_LONG; + +	case TPM2_CC_GET_RANDOM:              /* 17B */ +		return TPM_LONG; + +	case TPM2_CC_SEQUENCE_UPDATE:         /* 15C */ +		return TPM_MEDIUM; +	case TPM2_CC_SEQUENCE_COMPLETE:       /* 13E */ +		return TPM_MEDIUM; +	case TPM2_CC_EVENT_SEQUENCE_COMPLETE: /* 185 */ +		return TPM_MEDIUM; +	case TPM2_CC_HASH_SEQUENCE_START:     /* 186 */ +		return TPM_MEDIUM; + +	case TPM2_CC_VERIFY_SIGNATURE:        /* 177 */ +		return TPM_LONG; + +	case TPM2_CC_PCR_EXTEND:              /* 182 */ +		return TPM_MEDIUM; + +	case TPM2_CC_HIERARCHY_CONTROL:       /* 121 */ +		return TPM_LONG; +	case TPM2_CC_HIERARCHY_CHANGE_AUTH:   /* 129 */ +		return TPM_LONG; + +	case TPM2_CC_GET_CAPABILITY:          /* 17A */ +		return TPM_MEDIUM; + +	case TPM2_CC_NV_READ:                 /* 14E */ +		return TPM_LONG; + +	case TPM2_CC_CREATE_PRIMARY:          /* 131 */ +		return TPM_LONG_LONG; +	case TPM2_CC_CREATE:                  /* 153 */ +		return TPM_LONG_LONG; +	case TPM2_CC_CREATE_LOADED:           /* 191 */ +		return TPM_LONG_LONG; + +	default: +		return TPM_UNDEFINED; +	} +} + +/** + * tpm2_calc_ordinal_duration() - calculate the maximum command duration + * @chip:    TPM chip to use. + * @ordinal: TPM command ordinal. + * + * The function returns the maximum amount of time the chip could take + * to return the result for a particular ordinal in jiffies. + * + * Return: A maximal duration time for an ordinal in jiffies. + */ +unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) +{ +	unsigned int index; + +	index = tpm2_ordinal_duration_index(ordinal); + +	if (index != TPM_UNDEFINED) +		return chip->duration[index]; +	else +		return msecs_to_jiffies(TPM2_DURATION_DEFAULT); +} +  struct tpm2_pcr_read_out {  	__be32	update_cnt; @@ -183,7 +175,7 @@ struct tpm2_pcr_read_out {   *   * Return: Same as with tpm_transmit_cmd.   */ -int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) +int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf)  {  	int rc;  	struct tpm_buf buf; @@ -233,7 +225,7 @@ struct tpm2_null_auth_area {   *   * Return: Same as with tpm_transmit_cmd.   */ -int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, +int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, u32 count,  		    struct tpm2_digest *digests)  {  	struct tpm_buf buf; @@ -280,7 +272,6 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,  	return rc;  } -  struct tpm2_get_random_out {  	__be16 size;  	u8 buffer[TPM_MAX_RNG_DATA]; @@ -351,11 +342,10 @@ out:  /**   * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command - * @chip: TPM chip to use - * @payload: the key data in clear and encrypted form - * @options: authentication values and other options + * @chip:	TPM chip to use + * @handle:	context handle + * @flags:	tpm transmit flags - bitmap   * - * Return: same as with tpm_transmit_cmd   */  void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,  			    unsigned int flags) @@ -748,32 +738,6 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)  	tpm_buf_destroy(&buf);  } -/* - * tpm2_calc_ordinal_duration() - maximum duration for a command - * - * @chip:	TPM chip to use. - * @ordinal:	command code number. - * - * Return: maximum duration for a command - */ -unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) -{ -	int index = TPM_UNDEFINED; -	int duration = 0; - -	if (ordinal >= TPM2_CC_FIRST && ordinal <= TPM2_CC_LAST) -		index = tpm2_ordinal_duration[ordinal - TPM2_CC_FIRST]; - -	if (index != TPM_UNDEFINED) -		duration = chip->duration[index]; - -	if (duration <= 0) -		duration = msecs_to_jiffies(TPM2_DURATION_DEFAULT); - -	return duration; -} -EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration); -  /**   * tpm2_do_selftest() - ensure that all self tests have passed   * @@ -983,6 +947,36 @@ out:  }  /** + * tpm2_startup - turn on the TPM + * @chip: TPM chip to use + * + * Normally the firmware should start the TPM. This function is provided as a + * workaround if this does not happen. A legal case for this could be for + * example when a TPM emulator is used. + * + * Return: same as tpm_transmit_cmd() + */ + +static int tpm2_startup(struct tpm_chip *chip) +{ +	struct tpm_buf buf; +	int rc; + +	dev_info(&chip->dev, "starting up the TPM manually\n"); + +	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP); +	if (rc < 0) +		return rc; + +	tpm_buf_append_u16(&buf, TPM2_SU_CLEAR); +	rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, +			      "attempting to start the TPM"); +	tpm_buf_destroy(&buf); + +	return rc; +} + +/**   * tpm2_auto_startup - Perform the standard automatic TPM initialization   *                     sequence   * @chip: TPM chip to use @@ -993,7 +987,7 @@ int tpm2_auto_startup(struct tpm_chip *chip)  {  	int rc; -	rc = tpm_get_timeouts(chip); +	rc = tpm2_get_timeouts(chip);  	if (rc)  		goto out; @@ -1002,7 +996,7 @@ int tpm2_auto_startup(struct tpm_chip *chip)  		goto out;  	if (rc == TPM2_RC_INITIALIZE) { -		rc = tpm_startup(chip); +		rc = tpm2_startup(chip);  		if (rc)  			goto out; diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index d2e101b32482..dcdfde3c253e 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -373,7 +373,7 @@ static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp,  		dev_err(&chip->dev, "%s: unknown handle 0x%08X\n",  			__func__, phandle);  		break; -	}; +	}  	return 0;  out_no_slots: diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index caa86b19c76d..217f7f1cbde8 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c @@ -369,6 +369,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)  	struct device *dev = chip->dev.parent;  	struct i2c_client *client = to_i2c_client(dev);  	u32 ordinal; +	unsigned long duration;  	size_t count = 0;  	int burst_count, bytes2write, retries, rc = -EIO; @@ -455,12 +456,12 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)  		return rc;  	}  	ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); -	rc = i2c_nuvoton_wait_for_data_avail(chip, -					     tpm_calc_ordinal_duration(chip, -								       ordinal), -					     &priv->read_queue); +	duration = tpm_calc_ordinal_duration(chip, ordinal); + +	rc = i2c_nuvoton_wait_for_data_avail(chip, duration, &priv->read_queue);  	if (rc) { -		dev_err(dev, "%s() timeout command duration\n", __func__); +		dev_err(dev, "%s() timeout command duration %ld\n", +			__func__, duration);  		i2c_nuvoton_ready(chip);  		return rc;  	} diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c index 25f6e2665385..07b5a487d0c8 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ b/drivers/char/tpm/tpm_ibmvtpm.c @@ -39,8 +39,7 @@ static const struct vio_device_id tpm_ibmvtpm_device_table[] = {  MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table);  /** - * - * ibmvtpm_send_crq_word - Send a CRQ request + * ibmvtpm_send_crq_word() - Send a CRQ request   * @vdev:	vio device struct   * @w1:		pre-constructed first word of tpm crq (second word is reserved)   * @@ -54,8 +53,7 @@ static int ibmvtpm_send_crq_word(struct vio_dev *vdev, u64 w1)  }  /** - * - * ibmvtpm_send_crq - Send a CRQ request + * ibmvtpm_send_crq() - Send a CRQ request   *   * @vdev:	vio device struct   * @valid:	Valid field diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index d2345d9fd7b5..bf7e49cfa643 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -473,11 +473,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)  	if (chip->flags & TPM_CHIP_FLAG_IRQ) {  		ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); -		if (chip->flags & TPM_CHIP_FLAG_TPM2) -			dur = tpm2_calc_ordinal_duration(chip, ordinal); -		else -			dur = tpm_calc_ordinal_duration(chip, ordinal); - +		dur = tpm_calc_ordinal_duration(chip, ordinal);  		if (wait_for_tpm_stat  		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,  		     &priv->read_queue, false) < 0) { @@ -668,7 +664,7 @@ static int tpm_tis_gen_interrupt(struct tpm_chip *chip)  	if (chip->flags & TPM_CHIP_FLAG_TPM2)  		return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);  	else -		return tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, +		return tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc,  				  0);  } @@ -1060,7 +1056,7 @@ int tpm_tis_resume(struct device *dev)  	 * an error code but for unknown reason it isn't handled.  	 */  	if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) -		tpm_do_selftest(chip); +		tpm1_do_selftest(chip);  	return 0;  } diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 4609b94142d4..b49a55cf775f 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -53,8 +53,8 @@ struct tpm_class_ops {  #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)  extern int tpm_is_tpm2(struct tpm_chip *chip); -extern int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); -extern int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash); +extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf); +extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash);  extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen);  extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max);  extern int tpm_seal_trusted(struct tpm_chip *chip, @@ -69,15 +69,18 @@ static inline int tpm_is_tpm2(struct tpm_chip *chip)  {  	return -ENODEV;  } -static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) + +static inline int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf)  {  	return -ENODEV;  } -static inline int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, + +static inline int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,  				 const u8 *hash)  {  	return -ENODEV;  } +  static inline int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)  {  	return -ENODEV; diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index d9e7728027c6..acf2c7df7145 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -643,7 +643,7 @@ int ima_calc_buffer_hash(const void *buf, loff_t len,  	return calc_buffer_shash(buf, len, hash);  } -static void __init ima_pcrread(int idx, u8 *pcr) +static void __init ima_pcrread(u32 idx, u8 *pcr)  {  	if (!ima_tpm_chip)  		return; @@ -659,7 +659,8 @@ static int __init ima_calc_boot_aggregate_tfm(char *digest,  					      struct crypto_shash *tfm)  {  	u8 pcr_i[TPM_DIGEST_SIZE]; -	int rc, i; +	int rc; +	u32 i;  	SHASH_DESC_ON_STACK(shash, tfm);  	shash->tfm = tfm; | 
