diff options
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 9 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_bus.h | 1 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_api.c | 27 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_ep11misc.c | 60 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_ep11misc.h | 4 |
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 |