diff options
-rw-r--r-- | security/keys/trusted_defined.c | 149 |
1 files changed, 87 insertions, 62 deletions
diff --git a/security/keys/trusted_defined.c b/security/keys/trusted_defined.c index aaaa069967a6..3dc3db15b5d9 100644 --- a/security/keys/trusted_defined.c +++ b/security/keys/trusted_defined.c | |||
@@ -108,7 +108,8 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key, | |||
108 | goto out; | 108 | goto out; |
109 | } | 109 | } |
110 | va_end(argp); | 110 | va_end(argp); |
111 | ret = crypto_shash_final(&sdesc->shash, digest); | 111 | if (!ret) |
112 | ret = crypto_shash_final(&sdesc->shash, digest); | ||
112 | out: | 113 | out: |
113 | kfree(sdesc); | 114 | kfree(sdesc); |
114 | return ret; | 115 | return ret; |
@@ -117,9 +118,9 @@ out: | |||
117 | /* | 118 | /* |
118 | * calculate authorization info fields to send to TPM | 119 | * calculate authorization info fields to send to TPM |
119 | */ | 120 | */ |
120 | static uint32_t TSS_authhmac(unsigned char *digest, const unsigned char *key, | 121 | static int TSS_authhmac(unsigned char *digest, const unsigned char *key, |
121 | const unsigned int keylen, unsigned char *h1, | 122 | const unsigned int keylen, unsigned char *h1, |
122 | unsigned char *h2, unsigned char h3, ...) | 123 | unsigned char *h2, unsigned char h3, ...) |
123 | { | 124 | { |
124 | unsigned char paramdigest[SHA1_DIGEST_SIZE]; | 125 | unsigned char paramdigest[SHA1_DIGEST_SIZE]; |
125 | struct sdesc *sdesc; | 126 | struct sdesc *sdesc; |
@@ -146,15 +147,17 @@ static uint32_t TSS_authhmac(unsigned char *digest, const unsigned char *key, | |||
146 | break; | 147 | break; |
147 | data = va_arg(argp, unsigned char *); | 148 | data = va_arg(argp, unsigned char *); |
148 | ret = crypto_shash_update(&sdesc->shash, data, dlen); | 149 | ret = crypto_shash_update(&sdesc->shash, data, dlen); |
149 | if (ret < 0) | 150 | if (ret < 0) { |
151 | va_end(argp); | ||
150 | goto out; | 152 | goto out; |
153 | } | ||
151 | } | 154 | } |
152 | va_end(argp); | 155 | va_end(argp); |
153 | ret = crypto_shash_final(&sdesc->shash, paramdigest); | 156 | ret = crypto_shash_final(&sdesc->shash, paramdigest); |
154 | if (!ret) | 157 | if (!ret) |
155 | TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE, | 158 | ret = TSS_rawhmac(digest, key, keylen, SHA1_DIGEST_SIZE, |
156 | paramdigest, TPM_NONCE_SIZE, h1, | 159 | paramdigest, TPM_NONCE_SIZE, h1, |
157 | TPM_NONCE_SIZE, h2, 1, &c, 0, 0); | 160 | TPM_NONCE_SIZE, h2, 1, &c, 0, 0); |
158 | out: | 161 | out: |
159 | kfree(sdesc); | 162 | kfree(sdesc); |
160 | return ret; | 163 | return ret; |
@@ -163,11 +166,11 @@ out: | |||
163 | /* | 166 | /* |
164 | * verify the AUTH1_COMMAND (Seal) result from TPM | 167 | * verify the AUTH1_COMMAND (Seal) result from TPM |
165 | */ | 168 | */ |
166 | static uint32_t TSS_checkhmac1(unsigned char *buffer, | 169 | static int TSS_checkhmac1(unsigned char *buffer, |
167 | const uint32_t command, | 170 | const uint32_t command, |
168 | const unsigned char *ononce, | 171 | const unsigned char *ononce, |
169 | const unsigned char *key, | 172 | const unsigned char *key, |
170 | const unsigned int keylen, ...) | 173 | const unsigned int keylen, ...) |
171 | { | 174 | { |
172 | uint32_t bufsize; | 175 | uint32_t bufsize; |
173 | uint16_t tag; | 176 | uint16_t tag; |
@@ -219,18 +222,22 @@ static uint32_t TSS_checkhmac1(unsigned char *buffer, | |||
219 | break; | 222 | break; |
220 | dpos = va_arg(argp, unsigned int); | 223 | dpos = va_arg(argp, unsigned int); |
221 | ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); | 224 | ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); |
222 | if (ret < 0) | 225 | if (ret < 0) { |
226 | va_end(argp); | ||
223 | goto out; | 227 | goto out; |
228 | } | ||
224 | } | 229 | } |
225 | va_end(argp); | 230 | va_end(argp); |
226 | ret = crypto_shash_final(&sdesc->shash, paramdigest); | 231 | ret = crypto_shash_final(&sdesc->shash, paramdigest); |
227 | if (ret < 0) | 232 | if (ret < 0) |
228 | goto out; | 233 | goto out; |
234 | |||
229 | ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest, | 235 | ret = TSS_rawhmac(testhmac, key, keylen, SHA1_DIGEST_SIZE, paramdigest, |
230 | TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce, | 236 | TPM_NONCE_SIZE, enonce, TPM_NONCE_SIZE, ononce, |
231 | 1, continueflag, 0, 0); | 237 | 1, continueflag, 0, 0); |
232 | if (ret < 0) | 238 | if (ret < 0) |
233 | goto out; | 239 | goto out; |
240 | |||
234 | if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE)) | 241 | if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE)) |
235 | ret = -EINVAL; | 242 | ret = -EINVAL; |
236 | out: | 243 | out: |
@@ -241,13 +248,13 @@ out: | |||
241 | /* | 248 | /* |
242 | * verify the AUTH2_COMMAND (unseal) result from TPM | 249 | * verify the AUTH2_COMMAND (unseal) result from TPM |
243 | */ | 250 | */ |
244 | static uint32_t TSS_checkhmac2(unsigned char *buffer, | 251 | static int TSS_checkhmac2(unsigned char *buffer, |
245 | const uint32_t command, | 252 | const uint32_t command, |
246 | const unsigned char *ononce, | 253 | const unsigned char *ononce, |
247 | const unsigned char *key1, | 254 | const unsigned char *key1, |
248 | const unsigned int keylen1, | 255 | const unsigned int keylen1, |
249 | const unsigned char *key2, | 256 | const unsigned char *key2, |
250 | const unsigned int keylen2, ...) | 257 | const unsigned int keylen2, ...) |
251 | { | 258 | { |
252 | uint32_t bufsize; | 259 | uint32_t bufsize; |
253 | uint16_t tag; | 260 | uint16_t tag; |
@@ -309,9 +316,12 @@ static uint32_t TSS_checkhmac2(unsigned char *buffer, | |||
309 | break; | 316 | break; |
310 | dpos = va_arg(argp, unsigned int); | 317 | dpos = va_arg(argp, unsigned int); |
311 | ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); | 318 | ret = crypto_shash_update(&sdesc->shash, buffer + dpos, dlen); |
312 | if (ret < 0) | 319 | if (ret < 0) { |
320 | va_end(argp); | ||
313 | goto out; | 321 | goto out; |
322 | } | ||
314 | } | 323 | } |
324 | va_end(argp); | ||
315 | ret = crypto_shash_final(&sdesc->shash, paramdigest); | 325 | ret = crypto_shash_final(&sdesc->shash, paramdigest); |
316 | if (ret < 0) | 326 | if (ret < 0) |
317 | goto out; | 327 | goto out; |
@@ -319,6 +329,8 @@ static uint32_t TSS_checkhmac2(unsigned char *buffer, | |||
319 | ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE, | 329 | ret = TSS_rawhmac(testhmac1, key1, keylen1, SHA1_DIGEST_SIZE, |
320 | paramdigest, TPM_NONCE_SIZE, enonce1, | 330 | paramdigest, TPM_NONCE_SIZE, enonce1, |
321 | TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0); | 331 | TPM_NONCE_SIZE, ononce, 1, continueflag1, 0, 0); |
332 | if (ret < 0) | ||
333 | goto out; | ||
322 | if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) { | 334 | if (memcmp(testhmac1, authdata1, SHA1_DIGEST_SIZE)) { |
323 | ret = -EINVAL; | 335 | ret = -EINVAL; |
324 | goto out; | 336 | goto out; |
@@ -326,6 +338,8 @@ static uint32_t TSS_checkhmac2(unsigned char *buffer, | |||
326 | ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE, | 338 | ret = TSS_rawhmac(testhmac2, key2, keylen2, SHA1_DIGEST_SIZE, |
327 | paramdigest, TPM_NONCE_SIZE, enonce2, | 339 | paramdigest, TPM_NONCE_SIZE, enonce2, |
328 | TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0); | 340 | TPM_NONCE_SIZE, ononce, 1, continueflag2, 0, 0); |
341 | if (ret < 0) | ||
342 | goto out; | ||
329 | if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE)) | 343 | if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE)) |
330 | ret = -EINVAL; | 344 | ret = -EINVAL; |
331 | out: | 345 | out: |
@@ -364,8 +378,8 @@ static int tpm_get_random(struct tpm_buf *tb, unsigned char *buf, uint32_t len) | |||
364 | store32(tb, TPM_ORD_GETRANDOM); | 378 | store32(tb, TPM_ORD_GETRANDOM); |
365 | store32(tb, len); | 379 | store32(tb, len); |
366 | ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data); | 380 | ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data); |
367 | memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len); | 381 | if (!ret) |
368 | 382 | memcpy(buf, tb->data + TPM_GETRANDOM_SIZE, len); | |
369 | return ret; | 383 | return ret; |
370 | } | 384 | } |
371 | 385 | ||
@@ -392,10 +406,13 @@ static int my_get_random(unsigned char *buf, int len) | |||
392 | static int pcrlock(const int pcrnum) | 406 | static int pcrlock(const int pcrnum) |
393 | { | 407 | { |
394 | unsigned char hash[SHA1_DIGEST_SIZE]; | 408 | unsigned char hash[SHA1_DIGEST_SIZE]; |
409 | int ret; | ||
395 | 410 | ||
396 | if (!capable(CAP_SYS_ADMIN)) | 411 | if (!capable(CAP_SYS_ADMIN)) |
397 | return -EPERM; | 412 | return -EPERM; |
398 | my_get_random(hash, SHA1_DIGEST_SIZE); | 413 | ret = my_get_random(hash, SHA1_DIGEST_SIZE); |
414 | if (ret < 0) | ||
415 | return ret; | ||
399 | return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0; | 416 | return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0; |
400 | } | 417 | } |
401 | 418 | ||
@@ -431,9 +448,8 @@ static int osap(struct tpm_buf *tb, struct osapsess *s, | |||
431 | TPM_NONCE_SIZE); | 448 | TPM_NONCE_SIZE); |
432 | memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) + | 449 | memcpy(enonce, &(tb->data[TPM_DATA_OFFSET + sizeof(uint32_t) + |
433 | TPM_NONCE_SIZE]), TPM_NONCE_SIZE); | 450 | TPM_NONCE_SIZE]), TPM_NONCE_SIZE); |
434 | ret = TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE, | 451 | return TSS_rawhmac(s->secret, key, SHA1_DIGEST_SIZE, TPM_NONCE_SIZE, |
435 | enonce, TPM_NONCE_SIZE, ononce, 0, 0); | 452 | enonce, TPM_NONCE_SIZE, ononce, 0, 0); |
436 | return ret; | ||
437 | } | 453 | } |
438 | 454 | ||
439 | /* | 455 | /* |
@@ -454,7 +470,7 @@ static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) | |||
454 | *handle = LOAD32(tb->data, TPM_DATA_OFFSET); | 470 | *handle = LOAD32(tb->data, TPM_DATA_OFFSET); |
455 | memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)], | 471 | memcpy(nonce, &tb->data[TPM_DATA_OFFSET + sizeof(uint32_t)], |
456 | TPM_NONCE_SIZE); | 472 | TPM_NONCE_SIZE); |
457 | return ret; | 473 | return 0; |
458 | } | 474 | } |
459 | 475 | ||
460 | struct tpm_digests { | 476 | struct tpm_digests { |
@@ -521,20 +537,23 @@ static int tpm_seal(struct tpm_buf *tb, const uint16_t keytype, | |||
521 | /* calculate authorization HMAC value */ | 537 | /* calculate authorization HMAC value */ |
522 | if (pcrinfosize == 0) { | 538 | if (pcrinfosize == 0) { |
523 | /* no pcr info specified */ | 539 | /* no pcr info specified */ |
524 | TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, | 540 | ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, |
525 | sess.enonce, td->nonceodd, cont, sizeof(uint32_t), | 541 | sess.enonce, td->nonceodd, cont, |
526 | &ordinal, SHA1_DIGEST_SIZE, td->encauth, | 542 | sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE, |
527 | sizeof(uint32_t), &pcrsize, sizeof(uint32_t), | 543 | td->encauth, sizeof(uint32_t), &pcrsize, |
528 | &datsize, datalen, data, 0, 0); | 544 | sizeof(uint32_t), &datsize, datalen, data, 0, |
545 | 0); | ||
529 | } else { | 546 | } else { |
530 | /* pcr info specified */ | 547 | /* pcr info specified */ |
531 | TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, | 548 | ret = TSS_authhmac(td->pubauth, sess.secret, SHA1_DIGEST_SIZE, |
532 | sess.enonce, td->nonceodd, cont, sizeof(uint32_t), | 549 | sess.enonce, td->nonceodd, cont, |
533 | &ordinal, SHA1_DIGEST_SIZE, td->encauth, | 550 | sizeof(uint32_t), &ordinal, SHA1_DIGEST_SIZE, |
534 | sizeof(uint32_t), &pcrsize, pcrinfosize, | 551 | td->encauth, sizeof(uint32_t), &pcrsize, |
535 | pcrinfo, sizeof(uint32_t), &datsize, datalen, | 552 | pcrinfosize, pcrinfo, sizeof(uint32_t), |
536 | data, 0, 0); | 553 | &datsize, datalen, data, 0, 0); |
537 | } | 554 | } |
555 | if (ret < 0) | ||
556 | return ret; | ||
538 | 557 | ||
539 | /* build and send the TPM request packet */ | 558 | /* build and send the TPM request packet */ |
540 | INIT_BUF(tb); | 559 | INIT_BUF(tb); |
@@ -569,8 +588,10 @@ static int tpm_seal(struct tpm_buf *tb, const uint16_t keytype, | |||
569 | 0); | 588 | 0); |
570 | 589 | ||
571 | /* copy the returned blob to caller */ | 590 | /* copy the returned blob to caller */ |
572 | memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize); | 591 | if (!ret) { |
573 | *bloblen = storedsize; | 592 | memcpy(blob, tb->data + TPM_DATA_OFFSET, storedsize); |
593 | *bloblen = storedsize; | ||
594 | } | ||
574 | return ret; | 595 | return ret; |
575 | } | 596 | } |
576 | 597 | ||
@@ -614,12 +635,16 @@ static int tpm_unseal(struct tpm_buf *tb, | |||
614 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); | 635 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); |
615 | return ret; | 636 | return ret; |
616 | } | 637 | } |
617 | TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE, | 638 | ret = TSS_authhmac(authdata1, keyauth, TPM_NONCE_SIZE, |
618 | enonce1, nonceodd, cont, sizeof(uint32_t), | 639 | enonce1, nonceodd, cont, sizeof(uint32_t), |
619 | &ordinal, bloblen, blob, 0, 0); | 640 | &ordinal, bloblen, blob, 0, 0); |
620 | TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE, | 641 | if (ret < 0) |
621 | enonce2, nonceodd, cont, sizeof(uint32_t), | 642 | return ret; |
622 | &ordinal, bloblen, blob, 0, 0); | 643 | ret = TSS_authhmac(authdata2, blobauth, TPM_NONCE_SIZE, |
644 | enonce2, nonceodd, cont, sizeof(uint32_t), | ||
645 | &ordinal, bloblen, blob, 0, 0); | ||
646 | if (ret < 0) | ||
647 | return ret; | ||
623 | 648 | ||
624 | /* build and send TPM request packet */ | 649 | /* build and send TPM request packet */ |
625 | INIT_BUF(tb); | 650 | INIT_BUF(tb); |
@@ -650,10 +675,12 @@ static int tpm_unseal(struct tpm_buf *tb, | |||
650 | sizeof(uint32_t), TPM_DATA_OFFSET, | 675 | sizeof(uint32_t), TPM_DATA_OFFSET, |
651 | *datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0, | 676 | *datalen, TPM_DATA_OFFSET + sizeof(uint32_t), 0, |
652 | 0); | 677 | 0); |
653 | if (ret < 0) | 678 | if (ret < 0) { |
654 | pr_info("trusted_key: TSS_checkhmac2 failed (%d)\n", ret); | 679 | pr_info("trusted_key: TSS_checkhmac2 failed (%d)\n", ret); |
680 | return ret; | ||
681 | } | ||
655 | memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen); | 682 | memcpy(data, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t), *datalen); |
656 | return ret; | 683 | return 0; |
657 | } | 684 | } |
658 | 685 | ||
659 | /* | 686 | /* |
@@ -697,11 +724,11 @@ static int key_unseal(struct trusted_key_payload *p, | |||
697 | 724 | ||
698 | ret = tpm_unseal(tb, o->keyhandle, o->keyauth, p->blob, p->blob_len, | 725 | ret = tpm_unseal(tb, o->keyhandle, o->keyauth, p->blob, p->blob_len, |
699 | o->blobauth, p->key, &p->key_len); | 726 | o->blobauth, p->key, &p->key_len); |
700 | /* pull migratable flag out of sealed key */ | ||
701 | p->migratable = p->key[--p->key_len]; | ||
702 | |||
703 | if (ret < 0) | 727 | if (ret < 0) |
704 | pr_info("trusted_key: srkunseal failed (%d)\n", ret); | 728 | pr_info("trusted_key: srkunseal failed (%d)\n", ret); |
729 | else | ||
730 | /* pull migratable flag out of sealed key */ | ||
731 | p->migratable = p->key[--p->key_len]; | ||
705 | 732 | ||
706 | kfree(tb); | 733 | kfree(tb); |
707 | return ret; | 734 | return ret; |
@@ -854,12 +881,11 @@ static struct trusted_key_options *trusted_options_alloc(void) | |||
854 | struct trusted_key_options *options; | 881 | struct trusted_key_options *options; |
855 | 882 | ||
856 | options = kzalloc(sizeof *options, GFP_KERNEL); | 883 | options = kzalloc(sizeof *options, GFP_KERNEL); |
857 | if (!options) | 884 | if (options) { |
858 | return options; | 885 | /* set any non-zero defaults */ |
859 | 886 | options->keytype = SRK_keytype; | |
860 | /* set any non-zero defaults */ | 887 | options->keyhandle = SRKHANDLE; |
861 | options->keytype = SRK_keytype; | 888 | } |
862 | options->keyhandle = SRKHANDLE; | ||
863 | return options; | 889 | return options; |
864 | } | 890 | } |
865 | 891 | ||
@@ -872,9 +898,8 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) | |||
872 | if (ret < 0) | 898 | if (ret < 0) |
873 | return p; | 899 | return p; |
874 | p = kzalloc(sizeof *p, GFP_KERNEL); | 900 | p = kzalloc(sizeof *p, GFP_KERNEL); |
875 | 901 | if (p) | |
876 | /* migratable by default */ | 902 | p->migratable = 1; /* migratable by default */ |
877 | p->migratable = 1; | ||
878 | return p; | 903 | return p; |
879 | } | 904 | } |
880 | 905 | ||