diff options
Diffstat (limited to 'drivers/char/tpm/tpm.c')
-rw-r--r-- | drivers/char/tpm/tpm.c | 59 |
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) |