xref: /linux/drivers/s390/crypto/pkey_cca.c (revision ea88e1710a9f19345c94c195f9cd7365e50343b0)
186fbf5e2SHarald Freudenberger // SPDX-License-Identifier: GPL-2.0
286fbf5e2SHarald Freudenberger /*
386fbf5e2SHarald Freudenberger  *  pkey cca specific code
486fbf5e2SHarald Freudenberger  *
586fbf5e2SHarald Freudenberger  *  Copyright IBM Corp. 2024
686fbf5e2SHarald Freudenberger  */
786fbf5e2SHarald Freudenberger 
886fbf5e2SHarald Freudenberger #define KMSG_COMPONENT "pkey"
986fbf5e2SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
1086fbf5e2SHarald Freudenberger 
1186fbf5e2SHarald Freudenberger #include "zcrypt_api.h"
1286fbf5e2SHarald Freudenberger #include "zcrypt_ccamisc.h"
1386fbf5e2SHarald Freudenberger 
1486fbf5e2SHarald Freudenberger #include "pkey_base.h"
1586fbf5e2SHarald Freudenberger 
1686fbf5e2SHarald Freudenberger /*
1786fbf5e2SHarald Freudenberger  * Check key blob for known and supported CCA key.
1886fbf5e2SHarald Freudenberger  */
1986fbf5e2SHarald Freudenberger bool pkey_is_cca_key(const u8 *key, u32 keylen)
2086fbf5e2SHarald Freudenberger {
2186fbf5e2SHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
2286fbf5e2SHarald Freudenberger 
2386fbf5e2SHarald Freudenberger 	if (keylen < sizeof(*hdr))
2486fbf5e2SHarald Freudenberger 		return false;
2586fbf5e2SHarald Freudenberger 
2686fbf5e2SHarald Freudenberger 	switch (hdr->type) {
2786fbf5e2SHarald Freudenberger 	case TOKTYPE_CCA_INTERNAL:
2886fbf5e2SHarald Freudenberger 		switch (hdr->version) {
2986fbf5e2SHarald Freudenberger 		case TOKVER_CCA_AES:
3086fbf5e2SHarald Freudenberger 		case TOKVER_CCA_VLSC:
3186fbf5e2SHarald Freudenberger 			return true;
3286fbf5e2SHarald Freudenberger 		default:
3386fbf5e2SHarald Freudenberger 			return false;
3486fbf5e2SHarald Freudenberger 		}
3586fbf5e2SHarald Freudenberger 	case TOKTYPE_CCA_INTERNAL_PKA:
3686fbf5e2SHarald Freudenberger 		return true;
3786fbf5e2SHarald Freudenberger 	default:
3886fbf5e2SHarald Freudenberger 		return false;
3986fbf5e2SHarald Freudenberger 	}
4086fbf5e2SHarald Freudenberger }
4186fbf5e2SHarald Freudenberger 
4286fbf5e2SHarald Freudenberger bool pkey_is_cca_keytype(enum pkey_key_type key_type)
4386fbf5e2SHarald Freudenberger {
4486fbf5e2SHarald Freudenberger 	switch (key_type) {
4586fbf5e2SHarald Freudenberger 	case PKEY_TYPE_CCA_DATA:
4686fbf5e2SHarald Freudenberger 	case PKEY_TYPE_CCA_CIPHER:
4786fbf5e2SHarald Freudenberger 	case PKEY_TYPE_CCA_ECC:
4886fbf5e2SHarald Freudenberger 		return true;
4986fbf5e2SHarald Freudenberger 	default:
5086fbf5e2SHarald Freudenberger 		return false;
5186fbf5e2SHarald Freudenberger 	}
5286fbf5e2SHarald Freudenberger }
5386fbf5e2SHarald Freudenberger 
5486fbf5e2SHarald Freudenberger int pkey_cca_key2protkey(u16 card, u16 dom,
5586fbf5e2SHarald Freudenberger 			 const u8 *key, u32 keylen,
5686fbf5e2SHarald Freudenberger 			 u8 *protkey, u32 *protkeylen, u32 *protkeytype)
5786fbf5e2SHarald Freudenberger {
5886fbf5e2SHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
5986fbf5e2SHarald Freudenberger 	int rc;
6086fbf5e2SHarald Freudenberger 
6186fbf5e2SHarald Freudenberger 	if (keylen < sizeof(*hdr))
6286fbf5e2SHarald Freudenberger 		return -EINVAL;
6386fbf5e2SHarald Freudenberger 
6486fbf5e2SHarald Freudenberger 	zcrypt_wait_api_operational();
6586fbf5e2SHarald Freudenberger 
6686fbf5e2SHarald Freudenberger 	if (hdr->type == TOKTYPE_CCA_INTERNAL &&
6786fbf5e2SHarald Freudenberger 	    hdr->version == TOKVER_CCA_AES) {
6886fbf5e2SHarald Freudenberger 		/* CCA AES data key */
6986fbf5e2SHarald Freudenberger 		if (keylen != sizeof(struct secaeskeytoken))
7086fbf5e2SHarald Freudenberger 			return -EINVAL;
7186fbf5e2SHarald Freudenberger 		if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0))
7286fbf5e2SHarald Freudenberger 			return -EINVAL;
7386fbf5e2SHarald Freudenberger 		rc = cca_sec2protkey(card, dom, key, protkey,
7486fbf5e2SHarald Freudenberger 				     protkeylen, protkeytype);
7586fbf5e2SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
7686fbf5e2SHarald Freudenberger 		   hdr->version == TOKVER_CCA_VLSC) {
7786fbf5e2SHarald Freudenberger 		/* CCA AES cipher key */
7886fbf5e2SHarald Freudenberger 		if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
7986fbf5e2SHarald Freudenberger 			return -EINVAL;
8086fbf5e2SHarald Freudenberger 		if (cca_check_secaescipherkey(pkey_dbf_info,
8186fbf5e2SHarald Freudenberger 					      3, key, 0, 1))
8286fbf5e2SHarald Freudenberger 			return -EINVAL;
8386fbf5e2SHarald Freudenberger 		rc = cca_cipher2protkey(card, dom, key, protkey,
8486fbf5e2SHarald Freudenberger 					protkeylen, protkeytype);
8586fbf5e2SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
8686fbf5e2SHarald Freudenberger 		/* CCA ECC (private) key */
8786fbf5e2SHarald Freudenberger 		if (keylen < sizeof(struct eccprivkeytoken))
8886fbf5e2SHarald Freudenberger 			return -EINVAL;
8986fbf5e2SHarald Freudenberger 		if (cca_check_sececckeytoken(pkey_dbf_info, 3, key, keylen, 1))
9086fbf5e2SHarald Freudenberger 			return -EINVAL;
9186fbf5e2SHarald Freudenberger 		rc = cca_ecc2protkey(card, dom, key, protkey,
9286fbf5e2SHarald Freudenberger 				     protkeylen, protkeytype);
9386fbf5e2SHarald Freudenberger 	} else {
9486fbf5e2SHarald Freudenberger 		PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",
9586fbf5e2SHarald Freudenberger 			     __func__, hdr->type, hdr->version);
9686fbf5e2SHarald Freudenberger 		rc = -EINVAL;
9786fbf5e2SHarald Freudenberger 	}
9886fbf5e2SHarald Freudenberger 
9986fbf5e2SHarald Freudenberger 	pr_debug("card=%d dom=%d rc=%d\n", card, dom, rc);
10086fbf5e2SHarald Freudenberger 	return rc;
10186fbf5e2SHarald Freudenberger }
10286fbf5e2SHarald Freudenberger 
10386fbf5e2SHarald Freudenberger /*
10486fbf5e2SHarald Freudenberger  * Generate CCA secure key.
10586fbf5e2SHarald Freudenberger  * As of now only CCA AES Data or Cipher secure keys are
10686fbf5e2SHarald Freudenberger  * supported.
10786fbf5e2SHarald Freudenberger  * keytype is one of the PKEY_KEYTYPE_* constants,
10886fbf5e2SHarald Freudenberger  * subtype may be 0 or PKEY_TYPE_CCA_DATA or PKEY_TYPE_CCA_CIPHER,
10986fbf5e2SHarald Freudenberger  * keybitsize is the bit size of the key (may be 0 for
11086fbf5e2SHarald Freudenberger  * keytype PKEY_KEYTYPE_AES_*).
11186fbf5e2SHarald Freudenberger  */
11286fbf5e2SHarald Freudenberger int pkey_cca_gen_key(u16 card, u16 dom,
11386fbf5e2SHarald Freudenberger 		     u32 keytype, u32 subtype,
11486fbf5e2SHarald Freudenberger 		     u32 keybitsize, u32 flags,
115*ea88e171SHarald Freudenberger 		     u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
11686fbf5e2SHarald Freudenberger {
11786fbf5e2SHarald Freudenberger 	int len, rc;
11886fbf5e2SHarald Freudenberger 
11986fbf5e2SHarald Freudenberger 	/* check keytype, subtype, keybitsize */
12086fbf5e2SHarald Freudenberger 	switch (keytype) {
12186fbf5e2SHarald Freudenberger 	case PKEY_KEYTYPE_AES_128:
12286fbf5e2SHarald Freudenberger 	case PKEY_KEYTYPE_AES_192:
12386fbf5e2SHarald Freudenberger 	case PKEY_KEYTYPE_AES_256:
12486fbf5e2SHarald Freudenberger 		len = pkey_keytype_aes_to_size(keytype);
12586fbf5e2SHarald Freudenberger 		if (keybitsize && keybitsize != 8 * len) {
12686fbf5e2SHarald Freudenberger 			PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
12786fbf5e2SHarald Freudenberger 				     __func__, keybitsize);
12886fbf5e2SHarald Freudenberger 			return -EINVAL;
12986fbf5e2SHarald Freudenberger 		}
13086fbf5e2SHarald Freudenberger 		keybitsize = 8 * len;
13186fbf5e2SHarald Freudenberger 		switch (subtype) {
13286fbf5e2SHarald Freudenberger 		case 0:
13386fbf5e2SHarald Freudenberger 		case PKEY_TYPE_CCA_DATA:
13486fbf5e2SHarald Freudenberger 		case PKEY_TYPE_CCA_CIPHER:
13586fbf5e2SHarald Freudenberger 			break;
13686fbf5e2SHarald Freudenberger 		default:
13786fbf5e2SHarald Freudenberger 			PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
13886fbf5e2SHarald Freudenberger 				     __func__, subtype);
13986fbf5e2SHarald Freudenberger 			return -EINVAL;
14086fbf5e2SHarald Freudenberger 		}
14186fbf5e2SHarald Freudenberger 		break;
14286fbf5e2SHarald Freudenberger 	default:
14386fbf5e2SHarald Freudenberger 		PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
14486fbf5e2SHarald Freudenberger 			     __func__, keytype);
14586fbf5e2SHarald Freudenberger 		return -EINVAL;
14686fbf5e2SHarald Freudenberger 	}
14786fbf5e2SHarald Freudenberger 
14886fbf5e2SHarald Freudenberger 	zcrypt_wait_api_operational();
14986fbf5e2SHarald Freudenberger 
15086fbf5e2SHarald Freudenberger 	if (subtype == PKEY_TYPE_CCA_CIPHER) {
15186fbf5e2SHarald Freudenberger 		rc = cca_gencipherkey(card, dom, keybitsize, flags,
15286fbf5e2SHarald Freudenberger 				      keybuf, keybuflen);
15386fbf5e2SHarald Freudenberger 	} else {
15486fbf5e2SHarald Freudenberger 		/* 0 or PKEY_TYPE_CCA_DATA */
15586fbf5e2SHarald Freudenberger 		rc = cca_genseckey(card, dom, keybitsize, keybuf);
15686fbf5e2SHarald Freudenberger 		*keybuflen = (rc ? 0 : SECKEYBLOBSIZE);
15786fbf5e2SHarald Freudenberger 	}
15886fbf5e2SHarald Freudenberger 
15986fbf5e2SHarald Freudenberger 	pr_debug("card=%d dom=%d rc=%d\n", card, dom, rc);
16086fbf5e2SHarald Freudenberger 	return rc;
16186fbf5e2SHarald Freudenberger }
16286fbf5e2SHarald Freudenberger 
16386fbf5e2SHarald Freudenberger /*
16486fbf5e2SHarald Freudenberger  * Generate CCA secure key with given clear key value.
16586fbf5e2SHarald Freudenberger  * As of now only CCA AES Data or Cipher secure keys are
16686fbf5e2SHarald Freudenberger  * supported.
16786fbf5e2SHarald Freudenberger  * keytype is one of the PKEY_KEYTYPE_* constants,
16886fbf5e2SHarald Freudenberger  * subtype may be 0 or PKEY_TYPE_CCA_DATA or PKEY_TYPE_CCA_CIPHER,
16986fbf5e2SHarald Freudenberger  * keybitsize is the bit size of the key (may be 0 for
17086fbf5e2SHarald Freudenberger  * keytype PKEY_KEYTYPE_AES_*).
17186fbf5e2SHarald Freudenberger  */
17286fbf5e2SHarald Freudenberger int pkey_cca_clr2key(u16 card, u16 dom,
17386fbf5e2SHarald Freudenberger 		     u32 keytype, u32 subtype,
17486fbf5e2SHarald Freudenberger 		     u32 keybitsize, u32 flags,
17586fbf5e2SHarald Freudenberger 		     const u8 *clrkey, u32 clrkeylen,
176*ea88e171SHarald Freudenberger 		     u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
17786fbf5e2SHarald Freudenberger {
17886fbf5e2SHarald Freudenberger 	int len, rc;
17986fbf5e2SHarald Freudenberger 
18086fbf5e2SHarald Freudenberger 	/* check keytype, subtype, clrkeylen, keybitsize */
18186fbf5e2SHarald Freudenberger 	switch (keytype) {
18286fbf5e2SHarald Freudenberger 	case PKEY_KEYTYPE_AES_128:
18386fbf5e2SHarald Freudenberger 	case PKEY_KEYTYPE_AES_192:
18486fbf5e2SHarald Freudenberger 	case PKEY_KEYTYPE_AES_256:
18586fbf5e2SHarald Freudenberger 		len = pkey_keytype_aes_to_size(keytype);
18686fbf5e2SHarald Freudenberger 		if (keybitsize && keybitsize != 8 * len) {
18786fbf5e2SHarald Freudenberger 			PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
18886fbf5e2SHarald Freudenberger 				     __func__, keybitsize);
18986fbf5e2SHarald Freudenberger 			return -EINVAL;
19086fbf5e2SHarald Freudenberger 		}
19186fbf5e2SHarald Freudenberger 		keybitsize = 8 * len;
19286fbf5e2SHarald Freudenberger 		if (clrkeylen != len) {
19386fbf5e2SHarald Freudenberger 			PKEY_DBF_ERR("%s invalid clear key len %d != %d\n",
19486fbf5e2SHarald Freudenberger 				     __func__, clrkeylen, len);
19586fbf5e2SHarald Freudenberger 			return -EINVAL;
19686fbf5e2SHarald Freudenberger 		}
19786fbf5e2SHarald Freudenberger 		switch (subtype) {
19886fbf5e2SHarald Freudenberger 		case 0:
19986fbf5e2SHarald Freudenberger 		case PKEY_TYPE_CCA_DATA:
20086fbf5e2SHarald Freudenberger 		case PKEY_TYPE_CCA_CIPHER:
20186fbf5e2SHarald Freudenberger 			break;
20286fbf5e2SHarald Freudenberger 		default:
20386fbf5e2SHarald Freudenberger 			PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
20486fbf5e2SHarald Freudenberger 				     __func__, subtype);
20586fbf5e2SHarald Freudenberger 			return -EINVAL;
20686fbf5e2SHarald Freudenberger 		}
20786fbf5e2SHarald Freudenberger 		break;
20886fbf5e2SHarald Freudenberger 	default:
20986fbf5e2SHarald Freudenberger 		PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
21086fbf5e2SHarald Freudenberger 			     __func__, keytype);
21186fbf5e2SHarald Freudenberger 		return -EINVAL;
21286fbf5e2SHarald Freudenberger 	}
21386fbf5e2SHarald Freudenberger 
21486fbf5e2SHarald Freudenberger 	zcrypt_wait_api_operational();
21586fbf5e2SHarald Freudenberger 
21686fbf5e2SHarald Freudenberger 	if (subtype == PKEY_TYPE_CCA_CIPHER) {
21786fbf5e2SHarald Freudenberger 		rc = cca_clr2cipherkey(card, dom, keybitsize,
21886fbf5e2SHarald Freudenberger 				       flags, clrkey, keybuf, keybuflen);
21986fbf5e2SHarald Freudenberger 	} else {
22086fbf5e2SHarald Freudenberger 		/* 0 or PKEY_TYPE_CCA_DATA */
22186fbf5e2SHarald Freudenberger 		rc = cca_clr2seckey(card, dom, keybitsize,
22286fbf5e2SHarald Freudenberger 				    clrkey, keybuf);
22386fbf5e2SHarald Freudenberger 		*keybuflen = (rc ? 0 : SECKEYBLOBSIZE);
22486fbf5e2SHarald Freudenberger 	}
22586fbf5e2SHarald Freudenberger 
22686fbf5e2SHarald Freudenberger 	pr_debug("card=%d dom=%d rc=%d\n", card, dom, rc);
22786fbf5e2SHarald Freudenberger 	return rc;
22886fbf5e2SHarald Freudenberger }
22986fbf5e2SHarald Freudenberger 
23086fbf5e2SHarald Freudenberger int pkey_cca_verifykey(const u8 *key, u32 keylen,
23186fbf5e2SHarald Freudenberger 		       u16 *card, u16 *dom,
23286fbf5e2SHarald Freudenberger 		       u32 *keytype, u32 *keybitsize, u32 *flags)
23386fbf5e2SHarald Freudenberger {
23486fbf5e2SHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
23586fbf5e2SHarald Freudenberger 	u32 nr_apqns, *apqns = NULL;
23686fbf5e2SHarald Freudenberger 	int rc;
23786fbf5e2SHarald Freudenberger 
23886fbf5e2SHarald Freudenberger 	if (keylen < sizeof(*hdr))
23986fbf5e2SHarald Freudenberger 		return -EINVAL;
24086fbf5e2SHarald Freudenberger 
24186fbf5e2SHarald Freudenberger 	zcrypt_wait_api_operational();
24286fbf5e2SHarald Freudenberger 
24386fbf5e2SHarald Freudenberger 	if (hdr->type == TOKTYPE_CCA_INTERNAL &&
24486fbf5e2SHarald Freudenberger 	    hdr->version == TOKVER_CCA_AES) {
24586fbf5e2SHarald Freudenberger 		struct secaeskeytoken *t = (struct secaeskeytoken *)key;
24686fbf5e2SHarald Freudenberger 
24786fbf5e2SHarald Freudenberger 		rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0);
24886fbf5e2SHarald Freudenberger 		if (rc)
24986fbf5e2SHarald Freudenberger 			goto out;
25086fbf5e2SHarald Freudenberger 		*keytype = PKEY_TYPE_CCA_DATA;
25186fbf5e2SHarald Freudenberger 		*keybitsize = t->bitsize;
25286fbf5e2SHarald Freudenberger 		rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
25386fbf5e2SHarald Freudenberger 				   ZCRYPT_CEX3C, AES_MK_SET,
25486fbf5e2SHarald Freudenberger 				   t->mkvp, 0, 1);
25586fbf5e2SHarald Freudenberger 		if (!rc)
25686fbf5e2SHarald Freudenberger 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
25786fbf5e2SHarald Freudenberger 		if (rc == -ENODEV) {
25886fbf5e2SHarald Freudenberger 			rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
25986fbf5e2SHarald Freudenberger 					   ZCRYPT_CEX3C, AES_MK_SET,
26086fbf5e2SHarald Freudenberger 					   0, t->mkvp, 1);
26186fbf5e2SHarald Freudenberger 			if (!rc)
26286fbf5e2SHarald Freudenberger 				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
26386fbf5e2SHarald Freudenberger 		}
26486fbf5e2SHarald Freudenberger 		if (rc)
26586fbf5e2SHarald Freudenberger 			goto out;
26686fbf5e2SHarald Freudenberger 
26786fbf5e2SHarald Freudenberger 		*card = ((struct pkey_apqn *)apqns)->card;
26886fbf5e2SHarald Freudenberger 		*dom = ((struct pkey_apqn *)apqns)->domain;
26986fbf5e2SHarald Freudenberger 
27086fbf5e2SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
27186fbf5e2SHarald Freudenberger 		   hdr->version == TOKVER_CCA_VLSC) {
27286fbf5e2SHarald Freudenberger 		struct cipherkeytoken *t = (struct cipherkeytoken *)key;
27386fbf5e2SHarald Freudenberger 
27486fbf5e2SHarald Freudenberger 		rc = cca_check_secaescipherkey(pkey_dbf_info, 3, key, 0, 1);
27586fbf5e2SHarald Freudenberger 		if (rc)
27686fbf5e2SHarald Freudenberger 			goto out;
27786fbf5e2SHarald Freudenberger 		*keytype = PKEY_TYPE_CCA_CIPHER;
27886fbf5e2SHarald Freudenberger 		*keybitsize = PKEY_SIZE_UNKNOWN;
27986fbf5e2SHarald Freudenberger 		if (!t->plfver && t->wpllen == 512)
28086fbf5e2SHarald Freudenberger 			*keybitsize = PKEY_SIZE_AES_128;
28186fbf5e2SHarald Freudenberger 		else if (!t->plfver && t->wpllen == 576)
28286fbf5e2SHarald Freudenberger 			*keybitsize = PKEY_SIZE_AES_192;
28386fbf5e2SHarald Freudenberger 		else if (!t->plfver && t->wpllen == 640)
28486fbf5e2SHarald Freudenberger 			*keybitsize = PKEY_SIZE_AES_256;
28586fbf5e2SHarald Freudenberger 		rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
28686fbf5e2SHarald Freudenberger 				   ZCRYPT_CEX6, AES_MK_SET,
28786fbf5e2SHarald Freudenberger 				   t->mkvp0, 0, 1);
28886fbf5e2SHarald Freudenberger 		if (!rc)
28986fbf5e2SHarald Freudenberger 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
29086fbf5e2SHarald Freudenberger 		if (rc == -ENODEV) {
29186fbf5e2SHarald Freudenberger 			rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
29286fbf5e2SHarald Freudenberger 					   ZCRYPT_CEX6, AES_MK_SET,
29386fbf5e2SHarald Freudenberger 					   0, t->mkvp0, 1);
29486fbf5e2SHarald Freudenberger 			if (!rc)
29586fbf5e2SHarald Freudenberger 				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
29686fbf5e2SHarald Freudenberger 		}
29786fbf5e2SHarald Freudenberger 		if (rc)
29886fbf5e2SHarald Freudenberger 			goto out;
29986fbf5e2SHarald Freudenberger 
30086fbf5e2SHarald Freudenberger 		*card = ((struct pkey_apqn *)apqns)->card;
30186fbf5e2SHarald Freudenberger 		*dom = ((struct pkey_apqn *)apqns)->domain;
30286fbf5e2SHarald Freudenberger 
30386fbf5e2SHarald Freudenberger 	} else {
30486fbf5e2SHarald Freudenberger 		/* unknown/unsupported key blob */
30586fbf5e2SHarald Freudenberger 		rc = -EINVAL;
30686fbf5e2SHarald Freudenberger 	}
30786fbf5e2SHarald Freudenberger 
30886fbf5e2SHarald Freudenberger out:
30986fbf5e2SHarald Freudenberger 	kfree(apqns);
31086fbf5e2SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
31186fbf5e2SHarald Freudenberger 	return rc;
31286fbf5e2SHarald Freudenberger }
31386fbf5e2SHarald Freudenberger 
31486fbf5e2SHarald Freudenberger int pkey_cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
31586fbf5e2SHarald Freudenberger 		       struct pkey_apqn *apqns, size_t *nr_apqns)
31686fbf5e2SHarald Freudenberger {
31786fbf5e2SHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
31886fbf5e2SHarald Freudenberger 	u32 _nr_apqns, *_apqns = NULL;
31986fbf5e2SHarald Freudenberger 	int rc;
32086fbf5e2SHarald Freudenberger 
32186fbf5e2SHarald Freudenberger 	if (!flags)
32286fbf5e2SHarald Freudenberger 		flags = PKEY_FLAGS_MATCH_CUR_MKVP | PKEY_FLAGS_MATCH_ALT_MKVP;
32386fbf5e2SHarald Freudenberger 
32486fbf5e2SHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header))
32586fbf5e2SHarald Freudenberger 		return -EINVAL;
32686fbf5e2SHarald Freudenberger 
32786fbf5e2SHarald Freudenberger 	zcrypt_wait_api_operational();
32886fbf5e2SHarald Freudenberger 
32986fbf5e2SHarald Freudenberger 	if (hdr->type == TOKTYPE_CCA_INTERNAL) {
33086fbf5e2SHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
33186fbf5e2SHarald Freudenberger 		int minhwtype = ZCRYPT_CEX3C;
33286fbf5e2SHarald Freudenberger 
33386fbf5e2SHarald Freudenberger 		if (hdr->version == TOKVER_CCA_AES) {
33486fbf5e2SHarald Freudenberger 			struct secaeskeytoken *t = (struct secaeskeytoken *)key;
33586fbf5e2SHarald Freudenberger 
33686fbf5e2SHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
33786fbf5e2SHarald Freudenberger 				cur_mkvp = t->mkvp;
33886fbf5e2SHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
33986fbf5e2SHarald Freudenberger 				old_mkvp = t->mkvp;
34086fbf5e2SHarald Freudenberger 		} else if (hdr->version == TOKVER_CCA_VLSC) {
34186fbf5e2SHarald Freudenberger 			struct cipherkeytoken *t = (struct cipherkeytoken *)key;
34286fbf5e2SHarald Freudenberger 
34386fbf5e2SHarald Freudenberger 			minhwtype = ZCRYPT_CEX6;
34486fbf5e2SHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
34586fbf5e2SHarald Freudenberger 				cur_mkvp = t->mkvp0;
34686fbf5e2SHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
34786fbf5e2SHarald Freudenberger 				old_mkvp = t->mkvp0;
34886fbf5e2SHarald Freudenberger 		} else {
34986fbf5e2SHarald Freudenberger 			/* unknown CCA internal token type */
35086fbf5e2SHarald Freudenberger 			return -EINVAL;
35186fbf5e2SHarald Freudenberger 		}
35286fbf5e2SHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
35386fbf5e2SHarald Freudenberger 				   minhwtype, AES_MK_SET,
35486fbf5e2SHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
35586fbf5e2SHarald Freudenberger 		if (rc)
35686fbf5e2SHarald Freudenberger 			goto out;
35786fbf5e2SHarald Freudenberger 
35886fbf5e2SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
35986fbf5e2SHarald Freudenberger 		struct eccprivkeytoken *t = (struct eccprivkeytoken *)key;
36086fbf5e2SHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
36186fbf5e2SHarald Freudenberger 
36286fbf5e2SHarald Freudenberger 		if (t->secid == 0x20) {
36386fbf5e2SHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
36486fbf5e2SHarald Freudenberger 				cur_mkvp = t->mkvp;
36586fbf5e2SHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
36686fbf5e2SHarald Freudenberger 				old_mkvp = t->mkvp;
36786fbf5e2SHarald Freudenberger 		} else {
36886fbf5e2SHarald Freudenberger 			/* unknown CCA internal 2 token type */
36986fbf5e2SHarald Freudenberger 			return -EINVAL;
37086fbf5e2SHarald Freudenberger 		}
37186fbf5e2SHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
37286fbf5e2SHarald Freudenberger 				   ZCRYPT_CEX7, APKA_MK_SET,
37386fbf5e2SHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
37486fbf5e2SHarald Freudenberger 		if (rc)
37586fbf5e2SHarald Freudenberger 			goto out;
37686fbf5e2SHarald Freudenberger 
37786fbf5e2SHarald Freudenberger 	} else {
37886fbf5e2SHarald Freudenberger 		PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",
37986fbf5e2SHarald Freudenberger 			     __func__, hdr->type, hdr->version);
38086fbf5e2SHarald Freudenberger 		return -EINVAL;
38186fbf5e2SHarald Freudenberger 	}
38286fbf5e2SHarald Freudenberger 
38386fbf5e2SHarald Freudenberger 	if (apqns) {
38486fbf5e2SHarald Freudenberger 		if (*nr_apqns < _nr_apqns)
38586fbf5e2SHarald Freudenberger 			rc = -ENOSPC;
38686fbf5e2SHarald Freudenberger 		else
38786fbf5e2SHarald Freudenberger 			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
38886fbf5e2SHarald Freudenberger 	}
38986fbf5e2SHarald Freudenberger 	*nr_apqns = _nr_apqns;
39086fbf5e2SHarald Freudenberger 
39186fbf5e2SHarald Freudenberger out:
39286fbf5e2SHarald Freudenberger 	kfree(_apqns);
39386fbf5e2SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
39486fbf5e2SHarald Freudenberger 	return rc;
39586fbf5e2SHarald Freudenberger }
39686fbf5e2SHarald Freudenberger 
39786fbf5e2SHarald Freudenberger int pkey_cca_apqns4type(enum pkey_key_type ktype,
39886fbf5e2SHarald Freudenberger 			u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
39986fbf5e2SHarald Freudenberger 			struct pkey_apqn *apqns, size_t *nr_apqns)
40086fbf5e2SHarald Freudenberger {
40186fbf5e2SHarald Freudenberger 	u32 _nr_apqns, *_apqns = NULL;
40286fbf5e2SHarald Freudenberger 	int rc;
40386fbf5e2SHarald Freudenberger 
40486fbf5e2SHarald Freudenberger 	zcrypt_wait_api_operational();
40586fbf5e2SHarald Freudenberger 
40686fbf5e2SHarald Freudenberger 	if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) {
40786fbf5e2SHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
40886fbf5e2SHarald Freudenberger 		int minhwtype = ZCRYPT_CEX3C;
40986fbf5e2SHarald Freudenberger 
41086fbf5e2SHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
41186fbf5e2SHarald Freudenberger 			cur_mkvp = *((u64 *)cur_mkvp);
41286fbf5e2SHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
41386fbf5e2SHarald Freudenberger 			old_mkvp = *((u64 *)alt_mkvp);
41486fbf5e2SHarald Freudenberger 		if (ktype == PKEY_TYPE_CCA_CIPHER)
41586fbf5e2SHarald Freudenberger 			minhwtype = ZCRYPT_CEX6;
41686fbf5e2SHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
41786fbf5e2SHarald Freudenberger 				   minhwtype, AES_MK_SET,
41886fbf5e2SHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
41986fbf5e2SHarald Freudenberger 		if (rc)
42086fbf5e2SHarald Freudenberger 			goto out;
42186fbf5e2SHarald Freudenberger 
42286fbf5e2SHarald Freudenberger 	} else if (ktype == PKEY_TYPE_CCA_ECC) {
42386fbf5e2SHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
42486fbf5e2SHarald Freudenberger 
42586fbf5e2SHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
42686fbf5e2SHarald Freudenberger 			cur_mkvp = *((u64 *)cur_mkvp);
42786fbf5e2SHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
42886fbf5e2SHarald Freudenberger 			old_mkvp = *((u64 *)alt_mkvp);
42986fbf5e2SHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
43086fbf5e2SHarald Freudenberger 				   ZCRYPT_CEX7, APKA_MK_SET,
43186fbf5e2SHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
43286fbf5e2SHarald Freudenberger 		if (rc)
43386fbf5e2SHarald Freudenberger 			goto out;
43486fbf5e2SHarald Freudenberger 
43586fbf5e2SHarald Freudenberger 	} else {
43686fbf5e2SHarald Freudenberger 		PKEY_DBF_ERR("%s unknown/unsupported key type %d",
43786fbf5e2SHarald Freudenberger 			     __func__, (int)ktype);
43886fbf5e2SHarald Freudenberger 		return -EINVAL;
43986fbf5e2SHarald Freudenberger 	}
44086fbf5e2SHarald Freudenberger 
44186fbf5e2SHarald Freudenberger 	if (apqns) {
44286fbf5e2SHarald Freudenberger 		if (*nr_apqns < _nr_apqns)
44386fbf5e2SHarald Freudenberger 			rc = -ENOSPC;
44486fbf5e2SHarald Freudenberger 		else
44586fbf5e2SHarald Freudenberger 			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
44686fbf5e2SHarald Freudenberger 	}
44786fbf5e2SHarald Freudenberger 	*nr_apqns = _nr_apqns;
44886fbf5e2SHarald Freudenberger 
44986fbf5e2SHarald Freudenberger out:
45086fbf5e2SHarald Freudenberger 	kfree(_apqns);
45186fbf5e2SHarald Freudenberger 	pr_debug("rc=%d\n", rc);
45286fbf5e2SHarald Freudenberger 	return rc;
45386fbf5e2SHarald Freudenberger }
454