Commit da2863f1 authored by Holger Dengler's avatar Holger Dengler Committed by Heiko Carstens
Browse files

s390/pkey: fix PKEY_TYPE_EP11_AES handling in PKEY_CLR2SECK2 IOCTL



Commit 'fa6999e3 ("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: fa6999e3 ("s390/pkey: support CCA and EP11 secure ECC private keys")
Signed-off-by: default avatarHolger Dengler <dengler@linux.ibm.com>
Reviewed-by: default avatarIngo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent fb249ce7
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -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;
+46 −15
Original line number Diff line number Diff line
@@ -1000,7 +1000,7 @@ static int ep11_cryptsingle(u16 card, u16 domain,
	return rc;
}

static int ep11_unwrapkey(u16 card, u16 domain,
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,
@@ -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 @@ 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,
@@ -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;
@@ -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",
+2 −1
Original line number Diff line number Diff line
@@ -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: