s390/pkey: fix PKEY_TYPE_EP11_AES handling in PKEY_CLR2SECK2 IOCTL
authorHolger Dengler <dengler@linux.ibm.com>
Tue, 25 Jul 2023 09:24:47 +0000 (11:24 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 6 Oct 2023 12:56:44 +0000 (14:56 +0200)
[ Upstream commit da2863f15945de100b95c72d5656541d30956c5d ]

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: fa6999e326fe ("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>
drivers/s390/crypto/pkey_api.c
drivers/s390/crypto/zcrypt_ep11misc.c
drivers/s390/crypto/zcrypt_ep11misc.h

index 2b92ec2..df0f19e 100644 (file)
@@ -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;
        }
@@ -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;
        }
@@ -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);
@@ -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;
index 20bbeec..77e1ffa 100644 (file)
@@ -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",
index ed328c3..b7f9cbe 100644 (file)
@@ -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: