Пример #1
0
int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
		uint8_t *recvbuf, size_t *rbuf_len)
{
	uint8_t buf[TPM_BUFSIZE];

	if (!opened && tis_open())
		return -1;

	if (sizeof(buf) < sbuf_size)
		return -1;

	memcpy(buf, sendbuf, sbuf_size);

	int len = tpm_transmit(buf, sbuf_size);

	if (len < 10) {
		*rbuf_len = 0;
		return -1;
	}

	if (len > *rbuf_len) {
		*rbuf_len = len;
		return -1;
	}

	memcpy(recvbuf, buf, len);
	*rbuf_len = len;

	return 0;
}
Пример #2
0
int tpm_tis_posix_write(int fd, const uint8_t* buf, size_t count)
{
   struct tpm_chip* tpm;
   tpm = files[fd].tpm_tis.dev;

   if(tpm->locality < 0) {
      printk("tpm_tis_posix_write() failed! locality not set!\n");
      errno = EINPROGRESS;
      return -1;
   }
   if(count == 0) {
      return 0;
   }

   /* Return an error if we are already processing a command */
   if(count > TPM_BUFSIZE) {
      count = TPM_BUFSIZE;
   }
   /* Send the command now */
   memcpy(tpm->data_buffer, buf, count);
   if((tpm->data_len = tpm_transmit(tpm, tpm->data_buffer, TPM_BUFSIZE)) < 0) {
      errno = EIO;
      return -1;
   }
   return count;
}
Пример #3
0
int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
		uint8_t *recvbuf, size_t *rbuf_len)
{
	int len;
	uint8_t buf[4096];

	if (!tpm.inited)
		return -1;

	if (sizeof(buf) < sbuf_size)
		return -1;

	memcpy(buf, sendbuf, sbuf_size);

	if (tpm_select())
		return -1;

	len = tpm_transmit(buf, sbuf_size);

	tpm_deselect();

	if (len < 10) {
		*rbuf_len = 0;
		return -1;
	}

	memcpy(recvbuf, buf, len);
	*rbuf_len = len;

	return 0;
}
Пример #4
0
static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space,
				u8 *buf, size_t bufsiz)
{
	struct tpm_header *header = (void *)buf;
	ssize_t ret, len;

	ret = tpm2_prepare_space(chip, space, buf, bufsiz);
	/* If the command is not implemented by the TPM, synthesize a
	 * response with a TPM2_RC_COMMAND_CODE return for user-space.
	 */
	if (ret == -EOPNOTSUPP) {
		header->length = cpu_to_be32(sizeof(*header));
		header->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
		header->return_code = cpu_to_be32(TPM2_RC_COMMAND_CODE |
						  TSS2_RESMGR_TPM_RC_LAYER);
		ret = sizeof(*header);
	}
	if (ret)
		goto out_rc;

	len = tpm_transmit(chip, buf, bufsiz);
	if (len < 0)
		ret = len;

	if (!ret)
		ret = tpm2_commit_space(chip, space, buf, &len);

out_rc:
	return ret ? ret : len;
}
Пример #5
0
void tpm_continue_selftest(struct tpm_chip* chip) {
   uint8_t data[] = {
      0, 193,                 /* TPM_TAG_RQU_COMMAND */
      0, 0, 0, 10,            /* length */
      0, 0, 0, 83,            /* TPM_ORD_GetCapability */
   };

   tpm_transmit(chip, data, sizeof(data));
}
Пример #6
0
/**
 * 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;
	struct tpm_cmd_t cmd;

	duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST);

	loops = jiffies_to_msecs(duration) / delay_msec;

	rc = tpm_continue_selftest(chip);
	/* 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 */
		cmd.header.in = pcrread_header;
		cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0);
		rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE);
		/* 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");
			msleep(delay_msec);
			continue;
		}

		if (rc < TPM_HEADER_SIZE)
			return -EFAULT;

		rc = be32_to_cpu(cmd.header.out.return_code);
		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;
		msleep(delay_msec);
	} while (--loops > 0);

	return rc;
}
Пример #7
0
/*TPM2.0 Selftest*/
static void tpm2_selftest(struct tpm_chip* chip)
{
    uint8_t data[] = {
        0x80, 0x1,
        0x0, 0x0, 0x0, 0xb,
        0x0, 0x0, 0x1, 0x43,
        0x1,
    };

    tpm_transmit(chip, data, sizeof(data));
}
Пример #8
0
static ssize_t tpm_write(struct file *file, const char __user *buf,
			 size_t size, loff_t *off)
{
	struct file_priv *priv = file->private_data;
	size_t in_size = size;
	ssize_t out_size;

	/* cannot perform a write until the read has cleared
	   either via tpm_read or a user_read_timer timeout.
	   This also prevents splitted buffered writes from blocking here.
	*/
	if (atomic_read(&priv->data_pending) != 0)
		return -EBUSY;

	if (in_size > TPM_BUFSIZE)
		return -E2BIG;

	mutex_lock(&priv->buffer_mutex);

	if (copy_from_user
	    (priv->data_buffer, (void __user *) buf, in_size)) {
		mutex_unlock(&priv->buffer_mutex);
		return -EFAULT;
	}

	/* atomic tpm command send and result receive. We only hold the ops
	 * lock during this period so that the tpm can be unregistered even if
	 * the char dev is held open.
	 */
	if (tpm_try_get_ops(priv->chip)) {
		mutex_unlock(&priv->buffer_mutex);
		return -EPIPE;
	}
	out_size = tpm_transmit(priv->chip, priv->data_buffer,
				sizeof(priv->data_buffer));

	tpm_put_ops(priv->chip);
	if (out_size < 0) {
		mutex_unlock(&priv->buffer_mutex);
		return out_size;
	}

	atomic_set(&priv->data_pending, out_size);
	mutex_unlock(&priv->buffer_mutex);

	/* Set a timeout by which the reader must come claim the result */
	mod_timer(&priv->user_read_timer, jiffies + (60 * HZ));

	return in_size;
}
Пример #9
0
static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len,
			    char *desc)
{
	int err;

	len = tpm_transmit(chip, data, len);
	if (len <  0)
		return len;
	if (len == TPM_ERROR_SIZE) {
		err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)));
		dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
		return err;
	}
	return 0;
}
Пример #10
0
static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
                            int len, const char *desc)
{
        int err;

        len = tpm_transmit(chip,(uint8_t *) cmd, len);
        if (len <  0)
                return len;
        if (len == TPM_ERROR_SIZE) {
                err = be32_to_cpu(cmd->header.out.return_code);
                printk("A TPM error (%d) occurred %s\n", err, desc);
                return err;
        }
        return 0;
}
Пример #11
0
int tpm_tis_cmd(struct tpm_chip* tpm, uint8_t* req, size_t reqlen, uint8_t** resp, size_t* resplen)
{
   if(tpm->locality < 0) {
      printk("tpm_tis_cmd() failed! locality not set!\n");
      return -1;
   }
   if(reqlen > TPM_BUFSIZE) {
      reqlen = TPM_BUFSIZE;
   }
   memcpy(tpm->data_buffer, req, reqlen);
   *resplen = tpm_transmit(tpm, tpm->data_buffer, TPM_BUFSIZE);

   *resp = malloc(*resplen);
   memcpy(*resp, tpm->data_buffer, *resplen);
   return 0;
}
Пример #12
0
/* XXX for now this helper is duplicated in tpm-interface.c */
static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
			    int len, const char *desc)
{
	int err;

	len = tpm_transmit(chip, (u8 *) cmd, len);
	if (len <  0)
		return len;
	else if (len < TPM_HEADER_SIZE)
		return -EFAULT;

	err = be32_to_cpu(cmd->header.out.return_code);
	if (err != 0 && desc)
		dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);

	return err;
}
Пример #13
0
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd,
			 int len, unsigned int flags, const char *desc)
{
	const struct tpm_output_header *header;
	int err;

	len = tpm_transmit(chip, (const u8 *)cmd, len, flags);
	if (len <  0)
		return len;
	else if (len < TPM_HEADER_SIZE)
		return -EFAULT;

	header = cmd;

	err = be32_to_cpu(header->return_code);
	if (err != 0 && desc)
		dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err,
			desc);

	return err;
}
Пример #14
0
int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
		uint8_t *recvbuf, size_t *rbuf_len)
{
	ASSERT(sbuf_size >= 10);

	/* Display the TPM command */
	if (IS_ENABLED(CONFIG_DRIVER_TPM_DISPLAY_TIS_BYTES)) {
		printk(BIOS_DEBUG, "TPM Command: 0x%08x\n",
			read_at_be32(sendbuf, sizeof(uint16_t)
				+ sizeof(uint32_t)));
		hexdump(sendbuf, sbuf_size);
	}

	int len = tpm_transmit(sendbuf, sbuf_size, recvbuf, *rbuf_len);

	if (len < 10) {
		*rbuf_len = 0;
		return -1;
	}

	if (len > *rbuf_len) {
		*rbuf_len = len;
		return -1;
	}

	*rbuf_len = len;

	/* Display the TPM response */
	if (IS_ENABLED(CONFIG_DRIVER_TPM_DISPLAY_TIS_BYTES)) {
		printk(BIOS_DEBUG, "TPM Response: 0x%08x\n",
			read_at_be32(recvbuf, sizeof(uint16_t)
				+ sizeof(uint32_t)));
		hexdump(recvbuf, *rbuf_len);
	}

	return 0;
}
Пример #15
0
/**
 * tpm_transmit_cmd - send a tpm command to the device
 * @chip:			a TPM chip to use
 * @buf:			a TPM command buffer
 * @min_rsp_body_length:	minimum expected length of response body
 * @desc:			command description used in the error message
 *
 * Return:
 * * 0		- OK
 * * -errno	- A system error
 * * TPM_RC	- A TPM error
 */
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf,
			 size_t min_rsp_body_length, const char *desc)
{
	const struct tpm_header *header = (struct tpm_header *)buf->data;
	int err;
	ssize_t len;

	len = tpm_transmit(chip, buf->data, PAGE_SIZE);
	if (len <  0)
		return len;

	err = be32_to_cpu(header->return_code);
	if (err != 0 && err != TPM_ERR_DISABLED && err != TPM_ERR_DEACTIVATED
	    && err != TPM2_RC_TESTING && desc)
		dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err,
			desc);
	if (err)
		return err;

	if (len < min_rsp_body_length + TPM_HEADER_SIZE)
		return -EFAULT;

	return 0;
}