s390/pkey: fix PKEY_TYPE_EP11_AES handling in PKEY_CLR2SECK2 IOCTL
Commit 'fa6999e326fe ("s390/pkey: support CCA and EP11 secure ECC
private keys")' introduced PKEY_TYPE_EP11_AES for the PKEY_CLR2SECK2
IOCTL to convert an AES clearkey into a securekey of this type.
Unfortunately, all PKEY_CLR2SECK2 IOCTL requests with type
PKEY_TYPE_EP11_AES return with an error (-EINVAL). Fix the handling
for PKEY_TYPE_EP11_AES in PKEY_CLR2SECK2 IOCTL, so that userspace can
convert clearkey blobs into PKEY_TYPE_EP11_AES securekey blobs.
Cc: stable@vger.kernel.org # v5.10+
Fixes: fa6999e326
("s390/pkey: support CCA and EP11 secure ECC private keys")
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>
This commit is contained in:
parent
fb249ce7f7
commit
da2863f159
|
@ -272,7 +272,8 @@ static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen,
|
|||
card = apqns[i] >> 16;
|
||||
dom = apqns[i] & 0xFFFF;
|
||||
rc = ep11_clr2keyblob(card, dom, clrkeylen * 8,
|
||||
0, clrkey, keybuf, keybuflen);
|
||||
0, clrkey, keybuf, keybuflen,
|
||||
PKEY_TYPE_EP11);
|
||||
if (rc == 0)
|
||||
break;
|
||||
}
|
||||
|
@ -775,6 +776,11 @@ static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns,
|
|||
if (*keybufsize < MINEP11AESKEYBLOBSIZE)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PKEY_TYPE_EP11_AES:
|
||||
if (*keybufsize < (sizeof(struct ep11kblob_header) +
|
||||
MINEP11AESKEYBLOBSIZE))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -793,9 +799,11 @@ static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns,
|
|||
for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
|
||||
card = apqns[i].card;
|
||||
dom = apqns[i].domain;
|
||||
if (ktype == PKEY_TYPE_EP11) {
|
||||
if (ktype == PKEY_TYPE_EP11 ||
|
||||
ktype == PKEY_TYPE_EP11_AES) {
|
||||
rc = ep11_clr2keyblob(card, dom, ksize, kflags,
|
||||
clrkey, keybuf, keybufsize);
|
||||
clrkey, keybuf, keybufsize,
|
||||
ktype);
|
||||
} else if (ktype == PKEY_TYPE_CCA_DATA) {
|
||||
rc = cca_clr2seckey(card, dom, ksize,
|
||||
clrkey, keybuf);
|
||||
|
@ -1514,7 +1522,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
|
|||
apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries);
|
||||
if (IS_ERR(apqns))
|
||||
return PTR_ERR(apqns);
|
||||
kkey = kmalloc(klen, GFP_KERNEL);
|
||||
kkey = kzalloc(klen, GFP_KERNEL);
|
||||
if (!kkey) {
|
||||
kfree(apqns);
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -1000,12 +1000,12 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int ep11_unwrapkey(u16 card, u16 domain,
|
||||
const u8 *kek, size_t keksize,
|
||||
const u8 *enckey, size_t enckeysize,
|
||||
u32 mech, const u8 *iv,
|
||||
u32 keybitsize, u32 keygenflags,
|
||||
u8 *keybuf, size_t *keybufsize)
|
||||
static int _ep11_unwrapkey(u16 card, u16 domain,
|
||||
const u8 *kek, size_t keksize,
|
||||
const u8 *enckey, size_t enckeysize,
|
||||
u32 mech, const u8 *iv,
|
||||
u32 keybitsize, u32 keygenflags,
|
||||
u8 *keybuf, size_t *keybufsize)
|
||||
{
|
||||
struct uw_req_pl {
|
||||
struct pl_head head;
|
||||
|
@ -1042,7 +1042,6 @@ static int ep11_unwrapkey(u16 card, u16 domain,
|
|||
struct ep11_cprb *req = NULL, *rep = NULL;
|
||||
struct ep11_target_dev target;
|
||||
struct ep11_urb *urb = NULL;
|
||||
struct ep11keyblob *kb;
|
||||
size_t req_pl_size;
|
||||
int api, rc = -ENOMEM;
|
||||
u8 *p;
|
||||
|
@ -1124,14 +1123,9 @@ static int ep11_unwrapkey(u16 card, u16 domain,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* copy key blob and set header values */
|
||||
/* copy key blob */
|
||||
memcpy(keybuf, rep_pl->data, rep_pl->data_len);
|
||||
*keybufsize = rep_pl->data_len;
|
||||
kb = (struct ep11keyblob *)keybuf;
|
||||
kb->head.type = TOKTYPE_NON_CCA;
|
||||
kb->head.len = rep_pl->data_len;
|
||||
kb->head.version = TOKVER_EP11_AES;
|
||||
kb->head.bitlen = keybitsize;
|
||||
|
||||
out:
|
||||
kfree(req);
|
||||
|
@ -1140,6 +1134,42 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int ep11_unwrapkey(u16 card, u16 domain,
|
||||
const u8 *kek, size_t keksize,
|
||||
const u8 *enckey, size_t enckeysize,
|
||||
u32 mech, const u8 *iv,
|
||||
u32 keybitsize, u32 keygenflags,
|
||||
u8 *keybuf, size_t *keybufsize,
|
||||
u8 keybufver)
|
||||
{
|
||||
struct ep11kblob_header *hdr;
|
||||
size_t hdr_size, pl_size;
|
||||
u8 *pl;
|
||||
int rc;
|
||||
|
||||
rc = ep11_kb_split(keybuf, *keybufsize, keybufver,
|
||||
&hdr, &hdr_size, &pl, &pl_size);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = _ep11_unwrapkey(card, domain, kek, keksize, enckey, enckeysize,
|
||||
mech, iv, keybitsize, keygenflags,
|
||||
pl, &pl_size);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
*keybufsize = hdr_size + pl_size;
|
||||
|
||||
/* update header information */
|
||||
hdr = (struct ep11kblob_header *)keybuf;
|
||||
hdr->type = TOKTYPE_NON_CCA;
|
||||
hdr->len = *keybufsize;
|
||||
hdr->version = keybufver;
|
||||
hdr->bitlen = keybitsize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ep11_wrapkey(u16 card, u16 domain,
|
||||
const u8 *key, size_t keysize,
|
||||
u32 mech, const u8 *iv,
|
||||
|
@ -1274,7 +1304,8 @@ out:
|
|||
}
|
||||
|
||||
int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
|
||||
const u8 *clrkey, u8 *keybuf, size_t *keybufsize)
|
||||
const u8 *clrkey, u8 *keybuf, size_t *keybufsize,
|
||||
u32 keytype)
|
||||
{
|
||||
int rc;
|
||||
u8 encbuf[64], *kek = NULL;
|
||||
|
@ -1321,7 +1352,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);
|
||||
keybitsize, 0, keybuf, keybufsize, keytype);
|
||||
if (rc) {
|
||||
DEBUG_ERR(
|
||||
"%s importing key value as new key failed,, rc=%d\n",
|
||||
|
|
|
@ -113,7 +113,8 @@ int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
|
|||
* Generate EP11 AES secure key with given clear key value.
|
||||
*/
|
||||
int ep11_clr2keyblob(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
|
||||
const u8 *clrkey, u8 *keybuf, size_t *keybufsize);
|
||||
const u8 *clrkey, u8 *keybuf, size_t *keybufsize,
|
||||
u32 keytype);
|
||||
|
||||
/*
|
||||
* Build a list of ep11 apqns meeting the following constrains:
|
||||
|
|
Loading…
Reference in New Issue