aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/char/tpm/tpm.c59
-rw-r--r--drivers/char/tpm/tpm.h23
-rw-r--r--include/linux/tpm.h4
-rw-r--r--security/keys/trusted.c54
4 files changed, 92 insertions, 48 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)
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 917f727e6740..645136eea890 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -28,6 +28,12 @@
28#include <linux/io.h> 28#include <linux/io.h>
29#include <linux/tpm.h> 29#include <linux/tpm.h>
30 30
31enum tpm_const {
32 TPM_MINOR = 224, /* officially assigned */
33 TPM_BUFSIZE = 4096,
34 TPM_NUM_DEVICES = 256,
35};
36
31enum tpm_timeout { 37enum tpm_timeout {
32 TPM_TIMEOUT = 5, /* msecs */ 38 TPM_TIMEOUT = 5, /* msecs */
33}; 39};
@@ -269,6 +275,21 @@ struct tpm_pcrextend_in {
269 u8 hash[TPM_DIGEST_SIZE]; 275 u8 hash[TPM_DIGEST_SIZE];
270}__attribute__((packed)); 276}__attribute__((packed));
271 277
278/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
279 * bytes, but 128 is still a relatively large number of random bytes and
280 * anything much bigger causes users of struct tpm_cmd_t to start getting
281 * compiler warnings about stack frame size. */
282#define TPM_MAX_RNG_DATA 128
283
284struct tpm_getrandom_out {
285 __be32 rng_data_len;
286 u8 rng_data[TPM_MAX_RNG_DATA];
287}__attribute__((packed));
288
289struct tpm_getrandom_in {
290 __be32 num_bytes;
291}__attribute__((packed));
292
272typedef union { 293typedef union {
273 struct tpm_getcap_params_out getcap_out; 294 struct tpm_getcap_params_out getcap_out;
274 struct tpm_readpubek_params_out readpubek_out; 295 struct tpm_readpubek_params_out readpubek_out;
@@ -277,6 +298,8 @@ typedef union {
277 struct tpm_pcrread_in pcrread_in; 298 struct tpm_pcrread_in pcrread_in;
278 struct tpm_pcrread_out pcrread_out; 299 struct tpm_pcrread_out pcrread_out;
279 struct tpm_pcrextend_in pcrextend_in; 300 struct tpm_pcrextend_in pcrextend_in;
301 struct tpm_getrandom_in getrandom_in;
302 struct tpm_getrandom_out getrandom_out;
280} tpm_cmd_params; 303} tpm_cmd_params;
281 304
282struct tpm_cmd_t { 305struct tpm_cmd_t {
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index fdc718abf83b..fcb627ff8d3e 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -32,6 +32,7 @@
32extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf); 32extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
33extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash); 33extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
34extern int tpm_send(u32 chip_num, void *cmd, size_t buflen); 34extern int tpm_send(u32 chip_num, void *cmd, size_t buflen);
35extern int tpm_get_random(u32 chip_num, u8 *data, size_t max);
35#else 36#else
36static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) { 37static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
37 return -ENODEV; 38 return -ENODEV;
@@ -42,5 +43,8 @@ static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) {
42static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) { 43static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) {
43 return -ENODEV; 44 return -ENODEV;
44} 45}
46static inline int tpm_get_random(u32 chip_num, u8 *data, size_t max) {
47 return -ENODEV;
48}
45#endif 49#endif
46#endif 50#endif
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index 2d5d041f2049..3f163d0489ad 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -369,38 +369,6 @@ static int trusted_tpm_send(const u32 chip_num, unsigned char *cmd,
369} 369}
370 370
371/* 371/*
372 * get a random value from TPM
373 */
374static int tpm_get_random(struct tpm_buf *tb, unsigned char *buf, uint32_t len)
375{
376 int ret;
377
378 INIT_BUF(tb);
379 store16(tb, TPM_TAG_RQU_COMMAND);
380 store32(tb, TPM_GETRANDOM_SIZE);
381 store32(tb, TPM_ORD_GETRANDOM);
382 store32(tb, len);
383 ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data);
384 if (!ret)
385 memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len);
386 return ret;
387}
388
389static int my_get_random(unsigned char *buf, int len)
390{
391 struct tpm_buf *tb;
392 int ret;
393
394 tb = kmalloc(sizeof *tb, GFP_KERNEL);
395 if (!tb)
396 return -ENOMEM;
397 ret = tpm_get_random(tb, buf, len);
398
399 kfree(tb);
400 return ret;
401}
402
403/*
404 * Lock a trusted key, by extending a selected PCR. 372 * Lock a trusted key, by extending a selected PCR.
405 * 373 *
406 * Prevents a trusted key that is sealed to PCRs from being accessed. 374 * Prevents a trusted key that is sealed to PCRs from being accessed.
@@ -413,8 +381,8 @@ static int pcrlock(const int pcrnum)
413 381
414 if (!capable(CAP_SYS_ADMIN)) 382 if (!capable(CAP_SYS_ADMIN))
415 return -EPERM; 383 return -EPERM;
416 ret = my_get_random(hash, SHA1_DIGEST_SIZE); 384 ret = tpm_get_random(TPM_ANY_NUM, hash, SHA1_DIGEST_SIZE);
417 if (ret < 0) 385 if (ret != SHA1_DIGEST_SIZE)
418 return ret; 386 return ret;
419 return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0; 387 return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0;
420} 388}
@@ -429,8 +397,8 @@ static int osap(struct tpm_buf *tb, struct osapsess *s,
429 unsigned char ononce[TPM_NONCE_SIZE]; 397 unsigned char ononce[TPM_NONCE_SIZE];
430 int ret; 398 int ret;
431 399
432 ret = tpm_get_random(tb, ononce, TPM_NONCE_SIZE); 400 ret = tpm_get_random(TPM_ANY_NUM, ononce, TPM_NONCE_SIZE);
433 if (ret < 0) 401 if (ret != TPM_NONCE_SIZE)
434 return ret; 402 return ret;
435 403
436 INIT_BUF(tb); 404 INIT_BUF(tb);
@@ -524,8 +492,8 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
524 if (ret < 0) 492 if (ret < 0)
525 goto out; 493 goto out;
526 494
527 ret = tpm_get_random(tb, td->nonceodd, TPM_NONCE_SIZE); 495 ret = tpm_get_random(TPM_ANY_NUM, td->nonceodd, TPM_NONCE_SIZE);
528 if (ret < 0) 496 if (ret != TPM_NONCE_SIZE)
529 goto out; 497 goto out;
530 ordinal = htonl(TPM_ORD_SEAL); 498 ordinal = htonl(TPM_ORD_SEAL);
531 datsize = htonl(datalen); 499 datsize = htonl(datalen);
@@ -634,8 +602,8 @@ static int tpm_unseal(struct tpm_buf *tb,
634 602
635 ordinal = htonl(TPM_ORD_UNSEAL); 603 ordinal = htonl(TPM_ORD_UNSEAL);
636 keyhndl = htonl(SRKHANDLE); 604 keyhndl = htonl(SRKHANDLE);
637 ret = tpm_get_random(tb, nonceodd, TPM_NONCE_SIZE); 605 ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE);
638 if (ret < 0) { 606 if (ret != TPM_NONCE_SIZE) {
639 pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); 607 pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
640 return ret; 608 return ret;
641 } 609 }
@@ -935,6 +903,7 @@ static int trusted_instantiate(struct key *key, const void *data,
935 char *datablob; 903 char *datablob;
936 int ret = 0; 904 int ret = 0;
937 int key_cmd; 905 int key_cmd;
906 size_t key_len;
938 907
939 if (datalen <= 0 || datalen > 32767 || !data) 908 if (datalen <= 0 || datalen > 32767 || !data)
940 return -EINVAL; 909 return -EINVAL;
@@ -974,8 +943,9 @@ static int trusted_instantiate(struct key *key, const void *data,
974 pr_info("trusted_key: key_unseal failed (%d)\n", ret); 943 pr_info("trusted_key: key_unseal failed (%d)\n", ret);
975 break; 944 break;
976 case Opt_new: 945 case Opt_new:
977 ret = my_get_random(payload->key, payload->key_len); 946 key_len = payload->key_len;
978 if (ret < 0) { 947 ret = tpm_get_random(TPM_ANY_NUM, payload->key, key_len);
948 if (ret != key_len) {
979 pr_info("trusted_key: key_create failed (%d)\n", ret); 949 pr_info("trusted_key: key_create failed (%d)\n", ret);
980 goto out; 950 goto out;
981 } 951 }