aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm/tpm.c
diff options
context:
space:
mode:
authorKent Yoder <key@linux.vnet.ibm.com>2012-06-07 14:47:14 -0400
committerKent Yoder <key@linux.vnet.ibm.com>2012-08-22 12:11:33 -0400
commit41ab999c80f1d368f32a2554ba8f44feff26f54d (patch)
tree8d53970a210364e19ecbdc05f6d8c8f88e6aadbf /drivers/char/tpm/tpm.c
parente5dcd87fee12ed64a9ea911102025facc0c7d10c (diff)
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 @@
32#include "tpm.h" 32#include "tpm.h"
33#include "tpm_eventlog.h" 33#include "tpm_eventlog.h"
34 34
35enum tpm_const {
36 TPM_MINOR = 224, /* officially assigned */
37 TPM_BUFSIZE = 4096,
38 TPM_NUM_DEVICES = 256,
39};
40
41enum tpm_duration { 35enum tpm_duration {
42 TPM_SHORT = 0, 36 TPM_SHORT = 0,
43 TPM_MEDIUM = 1, 37 TPM_MEDIUM = 1,
@@ -483,6 +477,7 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
483#define TPM_INTERNAL_RESULT_SIZE 200 477#define TPM_INTERNAL_RESULT_SIZE 200
484#define TPM_TAG_RQU_COMMAND cpu_to_be16(193) 478#define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
485#define TPM_ORD_GET_CAP cpu_to_be32(101) 479#define TPM_ORD_GET_CAP cpu_to_be32(101)
480#define TPM_ORD_GET_RANDOM cpu_to_be32(70)
486 481
487static const struct tpm_input_header tpm_getcap_header = { 482static const struct tpm_input_header tpm_getcap_header = {
488 .tag = TPM_TAG_RQU_COMMAND, 483 .tag = TPM_TAG_RQU_COMMAND,
@@ -1327,6 +1322,58 @@ int tpm_pm_resume(struct device *dev)
1327} 1322}
1328EXPORT_SYMBOL_GPL(tpm_pm_resume); 1323EXPORT_SYMBOL_GPL(tpm_pm_resume);
1329 1324
1325#define TPM_GETRANDOM_RESULT_SIZE 18
1326static struct tpm_input_header tpm_getrandom_header = {
1327 .tag = TPM_TAG_RQU_COMMAND,
1328 .length = cpu_to_be32(14),
1329 .ordinal = TPM_ORD_GET_RANDOM
1330};
1331
1332/**
1333 * tpm_get_random() - Get random bytes from the tpm's RNG
1334 * @chip_num: A specific chip number for the request or TPM_ANY_NUM
1335 * @out: destination buffer for the random bytes
1336 * @max: the max number of bytes to write to @out
1337 *
1338 * Returns < 0 on error and the number of bytes read on success
1339 */
1340int tpm_get_random(u32 chip_num, u8 *out, size_t max)
1341{
1342 struct tpm_chip *chip;
1343 struct tpm_cmd_t tpm_cmd;
1344 u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
1345 int err, total = 0, retries = 5;
1346 u8 *dest = out;
1347
1348 chip = tpm_chip_find_get(chip_num);
1349 if (chip == NULL)
1350 return -ENODEV;
1351
1352 if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
1353 return -EINVAL;
1354
1355 do {
1356 tpm_cmd.header.in = tpm_getrandom_header;
1357 tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
1358
1359 err = transmit_cmd(chip, &tpm_cmd,
1360 TPM_GETRANDOM_RESULT_SIZE + num_bytes,
1361 "attempting get random");
1362 if (err)
1363 break;
1364
1365 recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
1366 memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
1367
1368 dest += recd;
1369 total += recd;
1370 num_bytes -= recd;
1371 } while (retries-- && total < max);
1372
1373 return total ? total : -EIO;
1374}
1375EXPORT_SYMBOL_GPL(tpm_get_random);
1376
1330/* In case vendor provided release function, call it too.*/ 1377/* In case vendor provided release function, call it too.*/
1331 1378
1332void tpm_dev_vendor_release(struct tpm_chip *chip) 1379void tpm_dev_vendor_release(struct tpm_chip *chip)