aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 }