diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 69ac7bf09a579..563801427fe46 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -1161,6 +1161,34 @@ void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus) } EXPORT_SYMBOL(zcrypt_device_status_mask_ext); +int zcrypt_device_status_ext(int card, int queue, + struct zcrypt_device_status_ext *devstat) +{ + struct zcrypt_card *zc; + struct zcrypt_queue *zq; + + memset(devstat, 0, sizeof(*devstat)); + + spin_lock(&zcrypt_list_lock); + for_each_zcrypt_card(zc) { + for_each_zcrypt_queue(zq, zc) { + if (card == AP_QID_CARD(zq->queue->qid) && + queue == AP_QID_QUEUE(zq->queue->qid)) { + devstat->hwtype = zc->card->ap_dev.device_type; + devstat->functions = zc->card->functions >> 26; + devstat->qid = zq->queue->qid; + devstat->online = zq->online ? 0x01 : 0x00; + spin_unlock(&zcrypt_list_lock); + return 0; + } + } + } + spin_unlock(&zcrypt_list_lock); + + return -ENODEV; +} +EXPORT_SYMBOL(zcrypt_device_status_ext); + static void zcrypt_status_mask(char status[], size_t max_adapters) { struct zcrypt_card *zc; diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index af67a768a3fc1..2d3f2732344f2 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -121,9 +121,6 @@ void zcrypt_card_get(struct zcrypt_card *); int zcrypt_card_put(struct zcrypt_card *); int zcrypt_card_register(struct zcrypt_card *); void zcrypt_card_unregister(struct zcrypt_card *); -struct zcrypt_card *zcrypt_card_get_best(unsigned int *, - unsigned int, unsigned int); -void zcrypt_card_put_best(struct zcrypt_card *, unsigned int); struct zcrypt_queue *zcrypt_queue_alloc(size_t); void zcrypt_queue_free(struct zcrypt_queue *); @@ -132,8 +129,6 @@ int zcrypt_queue_put(struct zcrypt_queue *); int zcrypt_queue_register(struct zcrypt_queue *); void zcrypt_queue_unregister(struct zcrypt_queue *); void zcrypt_queue_force_online(struct zcrypt_queue *, int); -struct zcrypt_queue *zcrypt_queue_get_best(unsigned int, unsigned int); -void zcrypt_queue_put_best(struct zcrypt_queue *, unsigned int); int zcrypt_rng_device_add(void); void zcrypt_rng_device_remove(void); @@ -145,5 +140,7 @@ int zcrypt_api_init(void); void zcrypt_api_exit(void); long zcrypt_send_cprb(struct ica_xcRB *xcRB); void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus); +int zcrypt_device_status_ext(int card, int queue, + struct zcrypt_device_status_ext *devstatus); #endif /* _ZCRYPT_API_H_ */ diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c index 9dd31577ce475..9b7a866141b81 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.c +++ b/drivers/s390/crypto/zcrypt_ccamisc.c @@ -779,7 +779,17 @@ static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci) int rc, found = 0; size_t rlen, vlen; u8 *rarray, *varray, *pg; + struct zcrypt_device_status_ext devstat; + memset(ci, 0, sizeof(*ci)); + + /* get first info from zcrypt device driver about this apqn */ + rc = zcrypt_device_status_ext(cardnr, domain, &devstat); + if (rc) + return rc; + ci->hwtype = devstat.hwtype; + + /* prep page for rule array and var array use */ pg = (u8 *) __get_free_page(GFP_KERNEL); if (!pg) return -ENOMEM; @@ -787,10 +797,10 @@ static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci) varray = pg + PAGE_SIZE/2; rlen = vlen = PAGE_SIZE/2; + /* QF for this card/domain */ rc = cca_query_crypto_facility(cardnr, domain, "STATICSA", rarray, &rlen, varray, &vlen); 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]; @@ -828,23 +838,19 @@ int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify) EXPORT_SYMBOL(cca_get_info); /* - * Search for a matching crypto card based on the Master Key - * Verification Pattern provided inside a secure key. - * Returns < 0 on failure, 0 if CURRENT MKVP matches and - * 1 if OLD MKVP matches. + * Search for a matching crypto card based on the + * Master Key Verification Pattern given. */ -int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) +static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain, + int verify, int minhwtype) { - const struct secaeskeytoken *t = (const struct secaeskeytoken *) seckey; struct zcrypt_device_status_ext *device_status; u16 card, dom; struct cca_info ci; int i, rc, oi = -1; - /* some simple checks of the given secure key token */ - if (t->type != TOKTYPE_CCA_INTERNAL || - t->version != TOKVER_CCA_AES || - t->mkvp == 0) + /* mkvp must not be zero, minhwtype needs to be >= 0 */ + if (mkvp == 0 || minhwtype < 0) return -EINVAL; /* fetch status of all crypto cards */ @@ -863,15 +869,17 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) device_status[i].functions & 0x04) { /* enabled CCA card, check current mkvp from cache */ if (cca_info_cache_fetch(card, dom, &ci) == 0 && + ci.hwtype >= minhwtype && ci.cur_mk_state == '2' && - ci.cur_mkvp == t->mkvp) { + ci.cur_mkvp == mkvp) { if (!verify) break; /* 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) + if (ci.hwtype >= minhwtype && + ci.cur_mk_state == '2' && + ci.cur_mkvp == mkvp) break; } } @@ -892,11 +900,13 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) /* fresh fetch mkvp from adapter */ 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) + if (ci.hwtype >= minhwtype && + ci.cur_mk_state == '2' && + ci.cur_mkvp == mkvp) break; - if (ci.old_mk_state == '2' && - ci.old_mkvp == t->mkvp && + if (ci.hwtype >= minhwtype && + ci.old_mk_state == '2' && + ci.old_mkvp == mkvp && oi < 0) oi = i; } @@ -919,6 +929,29 @@ int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify) kfree(device_status); return rc; } + +/* + * Search for a matching crypto card based on the Master Key + * Verification Pattern provided inside a secure key token. + */ +int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify) +{ + u64 mkvp; + const struct keytoken_header *hdr = (struct keytoken_header *) key; + + if (hdr->type != TOKTYPE_CCA_INTERNAL) + return -EINVAL; + + switch (hdr->version) { + case TOKVER_CCA_AES: + mkvp = ((struct secaeskeytoken *)key)->mkvp; + break; + default: + return -EINVAL; + } + + return findcard(mkvp, pcardnr, pdomain, verify, 0); +} EXPORT_SYMBOL(cca_findcard); void __exit zcrypt_ccamisc_exit(void) diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h index d92fb731602ae..e6f41e5baf18a 100644 --- a/drivers/s390/crypto/zcrypt_ccamisc.h +++ b/drivers/s390/crypto/zcrypt_ccamisc.h @@ -88,10 +88,11 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain, * Returns < 0 on failure, 0 if CURRENT MKVP matches and * 1 if OLD MKVP matches. */ -int cca_findcard(const u8 *seckey, u16 *pcardnr, u16 *pdomain, int verify); +int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify); /* struct to hold info for each CCA queue */ struct cca_info { + int hwtype; /* one of the defined AP_DEVICE_TYPE_* */ 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 */