diff options
Diffstat (limited to 'drivers/char/tpm/tpm.c')
-rw-r--r-- | drivers/char/tpm/tpm.c | 128 |
1 files changed, 95 insertions, 33 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index e1fc193d9396..ae766d868454 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -580,91 +580,133 @@ void tpm_continue_selftest(struct tpm_chip *chip) | |||
580 | } | 580 | } |
581 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); | 581 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); |
582 | 582 | ||
583 | #define TPM_INTERNAL_RESULT_SIZE 200 | ||
584 | |||
583 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, | 585 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, |
584 | char *buf) | 586 | char *buf) |
585 | { | 587 | { |
586 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; | 588 | u8 *data; |
587 | ssize_t rc; | 589 | ssize_t rc; |
588 | 590 | ||
589 | struct tpm_chip *chip = dev_get_drvdata(dev); | 591 | struct tpm_chip *chip = dev_get_drvdata(dev); |
590 | if (chip == NULL) | 592 | if (chip == NULL) |
591 | return -ENODEV; | 593 | return -ENODEV; |
592 | 594 | ||
595 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
596 | if (!data) | ||
597 | return -ENOMEM; | ||
598 | |||
593 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 599 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
594 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | 600 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; |
595 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | 601 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; |
596 | 602 | ||
597 | rc = transmit_cmd(chip, data, sizeof(data), | 603 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
598 | "attemtping to determine the permanent state"); | 604 | "attemtping to determine the permanent enabled state"); |
599 | if (rc) | 605 | if (rc) { |
606 | kfree(data); | ||
600 | return 0; | 607 | return 0; |
601 | return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); | 608 | } |
609 | |||
610 | rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); | ||
611 | |||
612 | kfree(data); | ||
613 | return rc; | ||
602 | } | 614 | } |
603 | EXPORT_SYMBOL_GPL(tpm_show_enabled); | 615 | EXPORT_SYMBOL_GPL(tpm_show_enabled); |
604 | 616 | ||
605 | ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, | 617 | ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, |
606 | char *buf) | 618 | char *buf) |
607 | { | 619 | { |
608 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; | 620 | u8 *data; |
609 | ssize_t rc; | 621 | ssize_t rc; |
610 | 622 | ||
611 | struct tpm_chip *chip = dev_get_drvdata(dev); | 623 | struct tpm_chip *chip = dev_get_drvdata(dev); |
612 | if (chip == NULL) | 624 | if (chip == NULL) |
613 | return -ENODEV; | 625 | return -ENODEV; |
614 | 626 | ||
627 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
628 | if (!data) | ||
629 | return -ENOMEM; | ||
630 | |||
615 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 631 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
616 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | 632 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; |
617 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | 633 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; |
618 | 634 | ||
619 | rc = transmit_cmd(chip, data, sizeof(data), | 635 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
620 | "attemtping to determine the permanent state"); | 636 | "attemtping to determine the permanent active state"); |
621 | if (rc) | 637 | if (rc) { |
638 | kfree(data); | ||
622 | return 0; | 639 | return 0; |
623 | return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); | 640 | } |
641 | |||
642 | rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); | ||
643 | |||
644 | kfree(data); | ||
645 | return rc; | ||
624 | } | 646 | } |
625 | EXPORT_SYMBOL_GPL(tpm_show_active); | 647 | EXPORT_SYMBOL_GPL(tpm_show_active); |
626 | 648 | ||
627 | ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, | 649 | ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, |
628 | char *buf) | 650 | char *buf) |
629 | { | 651 | { |
630 | u8 data[sizeof(tpm_cap)]; | 652 | u8 *data; |
631 | ssize_t rc; | 653 | ssize_t rc; |
632 | 654 | ||
633 | struct tpm_chip *chip = dev_get_drvdata(dev); | 655 | struct tpm_chip *chip = dev_get_drvdata(dev); |
634 | if (chip == NULL) | 656 | if (chip == NULL) |
635 | return -ENODEV; | 657 | return -ENODEV; |
636 | 658 | ||
659 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
660 | if (!data) | ||
661 | return -ENOMEM; | ||
662 | |||
637 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 663 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
638 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 664 | data[TPM_CAP_IDX] = TPM_CAP_PROP; |
639 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; | 665 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; |
640 | 666 | ||
641 | rc = transmit_cmd(chip, data, sizeof(data), | 667 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
642 | "attempting to determine the owner state"); | 668 | "attempting to determine the owner state"); |
643 | if (rc) | 669 | if (rc) { |
670 | kfree(data); | ||
644 | return 0; | 671 | return 0; |
645 | return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); | 672 | } |
673 | |||
674 | rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); | ||
675 | |||
676 | kfree(data); | ||
677 | return rc; | ||
646 | } | 678 | } |
647 | EXPORT_SYMBOL_GPL(tpm_show_owned); | 679 | EXPORT_SYMBOL_GPL(tpm_show_owned); |
648 | 680 | ||
649 | ssize_t tpm_show_temp_deactivated(struct device * dev, | 681 | ssize_t tpm_show_temp_deactivated(struct device * dev, |
650 | struct device_attribute * attr, char *buf) | 682 | struct device_attribute * attr, char *buf) |
651 | { | 683 | { |
652 | u8 data[sizeof(tpm_cap)]; | 684 | u8 *data; |
653 | ssize_t rc; | 685 | ssize_t rc; |
654 | 686 | ||
655 | struct tpm_chip *chip = dev_get_drvdata(dev); | 687 | struct tpm_chip *chip = dev_get_drvdata(dev); |
656 | if (chip == NULL) | 688 | if (chip == NULL) |
657 | return -ENODEV; | 689 | return -ENODEV; |
658 | 690 | ||
691 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
692 | if (!data) | ||
693 | return -ENOMEM; | ||
694 | |||
659 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 695 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
660 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | 696 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; |
661 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; | 697 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; |
662 | 698 | ||
663 | rc = transmit_cmd(chip, data, sizeof(data), | 699 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
664 | "attempting to determine the temporary state"); | 700 | "attempting to determine the temporary state"); |
665 | if (rc) | 701 | if (rc) { |
702 | kfree(data); | ||
666 | return 0; | 703 | return 0; |
667 | return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); | 704 | } |
705 | |||
706 | rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); | ||
707 | |||
708 | kfree(data); | ||
709 | return rc; | ||
668 | } | 710 | } |
669 | EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); | 711 | EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); |
670 | 712 | ||
@@ -678,7 +720,7 @@ static const u8 pcrread[] = { | |||
678 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | 720 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, |
679 | char *buf) | 721 | char *buf) |
680 | { | 722 | { |
681 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)]; | 723 | u8 *data; |
682 | ssize_t rc; | 724 | ssize_t rc; |
683 | int i, j, num_pcrs; | 725 | int i, j, num_pcrs; |
684 | __be32 index; | 726 | __be32 index; |
@@ -688,21 +730,27 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | |||
688 | if (chip == NULL) | 730 | if (chip == NULL) |
689 | return -ENODEV; | 731 | return -ENODEV; |
690 | 732 | ||
733 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
734 | if (!data) | ||
735 | return -ENOMEM; | ||
736 | |||
691 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 737 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
692 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 738 | data[TPM_CAP_IDX] = TPM_CAP_PROP; |
693 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; | 739 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; |
694 | 740 | ||
695 | rc = transmit_cmd(chip, data, sizeof(data), | 741 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
696 | "attempting to determine the number of PCRS"); | 742 | "attempting to determine the number of PCRS"); |
697 | if (rc) | 743 | if (rc) { |
744 | kfree(data); | ||
698 | return 0; | 745 | return 0; |
746 | } | ||
699 | 747 | ||
700 | num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); | 748 | num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); |
701 | for (i = 0; i < num_pcrs; i++) { | 749 | for (i = 0; i < num_pcrs; i++) { |
702 | memcpy(data, pcrread, sizeof(pcrread)); | 750 | memcpy(data, pcrread, sizeof(pcrread)); |
703 | index = cpu_to_be32(i); | 751 | index = cpu_to_be32(i); |
704 | memcpy(data + 10, &index, 4); | 752 | memcpy(data + 10, &index, 4); |
705 | rc = transmit_cmd(chip, data, sizeof(data), | 753 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
706 | "attempting to read a PCR"); | 754 | "attempting to read a PCR"); |
707 | if (rc) | 755 | if (rc) |
708 | goto out; | 756 | goto out; |
@@ -712,6 +760,7 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | |||
712 | str += sprintf(str, "\n"); | 760 | str += sprintf(str, "\n"); |
713 | } | 761 | } |
714 | out: | 762 | out: |
763 | kfree(data); | ||
715 | return str - buf; | 764 | return str - buf; |
716 | } | 765 | } |
717 | EXPORT_SYMBOL_GPL(tpm_show_pcrs); | 766 | EXPORT_SYMBOL_GPL(tpm_show_pcrs); |
@@ -795,7 +844,7 @@ static const u8 cap_version[] = { | |||
795 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, | 844 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, |
796 | char *buf) | 845 | char *buf) |
797 | { | 846 | { |
798 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; | 847 | u8 *data; |
799 | ssize_t rc; | 848 | ssize_t rc; |
800 | char *str = buf; | 849 | char *str = buf; |
801 | 850 | ||
@@ -803,21 +852,27 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, | |||
803 | if (chip == NULL) | 852 | if (chip == NULL) |
804 | return -ENODEV; | 853 | return -ENODEV; |
805 | 854 | ||
855 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
856 | if (!data) | ||
857 | return -ENOMEM; | ||
858 | |||
806 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 859 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
807 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 860 | data[TPM_CAP_IDX] = TPM_CAP_PROP; |
808 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | 861 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; |
809 | 862 | ||
810 | rc = transmit_cmd(chip, data, sizeof(data), | 863 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
811 | "attempting to determine the manufacturer"); | 864 | "attempting to determine the manufacturer"); |
812 | if (rc) | 865 | if (rc) { |
866 | kfree(data); | ||
813 | return 0; | 867 | return 0; |
868 | } | ||
814 | 869 | ||
815 | str += sprintf(str, "Manufacturer: 0x%x\n", | 870 | str += sprintf(str, "Manufacturer: 0x%x\n", |
816 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); | 871 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); |
817 | 872 | ||
818 | memcpy(data, cap_version, sizeof(cap_version)); | 873 | memcpy(data, cap_version, sizeof(cap_version)); |
819 | data[CAP_VERSION_IDX] = CAP_VERSION_1_1; | 874 | data[CAP_VERSION_IDX] = CAP_VERSION_1_1; |
820 | rc = transmit_cmd(chip, data, sizeof(data), | 875 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, |
821 | "attempting to determine the 1.1 version"); | 876 | "attempting to determine the 1.1 version"); |
822 | if (rc) | 877 | if (rc) |
823 | goto out; | 878 | goto out; |
@@ -828,6 +883,7 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, | |||
828 | (int) data[17]); | 883 | (int) data[17]); |
829 | 884 | ||
830 | out: | 885 | out: |
886 | kfree(data); | ||
831 | return str - buf; | 887 | return str - buf; |
832 | } | 888 | } |
833 | EXPORT_SYMBOL_GPL(tpm_show_caps); | 889 | EXPORT_SYMBOL_GPL(tpm_show_caps); |
@@ -835,7 +891,7 @@ EXPORT_SYMBOL_GPL(tpm_show_caps); | |||
835 | ssize_t tpm_show_caps_1_2(struct device * dev, | 891 | ssize_t tpm_show_caps_1_2(struct device * dev, |
836 | struct device_attribute * attr, char *buf) | 892 | struct device_attribute * attr, char *buf) |
837 | { | 893 | { |
838 | u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; | 894 | u8 *data; |
839 | ssize_t len; | 895 | ssize_t len; |
840 | char *str = buf; | 896 | char *str = buf; |
841 | 897 | ||
@@ -843,15 +899,20 @@ ssize_t tpm_show_caps_1_2(struct device * dev, | |||
843 | if (chip == NULL) | 899 | if (chip == NULL) |
844 | return -ENODEV; | 900 | return -ENODEV; |
845 | 901 | ||
902 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
903 | if (!data) | ||
904 | return -ENOMEM; | ||
905 | |||
846 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 906 | memcpy(data, tpm_cap, sizeof(tpm_cap)); |
847 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 907 | data[TPM_CAP_IDX] = TPM_CAP_PROP; |
848 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | 908 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; |
849 | 909 | ||
850 | if ((len = tpm_transmit(chip, data, sizeof(data))) <= | 910 | len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); |
851 | TPM_ERROR_SIZE) { | 911 | if (len <= TPM_ERROR_SIZE) { |
852 | dev_dbg(chip->dev, "A TPM error (%d) occurred " | 912 | dev_dbg(chip->dev, "A TPM error (%d) occurred " |
853 | "attempting to determine the manufacturer\n", | 913 | "attempting to determine the manufacturer\n", |
854 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | 914 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); |
915 | kfree(data); | ||
855 | return 0; | 916 | return 0; |
856 | } | 917 | } |
857 | 918 | ||
@@ -861,8 +922,8 @@ ssize_t tpm_show_caps_1_2(struct device * dev, | |||
861 | memcpy(data, cap_version, sizeof(cap_version)); | 922 | memcpy(data, cap_version, sizeof(cap_version)); |
862 | data[CAP_VERSION_IDX] = CAP_VERSION_1_2; | 923 | data[CAP_VERSION_IDX] = CAP_VERSION_1_2; |
863 | 924 | ||
864 | if ((len = tpm_transmit(chip, data, sizeof(data))) <= | 925 | len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); |
865 | TPM_ERROR_SIZE) { | 926 | if (len <= TPM_ERROR_SIZE) { |
866 | dev_err(chip->dev, "A TPM error (%d) occurred " | 927 | dev_err(chip->dev, "A TPM error (%d) occurred " |
867 | "attempting to determine the 1.2 version\n", | 928 | "attempting to determine the 1.2 version\n", |
868 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | 929 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); |
@@ -874,6 +935,7 @@ ssize_t tpm_show_caps_1_2(struct device * dev, | |||
874 | (int) data[19]); | 935 | (int) data[19]); |
875 | 936 | ||
876 | out: | 937 | out: |
938 | kfree(data); | ||
877 | return str - buf; | 939 | return str - buf; |
878 | } | 940 | } |
879 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); | 941 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); |
@@ -966,7 +1028,7 @@ ssize_t tpm_write(struct file *file, const char __user *buf, | |||
966 | size_t size, loff_t *off) | 1028 | size_t size, loff_t *off) |
967 | { | 1029 | { |
968 | struct tpm_chip *chip = file->private_data; | 1030 | struct tpm_chip *chip = file->private_data; |
969 | int in_size = size, out_size; | 1031 | size_t in_size = size, out_size; |
970 | 1032 | ||
971 | /* cannot perform a write until the read has cleared | 1033 | /* cannot perform a write until the read has cleared |
972 | either via tpm_read or a user_read_timer timeout */ | 1034 | either via tpm_read or a user_read_timer timeout */ |
@@ -1001,7 +1063,7 @@ ssize_t tpm_read(struct file *file, char __user *buf, | |||
1001 | size_t size, loff_t *off) | 1063 | size_t size, loff_t *off) |
1002 | { | 1064 | { |
1003 | struct tpm_chip *chip = file->private_data; | 1065 | struct tpm_chip *chip = file->private_data; |
1004 | int ret_size; | 1066 | ssize_t ret_size; |
1005 | 1067 | ||
1006 | del_singleshot_timer_sync(&chip->user_read_timer); | 1068 | del_singleshot_timer_sync(&chip->user_read_timer); |
1007 | flush_scheduled_work(); | 1069 | flush_scheduled_work(); |