Commit ca681ec8 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Martin Schwidefsky

s390/pkey: Fix wrong handling of secure key with old MKVP

When a secure key with an old Master Key Verification
Pattern was given to the pkey_findcard function, there was
no responsible card found because only the current MKVP of
each card was compared. With this fix also the old MKVP
values are considered and so a matching card able to handle
the key is reported back to the caller.
Signed-off-by: default avatarHarald Freudenberger <freude@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 0861b5a7
......@@ -572,6 +572,12 @@ int pkey_sec2protkey(u16 cardnr, u16 domain,
rc = -EIO;
goto out;
}
if (prepcblk->ccp_rscode != 0) {
DEBUG_WARN(
"pkey_sec2protkey unwrap secure key warning, card response %d/%d\n",
(int) prepcblk->ccp_rtcode,
(int) prepcblk->ccp_rscode);
}
/* process response cprb param block */
prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX);
......@@ -761,9 +767,10 @@ static int query_crypto_facility(u16 cardnr, u16 domain,
}
/*
* Fetch just the mkvp value via query_crypto_facility from adapter.
* Fetch the current and old mkvp values via
* query_crypto_facility from adapter.
*/
static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp)
static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2])
{
int rc, found = 0;
size_t rlen, vlen;
......@@ -779,9 +786,10 @@ static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp)
rc = query_crypto_facility(cardnr, domain, "STATICSA",
rarray, &rlen, varray, &vlen);
if (rc == 0 && rlen > 8*8 && vlen > 184+8) {
if (rarray[64] == '2') {
if (rarray[8*8] == '2') {
/* current master key state is valid */
*mkvp = *((u64 *)(varray + 184));
mkvp[0] = *((u64 *)(varray + 184));
mkvp[1] = *((u64 *)(varray + 172));
found = 1;
}
}
......@@ -796,14 +804,14 @@ struct mkvp_info {
struct list_head list;
u16 cardnr;
u16 domain;
u64 mkvp;
u64 mkvp[2];
};
/* a list with mkvp_info entries */
static LIST_HEAD(mkvp_list);
static DEFINE_SPINLOCK(mkvp_list_lock);
static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp)
static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 mkvp[2])
{
int rc = -ENOENT;
struct mkvp_info *ptr;
......@@ -812,7 +820,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp)
list_for_each_entry(ptr, &mkvp_list, list) {
if (ptr->cardnr == cardnr &&
ptr->domain == domain) {
*mkvp = ptr->mkvp;
memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64));
rc = 0;
break;
}
......@@ -822,7 +830,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp)
return rc;
}
static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp)
static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2])
{
int found = 0;
struct mkvp_info *ptr;
......@@ -831,7 +839,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp)
list_for_each_entry(ptr, &mkvp_list, list) {
if (ptr->cardnr == cardnr &&
ptr->domain == domain) {
ptr->mkvp = mkvp;
memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64));
found = 1;
break;
}
......@@ -844,7 +852,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp)
}
ptr->cardnr = cardnr;
ptr->domain = domain;
ptr->mkvp = mkvp;
memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64));
list_add(&ptr->list, &mkvp_list);
}
spin_unlock_bh(&mkvp_list_lock);
......@@ -888,8 +896,8 @@ int pkey_findcard(const struct pkey_seckey *seckey,
struct secaeskeytoken *t = (struct secaeskeytoken *) seckey;
struct zcrypt_device_matrix *device_matrix;
u16 card, dom;
u64 mkvp;
int i, rc;
u64 mkvp[2];
int i, rc, oi = -1;
/* mkvp must not be zero */
if (t->mkvp == 0)
......@@ -910,14 +918,14 @@ int pkey_findcard(const struct pkey_seckey *seckey,
device_matrix->device[i].functions & 0x04) {
/* an enabled CCA Coprocessor card */
/* try cached mkvp */
if (mkvp_cache_fetch(card, dom, &mkvp) == 0 &&
t->mkvp == mkvp) {
if (mkvp_cache_fetch(card, dom, mkvp) == 0 &&
t->mkvp == mkvp[0]) {
if (!verify)
break;
/* verify: fetch mkvp from adapter */
if (fetch_mkvp(card, dom, &mkvp) == 0) {
if (fetch_mkvp(card, dom, mkvp) == 0) {
mkvp_cache_update(card, dom, mkvp);
if (t->mkvp == mkvp)
if (t->mkvp == mkvp[0])
break;
}
}
......@@ -936,14 +944,21 @@ int pkey_findcard(const struct pkey_seckey *seckey,
card = AP_QID_CARD(device_matrix->device[i].qid);
dom = AP_QID_QUEUE(device_matrix->device[i].qid);
/* fresh fetch mkvp from adapter */
if (fetch_mkvp(card, dom, &mkvp) == 0) {
if (fetch_mkvp(card, dom, mkvp) == 0) {
mkvp_cache_update(card, dom, mkvp);
if (t->mkvp == mkvp)
if (t->mkvp == mkvp[0])
break;
if (t->mkvp == mkvp[1] && oi < 0)
oi = i;
}
}
if (i >= MAX_ZDEV_ENTRIES && oi >= 0) {
/* old mkvp matched, use this card then */
card = AP_QID_CARD(device_matrix->device[oi].qid);
dom = AP_QID_QUEUE(device_matrix->device[oi].qid);
}
}
if (i < MAX_ZDEV_ENTRIES) {
if (i < MAX_ZDEV_ENTRIES || oi >= 0) {
if (pcardnr)
*pcardnr = card;
if (pdomain)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment