summaryrefslogtreecommitdiff
path: root/drivers/s390/crypto
diff options
context:
space:
mode:
authorHolger Dengler <dengler@linux.ibm.com>2023-08-11 16:56:20 +0200
committerHeiko Carstens <hca@linux.ibm.com>2023-08-18 15:07:57 +0200
commit386cb81e4ba7811573765aaaeb91b472639c2bae (patch)
tree3ebc14e4894166f58fa4fb555d11e85ae5bd3116 /drivers/s390/crypto
parentcba33db3fc4dbf2e54294b0e499d2335a3a00d78 (diff)
s390/zcrypt_ep11misc: support API ordinal 6 with empty pin-blob
Secure execution guest environments require an empty pinblob in all key generation and unwrap requests. Empty pinblobs are only available in EP11 API ordinal 6 or higher. Add an empty pinblob to key generation and unwrap requests, if the AP secure binding facility is available. In all other cases, stay with the empty pin tag (no pinblob) and the current API ordinals. The EP11 API ordinal also needs to be considered when the pkey module tries to figure out the list of eligible cards for key operations with protected keys in secure execution environment. These changes are transparent to userspace but required for running an secure execution guest with handling key generate and key derive (e.g. secure key to protected key) correct. Especially using EP11 secure keys with the kernel dm-crypt layer requires this patch. Co-developed-by: Harald Freudenberger <freude@linux.ibm.com> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com> Signed-off-by: Holger Dengler <dengler@linux.ibm.com> Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'drivers/s390/crypto')
-rw-r--r--drivers/s390/crypto/ap_bus.c9
-rw-r--r--drivers/s390/crypto/ap_bus.h1
-rw-r--r--drivers/s390/crypto/pkey_api.c27
-rw-r--r--drivers/s390/crypto/zcrypt_ep11misc.c60
-rw-r--r--drivers/s390/crypto/zcrypt_ep11misc.h4
5 files changed, 76 insertions, 25 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index b1d2fedea086..339812efe822 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -219,6 +219,15 @@ int ap_sb_available(void)
}
/*
+ * ap_is_se_guest(): Check for SE guest with AP pass-through support.
+ */
+bool ap_is_se_guest(void)
+{
+ return is_prot_virt_guest() && ap_sb_available();
+}
+EXPORT_SYMBOL(ap_is_se_guest);
+
+/*
* ap_fetch_qci_info(): Fetch cryptographic config info
*
* Returns the ap configuration info fetched via PQAP(QCI).
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 47bbe9babc59..be54b070c031 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -274,6 +274,7 @@ void ap_flush_queue(struct ap_queue *aq);
void *ap_airq_ptr(void);
int ap_sb_available(void);
+bool ap_is_se_guest(void);
void ap_wait(enum ap_sm_wait wait);
void ap_request_timeout(struct timer_list *t);
void ap_bus_force_rescan(void);
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c
index 396a159afdf5..6cfb6b2340c9 100644
--- a/drivers/s390/crypto/pkey_api.c
+++ b/drivers/s390/crypto/pkey_api.c
@@ -263,7 +263,9 @@ static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen,
/* build a list of apqns suitable for ep11 keys with cpacf support */
rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
- ZCRYPT_CEX7, EP11_API_V, NULL);
+ ZCRYPT_CEX7,
+ ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4,
+ NULL);
if (rc)
goto out;
@@ -299,7 +301,8 @@ static int pkey_ep11key2pkey(const u8 *key, size_t keylen,
/* build a list of apqns suitable for this key */
rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
- ZCRYPT_CEX7, EP11_API_V,
+ ZCRYPT_CEX7,
+ ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4,
ep11_kb_wkvp(key, keylen));
if (rc)
goto out;
@@ -902,6 +905,7 @@ static int pkey_verifykey2(const u8 *key, size_t keylen,
} else if (hdr->type == TOKTYPE_NON_CCA &&
hdr->version == TOKVER_EP11_AES) {
struct ep11keyblob *kb = (struct ep11keyblob *)key;
+ int api;
rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1);
if (rc)
@@ -911,8 +915,9 @@ static int pkey_verifykey2(const u8 *key, size_t keylen,
if (ksize)
*ksize = kb->head.bitlen;
+ api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
- ZCRYPT_CEX7, EP11_API_V,
+ ZCRYPT_CEX7, api,
ep11_kb_wkvp(key, keylen));
if (rc)
goto out;
@@ -926,6 +931,7 @@ static int pkey_verifykey2(const u8 *key, size_t keylen,
} else if (hdr->type == TOKTYPE_NON_CCA &&
hdr->version == TOKVER_EP11_AES_WITH_HEADER) {
struct ep11kblob_header *kh = (struct ep11kblob_header *)key;
+ int api;
rc = ep11_check_aes_key_with_hdr(debug_info, 3,
key, keylen, 1);
@@ -936,8 +942,9 @@ static int pkey_verifykey2(const u8 *key, size_t keylen,
if (ksize)
*ksize = kh->bitlen;
+ api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
- ZCRYPT_CEX7, EP11_API_V,
+ ZCRYPT_CEX7, api,
ep11_kb_wkvp(key, keylen));
if (rc)
goto out;
@@ -1056,7 +1063,7 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
return -EINVAL;
if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) {
minhwtype = ZCRYPT_CEX7;
- api = EP11_API_V;
+ api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
}
rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
minhwtype, api, kb->wkvp);
@@ -1072,7 +1079,7 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
return -EINVAL;
if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) {
minhwtype = ZCRYPT_CEX7;
- api = EP11_API_V;
+ api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
}
rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
minhwtype, api, kb->wkvp);
@@ -1182,11 +1189,13 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype,
ktype == PKEY_TYPE_EP11_AES ||
ktype == PKEY_TYPE_EP11_ECC) {
u8 *wkvp = NULL;
+ int api;
if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
wkvp = cur_mkvp;
+ api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
- ZCRYPT_CEX7, EP11_API_V, wkvp);
+ ZCRYPT_CEX7, api, wkvp);
if (rc)
goto out;
@@ -2160,7 +2169,9 @@ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits,
/* build a list of apqns able to generate an cipher key */
rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
- ZCRYPT_CEX7, EP11_API_V, NULL);
+ ZCRYPT_CEX7,
+ ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4,
+ NULL);
if (rc)
return rc;
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
index 669ad6f5d5b0..0a877f9792c2 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.c
+++ b/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -29,6 +29,8 @@
#define DEBUG_WARN(...) ZCRYPT_DBF(DBF_WARN, ##__VA_ARGS__)
#define DEBUG_ERR(...) ZCRYPT_DBF(DBF_ERR, ##__VA_ARGS__)
+#define EP11_PINBLOB_V1_BYTES 56
+
/* default iv used here */
static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
@@ -592,7 +594,7 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
struct ep11_cprb *req = NULL, *rep = NULL;
struct ep11_target_dev target;
struct ep11_urb *urb = NULL;
- int api = 1, rc = -ENOMEM;
+ int api = EP11_API_V1, rc = -ENOMEM;
/* request cprb and payload */
req = alloc_cprb(sizeof(struct ep11_info_req_pl));
@@ -789,8 +791,7 @@ static int _ep11_genaeskey(u16 card, u16 domain,
u32 attr_bool_bits;
u32 attr_val_len_type;
u32 attr_val_len_value;
- u8 pin_tag;
- u8 pin_len;
+ /* followed by empty pin tag or empty pinblob tag */
} __packed * req_pl;
struct keygen_rep_pl {
struct pl_head head;
@@ -803,9 +804,11 @@ static int _ep11_genaeskey(u16 card, u16 domain,
u8 data[512];
} __packed * rep_pl;
struct ep11_cprb *req = NULL, *rep = NULL;
+ size_t req_pl_size, pinblob_size = 0;
struct ep11_target_dev target;
struct ep11_urb *urb = NULL;
int api, rc = -ENOMEM;
+ u8 *p;
switch (keybitsize) {
case 128:
@@ -821,12 +824,22 @@ static int _ep11_genaeskey(u16 card, u16 domain,
}
/* request cprb and payload */
- req = alloc_cprb(sizeof(struct keygen_req_pl));
+ api = (!keygenflags || keygenflags & 0x00200000) ?
+ EP11_API_V4 : EP11_API_V1;
+ if (ap_is_se_guest()) {
+ /*
+ * genkey within SE environment requires API ordinal 6
+ * with empty pinblob
+ */
+ api = EP11_API_V6;
+ pinblob_size = EP11_PINBLOB_V1_BYTES;
+ }
+ req_pl_size = sizeof(struct keygen_req_pl) + ASN1TAGLEN(pinblob_size);
+ req = alloc_cprb(req_pl_size);
if (!req)
goto out;
req_pl = (struct keygen_req_pl *)(((u8 *)req) + sizeof(*req));
- api = (!keygenflags || keygenflags & 0x00200000) ? 4 : 1;
- prep_head(&req_pl->head, sizeof(*req_pl), api, 21); /* GenerateKey */
+ prep_head(&req_pl->head, req_pl_size, api, 21); /* GenerateKey */
req_pl->var_tag = 0x04;
req_pl->var_len = sizeof(u32);
req_pl->keybytes_tag = 0x04;
@@ -842,7 +855,10 @@ static int _ep11_genaeskey(u16 card, u16 domain,
req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
req_pl->attr_val_len_type = 0x00000161; /* CKA_VALUE_LEN */
req_pl->attr_val_len_value = keybitsize / 8;
- req_pl->pin_tag = 0x04;
+ p = ((u8 *)req_pl) + sizeof(*req_pl);
+ /* pin tag */
+ *p++ = 0x04;
+ *p++ = pinblob_size;
/* reply cprb and payload */
rep = alloc_cprb(sizeof(struct keygen_rep_pl));
@@ -857,7 +873,7 @@ static int _ep11_genaeskey(u16 card, u16 domain,
target.ap_id = card;
target.dom_id = domain;
prep_urb(urb, &target, 1,
- req, sizeof(*req) + sizeof(*req_pl),
+ req, sizeof(*req) + req_pl_size,
rep, sizeof(*rep) + sizeof(*rep_pl));
rc = zcrypt_send_ep11_cprb(urb);
@@ -965,7 +981,7 @@ static int ep11_cryptsingle(u16 card, u16 domain,
struct ep11_target_dev target;
struct ep11_urb *urb = NULL;
size_t req_pl_size, rep_pl_size;
- int n, api = 1, rc = -ENOMEM;
+ int n, api = EP11_API_V1, rc = -ENOMEM;
u8 *p;
/* the simple asn1 coding used has length limits */
@@ -1084,7 +1100,7 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
* maybe followed by iv data
* followed by kek tag + kek blob
* followed by empty mac tag
- * followed by empty pin tag
+ * followed by empty pin tag or empty pinblob tag
* followed by encryted key tag + bytes
*/
} __packed * req_pl;
@@ -1099,20 +1115,30 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
u8 data[512];
} __packed * rep_pl;
struct ep11_cprb *req = NULL, *rep = NULL;
+ size_t req_pl_size, pinblob_size = 0;
struct ep11_target_dev target;
struct ep11_urb *urb = NULL;
- size_t req_pl_size;
int api, rc = -ENOMEM;
u8 *p;
/* request cprb and payload */
+ api = (!keygenflags || keygenflags & 0x00200000) ?
+ EP11_API_V4 : EP11_API_V1;
+ if (ap_is_se_guest()) {
+ /*
+ * unwrap within SE environment requires API ordinal 6
+ * with empty pinblob
+ */
+ api = EP11_API_V6;
+ pinblob_size = EP11_PINBLOB_V1_BYTES;
+ }
req_pl_size = sizeof(struct uw_req_pl) + (iv ? 16 : 0)
- + ASN1TAGLEN(keksize) + 4 + ASN1TAGLEN(enckeysize);
+ + ASN1TAGLEN(keksize) + ASN1TAGLEN(0)
+ + ASN1TAGLEN(pinblob_size) + ASN1TAGLEN(enckeysize);
req = alloc_cprb(req_pl_size);
if (!req)
goto out;
req_pl = (struct uw_req_pl *)(((u8 *)req) + sizeof(*req));
- api = (!keygenflags || keygenflags & 0x00200000) ? 4 : 1;
prep_head(&req_pl->head, req_pl_size, api, 34); /* UnwrapKey */
req_pl->attr_tag = 0x04;
req_pl->attr_len = 7 * sizeof(u32);
@@ -1137,9 +1163,10 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
/* empty mac key tag */
*p++ = 0x04;
*p++ = 0;
- /* empty pin tag */
+ /* pin tag */
*p++ = 0x04;
- *p++ = 0;
+ *p++ = pinblob_size;
+ p += pinblob_size;
/* encrypted key value tag and bytes */
p += asn1tag_write(p, 0x04, enckey, enckeysize);
@@ -1275,7 +1302,8 @@ static int _ep11_wrapkey(u16 card, u16 domain,
if (!mech || mech == 0x80060001)
req->flags |= 0x20; /* CPACF_WRAP needs special bit */
req_pl = (struct wk_req_pl *)(((u8 *)req) + sizeof(*req));
- api = (!mech || mech == 0x80060001) ? 4 : 1; /* CKM_IBM_CPACF_WRAP */
+ api = (!mech || mech == 0x80060001) ? /* CKM_IBM_CPACF_WRAP */
+ EP11_API_V4 : EP11_API_V1;
prep_head(&req_pl->head, req_pl_size, api, 33); /* WrapKey */
req_pl->var_tag = 0x04;
req_pl->var_len = sizeof(u32);
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.h b/drivers/s390/crypto/zcrypt_ep11misc.h
index a0de1cccebbe..9d17fd5228a7 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.h
+++ b/drivers/s390/crypto/zcrypt_ep11misc.h
@@ -12,7 +12,9 @@
#include <asm/zcrypt.h>
#include <asm/pkey.h>
-#define EP11_API_V 4 /* highest known and supported EP11 API version */
+#define EP11_API_V1 1 /* min EP11 API, default if no higher api required */
+#define EP11_API_V4 4 /* supported EP11 API for the ep11misc cprbs */
+#define EP11_API_V6 6 /* min EP11 API for some cprbs in SE environment */
#define EP11_STRUCT_MAGIC 0x1234
#define EP11_BLOB_PKEY_EXTRACTABLE 0x00200000