mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02:00
s390/zcrypt: Rework ep11 misc functions to use cprb mempool
There are two places in the ep11 misc code where a short term memory buffer is needed. Rework this code to use the cprb mempool to satisfy this ephemeral memory requirements. Signed-off-by: Harald Freudenberger <freude@linux.ibm.com> Reviewed-by: Holger Dengler <dengler@linux.ibm.com> Link: https://lore.kernel.org/r/20250424133619.16495-19-freude@linux.ibm.com Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
parent
e9f45ef675
commit
6fecab9b92
|
|
@ -280,6 +280,7 @@ static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
|
|||
{
|
||||
struct pkey_apqn *local_apqns = NULL;
|
||||
int i, len, rc;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* check keytype, subtype, keybitsize */
|
||||
switch (keytype) {
|
||||
|
|
@ -328,7 +329,7 @@ static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
|
|||
for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
|
||||
rc = ep11_genaeskey(apqns[i].card, apqns[i].domain,
|
||||
keybitsize, flags,
|
||||
keybuf, keybuflen, subtype);
|
||||
keybuf, keybuflen, subtype, xflags);
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ static ssize_t ep11_api_ordinalnr_show(struct device *dev,
|
|||
|
||||
memset(&ci, 0, sizeof(ci));
|
||||
|
||||
ep11_get_card_info(ac->id, &ci);
|
||||
ep11_get_card_info(ac->id, &ci, 0);
|
||||
|
||||
if (ci.API_ord_nr > 0)
|
||||
return sysfs_emit(buf, "%u\n", ci.API_ord_nr);
|
||||
|
|
@ -234,7 +234,7 @@ static ssize_t ep11_fw_version_show(struct device *dev,
|
|||
|
||||
memset(&ci, 0, sizeof(ci));
|
||||
|
||||
ep11_get_card_info(ac->id, &ci);
|
||||
ep11_get_card_info(ac->id, &ci, 0);
|
||||
|
||||
if (ci.FW_version > 0)
|
||||
return sysfs_emit(buf, "%d.%d\n",
|
||||
|
|
@ -256,7 +256,7 @@ static ssize_t ep11_serialnr_show(struct device *dev,
|
|||
|
||||
memset(&ci, 0, sizeof(ci));
|
||||
|
||||
ep11_get_card_info(ac->id, &ci);
|
||||
ep11_get_card_info(ac->id, &ci, 0);
|
||||
|
||||
if (ci.serial[0])
|
||||
return sysfs_emit(buf, "%16.16s\n", ci.serial);
|
||||
|
|
@ -293,7 +293,7 @@ static ssize_t ep11_card_op_modes_show(struct device *dev,
|
|||
|
||||
memset(&ci, 0, sizeof(ci));
|
||||
|
||||
ep11_get_card_info(ac->id, &ci);
|
||||
ep11_get_card_info(ac->id, &ci, 0);
|
||||
|
||||
for (i = 0; ep11_op_modes[i].mode_txt; i++) {
|
||||
if (ci.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) {
|
||||
|
|
@ -343,7 +343,7 @@ static ssize_t ep11_mkvps_show(struct device *dev,
|
|||
if (zq->online)
|
||||
ep11_get_domain_info(AP_QID_CARD(zq->queue->qid),
|
||||
AP_QID_QUEUE(zq->queue->qid),
|
||||
&di);
|
||||
&di, 0);
|
||||
|
||||
if (di.cur_wk_state == '0') {
|
||||
n = sysfs_emit(buf, "WK CUR: %s -\n",
|
||||
|
|
@ -390,7 +390,7 @@ static ssize_t ep11_queue_op_modes_show(struct device *dev,
|
|||
if (zq->online)
|
||||
ep11_get_domain_info(AP_QID_CARD(zq->queue->qid),
|
||||
AP_QID_QUEUE(zq->queue->qid),
|
||||
&di);
|
||||
&di, 0);
|
||||
|
||||
for (i = 0; ep11_op_modes[i].mode_txt; i++) {
|
||||
if (di.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) {
|
||||
|
|
|
|||
|
|
@ -549,7 +549,7 @@ static int check_reply_cprb(const struct ep11_cprb *rep, const char *func)
|
|||
* Helper function which does an ep11 query with given query type.
|
||||
*/
|
||||
static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
|
||||
size_t buflen, u8 *buf)
|
||||
size_t buflen, u8 *buf, u32 xflags)
|
||||
{
|
||||
struct ep11_info_req_pl {
|
||||
struct pl_head head;
|
||||
|
|
@ -573,7 +573,6 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
|
|||
struct ep11_target_dev target;
|
||||
struct ep11_urb urb;
|
||||
int api = EP11_API_V1, rc = -ENOMEM;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* request cprb and payload */
|
||||
req = alloc_cprbmem(sizeof(struct ep11_info_req_pl), xflags);
|
||||
|
|
@ -639,7 +638,7 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
|
|||
/*
|
||||
* Provide information about an EP11 card.
|
||||
*/
|
||||
int ep11_get_card_info(u16 card, struct ep11_card_info *info)
|
||||
int ep11_get_card_info(u16 card, struct ep11_card_info *info, u32 xflags)
|
||||
{
|
||||
int rc;
|
||||
struct ep11_module_query_info {
|
||||
|
|
@ -669,12 +668,15 @@ int ep11_get_card_info(u16 card, struct ep11_card_info *info)
|
|||
u32 max_CP_index;
|
||||
} __packed * pmqi = NULL;
|
||||
|
||||
pmqi = kmalloc(sizeof(*pmqi), GFP_KERNEL);
|
||||
/* use the cprb mempool to satisfy this short term mem alloc */
|
||||
pmqi = (xflags & ZCRYPT_XFLAG_NOMEMALLOC) ?
|
||||
mempool_alloc_preallocated(cprb_mempool) :
|
||||
mempool_alloc(cprb_mempool, GFP_KERNEL);
|
||||
if (!pmqi)
|
||||
return -ENOMEM;
|
||||
rc = ep11_query_info(card, AUTOSEL_DOM,
|
||||
0x01 /* module info query */,
|
||||
sizeof(*pmqi), (u8 *)pmqi);
|
||||
sizeof(*pmqi), (u8 *)pmqi, xflags);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
|
@ -685,7 +687,7 @@ int ep11_get_card_info(u16 card, struct ep11_card_info *info)
|
|||
info->op_mode = pmqi->op_mode;
|
||||
|
||||
out:
|
||||
kfree(pmqi);
|
||||
mempool_free(pmqi, cprb_mempool);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(ep11_get_card_info);
|
||||
|
|
@ -693,7 +695,8 @@ EXPORT_SYMBOL(ep11_get_card_info);
|
|||
/*
|
||||
* Provide information about a domain within an EP11 card.
|
||||
*/
|
||||
int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info)
|
||||
int ep11_get_domain_info(u16 card, u16 domain,
|
||||
struct ep11_domain_info *info, u32 xflags)
|
||||
{
|
||||
int rc;
|
||||
struct ep11_domain_query_info {
|
||||
|
|
@ -705,7 +708,8 @@ int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info)
|
|||
} __packed dom_query_info;
|
||||
|
||||
rc = ep11_query_info(card, domain, 0x03 /* domain info query */,
|
||||
sizeof(dom_query_info), (u8 *)&dom_query_info);
|
||||
sizeof(dom_query_info), (u8 *)&dom_query_info,
|
||||
xflags);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
|
@ -739,7 +743,7 @@ EXPORT_SYMBOL(ep11_get_domain_info);
|
|||
|
||||
static int _ep11_genaeskey(u16 card, u16 domain,
|
||||
u32 keybitsize, u32 keygenflags,
|
||||
u8 *keybuf, size_t *keybufsize)
|
||||
u8 *keybuf, size_t *keybufsize, u32 xflags)
|
||||
{
|
||||
struct keygen_req_pl {
|
||||
struct pl_head head;
|
||||
|
|
@ -777,7 +781,6 @@ static int _ep11_genaeskey(u16 card, u16 domain,
|
|||
struct ep11_urb urb;
|
||||
int api, rc = -ENOMEM;
|
||||
u8 *p;
|
||||
const u32 xflags = 0;
|
||||
|
||||
switch (keybitsize) {
|
||||
case 128:
|
||||
|
|
@ -880,7 +883,7 @@ static int _ep11_genaeskey(u16 card, u16 domain,
|
|||
}
|
||||
|
||||
int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
|
||||
u8 *keybuf, u32 *keybufsize, u32 keybufver)
|
||||
u8 *keybuf, u32 *keybufsize, u32 keybufver, u32 xflags)
|
||||
{
|
||||
struct ep11kblob_header *hdr;
|
||||
size_t hdr_size, pl_size;
|
||||
|
|
@ -901,7 +904,7 @@ int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
|
|||
return rc;
|
||||
|
||||
rc = _ep11_genaeskey(card, domain, keybitsize, keygenflags,
|
||||
pl, &pl_size);
|
||||
pl, &pl_size, xflags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -921,7 +924,8 @@ static int ep11_cryptsingle(u16 card, u16 domain,
|
|||
u16 mode, u32 mech, const u8 *iv,
|
||||
const u8 *key, size_t keysize,
|
||||
const u8 *inbuf, size_t inbufsize,
|
||||
u8 *outbuf, size_t *outbufsize)
|
||||
u8 *outbuf, size_t *outbufsize,
|
||||
u32 xflags)
|
||||
{
|
||||
struct crypt_req_pl {
|
||||
struct pl_head head;
|
||||
|
|
@ -952,7 +956,6 @@ static int ep11_cryptsingle(u16 card, u16 domain,
|
|||
size_t req_pl_size, rep_pl_size = 0;
|
||||
int n, api = EP11_API_V1, rc = -ENOMEM;
|
||||
u8 *p;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* the simple asn1 coding used has length limits */
|
||||
if (keysize > 0xFFFF || inbufsize > 0xFFFF)
|
||||
|
|
@ -1051,7 +1054,7 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
|
|||
const u8 *enckey, size_t enckeysize,
|
||||
u32 mech, const u8 *iv,
|
||||
u32 keybitsize, u32 keygenflags,
|
||||
u8 *keybuf, size_t *keybufsize)
|
||||
u8 *keybuf, size_t *keybufsize, u32 xflags)
|
||||
{
|
||||
struct uw_req_pl {
|
||||
struct pl_head head;
|
||||
|
|
@ -1091,7 +1094,6 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
|
|||
struct ep11_urb urb;
|
||||
int api, rc = -ENOMEM;
|
||||
u8 *p;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* request cprb and payload */
|
||||
api = (!keygenflags || keygenflags & 0x00200000) ?
|
||||
|
|
@ -1199,7 +1201,7 @@ static int ep11_unwrapkey(u16 card, u16 domain,
|
|||
u32 mech, const u8 *iv,
|
||||
u32 keybitsize, u32 keygenflags,
|
||||
u8 *keybuf, u32 *keybufsize,
|
||||
u8 keybufver)
|
||||
u8 keybufver, u32 xflags)
|
||||
{
|
||||
struct ep11kblob_header *hdr;
|
||||
size_t hdr_size, pl_size;
|
||||
|
|
@ -1213,7 +1215,7 @@ static int ep11_unwrapkey(u16 card, u16 domain,
|
|||
|
||||
rc = _ep11_unwrapkey(card, domain, kek, keksize, enckey, enckeysize,
|
||||
mech, iv, keybitsize, keygenflags,
|
||||
pl, &pl_size);
|
||||
pl, &pl_size, xflags);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -1232,7 +1234,7 @@ static int ep11_unwrapkey(u16 card, u16 domain,
|
|||
static int _ep11_wrapkey(u16 card, u16 domain,
|
||||
const u8 *key, size_t keysize,
|
||||
u32 mech, const u8 *iv,
|
||||
u8 *databuf, size_t *datasize)
|
||||
u8 *databuf, size_t *datasize, u32 xflags)
|
||||
{
|
||||
struct wk_req_pl {
|
||||
struct pl_head head;
|
||||
|
|
@ -1265,7 +1267,6 @@ static int _ep11_wrapkey(u16 card, u16 domain,
|
|||
size_t req_pl_size;
|
||||
int api, rc = -ENOMEM;
|
||||
u8 *p;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* request cprb and payload */
|
||||
req_pl_size = sizeof(struct wk_req_pl) + (iv ? 16 : 0)
|
||||
|
|
@ -1355,8 +1356,10 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
|
|||
u32 keytype)
|
||||
{
|
||||
int rc;
|
||||
u8 encbuf[64], *kek = NULL;
|
||||
void *mem;
|
||||
u8 encbuf[64], *kek;
|
||||
size_t clrkeylen, keklen, encbuflen = sizeof(encbuf);
|
||||
const u32 xflags = 0;
|
||||
|
||||
if (keybitsize == 128 || keybitsize == 192 || keybitsize == 256) {
|
||||
clrkeylen = keybitsize / 8;
|
||||
|
|
@ -1366,18 +1369,24 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* allocate memory for the temp kek */
|
||||
/*
|
||||
* Allocate space for the temp kek.
|
||||
* Also we only need up to MAXEP11AESKEYBLOBSIZE bytes for this
|
||||
* we use the already existing cprb mempool to solve this
|
||||
* short term memory requirement.
|
||||
*/
|
||||
mem = (xflags & ZCRYPT_XFLAG_NOMEMALLOC) ?
|
||||
mempool_alloc_preallocated(cprb_mempool) :
|
||||
mempool_alloc(cprb_mempool, GFP_KERNEL);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
kek = (u8 *)mem;
|
||||
keklen = MAXEP11AESKEYBLOBSIZE;
|
||||
kek = kmalloc(keklen, GFP_ATOMIC);
|
||||
if (!kek) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Step 1: generate AES 256 bit random kek key */
|
||||
rc = _ep11_genaeskey(card, domain, 256,
|
||||
0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */
|
||||
kek, &keklen);
|
||||
kek, &keklen, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s generate kek key failed, rc=%d\n",
|
||||
__func__, rc);
|
||||
|
|
@ -1386,7 +1395,7 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
|
|||
|
||||
/* Step 2: encrypt clear key value with the kek key */
|
||||
rc = ep11_cryptsingle(card, domain, 0, 0, def_iv, kek, keklen,
|
||||
clrkey, clrkeylen, encbuf, &encbuflen);
|
||||
clrkey, clrkeylen, encbuf, &encbuflen, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s encrypting key value with kek key failed, rc=%d\n",
|
||||
__func__, rc);
|
||||
|
|
@ -1396,7 +1405,7 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
|
|||
/* Step 3: import the encrypted key value as a new key */
|
||||
rc = ep11_unwrapkey(card, domain, kek, keklen,
|
||||
encbuf, encbuflen, 0, def_iv,
|
||||
keybitsize, 0, keybuf, keybufsize, keytype);
|
||||
keybitsize, 0, keybuf, keybufsize, keytype, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s importing key value as new key failed, rc=%d\n",
|
||||
__func__, rc);
|
||||
|
|
@ -1404,7 +1413,7 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
|
|||
}
|
||||
|
||||
out:
|
||||
kfree(kek);
|
||||
mempool_free(mem, cprb_mempool);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(ep11_clr2keyblob);
|
||||
|
|
@ -1427,6 +1436,7 @@ int ep11_kblob2protkey(u16 card, u16 dom,
|
|||
} __packed * wki;
|
||||
u8 *wkbuf = NULL;
|
||||
int rc = -EIO;
|
||||
const u32 xflags = 0;
|
||||
|
||||
if (ep11_kb_decode((u8 *)keyblob, keybloblen, &hdr, NULL, &key, &keylen))
|
||||
return -EINVAL;
|
||||
|
|
@ -1437,15 +1447,29 @@ int ep11_kblob2protkey(u16 card, u16 dom,
|
|||
}
|
||||
/* !!! hdr is no longer a valid header !!! */
|
||||
|
||||
/* alloc temp working buffer */
|
||||
/* need a temp working buffer */
|
||||
wkbuflen = (keylen + AES_BLOCK_SIZE) & (~(AES_BLOCK_SIZE - 1));
|
||||
wkbuf = kmalloc(wkbuflen, GFP_ATOMIC);
|
||||
if (!wkbuf)
|
||||
return -ENOMEM;
|
||||
if (wkbuflen > CPRB_MEMPOOL_ITEM_SIZE) {
|
||||
/* this should never happen */
|
||||
rc = -ENOMEM;
|
||||
ZCRYPT_DBF_WARN("%s wkbuflen %d > cprb mempool item size %d, rc=%d\n",
|
||||
__func__, (int)wkbuflen, CPRB_MEMPOOL_ITEM_SIZE, rc);
|
||||
return rc;
|
||||
}
|
||||
/* use the cprb mempool to satisfy this short term mem allocation */
|
||||
wkbuf = (xflags & ZCRYPT_XFLAG_NOMEMALLOC) ?
|
||||
mempool_alloc_preallocated(cprb_mempool) :
|
||||
mempool_alloc(cprb_mempool, GFP_ATOMIC);
|
||||
if (!wkbuf) {
|
||||
rc = -ENOMEM;
|
||||
ZCRYPT_DBF_WARN("%s allocating tmp buffer via cprb mempool failed, rc=%d\n",
|
||||
__func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* ep11 secure key -> protected key + info */
|
||||
rc = _ep11_wrapkey(card, dom, (u8 *)key, keylen,
|
||||
0, def_iv, wkbuf, &wkbuflen);
|
||||
0, def_iv, wkbuf, &wkbuflen, xflags);
|
||||
if (rc) {
|
||||
ZCRYPT_DBF_ERR("%s rewrapping ep11 key to pkey failed, rc=%d\n",
|
||||
__func__, rc);
|
||||
|
|
@ -1512,7 +1536,7 @@ int ep11_kblob2protkey(u16 card, u16 dom,
|
|||
*protkeylen = wki->pkeysize;
|
||||
|
||||
out:
|
||||
kfree(wkbuf);
|
||||
mempool_free(wkbuf, cprb_mempool);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(ep11_kblob2protkey);
|
||||
|
|
@ -1525,6 +1549,7 @@ int ep11_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
|
|||
struct ep11_card_info eci;
|
||||
u32 _nr_apqns = 0;
|
||||
int i, card, dom;
|
||||
const u32 xflags = 0;
|
||||
|
||||
/* occupy the device status memory */
|
||||
mutex_lock(&dev_status_mem_mutex);
|
||||
|
|
@ -1557,14 +1582,14 @@ int ep11_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
|
|||
continue;
|
||||
/* check min api version if given */
|
||||
if (minapi > 0) {
|
||||
if (ep11_get_card_info(card, &eci))
|
||||
if (ep11_get_card_info(card, &eci, xflags))
|
||||
continue;
|
||||
if (minapi > eci.API_ord_nr)
|
||||
continue;
|
||||
}
|
||||
/* check wkvp if given */
|
||||
if (wkvp) {
|
||||
if (ep11_get_domain_info(card, dom, &edi))
|
||||
if (ep11_get_domain_info(card, dom, &edi, xflags))
|
||||
continue;
|
||||
if (edi.cur_wk_state != '1')
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -104,18 +104,19 @@ struct ep11_domain_info {
|
|||
/*
|
||||
* Provide information about an EP11 card.
|
||||
*/
|
||||
int ep11_get_card_info(u16 card, struct ep11_card_info *info);
|
||||
int ep11_get_card_info(u16 card, struct ep11_card_info *info, u32 xflags);
|
||||
|
||||
/*
|
||||
* Provide information about a domain within an EP11 card.
|
||||
*/
|
||||
int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info);
|
||||
int ep11_get_domain_info(u16 card, u16 domain,
|
||||
struct ep11_domain_info *info, u32 xflags);
|
||||
|
||||
/*
|
||||
* Generate (random) EP11 AES secure key.
|
||||
*/
|
||||
int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
|
||||
u8 *keybuf, u32 *keybufsize, u32 keybufver);
|
||||
u8 *keybuf, u32 *keybufsize, u32 keybufver, u32 xflags);
|
||||
|
||||
/*
|
||||
* Generate EP11 AES secure key with given clear key value.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user