summaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm/tpm.c
diff options
context:
space:
mode:
authorKent Yoder <key@linux.vnet.ibm.com>2012-06-07 20:47:14 +0200
committerKent Yoder <key@linux.vnet.ibm.com>2012-08-22 18:11:33 +0200
commit41ab999c80f1d368f32a2554ba8f44feff26f54d (patch)
tree8d53970a210364e19ecbdc05f6d8c8f88e6aadbf /drivers/char/tpm/tpm.c
parenttpm: modularize event log collection (diff)
downloadlinux-41ab999c80f1d368f32a2554ba8f44feff26f54d.tar.xz
linux-41ab999c80f1d368f32a2554ba8f44feff26f54d.zip
tpm: Move tpm_get_random api into the TPM device driver
Move the tpm_get_random api from the trusted keys code into the TPM device driver itself so that other callers can make use of it. Also, change the api slightly so that the number of bytes read is returned in the call, since the TPM command can potentially return fewer bytes than requested. Acked-by: David Safford <safford@linux.vnet.ibm.com> Reviewed-by: H. Peter Anvin <hpa@linux.intel.com> Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
Diffstat (limited to 'drivers/char/tpm/tpm.c')
-rw-r--r--drivers/char/tpm/tpm.c59
1 files changed, 53 insertions, 6 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 677c6e26593f..36e43e50dcef 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -32,12 +32,6 @@
#include "tpm.h"
#include "tpm_eventlog.h"
-enum tpm_const {
- TPM_MINOR = 224, /* officially assigned */
- TPM_BUFSIZE = 4096,
- TPM_NUM_DEVICES = 256,
-};
-
enum tpm_duration {
TPM_SHORT = 0,
TPM_MEDIUM = 1,
@@ -483,6 +477,7 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
#define TPM_INTERNAL_RESULT_SIZE 200
#define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
#define TPM_ORD_GET_CAP cpu_to_be32(101)
+#define TPM_ORD_GET_RANDOM cpu_to_be32(70)
static const struct tpm_input_header tpm_getcap_header = {
.tag = TPM_TAG_RQU_COMMAND,
@@ -1327,6 +1322,58 @@ int tpm_pm_resume(struct device *dev)
}
EXPORT_SYMBOL_GPL(tpm_pm_resume);
+#define TPM_GETRANDOM_RESULT_SIZE 18
+static struct tpm_input_header tpm_getrandom_header = {
+ .tag = TPM_TAG_RQU_COMMAND,
+ .length = cpu_to_be32(14),
+ .ordinal = TPM_ORD_GET_RANDOM
+};
+
+/**
+ * tpm_get_random() - Get random bytes from the tpm's RNG
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @out: destination buffer for the random bytes
+ * @max: the max number of bytes to write to @out
+ *
+ * Returns < 0 on error and the number of bytes read on success
+ */
+int tpm_get_random(u32 chip_num, u8 *out, size_t max)
+{
+ struct tpm_chip *chip;
+ struct tpm_cmd_t tpm_cmd;
+ u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
+ int err, total = 0, retries = 5;
+ u8 *dest = out;
+
+ chip = tpm_chip_find_get(chip_num);
+ if (chip == NULL)
+ return -ENODEV;
+
+ if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
+ return -EINVAL;
+
+ do {
+ tpm_cmd.header.in = tpm_getrandom_header;
+ tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
+
+ err = transmit_cmd(chip, &tpm_cmd,
+ TPM_GETRANDOM_RESULT_SIZE + num_bytes,
+ "attempting get random");
+ if (err)
+ break;
+
+ recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
+ memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
+
+ dest += recd;
+ total += recd;
+ num_bytes -= recd;
+ } while (retries-- && total < max);
+
+ return total ? total : -EIO;
+}
+EXPORT_SYMBOL_GPL(tpm_get_random);
+
/* In case vendor provided release function, call it too.*/
void tpm_dev_vendor_release(struct tpm_chip *chip)