diff options
author | Jarkko Sakkinen | 2016-08-16 14:00:38 -0500 |
---|---|---|
committer | Greg Kroah-Hartman | 2016-10-16 10:36:15 -0500 |
commit | c0201ae6796a830fa7eb0cb537239102bedcbcc5 (patch) | |
tree | 6fa9c6ca61906a98a7e42d5e8eabeac1f7ce7c6f | |
parent | 0040b7466cbd6d7a7f84d0eed86e328da21c0e27 (diff) | |
download | graphics-kernel-feature-tree-c0201ae6796a830fa7eb0cb537239102bedcbcc5.tar.gz graphics-kernel-feature-tree-c0201ae6796a830fa7eb0cb537239102bedcbcc5.tar.xz graphics-kernel-feature-tree-c0201ae6796a830fa7eb0cb537239102bedcbcc5.zip |
tpm: fix a race condition in tpm2_unseal_trusted()
commit d4816edfe706497a8525480c1685ceb9871bc118 upstream.
Unseal and load operations should be done as an atomic operation. This
commit introduces unlocked tpm_transmit() so that tpm2_unseal_trusted()
can do the locking by itself.
Fixes: 0fe5480303a1 ("keys, trusted: seal/unseal with TPM 2.0 chips")
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/char/tpm/tpm-dev.c | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 51 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-sysfs.c | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 12 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 101 |
5 files changed, 103 insertions, 65 deletions
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c index de0337ebd658..4f3137d9a35e 100644 --- a/drivers/char/tpm/tpm-dev.c +++ b/drivers/char/tpm/tpm-dev.c | |||
@@ -139,7 +139,7 @@ static ssize_t tpm_write(struct file *file, const char __user *buf, | |||
139 | 139 | ||
140 | /* atomic tpm command send and result receive */ | 140 | /* atomic tpm command send and result receive */ |
141 | out_size = tpm_transmit(priv->chip, priv->data_buffer, | 141 | out_size = tpm_transmit(priv->chip, priv->data_buffer, |
142 | sizeof(priv->data_buffer)); | 142 | sizeof(priv->data_buffer), 0); |
143 | if (out_size < 0) { | 143 | if (out_size < 0) { |
144 | mutex_unlock(&priv->buffer_mutex); | 144 | mutex_unlock(&priv->buffer_mutex); |
145 | return out_size; | 145 | return out_size; |
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index c50637db3a8a..17abe52e6365 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
@@ -328,8 +328,8 @@ EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); | |||
328 | /* | 328 | /* |
329 | * Internal kernel interface to transmit TPM commands | 329 | * Internal kernel interface to transmit TPM commands |
330 | */ | 330 | */ |
331 | ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | 331 | ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, |
332 | size_t bufsiz) | 332 | unsigned int flags) |
333 | { | 333 | { |
334 | ssize_t rc; | 334 | ssize_t rc; |
335 | u32 count, ordinal; | 335 | u32 count, ordinal; |
@@ -348,7 +348,8 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | |||
348 | return -E2BIG; | 348 | return -E2BIG; |
349 | } | 349 | } |
350 | 350 | ||
351 | mutex_lock(&chip->tpm_mutex); | 351 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) |
352 | mutex_lock(&chip->tpm_mutex); | ||
352 | 353 | ||
353 | rc = chip->ops->send(chip, (u8 *) buf, count); | 354 | rc = chip->ops->send(chip, (u8 *) buf, count); |
354 | if (rc < 0) { | 355 | if (rc < 0) { |
@@ -391,20 +392,21 @@ out_recv: | |||
391 | dev_err(chip->pdev, | 392 | dev_err(chip->pdev, |
392 | "tpm_transmit: tpm_recv: error %zd\n", rc); | 393 | "tpm_transmit: tpm_recv: error %zd\n", rc); |
393 | out: | 394 | out: |
394 | mutex_unlock(&chip->tpm_mutex); | 395 | if (!(flags & TPM_TRANSMIT_UNLOCKED)) |
396 | mutex_unlock(&chip->tpm_mutex); | ||
395 | return rc; | 397 | return rc; |
396 | } | 398 | } |
397 | 399 | ||
398 | #define TPM_DIGEST_SIZE 20 | 400 | #define TPM_DIGEST_SIZE 20 |
399 | #define TPM_RET_CODE_IDX 6 | 401 | #define TPM_RET_CODE_IDX 6 |
400 | 402 | ||
401 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, | 403 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, |
402 | int len, const char *desc) | 404 | int len, unsigned int flags, const char *desc) |
403 | { | 405 | { |
404 | struct tpm_output_header *header; | 406 | const struct tpm_output_header *header; |
405 | int err; | 407 | int err; |
406 | 408 | ||
407 | len = tpm_transmit(chip, (u8 *) cmd, len); | 409 | len = tpm_transmit(chip, (const u8 *)cmd, len, flags); |
408 | if (len < 0) | 410 | if (len < 0) |
409 | return len; | 411 | return len; |
410 | else if (len < TPM_HEADER_SIZE) | 412 | else if (len < TPM_HEADER_SIZE) |
@@ -452,7 +454,8 @@ ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap, | |||
452 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | 454 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
453 | tpm_cmd.params.getcap_in.subcap = subcap_id; | 455 | tpm_cmd.params.getcap_in.subcap = subcap_id; |
454 | } | 456 | } |
455 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc); | 457 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0, |
458 | desc); | ||
456 | if (!rc) | 459 | if (!rc) |
457 | *cap = tpm_cmd.params.getcap_out.cap; | 460 | *cap = tpm_cmd.params.getcap_out.cap; |
458 | return rc; | 461 | return rc; |
@@ -468,7 +471,7 @@ void tpm_gen_interrupt(struct tpm_chip *chip) | |||
468 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | 471 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
469 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; | 472 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; |
470 | 473 | ||
471 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | 474 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0, |
472 | "attempting to determine the timeouts"); | 475 | "attempting to determine the timeouts"); |
473 | } | 476 | } |
474 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); | 477 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); |
@@ -489,7 +492,7 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) | |||
489 | start_cmd.header.in = tpm_startup_header; | 492 | start_cmd.header.in = tpm_startup_header; |
490 | 493 | ||
491 | start_cmd.params.startup_in.startup_type = startup_type; | 494 | start_cmd.params.startup_in.startup_type = startup_type; |
492 | return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, | 495 | return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, 0, |
493 | "attempting to start the TPM"); | 496 | "attempting to start the TPM"); |
494 | } | 497 | } |
495 | 498 | ||
@@ -505,7 +508,8 @@ int tpm_get_timeouts(struct tpm_chip *chip) | |||
505 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; | 508 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; |
506 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | 509 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
507 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; | 510 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; |
508 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, NULL); | 511 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0, |
512 | NULL); | ||
509 | 513 | ||
510 | if (rc == TPM_ERR_INVALID_POSTINIT) { | 514 | if (rc == TPM_ERR_INVALID_POSTINIT) { |
511 | /* The TPM is not started, we are the first to talk to it. | 515 | /* The TPM is not started, we are the first to talk to it. |
@@ -519,7 +523,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) | |||
519 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | 523 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
520 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; | 524 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; |
521 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | 525 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
522 | NULL); | 526 | 0, NULL); |
523 | } | 527 | } |
524 | if (rc) { | 528 | if (rc) { |
525 | dev_err(chip->pdev, | 529 | dev_err(chip->pdev, |
@@ -580,7 +584,7 @@ duration: | |||
580 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | 584 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
581 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; | 585 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; |
582 | 586 | ||
583 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | 587 | rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0, |
584 | "attempting to determine the durations"); | 588 | "attempting to determine the durations"); |
585 | if (rc) | 589 | if (rc) |
586 | return rc; | 590 | return rc; |
@@ -636,7 +640,7 @@ static int tpm_continue_selftest(struct tpm_chip *chip) | |||
636 | struct tpm_cmd_t cmd; | 640 | struct tpm_cmd_t cmd; |
637 | 641 | ||
638 | cmd.header.in = continue_selftest_header; | 642 | cmd.header.in = continue_selftest_header; |
639 | rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, | 643 | rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, 0, |
640 | "continue selftest"); | 644 | "continue selftest"); |
641 | return rc; | 645 | return rc; |
642 | } | 646 | } |
@@ -656,7 +660,7 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | |||
656 | 660 | ||
657 | cmd.header.in = pcrread_header; | 661 | cmd.header.in = pcrread_header; |
658 | cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); | 662 | cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); |
659 | rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, | 663 | rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, 0, |
660 | "attempting to read a pcr value"); | 664 | "attempting to read a pcr value"); |
661 | 665 | ||
662 | if (rc == 0) | 666 | if (rc == 0) |
@@ -754,7 +758,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) | |||
754 | cmd.header.in = pcrextend_header; | 758 | cmd.header.in = pcrextend_header; |
755 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); | 759 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); |
756 | memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); | 760 | memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); |
757 | rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, | 761 | rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, 0, |
758 | "attempting extend a PCR value"); | 762 | "attempting extend a PCR value"); |
759 | 763 | ||
760 | tpm_chip_put(chip); | 764 | tpm_chip_put(chip); |
@@ -793,7 +797,7 @@ int tpm_do_selftest(struct tpm_chip *chip) | |||
793 | /* Attempt to read a PCR value */ | 797 | /* Attempt to read a PCR value */ |
794 | cmd.header.in = pcrread_header; | 798 | cmd.header.in = pcrread_header; |
795 | cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0); | 799 | cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0); |
796 | rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE); | 800 | rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE, 0); |
797 | /* Some buggy TPMs will not respond to tpm_tis_ready() for | 801 | /* Some buggy TPMs will not respond to tpm_tis_ready() for |
798 | * around 300ms while the self test is ongoing, keep trying | 802 | * around 300ms while the self test is ongoing, keep trying |
799 | * until the self test duration expires. */ | 803 | * until the self test duration expires. */ |
@@ -834,7 +838,7 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen) | |||
834 | if (chip == NULL) | 838 | if (chip == NULL) |
835 | return -ENODEV; | 839 | return -ENODEV; |
836 | 840 | ||
837 | rc = tpm_transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd"); | 841 | rc = tpm_transmit_cmd(chip, cmd, buflen, 0, "attempting tpm_cmd"); |
838 | 842 | ||
839 | tpm_chip_put(chip); | 843 | tpm_chip_put(chip); |
840 | return rc; | 844 | return rc; |
@@ -936,14 +940,15 @@ int tpm_pm_suspend(struct device *dev) | |||
936 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); | 940 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); |
937 | memcpy(cmd.params.pcrextend_in.hash, dummy_hash, | 941 | memcpy(cmd.params.pcrextend_in.hash, dummy_hash, |
938 | TPM_DIGEST_SIZE); | 942 | TPM_DIGEST_SIZE); |
939 | rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, | 943 | rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, 0, |
940 | "extending dummy pcr before suspend"); | 944 | "extending dummy pcr before suspend"); |
941 | } | 945 | } |
942 | 946 | ||
943 | /* now do the actual savestate */ | 947 | /* now do the actual savestate */ |
944 | for (try = 0; try < TPM_RETRY; try++) { | 948 | for (try = 0; try < TPM_RETRY; try++) { |
945 | cmd.header.in = savestate_header; | 949 | cmd.header.in = savestate_header; |
946 | rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL); | 950 | rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, 0, |
951 | NULL); | ||
947 | 952 | ||
948 | /* | 953 | /* |
949 | * If the TPM indicates that it is too busy to respond to | 954 | * If the TPM indicates that it is too busy to respond to |
@@ -1027,8 +1032,8 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) | |||
1027 | tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); | 1032 | tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); |
1028 | 1033 | ||
1029 | err = tpm_transmit_cmd(chip, &tpm_cmd, | 1034 | err = tpm_transmit_cmd(chip, &tpm_cmd, |
1030 | TPM_GETRANDOM_RESULT_SIZE + num_bytes, | 1035 | TPM_GETRANDOM_RESULT_SIZE + num_bytes, |
1031 | "attempting get random"); | 1036 | 0, "attempting get random"); |
1032 | if (err) | 1037 | if (err) |
1033 | break; | 1038 | break; |
1034 | 1039 | ||
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index ee66fd4673f3..f880856aa75e 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c | |||
@@ -39,7 +39,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, | |||
39 | struct tpm_chip *chip = dev_get_drvdata(dev); | 39 | struct tpm_chip *chip = dev_get_drvdata(dev); |
40 | 40 | ||
41 | tpm_cmd.header.in = tpm_readpubek_header; | 41 | tpm_cmd.header.in = tpm_readpubek_header; |
42 | err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, | 42 | err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, 0, |
43 | "attempting to read the PUBEK"); | 43 | "attempting to read the PUBEK"); |
44 | if (err) | 44 | if (err) |
45 | goto out; | 45 | goto out; |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index a4257a32964f..2216861f89f1 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -498,11 +498,15 @@ extern struct class *tpm_class; | |||
498 | extern dev_t tpm_devt; | 498 | extern dev_t tpm_devt; |
499 | extern const struct file_operations tpm_fops; | 499 | extern const struct file_operations tpm_fops; |
500 | 500 | ||
501 | enum tpm_transmit_flags { | ||
502 | TPM_TRANSMIT_UNLOCKED = BIT(0), | ||
503 | }; | ||
504 | |||
505 | ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, | ||
506 | unsigned int flags); | ||
507 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, int len, | ||
508 | unsigned int flags, const char *desc); | ||
501 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); | 509 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); |
502 | ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | ||
503 | size_t bufsiz); | ||
504 | ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, int len, | ||
505 | const char *desc); | ||
506 | extern int tpm_get_timeouts(struct tpm_chip *); | 510 | extern int tpm_get_timeouts(struct tpm_chip *); |
507 | extern void tpm_gen_interrupt(struct tpm_chip *); | 511 | extern void tpm_gen_interrupt(struct tpm_chip *); |
508 | extern int tpm_do_selftest(struct tpm_chip *); | 512 | extern int tpm_do_selftest(struct tpm_chip *); |
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 678af51fb29e..cb7e4f6b70ba 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
@@ -264,7 +264,7 @@ int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | |||
264 | sizeof(cmd.params.pcrread_in.pcr_select)); | 264 | sizeof(cmd.params.pcrread_in.pcr_select)); |
265 | cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); | 265 | cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); |
266 | 266 | ||
267 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | 267 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, |
268 | "attempting to read a pcr value"); | 268 | "attempting to read a pcr value"); |
269 | if (rc == 0) { | 269 | if (rc == 0) { |
270 | buf = cmd.params.pcrread_out.digest; | 270 | buf = cmd.params.pcrread_out.digest; |
@@ -312,7 +312,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) | |||
312 | cmd.params.pcrextend_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1); | 312 | cmd.params.pcrextend_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1); |
313 | memcpy(cmd.params.pcrextend_in.digest, hash, TPM_DIGEST_SIZE); | 313 | memcpy(cmd.params.pcrextend_in.digest, hash, TPM_DIGEST_SIZE); |
314 | 314 | ||
315 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | 315 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, |
316 | "attempting extend a PCR value"); | 316 | "attempting extend a PCR value"); |
317 | 317 | ||
318 | return rc; | 318 | return rc; |
@@ -358,7 +358,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max) | |||
358 | cmd.header.in = tpm2_getrandom_header; | 358 | cmd.header.in = tpm2_getrandom_header; |
359 | cmd.params.getrandom_in.size = cpu_to_be16(num_bytes); | 359 | cmd.params.getrandom_in.size = cpu_to_be16(num_bytes); |
360 | 360 | ||
361 | err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | 361 | err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, |
362 | "attempting get random"); | 362 | "attempting get random"); |
363 | if (err) | 363 | if (err) |
364 | break; | 364 | break; |
@@ -416,12 +416,12 @@ static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle, | |||
416 | } | 416 | } |
417 | 417 | ||
418 | /** | 418 | /** |
419 | * tpm2_seal_trusted() - seal a trusted key | 419 | * tpm2_seal_trusted() - seal the payload of a trusted key |
420 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | 420 | * @chip_num: TPM chip to use |
421 | * @options: authentication values and other options | ||
422 | * @payload: the key data in clear and encrypted form | 421 | * @payload: the key data in clear and encrypted form |
422 | * @options: authentication values and other options | ||
423 | * | 423 | * |
424 | * Returns < 0 on error and 0 on success. | 424 | * Return: < 0 on error and 0 on success. |
425 | */ | 425 | */ |
426 | int tpm2_seal_trusted(struct tpm_chip *chip, | 426 | int tpm2_seal_trusted(struct tpm_chip *chip, |
427 | struct trusted_key_payload *payload, | 427 | struct trusted_key_payload *payload, |
@@ -472,7 +472,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, | |||
472 | goto out; | 472 | goto out; |
473 | } | 473 | } |
474 | 474 | ||
475 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "sealing data"); | 475 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, "sealing data"); |
476 | if (rc) | 476 | if (rc) |
477 | goto out; | 477 | goto out; |
478 | 478 | ||
@@ -494,10 +494,18 @@ out: | |||
494 | return rc; | 494 | return rc; |
495 | } | 495 | } |
496 | 496 | ||
497 | static int tpm2_load(struct tpm_chip *chip, | 497 | /** |
498 | struct trusted_key_payload *payload, | 498 | * tpm2_load_cmd() - execute a TPM2_Load command |
499 | struct trusted_key_options *options, | 499 | * @chip_num: TPM chip to use |
500 | u32 *blob_handle) | 500 | * @payload: the key data in clear and encrypted form |
501 | * @options: authentication values and other options | ||
502 | * | ||
503 | * Return: same as with tpm_transmit_cmd | ||
504 | */ | ||
505 | static int tpm2_load_cmd(struct tpm_chip *chip, | ||
506 | struct trusted_key_payload *payload, | ||
507 | struct trusted_key_options *options, | ||
508 | u32 *blob_handle, unsigned int flags) | ||
501 | { | 509 | { |
502 | struct tpm_buf buf; | 510 | struct tpm_buf buf; |
503 | unsigned int private_len; | 511 | unsigned int private_len; |
@@ -532,7 +540,7 @@ static int tpm2_load(struct tpm_chip *chip, | |||
532 | goto out; | 540 | goto out; |
533 | } | 541 | } |
534 | 542 | ||
535 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "loading blob"); | 543 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags, "loading blob"); |
536 | if (!rc) | 544 | if (!rc) |
537 | *blob_handle = be32_to_cpup( | 545 | *blob_handle = be32_to_cpup( |
538 | (__be32 *) &buf.data[TPM_HEADER_SIZE]); | 546 | (__be32 *) &buf.data[TPM_HEADER_SIZE]); |
@@ -546,7 +554,16 @@ out: | |||
546 | return rc; | 554 | return rc; |
547 | } | 555 | } |
548 | 556 | ||
549 | static void tpm2_flush_context(struct tpm_chip *chip, u32 handle) | 557 | /** |
558 | * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command | ||
559 | * @chip_num: TPM chip to use | ||
560 | * @payload: the key data in clear and encrypted form | ||
561 | * @options: authentication values and other options | ||
562 | * | ||
563 | * Return: same as with tpm_transmit_cmd | ||
564 | */ | ||
565 | static void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, | ||
566 | unsigned int flags) | ||
550 | { | 567 | { |
551 | struct tpm_buf buf; | 568 | struct tpm_buf buf; |
552 | int rc; | 569 | int rc; |
@@ -560,7 +577,8 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle) | |||
560 | 577 | ||
561 | tpm_buf_append_u32(&buf, handle); | 578 | tpm_buf_append_u32(&buf, handle); |
562 | 579 | ||
563 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context"); | 580 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags, |
581 | "flushing context"); | ||
564 | if (rc) | 582 | if (rc) |
565 | dev_warn(chip->pdev, "0x%08x was not flushed, rc=%d\n", handle, | 583 | dev_warn(chip->pdev, "0x%08x was not flushed, rc=%d\n", handle, |
566 | rc); | 584 | rc); |
@@ -568,10 +586,18 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle) | |||
568 | tpm_buf_destroy(&buf); | 586 | tpm_buf_destroy(&buf); |
569 | } | 587 | } |
570 | 588 | ||
571 | static int tpm2_unseal(struct tpm_chip *chip, | 589 | /** |
572 | struct trusted_key_payload *payload, | 590 | * tpm2_unseal_cmd() - execute a TPM2_Unload command |
573 | struct trusted_key_options *options, | 591 | * @chip_num: TPM chip to use |
574 | u32 blob_handle) | 592 | * @payload: the key data in clear and encrypted form |
593 | * @options: authentication values and other options | ||
594 | * | ||
595 | * Return: same as with tpm_transmit_cmd | ||
596 | */ | ||
597 | static int tpm2_unseal_cmd(struct tpm_chip *chip, | ||
598 | struct trusted_key_payload *payload, | ||
599 | struct trusted_key_options *options, | ||
600 | u32 blob_handle, unsigned int flags) | ||
575 | { | 601 | { |
576 | struct tpm_buf buf; | 602 | struct tpm_buf buf; |
577 | u16 data_len; | 603 | u16 data_len; |
@@ -589,7 +615,7 @@ static int tpm2_unseal(struct tpm_chip *chip, | |||
589 | options->blobauth /* hmac */, | 615 | options->blobauth /* hmac */, |
590 | TPM_DIGEST_SIZE); | 616 | TPM_DIGEST_SIZE); |
591 | 617 | ||
592 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "unsealing"); | 618 | rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags, "unsealing"); |
593 | if (rc > 0) | 619 | if (rc > 0) |
594 | rc = -EPERM; | 620 | rc = -EPERM; |
595 | 621 | ||
@@ -608,12 +634,12 @@ static int tpm2_unseal(struct tpm_chip *chip, | |||
608 | } | 634 | } |
609 | 635 | ||
610 | /** | 636 | /** |
611 | * tpm_unseal_trusted() - unseal a trusted key | 637 | * tpm_unseal_trusted() - unseal the payload of a trusted key |
612 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | 638 | * @chip_num: TPM chip to use |
613 | * @options: authentication values and other options | ||
614 | * @payload: the key data in clear and encrypted form | 639 | * @payload: the key data in clear and encrypted form |
640 | * @options: authentication values and other options | ||
615 | * | 641 | * |
616 | * Returns < 0 on error and 0 on success. | 642 | * Return: < 0 on error and 0 on success. |
617 | */ | 643 | */ |
618 | int tpm2_unseal_trusted(struct tpm_chip *chip, | 644 | int tpm2_unseal_trusted(struct tpm_chip *chip, |
619 | struct trusted_key_payload *payload, | 645 | struct trusted_key_payload *payload, |
@@ -622,14 +648,17 @@ int tpm2_unseal_trusted(struct tpm_chip *chip, | |||
622 | u32 blob_handle; | 648 | u32 blob_handle; |
623 | int rc; | 649 | int rc; |
624 | 650 | ||
625 | rc = tpm2_load(chip, payload, options, &blob_handle); | 651 | mutex_lock(&chip->tpm_mutex); |
652 | rc = tpm2_load_cmd(chip, payload, options, &blob_handle, | ||
653 | TPM_TRANSMIT_UNLOCKED); | ||
626 | if (rc) | 654 | if (rc) |
627 | return rc; | 655 | goto out; |
628 | |||
629 | rc = tpm2_unseal(chip, payload, options, blob_handle); | ||
630 | |||
631 | tpm2_flush_context(chip, blob_handle); | ||
632 | 656 | ||
657 | rc = tpm2_unseal_cmd(chip, payload, options, blob_handle, | ||
658 | TPM_TRANSMIT_UNLOCKED); | ||
659 | tpm2_flush_context_cmd(chip, blob_handle, TPM_TRANSMIT_UNLOCKED); | ||
660 | out: | ||
661 | mutex_unlock(&chip->tpm_mutex); | ||
633 | return rc; | 662 | return rc; |
634 | } | 663 | } |
635 | 664 | ||
@@ -655,7 +684,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, | |||
655 | cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id); | 684 | cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id); |
656 | cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); | 685 | cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); |
657 | 686 | ||
658 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), desc); | 687 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, desc); |
659 | if (!rc) | 688 | if (!rc) |
660 | *value = be32_to_cpu(cmd.params.get_tpm_pt_out.value); | 689 | *value = be32_to_cpu(cmd.params.get_tpm_pt_out.value); |
661 | 690 | ||
@@ -689,7 +718,7 @@ int tpm2_startup(struct tpm_chip *chip, u16 startup_type) | |||
689 | cmd.header.in = tpm2_startup_header; | 718 | cmd.header.in = tpm2_startup_header; |
690 | 719 | ||
691 | cmd.params.startup_in.startup_type = cpu_to_be16(startup_type); | 720 | cmd.params.startup_in.startup_type = cpu_to_be16(startup_type); |
692 | return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | 721 | return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, |
693 | "attempting to start the TPM"); | 722 | "attempting to start the TPM"); |
694 | } | 723 | } |
695 | EXPORT_SYMBOL_GPL(tpm2_startup); | 724 | EXPORT_SYMBOL_GPL(tpm2_startup); |
@@ -718,7 +747,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) | |||
718 | cmd.header.in = tpm2_shutdown_header; | 747 | cmd.header.in = tpm2_shutdown_header; |
719 | cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); | 748 | cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); |
720 | 749 | ||
721 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), "stopping the TPM"); | 750 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, "stopping the TPM"); |
722 | 751 | ||
723 | /* In places where shutdown command is sent there's no much we can do | 752 | /* In places where shutdown command is sent there's no much we can do |
724 | * except print the error code on a system failure. | 753 | * except print the error code on a system failure. |
@@ -784,7 +813,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full) | |||
784 | cmd.header.in = tpm2_selftest_header; | 813 | cmd.header.in = tpm2_selftest_header; |
785 | cmd.params.selftest_in.full_test = full; | 814 | cmd.params.selftest_in.full_test = full; |
786 | 815 | ||
787 | rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE, | 816 | rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, |
788 | "continue selftest"); | 817 | "continue selftest"); |
789 | 818 | ||
790 | /* At least some prototype chips seem to give RC_TESTING error | 819 | /* At least some prototype chips seem to give RC_TESTING error |
@@ -836,7 +865,7 @@ int tpm2_do_selftest(struct tpm_chip *chip) | |||
836 | cmd.params.pcrread_in.pcr_select[1] = 0x00; | 865 | cmd.params.pcrread_in.pcr_select[1] = 0x00; |
837 | cmd.params.pcrread_in.pcr_select[2] = 0x00; | 866 | cmd.params.pcrread_in.pcr_select[2] = 0x00; |
838 | 867 | ||
839 | rc = tpm_transmit_cmd(chip, (u8 *) &cmd, sizeof(cmd), NULL); | 868 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, NULL); |
840 | if (rc < 0) | 869 | if (rc < 0) |
841 | break; | 870 | break; |
842 | 871 | ||
@@ -885,7 +914,7 @@ int tpm2_probe(struct tpm_chip *chip) | |||
885 | cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100); | 914 | cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100); |
886 | cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); | 915 | cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); |
887 | 916 | ||
888 | rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd)); | 917 | rc = tpm_transmit(chip, (const u8 *)&cmd, sizeof(cmd), 0); |
889 | if (rc < 0) | 918 | if (rc < 0) |
890 | return rc; | 919 | return rc; |
891 | else if (rc < TPM_HEADER_SIZE) | 920 | else if (rc < TPM_HEADER_SIZE) |