diff options
Diffstat (limited to 'drivers/s390/crypto/pkey_api.c')
-rw-r--r-- | drivers/s390/crypto/pkey_api.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 40f1136f5568..058db724b5a2 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c | |||
@@ -572,6 +572,12 @@ int pkey_sec2protkey(u16 cardnr, u16 domain, | |||
572 | rc = -EIO; | 572 | rc = -EIO; |
573 | goto out; | 573 | goto out; |
574 | } | 574 | } |
575 | if (prepcblk->ccp_rscode != 0) { | ||
576 | DEBUG_WARN( | ||
577 | "pkey_sec2protkey unwrap secure key warning, card response %d/%d\n", | ||
578 | (int) prepcblk->ccp_rtcode, | ||
579 | (int) prepcblk->ccp_rscode); | ||
580 | } | ||
575 | 581 | ||
576 | /* process response cprb param block */ | 582 | /* process response cprb param block */ |
577 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | 583 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); |
@@ -761,9 +767,10 @@ out: | |||
761 | } | 767 | } |
762 | 768 | ||
763 | /* | 769 | /* |
764 | * Fetch just the mkvp value via query_crypto_facility from adapter. | 770 | * Fetch the current and old mkvp values via |
771 | * query_crypto_facility from adapter. | ||
765 | */ | 772 | */ |
766 | static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp) | 773 | static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2]) |
767 | { | 774 | { |
768 | int rc, found = 0; | 775 | int rc, found = 0; |
769 | size_t rlen, vlen; | 776 | size_t rlen, vlen; |
@@ -779,9 +786,10 @@ static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp) | |||
779 | rc = query_crypto_facility(cardnr, domain, "STATICSA", | 786 | rc = query_crypto_facility(cardnr, domain, "STATICSA", |
780 | rarray, &rlen, varray, &vlen); | 787 | rarray, &rlen, varray, &vlen); |
781 | if (rc == 0 && rlen > 8*8 && vlen > 184+8) { | 788 | if (rc == 0 && rlen > 8*8 && vlen > 184+8) { |
782 | if (rarray[64] == '2') { | 789 | if (rarray[8*8] == '2') { |
783 | /* current master key state is valid */ | 790 | /* current master key state is valid */ |
784 | *mkvp = *((u64 *)(varray + 184)); | 791 | mkvp[0] = *((u64 *)(varray + 184)); |
792 | mkvp[1] = *((u64 *)(varray + 172)); | ||
785 | found = 1; | 793 | found = 1; |
786 | } | 794 | } |
787 | } | 795 | } |
@@ -796,14 +804,14 @@ struct mkvp_info { | |||
796 | struct list_head list; | 804 | struct list_head list; |
797 | u16 cardnr; | 805 | u16 cardnr; |
798 | u16 domain; | 806 | u16 domain; |
799 | u64 mkvp; | 807 | u64 mkvp[2]; |
800 | }; | 808 | }; |
801 | 809 | ||
802 | /* a list with mkvp_info entries */ | 810 | /* a list with mkvp_info entries */ |
803 | static LIST_HEAD(mkvp_list); | 811 | static LIST_HEAD(mkvp_list); |
804 | static DEFINE_SPINLOCK(mkvp_list_lock); | 812 | static DEFINE_SPINLOCK(mkvp_list_lock); |
805 | 813 | ||
806 | static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp) | 814 | static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 mkvp[2]) |
807 | { | 815 | { |
808 | int rc = -ENOENT; | 816 | int rc = -ENOENT; |
809 | struct mkvp_info *ptr; | 817 | struct mkvp_info *ptr; |
@@ -812,7 +820,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp) | |||
812 | list_for_each_entry(ptr, &mkvp_list, list) { | 820 | list_for_each_entry(ptr, &mkvp_list, list) { |
813 | if (ptr->cardnr == cardnr && | 821 | if (ptr->cardnr == cardnr && |
814 | ptr->domain == domain) { | 822 | ptr->domain == domain) { |
815 | *mkvp = ptr->mkvp; | 823 | memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64)); |
816 | rc = 0; | 824 | rc = 0; |
817 | break; | 825 | break; |
818 | } | 826 | } |
@@ -822,7 +830,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp) | |||
822 | return rc; | 830 | return rc; |
823 | } | 831 | } |
824 | 832 | ||
825 | static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp) | 833 | static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2]) |
826 | { | 834 | { |
827 | int found = 0; | 835 | int found = 0; |
828 | struct mkvp_info *ptr; | 836 | struct mkvp_info *ptr; |
@@ -831,7 +839,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp) | |||
831 | list_for_each_entry(ptr, &mkvp_list, list) { | 839 | list_for_each_entry(ptr, &mkvp_list, list) { |
832 | if (ptr->cardnr == cardnr && | 840 | if (ptr->cardnr == cardnr && |
833 | ptr->domain == domain) { | 841 | ptr->domain == domain) { |
834 | ptr->mkvp = mkvp; | 842 | memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); |
835 | found = 1; | 843 | found = 1; |
836 | break; | 844 | break; |
837 | } | 845 | } |
@@ -844,7 +852,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp) | |||
844 | } | 852 | } |
845 | ptr->cardnr = cardnr; | 853 | ptr->cardnr = cardnr; |
846 | ptr->domain = domain; | 854 | ptr->domain = domain; |
847 | ptr->mkvp = mkvp; | 855 | memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); |
848 | list_add(&ptr->list, &mkvp_list); | 856 | list_add(&ptr->list, &mkvp_list); |
849 | } | 857 | } |
850 | spin_unlock_bh(&mkvp_list_lock); | 858 | spin_unlock_bh(&mkvp_list_lock); |
@@ -888,8 +896,8 @@ int pkey_findcard(const struct pkey_seckey *seckey, | |||
888 | struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; | 896 | struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; |
889 | struct zcrypt_device_matrix *device_matrix; | 897 | struct zcrypt_device_matrix *device_matrix; |
890 | u16 card, dom; | 898 | u16 card, dom; |
891 | u64 mkvp; | 899 | u64 mkvp[2]; |
892 | int i, rc; | 900 | int i, rc, oi = -1; |
893 | 901 | ||
894 | /* mkvp must not be zero */ | 902 | /* mkvp must not be zero */ |
895 | if (t->mkvp == 0) | 903 | if (t->mkvp == 0) |
@@ -910,14 +918,14 @@ int pkey_findcard(const struct pkey_seckey *seckey, | |||
910 | device_matrix->device[i].functions & 0x04) { | 918 | device_matrix->device[i].functions & 0x04) { |
911 | /* an enabled CCA Coprocessor card */ | 919 | /* an enabled CCA Coprocessor card */ |
912 | /* try cached mkvp */ | 920 | /* try cached mkvp */ |
913 | if (mkvp_cache_fetch(card, dom, &mkvp) == 0 && | 921 | if (mkvp_cache_fetch(card, dom, mkvp) == 0 && |
914 | t->mkvp == mkvp) { | 922 | t->mkvp == mkvp[0]) { |
915 | if (!verify) | 923 | if (!verify) |
916 | break; | 924 | break; |
917 | /* verify: fetch mkvp from adapter */ | 925 | /* verify: fetch mkvp from adapter */ |
918 | if (fetch_mkvp(card, dom, &mkvp) == 0) { | 926 | if (fetch_mkvp(card, dom, mkvp) == 0) { |
919 | mkvp_cache_update(card, dom, mkvp); | 927 | mkvp_cache_update(card, dom, mkvp); |
920 | if (t->mkvp == mkvp) | 928 | if (t->mkvp == mkvp[0]) |
921 | break; | 929 | break; |
922 | } | 930 | } |
923 | } | 931 | } |
@@ -936,14 +944,21 @@ int pkey_findcard(const struct pkey_seckey *seckey, | |||
936 | card = AP_QID_CARD(device_matrix->device[i].qid); | 944 | card = AP_QID_CARD(device_matrix->device[i].qid); |
937 | dom = AP_QID_QUEUE(device_matrix->device[i].qid); | 945 | dom = AP_QID_QUEUE(device_matrix->device[i].qid); |
938 | /* fresh fetch mkvp from adapter */ | 946 | /* fresh fetch mkvp from adapter */ |
939 | if (fetch_mkvp(card, dom, &mkvp) == 0) { | 947 | if (fetch_mkvp(card, dom, mkvp) == 0) { |
940 | mkvp_cache_update(card, dom, mkvp); | 948 | mkvp_cache_update(card, dom, mkvp); |
941 | if (t->mkvp == mkvp) | 949 | if (t->mkvp == mkvp[0]) |
942 | break; | 950 | break; |
951 | if (t->mkvp == mkvp[1] && oi < 0) | ||
952 | oi = i; | ||
943 | } | 953 | } |
944 | } | 954 | } |
955 | if (i >= MAX_ZDEV_ENTRIES && oi >= 0) { | ||
956 | /* old mkvp matched, use this card then */ | ||
957 | card = AP_QID_CARD(device_matrix->device[oi].qid); | ||
958 | dom = AP_QID_QUEUE(device_matrix->device[oi].qid); | ||
959 | } | ||
945 | } | 960 | } |
946 | if (i < MAX_ZDEV_ENTRIES) { | 961 | if (i < MAX_ZDEV_ENTRIES || oi >= 0) { |
947 | if (pcardnr) | 962 | if (pcardnr) |
948 | *pcardnr = card; | 963 | *pcardnr = card; |
949 | if (pdomain) | 964 | if (pdomain) |