summaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorHarald Freudenberger <freude@linux.ibm.com>2019-06-18 15:53:12 +0200
committerVasily Gorbik <gor@linux.ibm.com>2019-08-21 12:58:54 +0200
commit4da57a2fea064f662c29e77da043baebb8d6cdc8 (patch)
treedb03651f0faa192a910569d59a0f86d404956522 /drivers/s390
parent183cb46954dd204e3578a25ad1284aab3debec52 (diff)
downloadlinux-4da57a2fea064f662c29e77da043baebb8d6cdc8.tar.bz2
s390/zcrypt: extend cca_findcard function and helper
Rework and extension of the cca_findcard function to be prepared for other types of secure key blobs. Split the function and extract an internal function which has no awareness of key blobs any more. Improve this function and the helper code around to be able to check for a minimal crypto card hardware level (Background: the newer AES cipher keys need to match to the master key verification pattern and need to have a crypto card CEX6 or higher). No API change, neither for the in-kernel API nor the ioctl interface. 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_api.c28
-rw-r--r--drivers/s390/crypto/zcrypt_api.h7
-rw-r--r--drivers/s390/crypto/zcrypt_ccamisc.c69
-rw-r--r--drivers/s390/crypto/zcrypt_ccamisc.h3
4 files changed, 83 insertions, 24 deletions
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 69ac7bf09a57..563801427fe4 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 af67a768a3fc..2d3f2732344f 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 9dd31577ce47..9b7a866141b8 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 d92fb731602a..e6f41e5baf18 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 */