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; }
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; }
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; }
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; }
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)); }
/** * 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; }
/*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)); }
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; }
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; }
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; }
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; }
/* 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; }
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; }
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; }
/** * 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; }