diff options
author | Harald Freudenberger <freude@linux.ibm.com> | 2019-06-11 14:10:47 +0200 |
---|---|---|
committer | Vasily Gorbik <gor@linux.ibm.com> | 2019-07-29 18:14:17 +0200 |
commit | 94bbd34e51bc7809357e24e4011b169d321a8272 (patch) | |
tree | 38682de5d0f5425f9f591f4698ba0fb4751c9788 /drivers/s390 | |
parent | s390/zcrypt: move cca misc functions to new code file (diff) | |
download | linux-94bbd34e51bc7809357e24e4011b169d321a8272.tar.xz linux-94bbd34e51bc7809357e24e4011b169d321a8272.zip |
s390/zcrypt: add base code for cca crypto card info support
This patch widens the information held for cca crypto apqns.
Currently the current and old master key verification pattern
is used by the existing code. Now the new master key registers
mkvp, the 8 byte serial number and state info about each master
key register is part of the cca info cache.
In a next step this information will be used to provide some
additional attributes in sysfs for each CCA crypto adapter.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/crypto/zcrypt_ccamisc.c | 131 |
1 files changed, 75 insertions, 56 deletions
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index 3a76c7b5e33c..b1f9332a0298 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -33,17 +33,27 @@ /* Size of vardata block used for some of the cca requests/replies */ #define VARDATASIZE 4096 -/* struct to hold cached mkvp info for each CCA card/domain */ -struct mkvp_info { +/* struct to hold cached info for each CCA card/domain */ +struct cca_info { + char new_mk_state; /* '1' Empty, '2' Partially full, '3' Full */ + char cur_mk_state; /* '1' Invalid, '2' Valid */ + char old_mk_state; /* '1' Invalid, '2' Valid */ + u64 new_mkvp; /* truncated sha256 hash of new master key */ + u64 cur_mkvp; /* truncated sha256 hash of current master key */ + u64 old_mkvp; /* truncated sha256 hash of old master key */ + char serial[9]; +}; + +struct cca_info_list_entry { struct list_head list; u16 cardnr; u16 domain; - u64 mkvp[2]; + struct cca_info info; }; -/* a list with mkvp_info entries */ -static LIST_HEAD(mkvp_list); -static DEFINE_SPINLOCK(mkvp_list_lock); +/* a list with cca_info_list_entry entries */ +static LIST_HEAD(cca_info_list); +static DEFINE_SPINLOCK(cca_info_list_lock); /* * Simple check if the token is a valid CCA secure AES key @@ -697,35 +707,35 @@ out: } EXPORT_SYMBOL(cca_query_crypto_facility); -static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 mkvp[2]) +static int cca_info_cache_fetch(u16 cardnr, u16 domain, struct cca_info *ci) { int rc = -ENOENT; - struct mkvp_info *ptr; + struct cca_info_list_entry *ptr; - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry(ptr, &mkvp_list, list) { - if (ptr->cardnr == cardnr && - ptr->domain == domain) { - memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64)); + spin_lock_bh(&cca_info_list_lock); + list_for_each_entry(ptr, &cca_info_list, list) { + if (ptr->cardnr == cardnr && ptr->domain == domain) { + memcpy(ci, &ptr->info, sizeof(*ci)); rc = 0; break; } } - spin_unlock_bh(&mkvp_list_lock); + spin_unlock_bh(&cca_info_list_lock); return rc; } -static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2]) +static void cca_info_cache_update(u16 cardnr, u16 domain, + const struct cca_info *ci) { int found = 0; - struct mkvp_info *ptr; + struct cca_info_list_entry *ptr; - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry(ptr, &mkvp_list, list) { + spin_lock_bh(&cca_info_list_lock); + list_for_each_entry(ptr, &cca_info_list, list) { if (ptr->cardnr == cardnr && ptr->domain == domain) { - memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); + memcpy(&ptr->info, ci, sizeof(*ci)); found = 1; break; } @@ -733,23 +743,23 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2]) if (!found) { ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); if (!ptr) { - spin_unlock_bh(&mkvp_list_lock); + spin_unlock_bh(&cca_info_list_lock); return; } ptr->cardnr = cardnr; ptr->domain = domain; - memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); - list_add(&ptr->list, &mkvp_list); + memcpy(&ptr->info, ci, sizeof(*ci)); + list_add(&ptr->list, &cca_info_list); } - spin_unlock_bh(&mkvp_list_lock); + spin_unlock_bh(&cca_info_list_lock); } -static void mkvp_cache_scrub(u16 cardnr, u16 domain) +static void cca_info_cache_scrub(u16 cardnr, u16 domain) { - struct mkvp_info *ptr; + struct cca_info_list_entry *ptr; - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry(ptr, &mkvp_list, list) { + spin_lock_bh(&cca_info_list_lock); + list_for_each_entry(ptr, &cca_info_list, list) { if (ptr->cardnr == cardnr && ptr->domain == domain) { list_del(&ptr->list); @@ -757,26 +767,25 @@ static void mkvp_cache_scrub(u16 cardnr, u16 domain) break; } } - spin_unlock_bh(&mkvp_list_lock); + spin_unlock_bh(&cca_info_list_lock); } static void __exit mkvp_cache_free(void) { - struct mkvp_info *ptr, *pnext; + struct cca_info_list_entry *ptr, *pnext; - spin_lock_bh(&mkvp_list_lock); - list_for_each_entry_safe(ptr, pnext, &mkvp_list, list) { + spin_lock_bh(&cca_info_list_lock); + list_for_each_entry_safe(ptr, pnext, &cca_info_list, list) { list_del(&ptr->list); kfree(ptr); } - spin_unlock_bh(&mkvp_list_lock); + spin_unlock_bh(&cca_info_list_lock); } /* - * Fetch the current and old mkvp values via - * query_crypto_facility from adapter. + * Fetch cca_info values via query_crypto_facility from adapter. */ -static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2]) +static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci) { int rc, found = 0; size_t rlen, vlen; @@ -791,13 +800,19 @@ static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2]) rc = cca_query_crypto_facility(cardnr, domain, "STATICSA", rarray, &rlen, varray, &vlen); - if (rc == 0 && rlen > 8*8 && vlen > 184+8) { - if (rarray[8*8] == '2') { - /* current master key state is valid */ - mkvp[0] = *((u64 *)(varray + 184)); - mkvp[1] = *((u64 *)(varray + 172)); - found = 1; - } + if (rc == 0 && rlen >= 10*8 && vlen >= 204) { + memset(ci, 0, sizeof(*ci)); + memcpy(ci->serial, rarray, 8); + ci->new_mk_state = (char) rarray[7*8]; + ci->cur_mk_state = (char) rarray[8*8]; + ci->old_mk_state = (char) rarray[9*8]; + if (ci->old_mk_state == '2') + memcpy(&ci->old_mkvp, varray + 172, 8); + if (ci->cur_mk_state == '2') + memcpy(&ci->cur_mkvp, varray + 184, 8); + if (ci->new_mk_state == '3') + memcpy(&ci->new_mkvp, varray + 196, 8); + found = 1; } free_page((unsigned long) pg); @@ -816,7 +831,7 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) const struct secaeskeytoken *t = (const struct secaeskeytoken *) seckey; struct zcrypt_device_status_ext *device_status; u16 card, dom; - u64 mkvp[2]; + struct cca_info ci; int i, rc, oi = -1; /* some simple checks of the given secure key token */ @@ -839,23 +854,24 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) dom = AP_QID_QUEUE(device_status[i].qid); if (device_status[i].online && device_status[i].functions & 0x04) { - /* an enabled CCA Coprocessor card */ - /* try cached mkvp */ - if (mkvp_cache_fetch(card, dom, mkvp) == 0 && - t->mkvp == mkvp[0]) { + /* enabled CCA card, check current mkvp from cache */ + if (cca_info_cache_fetch(card, dom, &ci) == 0 && + ci.cur_mk_state == '2' && + ci.cur_mkvp == t->mkvp) { if (!verify) break; - /* verify: fetch mkvp from adapter */ - if (fetch_mkvp(card, dom, mkvp) == 0) { - mkvp_cache_update(card, dom, mkvp); - if (t->mkvp == mkvp[0]) + /* verify: refresh card info */ + if (fetch_cca_info(card, dom, &ci) == 0) { + cca_info_cache_update(card, dom, &ci); + if (ci.cur_mk_state == '2' && + ci.cur_mkvp == t->mkvp) break; } } } else { /* Card is offline and/or not a CCA card. */ /* del mkvp entry from cache if it exists */ - mkvp_cache_scrub(card, dom); + cca_info_cache_scrub(card, dom); } } if (i >= MAX_ZDEV_ENTRIES_EXT) { @@ -867,11 +883,14 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) card = AP_QID_CARD(device_status[i].qid); dom = AP_QID_QUEUE(device_status[i].qid); /* fresh fetch mkvp from adapter */ - if (fetch_mkvp(card, dom, mkvp) == 0) { - mkvp_cache_update(card, dom, mkvp); - if (t->mkvp == mkvp[0]) + if (fetch_cca_info(card, dom, &ci) == 0) { + cca_info_cache_update(card, dom, &ci); + if (ci.cur_mk_state == '2' && + ci.cur_mkvp == t->mkvp) break; - if (t->mkvp == mkvp[1] && oi < 0) + if (ci.old_mk_state == '2' && + ci.old_mkvp == t->mkvp && + oi < 0) oi = i; } } |