Skip to content

Commit

Permalink
s390/pkey: fix PKEY_TYPE_EP11_AES handling in PKEY_CLR2SECK2 IOCTL
Browse files Browse the repository at this point in the history
[ Upstream commit da2863f ]

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: fa6999e ("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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
holger-dengler authored and gregkh committed Oct 6, 2023
1 parent a84ac89 commit 03b8080
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 20 deletions.
16 changes: 12 additions & 4 deletions drivers/s390/crypto/pkey_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,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;
}
Expand Down Expand Up @@ -627,6 +628,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;
}
Expand All @@ -645,9 +651,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);
Expand Down Expand Up @@ -1361,7 +1369,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;
Expand Down
61 changes: 46 additions & 15 deletions drivers/s390/crypto/zcrypt_ep11misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1000,12 +1000,12 @@ static int ep11_cryptsingle(u16 card, u16 domain,
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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -1140,6 +1134,42 @@ static int ep11_unwrapkey(u16 card, u16 domain,
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,
Expand Down Expand Up @@ -1274,7 +1304,8 @@ static int ep11_wrapkey(u16 card, u16 domain,
}

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;
Expand Down Expand Up @@ -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",
Expand Down
3 changes: 2 additions & 1 deletion drivers/s390/crypto/zcrypt_ep11misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit 03b8080

Please sign in to comment.