diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /security/keys/trusted.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'security/keys/trusted.c')
-rw-r--r-- | security/keys/trusted.c | 95 |
1 files changed, 56 insertions, 39 deletions
diff --git a/security/keys/trusted.c b/security/keys/trusted.c index e13fcf7636f..0c33e2ea1f3 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c | |||
@@ -369,6 +369,38 @@ 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 | */ | ||
374 | static 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 | |||
389 | static 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 | /* | ||
372 | * Lock a trusted key, by extending a selected PCR. | 404 | * Lock a trusted key, by extending a selected PCR. |
373 | * | 405 | * |
374 | * Prevents a trusted key that is sealed to PCRs from being accessed. | 406 | * Prevents a trusted key that is sealed to PCRs from being accessed. |
@@ -381,8 +413,8 @@ static int pcrlock(const int pcrnum) | |||
381 | 413 | ||
382 | if (!capable(CAP_SYS_ADMIN)) | 414 | if (!capable(CAP_SYS_ADMIN)) |
383 | return -EPERM; | 415 | return -EPERM; |
384 | ret = tpm_get_random(TPM_ANY_NUM, hash, SHA1_DIGEST_SIZE); | 416 | ret = my_get_random(hash, SHA1_DIGEST_SIZE); |
385 | if (ret != SHA1_DIGEST_SIZE) | 417 | if (ret < 0) |
386 | return ret; | 418 | return ret; |
387 | return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0; | 419 | return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0; |
388 | } | 420 | } |
@@ -397,8 +429,8 @@ static int osap(struct tpm_buf *tb, struct osapsess *s, | |||
397 | unsigned char ononce[TPM_NONCE_SIZE]; | 429 | unsigned char ononce[TPM_NONCE_SIZE]; |
398 | int ret; | 430 | int ret; |
399 | 431 | ||
400 | ret = tpm_get_random(TPM_ANY_NUM, ononce, TPM_NONCE_SIZE); | 432 | ret = tpm_get_random(tb, ononce, TPM_NONCE_SIZE); |
401 | if (ret != TPM_NONCE_SIZE) | 433 | if (ret < 0) |
402 | return ret; | 434 | return ret; |
403 | 435 | ||
404 | INIT_BUF(tb); | 436 | INIT_BUF(tb); |
@@ -492,8 +524,8 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, | |||
492 | if (ret < 0) | 524 | if (ret < 0) |
493 | goto out; | 525 | goto out; |
494 | 526 | ||
495 | ret = tpm_get_random(TPM_ANY_NUM, td->nonceodd, TPM_NONCE_SIZE); | 527 | ret = tpm_get_random(tb, td->nonceodd, TPM_NONCE_SIZE); |
496 | if (ret != TPM_NONCE_SIZE) | 528 | if (ret < 0) |
497 | goto out; | 529 | goto out; |
498 | ordinal = htonl(TPM_ORD_SEAL); | 530 | ordinal = htonl(TPM_ORD_SEAL); |
499 | datsize = htonl(datalen); | 531 | datsize = htonl(datalen); |
@@ -602,8 +634,8 @@ static int tpm_unseal(struct tpm_buf *tb, | |||
602 | 634 | ||
603 | ordinal = htonl(TPM_ORD_UNSEAL); | 635 | ordinal = htonl(TPM_ORD_UNSEAL); |
604 | keyhndl = htonl(SRKHANDLE); | 636 | keyhndl = htonl(SRKHANDLE); |
605 | ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE); | 637 | ret = tpm_get_random(tb, nonceodd, TPM_NONCE_SIZE); |
606 | if (ret != TPM_NONCE_SIZE) { | 638 | if (ret < 0) { |
607 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); | 639 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); |
608 | return ret; | 640 | return ret; |
609 | } | 641 | } |
@@ -747,10 +779,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay, | |||
747 | opt->pcrinfo_len = strlen(args[0].from) / 2; | 779 | opt->pcrinfo_len = strlen(args[0].from) / 2; |
748 | if (opt->pcrinfo_len > MAX_PCRINFO_SIZE) | 780 | if (opt->pcrinfo_len > MAX_PCRINFO_SIZE) |
749 | return -EINVAL; | 781 | return -EINVAL; |
750 | res = hex2bin(opt->pcrinfo, args[0].from, | 782 | hex2bin(opt->pcrinfo, args[0].from, opt->pcrinfo_len); |
751 | opt->pcrinfo_len); | ||
752 | if (res < 0) | ||
753 | return -EINVAL; | ||
754 | break; | 783 | break; |
755 | case Opt_keyhandle: | 784 | case Opt_keyhandle: |
756 | res = strict_strtoul(args[0].from, 16, &handle); | 785 | res = strict_strtoul(args[0].from, 16, &handle); |
@@ -762,18 +791,12 @@ static int getoptions(char *c, struct trusted_key_payload *pay, | |||
762 | case Opt_keyauth: | 791 | case Opt_keyauth: |
763 | if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE) | 792 | if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE) |
764 | return -EINVAL; | 793 | return -EINVAL; |
765 | res = hex2bin(opt->keyauth, args[0].from, | 794 | hex2bin(opt->keyauth, args[0].from, SHA1_DIGEST_SIZE); |
766 | SHA1_DIGEST_SIZE); | ||
767 | if (res < 0) | ||
768 | return -EINVAL; | ||
769 | break; | 795 | break; |
770 | case Opt_blobauth: | 796 | case Opt_blobauth: |
771 | if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE) | 797 | if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE) |
772 | return -EINVAL; | 798 | return -EINVAL; |
773 | res = hex2bin(opt->blobauth, args[0].from, | 799 | hex2bin(opt->blobauth, args[0].from, SHA1_DIGEST_SIZE); |
774 | SHA1_DIGEST_SIZE); | ||
775 | if (res < 0) | ||
776 | return -EINVAL; | ||
777 | break; | 800 | break; |
778 | case Opt_migratable: | 801 | case Opt_migratable: |
779 | if (*args[0].from == '0') | 802 | if (*args[0].from == '0') |
@@ -837,9 +860,7 @@ static int datablob_parse(char *datablob, struct trusted_key_payload *p, | |||
837 | p->blob_len = strlen(c) / 2; | 860 | p->blob_len = strlen(c) / 2; |
838 | if (p->blob_len > MAX_BLOB_SIZE) | 861 | if (p->blob_len > MAX_BLOB_SIZE) |
839 | return -EINVAL; | 862 | return -EINVAL; |
840 | ret = hex2bin(p->blob, c, p->blob_len); | 863 | hex2bin(p->blob, c, p->blob_len); |
841 | if (ret < 0) | ||
842 | return -EINVAL; | ||
843 | ret = getoptions(datablob, p, o); | 864 | ret = getoptions(datablob, p, o); |
844 | if (ret < 0) | 865 | if (ret < 0) |
845 | return ret; | 866 | return ret; |
@@ -895,24 +916,22 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) | |||
895 | * | 916 | * |
896 | * On success, return 0. Otherwise return errno. | 917 | * On success, return 0. Otherwise return errno. |
897 | */ | 918 | */ |
898 | static int trusted_instantiate(struct key *key, | 919 | static int trusted_instantiate(struct key *key, const void *data, |
899 | struct key_preparsed_payload *prep) | 920 | size_t datalen) |
900 | { | 921 | { |
901 | struct trusted_key_payload *payload = NULL; | 922 | struct trusted_key_payload *payload = NULL; |
902 | struct trusted_key_options *options = NULL; | 923 | struct trusted_key_options *options = NULL; |
903 | size_t datalen = prep->datalen; | ||
904 | char *datablob; | 924 | char *datablob; |
905 | int ret = 0; | 925 | int ret = 0; |
906 | int key_cmd; | 926 | int key_cmd; |
907 | size_t key_len; | ||
908 | 927 | ||
909 | if (datalen <= 0 || datalen > 32767 || !prep->data) | 928 | if (datalen <= 0 || datalen > 32767 || !data) |
910 | return -EINVAL; | 929 | return -EINVAL; |
911 | 930 | ||
912 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 931 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
913 | if (!datablob) | 932 | if (!datablob) |
914 | return -ENOMEM; | 933 | return -ENOMEM; |
915 | memcpy(datablob, prep->data, datalen); | 934 | memcpy(datablob, data, datalen); |
916 | datablob[datalen] = '\0'; | 935 | datablob[datalen] = '\0'; |
917 | 936 | ||
918 | options = trusted_options_alloc(); | 937 | options = trusted_options_alloc(); |
@@ -944,9 +963,8 @@ static int trusted_instantiate(struct key *key, | |||
944 | pr_info("trusted_key: key_unseal failed (%d)\n", ret); | 963 | pr_info("trusted_key: key_unseal failed (%d)\n", ret); |
945 | break; | 964 | break; |
946 | case Opt_new: | 965 | case Opt_new: |
947 | key_len = payload->key_len; | 966 | ret = my_get_random(payload->key, payload->key_len); |
948 | ret = tpm_get_random(TPM_ANY_NUM, payload->key, key_len); | 967 | if (ret < 0) { |
949 | if (ret != key_len) { | ||
950 | pr_info("trusted_key: key_create failed (%d)\n", ret); | 968 | pr_info("trusted_key: key_create failed (%d)\n", ret); |
951 | goto out; | 969 | goto out; |
952 | } | 970 | } |
@@ -964,7 +982,7 @@ out: | |||
964 | kfree(datablob); | 982 | kfree(datablob); |
965 | kfree(options); | 983 | kfree(options); |
966 | if (!ret) | 984 | if (!ret) |
967 | rcu_assign_keypointer(key, payload); | 985 | rcu_assign_pointer(key->payload.data, payload); |
968 | else | 986 | else |
969 | kfree(payload); | 987 | kfree(payload); |
970 | return ret; | 988 | return ret; |
@@ -982,18 +1000,17 @@ static void trusted_rcu_free(struct rcu_head *rcu) | |||
982 | /* | 1000 | /* |
983 | * trusted_update - reseal an existing key with new PCR values | 1001 | * trusted_update - reseal an existing key with new PCR values |
984 | */ | 1002 | */ |
985 | static int trusted_update(struct key *key, struct key_preparsed_payload *prep) | 1003 | static int trusted_update(struct key *key, const void *data, size_t datalen) |
986 | { | 1004 | { |
987 | struct trusted_key_payload *p = key->payload.data; | 1005 | struct trusted_key_payload *p = key->payload.data; |
988 | struct trusted_key_payload *new_p; | 1006 | struct trusted_key_payload *new_p; |
989 | struct trusted_key_options *new_o; | 1007 | struct trusted_key_options *new_o; |
990 | size_t datalen = prep->datalen; | ||
991 | char *datablob; | 1008 | char *datablob; |
992 | int ret = 0; | 1009 | int ret = 0; |
993 | 1010 | ||
994 | if (!p->migratable) | 1011 | if (!p->migratable) |
995 | return -EPERM; | 1012 | return -EPERM; |
996 | if (datalen <= 0 || datalen > 32767 || !prep->data) | 1013 | if (datalen <= 0 || datalen > 32767 || !data) |
997 | return -EINVAL; | 1014 | return -EINVAL; |
998 | 1015 | ||
999 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 1016 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
@@ -1010,7 +1027,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) | |||
1010 | goto out; | 1027 | goto out; |
1011 | } | 1028 | } |
1012 | 1029 | ||
1013 | memcpy(datablob, prep->data, datalen); | 1030 | memcpy(datablob, data, datalen); |
1014 | datablob[datalen] = '\0'; | 1031 | datablob[datalen] = '\0'; |
1015 | ret = datablob_parse(datablob, new_p, new_o); | 1032 | ret = datablob_parse(datablob, new_p, new_o); |
1016 | if (ret != Opt_update) { | 1033 | if (ret != Opt_update) { |
@@ -1039,7 +1056,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) | |||
1039 | goto out; | 1056 | goto out; |
1040 | } | 1057 | } |
1041 | } | 1058 | } |
1042 | rcu_assign_keypointer(key, new_p); | 1059 | rcu_assign_pointer(key->payload.data, new_p); |
1043 | call_rcu(&p->rcu, trusted_rcu_free); | 1060 | call_rcu(&p->rcu, trusted_rcu_free); |
1044 | out: | 1061 | out: |
1045 | kfree(datablob); | 1062 | kfree(datablob); |
@@ -1070,7 +1087,7 @@ static long trusted_read(const struct key *key, char __user *buffer, | |||
1070 | 1087 | ||
1071 | bufp = ascii_buf; | 1088 | bufp = ascii_buf; |
1072 | for (i = 0; i < p->blob_len; i++) | 1089 | for (i = 0; i < p->blob_len; i++) |
1073 | bufp = hex_byte_pack(bufp, p->blob[i]); | 1090 | bufp = pack_hex_byte(bufp, p->blob[i]); |
1074 | if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) { | 1091 | if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) { |
1075 | kfree(ascii_buf); | 1092 | kfree(ascii_buf); |
1076 | return -EFAULT; | 1093 | return -EFAULT; |