xref: /openbmc/linux/drivers/s390/crypto/pkey_api.c (revision f370f45c6475ad0058277ae111f28fb32f58aa46)
1812141a9SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2e80d4af0SHarald Freudenberger /*
3e80d4af0SHarald Freudenberger  *  pkey device driver
4e80d4af0SHarald Freudenberger  *
5183cb469SHarald Freudenberger  *  Copyright IBM Corp. 2017,2019
6e80d4af0SHarald Freudenberger  *  Author(s): Harald Freudenberger
7e80d4af0SHarald Freudenberger  */
8e80d4af0SHarald Freudenberger 
9e80d4af0SHarald Freudenberger #define KMSG_COMPONENT "pkey"
10e80d4af0SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11e80d4af0SHarald Freudenberger 
12e80d4af0SHarald Freudenberger #include <linux/fs.h>
13e80d4af0SHarald Freudenberger #include <linux/init.h>
14e80d4af0SHarald Freudenberger #include <linux/miscdevice.h>
15e80d4af0SHarald Freudenberger #include <linux/module.h>
16e80d4af0SHarald Freudenberger #include <linux/slab.h>
17e80d4af0SHarald Freudenberger #include <linux/kallsyms.h>
18e80d4af0SHarald Freudenberger #include <linux/debugfs.h>
19a45a5c7dSIngo Franzki #include <linux/random.h>
2063c19be0SIngo Franzki #include <linux/cpufeature.h>
21e80d4af0SHarald Freudenberger #include <asm/zcrypt.h>
22e80d4af0SHarald Freudenberger #include <asm/cpacf.h>
23e80d4af0SHarald Freudenberger #include <asm/pkey.h>
24cb26b9ffSIngo Franzki #include <crypto/aes.h>
25e80d4af0SHarald Freudenberger 
26e80d4af0SHarald Freudenberger #include "zcrypt_api.h"
27efc598e6SHarald Freudenberger #include "zcrypt_ccamisc.h"
2855d0a513SHarald Freudenberger #include "zcrypt_ep11misc.h"
29e80d4af0SHarald Freudenberger 
30e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL");
31e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation");
32e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface");
33e80d4af0SHarald Freudenberger 
34f2bbc96eSHarald Freudenberger #define KEYBLOBBUFSIZE 8192	/* key buffer size used for internal processing */
35fa6999e3SHarald Freudenberger #define PROTKEYBLOBBUFSIZE 256	/* protected key buffer size used internal */
36f2bbc96eSHarald Freudenberger #define MAXAPQNSINLIST 64	/* max 64 apqns within a apqn list */
37*f370f45cSHarald Freudenberger #define AES_WK_VP_SIZE 32	/* Size of WK VP block appended to a prot key */
38f2bbc96eSHarald Freudenberger 
39e80d4af0SHarald Freudenberger /*
40e80d4af0SHarald Freudenberger  * debug feature data and functions
41e80d4af0SHarald Freudenberger  */
42e80d4af0SHarald Freudenberger 
43e80d4af0SHarald Freudenberger static debug_info_t *debug_info;
44e80d4af0SHarald Freudenberger 
45e80d4af0SHarald Freudenberger #define DEBUG_DBG(...)	debug_sprintf_event(debug_info, 6, ##__VA_ARGS__)
46e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__)
47e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__)
48e80d4af0SHarald Freudenberger #define DEBUG_ERR(...)	debug_sprintf_event(debug_info, 3, ##__VA_ARGS__)
49e80d4af0SHarald Freudenberger 
50e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void)
51e80d4af0SHarald Freudenberger {
526b1f16baSHarald Freudenberger 	/* 5 arguments per dbf entry (including the format string ptr) */
536b1f16baSHarald Freudenberger 	debug_info = debug_register("pkey", 1, 1, 5 * sizeof(long));
54e80d4af0SHarald Freudenberger 	debug_register_view(debug_info, &debug_sprintf_view);
55e80d4af0SHarald Freudenberger 	debug_set_level(debug_info, 3);
56e80d4af0SHarald Freudenberger }
57e80d4af0SHarald Freudenberger 
58e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void)
59e80d4af0SHarald Freudenberger {
60e80d4af0SHarald Freudenberger 	debug_unregister(debug_info);
61e80d4af0SHarald Freudenberger }
62e80d4af0SHarald Freudenberger 
630534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */
640534bde7SIngo Franzki struct protaeskeytoken {
650534bde7SIngo Franzki 	u8  type;     /* 0x00 for PAES specific key tokens */
660534bde7SIngo Franzki 	u8  res0[3];
670534bde7SIngo Franzki 	u8  version;  /* should be 0x01 for protected AES key token */
680534bde7SIngo Franzki 	u8  res1[3];
690534bde7SIngo Franzki 	u32 keytype;  /* key type, one of the PKEY_KEYTYPE values */
700534bde7SIngo Franzki 	u32 len;      /* bytes actually stored in protkey[] */
710534bde7SIngo Franzki 	u8  protkey[MAXPROTKEYSIZE]; /* the protected key blob */
720534bde7SIngo Franzki } __packed;
730534bde7SIngo Franzki 
74888edbc4SHarald Freudenberger /* inside view of a clear key token (type 0x00 version 0x02) */
75888edbc4SHarald Freudenberger struct clearaeskeytoken {
76888edbc4SHarald Freudenberger 	u8  type;	 /* 0x00 for PAES specific key tokens */
77888edbc4SHarald Freudenberger 	u8  res0[3];
78888edbc4SHarald Freudenberger 	u8  version;	 /* 0x02 for clear AES key token */
79888edbc4SHarald Freudenberger 	u8  res1[3];
80888edbc4SHarald Freudenberger 	u32 keytype;	 /* key type, one of the PKEY_KEYTYPE values */
81888edbc4SHarald Freudenberger 	u32 len;	 /* bytes actually stored in clearkey[] */
82fa226f1dSGustavo A. R. Silva 	u8  clearkey[]; /* clear key value */
83888edbc4SHarald Freudenberger } __packed;
84888edbc4SHarald Freudenberger 
85e80d4af0SHarald Freudenberger /*
86*f370f45cSHarald Freudenberger  * Create a protected key from a clear key value via PCKMO instruction.
87e80d4af0SHarald Freudenberger  */
88*f370f45cSHarald Freudenberger static int pkey_clr2protkey(u32 keytype, const u8 *clrkey,
89*f370f45cSHarald Freudenberger 			    u8 *protkey, u32 *protkeylen, u32 *protkeytype)
90e80d4af0SHarald Freudenberger {
915b35047eSHarald Freudenberger 	/* mask of available pckmo subfunctions */
925b35047eSHarald Freudenberger 	static cpacf_mask_t pckmo_functions;
935b35047eSHarald Freudenberger 
94e80d4af0SHarald Freudenberger 	u8 paramblock[64];
9546a29b03SHarald Freudenberger 	int keysize;
9646a29b03SHarald Freudenberger 	long fc;
97e80d4af0SHarald Freudenberger 
98e80d4af0SHarald Freudenberger 	switch (keytype) {
99e80d4af0SHarald Freudenberger 	case PKEY_KEYTYPE_AES_128:
100e80d4af0SHarald Freudenberger 		keysize = 16;
101e80d4af0SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_AES_128_KEY;
102e80d4af0SHarald Freudenberger 		break;
103e80d4af0SHarald Freudenberger 	case PKEY_KEYTYPE_AES_192:
104e80d4af0SHarald Freudenberger 		keysize = 24;
105e80d4af0SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_AES_192_KEY;
106e80d4af0SHarald Freudenberger 		break;
107e80d4af0SHarald Freudenberger 	case PKEY_KEYTYPE_AES_256:
108e80d4af0SHarald Freudenberger 		keysize = 32;
109e80d4af0SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_AES_256_KEY;
110e80d4af0SHarald Freudenberger 		break;
111e80d4af0SHarald Freudenberger 	default:
112*f370f45cSHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported keytype %u\n",
113ac2b96f3SHarald Freudenberger 			  __func__, keytype);
114e80d4af0SHarald Freudenberger 		return -EINVAL;
115e80d4af0SHarald Freudenberger 	}
116e80d4af0SHarald Freudenberger 
117*f370f45cSHarald Freudenberger 	if (*protkeylen < keysize + AES_WK_VP_SIZE) {
118*f370f45cSHarald Freudenberger 		DEBUG_ERR("%s prot key buffer size too small: %u < %d\n",
119*f370f45cSHarald Freudenberger 			  __func__, *protkeylen, keysize + AES_WK_VP_SIZE);
120*f370f45cSHarald Freudenberger 		return -EINVAL;
121*f370f45cSHarald Freudenberger 	}
122*f370f45cSHarald Freudenberger 
1235b35047eSHarald Freudenberger 	/* Did we already check for PCKMO ? */
1245b35047eSHarald Freudenberger 	if (!pckmo_functions.bytes[0]) {
1255b35047eSHarald Freudenberger 		/* no, so check now */
1265b35047eSHarald Freudenberger 		if (!cpacf_query(CPACF_PCKMO, &pckmo_functions))
1275b35047eSHarald Freudenberger 			return -ENODEV;
1285b35047eSHarald Freudenberger 	}
1295b35047eSHarald Freudenberger 	/* check for the pckmo subfunction we need now */
130f822ad2cSHarald Freudenberger 	if (!cpacf_test_func(&pckmo_functions, fc)) {
131f822ad2cSHarald Freudenberger 		DEBUG_ERR("%s pckmo functions not available\n", __func__);
13258443b67SDavid Hildenbrand 		return -ENODEV;
133f822ad2cSHarald Freudenberger 	}
134f822ad2cSHarald Freudenberger 
135e80d4af0SHarald Freudenberger 	/* prepare param block */
136e80d4af0SHarald Freudenberger 	memset(paramblock, 0, sizeof(paramblock));
137*f370f45cSHarald Freudenberger 	memcpy(paramblock, clrkey, keysize);
138e80d4af0SHarald Freudenberger 
139e80d4af0SHarald Freudenberger 	/* call the pckmo instruction */
140e80d4af0SHarald Freudenberger 	cpacf_pckmo(fc, paramblock);
141e80d4af0SHarald Freudenberger 
142*f370f45cSHarald Freudenberger 	/* copy created protected key to key buffer including the wkvp block */
143*f370f45cSHarald Freudenberger 	*protkeylen = keysize + AES_WK_VP_SIZE;
144*f370f45cSHarald Freudenberger 	memcpy(protkey, paramblock, *protkeylen);
145*f370f45cSHarald Freudenberger 	*protkeytype = keytype;
146e80d4af0SHarald Freudenberger 
147e80d4af0SHarald Freudenberger 	return 0;
148e80d4af0SHarald Freudenberger }
149e80d4af0SHarald Freudenberger 
150e80d4af0SHarald Freudenberger /*
151e80d4af0SHarald Freudenberger  * Find card and transform secure key into protected key.
152e80d4af0SHarald Freudenberger  */
153*f370f45cSHarald Freudenberger static int pkey_skey2pkey(const u8 *key, u8 *protkey,
154*f370f45cSHarald Freudenberger 			  u32 *protkeylen, u32 *protkeytype)
155e80d4af0SHarald Freudenberger {
156f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
15746a29b03SHarald Freudenberger 	u16 cardnr, domain;
15846a29b03SHarald Freudenberger 	int rc, verify;
159e80d4af0SHarald Freudenberger 
16043cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
16143cb5a7cSHarald Freudenberger 
162e80d4af0SHarald Freudenberger 	/*
163f2bbc96eSHarald Freudenberger 	 * The cca_xxx2protkey call may fail when a card has been
164e80d4af0SHarald Freudenberger 	 * addressed where the master key was changed after last fetch
165f4272c03SJulia Lawall 	 * of the mkvp into the cache. Try 3 times: First without verify
166efc598e6SHarald Freudenberger 	 * then with verify and last round with verify and old master
167efc598e6SHarald Freudenberger 	 * key verification pattern match not ignored.
168e80d4af0SHarald Freudenberger 	 */
169efc598e6SHarald Freudenberger 	for (verify = 0; verify < 3; verify++) {
170f2bbc96eSHarald Freudenberger 		rc = cca_findcard(key, &cardnr, &domain, verify);
171efc598e6SHarald Freudenberger 		if (rc < 0)
172e80d4af0SHarald Freudenberger 			continue;
173efc598e6SHarald Freudenberger 		if (rc > 0 && verify < 2)
174efc598e6SHarald Freudenberger 			continue;
175f2bbc96eSHarald Freudenberger 		switch (hdr->version) {
176f2bbc96eSHarald Freudenberger 		case TOKVER_CCA_AES:
177*f370f45cSHarald Freudenberger 			rc = cca_sec2protkey(cardnr, domain, key,
178*f370f45cSHarald Freudenberger 					     protkey, protkeylen, protkeytype);
179f2bbc96eSHarald Freudenberger 			break;
180f2bbc96eSHarald Freudenberger 		case TOKVER_CCA_VLSC:
181*f370f45cSHarald Freudenberger 			rc = cca_cipher2protkey(cardnr, domain, key,
182*f370f45cSHarald Freudenberger 						protkey, protkeylen,
183*f370f45cSHarald Freudenberger 						protkeytype);
184f2bbc96eSHarald Freudenberger 			break;
185f2bbc96eSHarald Freudenberger 		default:
186f2bbc96eSHarald Freudenberger 			return -EINVAL;
187f2bbc96eSHarald Freudenberger 		}
188e80d4af0SHarald Freudenberger 		if (rc == 0)
189e80d4af0SHarald Freudenberger 			break;
190e80d4af0SHarald Freudenberger 	}
191e80d4af0SHarald Freudenberger 
192e80d4af0SHarald Freudenberger 	if (rc)
193ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s failed rc=%d\n", __func__, rc);
194e80d4af0SHarald Freudenberger 
195e80d4af0SHarald Freudenberger 	return rc;
196e80d4af0SHarald Freudenberger }
197e80d4af0SHarald Freudenberger 
198e80d4af0SHarald Freudenberger /*
19955d0a513SHarald Freudenberger  * Construct EP11 key with given clear key value.
20055d0a513SHarald Freudenberger  */
20155d0a513SHarald Freudenberger static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen,
20255d0a513SHarald Freudenberger 			    u8 *keybuf, size_t *keybuflen)
20355d0a513SHarald Freudenberger {
20455d0a513SHarald Freudenberger 	u32 nr_apqns, *apqns = NULL;
20546a29b03SHarald Freudenberger 	u16 card, dom;
20646a29b03SHarald Freudenberger 	int i, rc;
20755d0a513SHarald Freudenberger 
20843cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
20943cb5a7cSHarald Freudenberger 
21055d0a513SHarald Freudenberger 	/* build a list of apqns suitable for ep11 keys with cpacf support */
21155d0a513SHarald Freudenberger 	rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
21255d0a513SHarald Freudenberger 			    ZCRYPT_CEX7, EP11_API_V, NULL);
21355d0a513SHarald Freudenberger 	if (rc)
21455d0a513SHarald Freudenberger 		goto out;
21555d0a513SHarald Freudenberger 
21655d0a513SHarald Freudenberger 	/* go through the list of apqns and try to bild an ep11 key */
21755d0a513SHarald Freudenberger 	for (rc = -ENODEV, i = 0; i < nr_apqns; i++) {
21855d0a513SHarald Freudenberger 		card = apqns[i] >> 16;
21955d0a513SHarald Freudenberger 		dom = apqns[i] & 0xFFFF;
22055d0a513SHarald Freudenberger 		rc = ep11_clr2keyblob(card, dom, clrkeylen * 8,
22155d0a513SHarald Freudenberger 				      0, clrkey, keybuf, keybuflen);
22255d0a513SHarald Freudenberger 		if (rc == 0)
22355d0a513SHarald Freudenberger 			break;
22455d0a513SHarald Freudenberger 	}
22555d0a513SHarald Freudenberger 
22655d0a513SHarald Freudenberger out:
22755d0a513SHarald Freudenberger 	kfree(apqns);
22855d0a513SHarald Freudenberger 	if (rc)
22955d0a513SHarald Freudenberger 		DEBUG_DBG("%s failed rc=%d\n", __func__, rc);
23055d0a513SHarald Freudenberger 	return rc;
23155d0a513SHarald Freudenberger }
23255d0a513SHarald Freudenberger 
23355d0a513SHarald Freudenberger /*
23455d0a513SHarald Freudenberger  * Find card and transform EP11 secure key into protected key.
23555d0a513SHarald Freudenberger  */
236*f370f45cSHarald Freudenberger static int pkey_ep11key2pkey(const u8 *key, u8 *protkey,
237*f370f45cSHarald Freudenberger 			     u32 *protkeylen, u32 *protkeytype)
23855d0a513SHarald Freudenberger {
23955d0a513SHarald Freudenberger 	struct ep11keyblob *kb = (struct ep11keyblob *)key;
24046a29b03SHarald Freudenberger 	u32 nr_apqns, *apqns = NULL;
24146a29b03SHarald Freudenberger 	u16 card, dom;
24246a29b03SHarald Freudenberger 	int i, rc;
24355d0a513SHarald Freudenberger 
24443cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
24543cb5a7cSHarald Freudenberger 
24655d0a513SHarald Freudenberger 	/* build a list of apqns suitable for this key */
24755d0a513SHarald Freudenberger 	rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
24855d0a513SHarald Freudenberger 			    ZCRYPT_CEX7, EP11_API_V, kb->wkvp);
24955d0a513SHarald Freudenberger 	if (rc)
25055d0a513SHarald Freudenberger 		goto out;
25155d0a513SHarald Freudenberger 
25255d0a513SHarald Freudenberger 	/* go through the list of apqns and try to derive an pkey */
25355d0a513SHarald Freudenberger 	for (rc = -ENODEV, i = 0; i < nr_apqns; i++) {
25455d0a513SHarald Freudenberger 		card = apqns[i] >> 16;
25555d0a513SHarald Freudenberger 		dom = apqns[i] & 0xFFFF;
256fa6999e3SHarald Freudenberger 		rc = ep11_kblob2protkey(card, dom, key, kb->head.len,
257*f370f45cSHarald Freudenberger 					protkey, protkeylen, protkeytype);
25855d0a513SHarald Freudenberger 		if (rc == 0)
25955d0a513SHarald Freudenberger 			break;
26055d0a513SHarald Freudenberger 	}
26155d0a513SHarald Freudenberger 
26255d0a513SHarald Freudenberger out:
26355d0a513SHarald Freudenberger 	kfree(apqns);
26455d0a513SHarald Freudenberger 	if (rc)
26555d0a513SHarald Freudenberger 		DEBUG_DBG("%s failed rc=%d\n", __func__, rc);
26655d0a513SHarald Freudenberger 	return rc;
26755d0a513SHarald Freudenberger }
26855d0a513SHarald Freudenberger 
26955d0a513SHarald Freudenberger /*
270e61a6134SHarald Freudenberger  * Verify key and give back some info about the key.
271e61a6134SHarald Freudenberger  */
272183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey,
273e61a6134SHarald Freudenberger 			  u16 *pcardnr, u16 *pdomain,
274e61a6134SHarald Freudenberger 			  u16 *pkeysize, u32 *pattributes)
275e61a6134SHarald Freudenberger {
276e61a6134SHarald Freudenberger 	struct secaeskeytoken *t = (struct secaeskeytoken *)seckey;
277e61a6134SHarald Freudenberger 	u16 cardnr, domain;
278e61a6134SHarald Freudenberger 	int rc;
279e61a6134SHarald Freudenberger 
280e61a6134SHarald Freudenberger 	/* check the secure key for valid AES secure key */
281efc598e6SHarald Freudenberger 	rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *)seckey, 0);
282e61a6134SHarald Freudenberger 	if (rc)
283e61a6134SHarald Freudenberger 		goto out;
284e61a6134SHarald Freudenberger 	if (pattributes)
285e61a6134SHarald Freudenberger 		*pattributes = PKEY_VERIFY_ATTR_AES;
286e61a6134SHarald Freudenberger 	if (pkeysize)
287e61a6134SHarald Freudenberger 		*pkeysize = t->bitsize;
288e61a6134SHarald Freudenberger 
289e61a6134SHarald Freudenberger 	/* try to find a card which can handle this key */
290efc598e6SHarald Freudenberger 	rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1);
291efc598e6SHarald Freudenberger 	if (rc < 0)
292e61a6134SHarald Freudenberger 		goto out;
293e61a6134SHarald Freudenberger 
294efc598e6SHarald Freudenberger 	if (rc > 0) {
295efc598e6SHarald Freudenberger 		/* key mkvp matches to old master key mkvp */
296ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s secure key has old mkvp\n", __func__);
297e61a6134SHarald Freudenberger 		if (pattributes)
298e61a6134SHarald Freudenberger 			*pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP;
299efc598e6SHarald Freudenberger 		rc = 0;
300e61a6134SHarald Freudenberger 	}
301e61a6134SHarald Freudenberger 
302e61a6134SHarald Freudenberger 	if (pcardnr)
303e61a6134SHarald Freudenberger 		*pcardnr = cardnr;
304e61a6134SHarald Freudenberger 	if (pdomain)
305e61a6134SHarald Freudenberger 		*pdomain = domain;
306e61a6134SHarald Freudenberger 
307e61a6134SHarald Freudenberger out:
308ac2b96f3SHarald Freudenberger 	DEBUG_DBG("%s rc=%d\n", __func__, rc);
309e61a6134SHarald Freudenberger 	return rc;
310e61a6134SHarald Freudenberger }
311e61a6134SHarald Freudenberger 
312e61a6134SHarald Freudenberger /*
313a45a5c7dSIngo Franzki  * Generate a random protected key
314a45a5c7dSIngo Franzki  */
315*f370f45cSHarald Freudenberger static int pkey_genprotkey(u32 keytype, u8 *protkey,
316*f370f45cSHarald Freudenberger 			   u32 *protkeylen, u32 *protkeytype)
317a45a5c7dSIngo Franzki {
318*f370f45cSHarald Freudenberger 	u8 clrkey[32];
319a45a5c7dSIngo Franzki 	int keysize;
320a45a5c7dSIngo Franzki 	int rc;
321a45a5c7dSIngo Franzki 
322a45a5c7dSIngo Franzki 	switch (keytype) {
323a45a5c7dSIngo Franzki 	case PKEY_KEYTYPE_AES_128:
324a45a5c7dSIngo Franzki 		keysize = 16;
325a45a5c7dSIngo Franzki 		break;
326a45a5c7dSIngo Franzki 	case PKEY_KEYTYPE_AES_192:
327a45a5c7dSIngo Franzki 		keysize = 24;
328a45a5c7dSIngo Franzki 		break;
329a45a5c7dSIngo Franzki 	case PKEY_KEYTYPE_AES_256:
330a45a5c7dSIngo Franzki 		keysize = 32;
331a45a5c7dSIngo Franzki 		break;
332a45a5c7dSIngo Franzki 	default:
333a45a5c7dSIngo Franzki 		DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__,
334a45a5c7dSIngo Franzki 			  keytype);
335a45a5c7dSIngo Franzki 		return -EINVAL;
336a45a5c7dSIngo Franzki 	}
337a45a5c7dSIngo Franzki 
338a45a5c7dSIngo Franzki 	/* generate a dummy random clear key */
339*f370f45cSHarald Freudenberger 	get_random_bytes(clrkey, keysize);
340a45a5c7dSIngo Franzki 
341a45a5c7dSIngo Franzki 	/* convert it to a dummy protected key */
342*f370f45cSHarald Freudenberger 	rc = pkey_clr2protkey(keytype, clrkey,
343*f370f45cSHarald Freudenberger 			      protkey, protkeylen, protkeytype);
344a45a5c7dSIngo Franzki 	if (rc)
345a45a5c7dSIngo Franzki 		return rc;
346a45a5c7dSIngo Franzki 
347a45a5c7dSIngo Franzki 	/* replace the key part of the protected key with random bytes */
348*f370f45cSHarald Freudenberger 	get_random_bytes(protkey, keysize);
349a45a5c7dSIngo Franzki 
350a45a5c7dSIngo Franzki 	return 0;
351a45a5c7dSIngo Franzki }
352a45a5c7dSIngo Franzki 
353a45a5c7dSIngo Franzki /*
354cb26b9ffSIngo Franzki  * Verify if a protected key is still valid
355cb26b9ffSIngo Franzki  */
356*f370f45cSHarald Freudenberger static int pkey_verifyprotkey(const u8 *protkey, u32 protkeylen,
357*f370f45cSHarald Freudenberger 			      u32 protkeytype)
358cb26b9ffSIngo Franzki {
359cb26b9ffSIngo Franzki 	struct {
360cb26b9ffSIngo Franzki 		u8 iv[AES_BLOCK_SIZE];
361cb26b9ffSIngo Franzki 		u8 key[MAXPROTKEYSIZE];
362cb26b9ffSIngo Franzki 	} param;
363cb26b9ffSIngo Franzki 	u8 null_msg[AES_BLOCK_SIZE];
364cb26b9ffSIngo Franzki 	u8 dest_buf[AES_BLOCK_SIZE];
365*f370f45cSHarald Freudenberger 	unsigned int k, pkeylen;
36646a29b03SHarald Freudenberger 	unsigned long fc;
367cb26b9ffSIngo Franzki 
368*f370f45cSHarald Freudenberger 	switch (protkeytype) {
369cb26b9ffSIngo Franzki 	case PKEY_KEYTYPE_AES_128:
370*f370f45cSHarald Freudenberger 		pkeylen = 16 + AES_WK_VP_SIZE;
371cb26b9ffSIngo Franzki 		fc = CPACF_KMC_PAES_128;
372cb26b9ffSIngo Franzki 		break;
373cb26b9ffSIngo Franzki 	case PKEY_KEYTYPE_AES_192:
374*f370f45cSHarald Freudenberger 		pkeylen = 24 + AES_WK_VP_SIZE;
375cb26b9ffSIngo Franzki 		fc = CPACF_KMC_PAES_192;
376cb26b9ffSIngo Franzki 		break;
377cb26b9ffSIngo Franzki 	case PKEY_KEYTYPE_AES_256:
378*f370f45cSHarald Freudenberger 		pkeylen = 32 + AES_WK_VP_SIZE;
379cb26b9ffSIngo Franzki 		fc = CPACF_KMC_PAES_256;
380cb26b9ffSIngo Franzki 		break;
381cb26b9ffSIngo Franzki 	default:
382*f370f45cSHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported keytype %u\n", __func__,
383*f370f45cSHarald Freudenberger 			  protkeytype);
384*f370f45cSHarald Freudenberger 		return -EINVAL;
385*f370f45cSHarald Freudenberger 	}
386*f370f45cSHarald Freudenberger 	if (protkeylen != pkeylen) {
387*f370f45cSHarald Freudenberger 		DEBUG_ERR("%s invalid protected key size %u for keytype %u\n",
388*f370f45cSHarald Freudenberger 			  __func__, protkeylen, protkeytype);
389cb26b9ffSIngo Franzki 		return -EINVAL;
390cb26b9ffSIngo Franzki 	}
391cb26b9ffSIngo Franzki 
392cb26b9ffSIngo Franzki 	memset(null_msg, 0, sizeof(null_msg));
393cb26b9ffSIngo Franzki 
394cb26b9ffSIngo Franzki 	memset(param.iv, 0, sizeof(param.iv));
395*f370f45cSHarald Freudenberger 	memcpy(param.key, protkey, protkeylen);
396cb26b9ffSIngo Franzki 
397cb26b9ffSIngo Franzki 	k = cpacf_kmc(fc | CPACF_ENCRYPT, &param, null_msg, dest_buf,
398cb26b9ffSIngo Franzki 		      sizeof(null_msg));
399cb26b9ffSIngo Franzki 	if (k != sizeof(null_msg)) {
400cb26b9ffSIngo Franzki 		DEBUG_ERR("%s protected key is not valid\n", __func__);
401cb26b9ffSIngo Franzki 		return -EKEYREJECTED;
402cb26b9ffSIngo Franzki 	}
403cb26b9ffSIngo Franzki 
404cb26b9ffSIngo Franzki 	return 0;
405cb26b9ffSIngo Franzki }
406cb26b9ffSIngo Franzki 
407cb26b9ffSIngo Franzki /*
408fb1136d6SIngo Franzki  * Transform a non-CCA key token into a protected key
409fb1136d6SIngo Franzki  */
410183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
411*f370f45cSHarald Freudenberger 			       u8 *protkey, u32 *protkeylen, u32 *protkeytype)
412fb1136d6SIngo Franzki {
413fb1136d6SIngo Franzki 	struct keytoken_header *hdr = (struct keytoken_header *)key;
41446a29b03SHarald Freudenberger 	u8 *tmpbuf = NULL;
41546a29b03SHarald Freudenberger 	int rc = -EINVAL;
416fb1136d6SIngo Franzki 
417fb1136d6SIngo Franzki 	switch (hdr->version) {
418888edbc4SHarald Freudenberger 	case TOKVER_PROTECTED_KEY: {
419888edbc4SHarald Freudenberger 		struct protaeskeytoken *t;
420fb1136d6SIngo Franzki 
421888edbc4SHarald Freudenberger 		if (keylen != sizeof(struct protaeskeytoken))
422888edbc4SHarald Freudenberger 			goto out;
423fb1136d6SIngo Franzki 		t = (struct protaeskeytoken *)key;
424*f370f45cSHarald Freudenberger 		rc = pkey_verifyprotkey(t->protkey, t->len, t->keytype);
425*f370f45cSHarald Freudenberger 		if (rc)
426*f370f45cSHarald Freudenberger 			goto out;
427*f370f45cSHarald Freudenberger 		memcpy(protkey, t->protkey, t->len);
428*f370f45cSHarald Freudenberger 		*protkeylen = t->len;
429*f370f45cSHarald Freudenberger 		*protkeytype = t->keytype;
430888edbc4SHarald Freudenberger 		break;
431888edbc4SHarald Freudenberger 	}
432888edbc4SHarald Freudenberger 	case TOKVER_CLEAR_KEY: {
433888edbc4SHarald Freudenberger 		struct clearaeskeytoken *t;
434888edbc4SHarald Freudenberger 		struct pkey_clrkey ckey;
43555d0a513SHarald Freudenberger 		union u_tmpbuf {
43655d0a513SHarald Freudenberger 			u8 skey[SECKEYBLOBSIZE];
43755d0a513SHarald Freudenberger 			u8 ep11key[MAXEP11AESKEYBLOBSIZE];
43855d0a513SHarald Freudenberger 		};
43955d0a513SHarald Freudenberger 		size_t tmpbuflen = sizeof(union u_tmpbuf);
440fb1136d6SIngo Franzki 
441888edbc4SHarald Freudenberger 		if (keylen < sizeof(struct clearaeskeytoken))
442888edbc4SHarald Freudenberger 			goto out;
443888edbc4SHarald Freudenberger 		t = (struct clearaeskeytoken *)key;
444888edbc4SHarald Freudenberger 		if (keylen != sizeof(*t) + t->len)
445888edbc4SHarald Freudenberger 			goto out;
4462004b57cSHarald Freudenberger 		if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) ||
4472004b57cSHarald Freudenberger 		    (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) ||
4482004b57cSHarald Freudenberger 		    (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32))
449888edbc4SHarald Freudenberger 			memcpy(ckey.clrkey, t->clearkey, t->len);
450888edbc4SHarald Freudenberger 		else
451888edbc4SHarald Freudenberger 			goto out;
45255d0a513SHarald Freudenberger 		/* alloc temp key buffer space */
45355d0a513SHarald Freudenberger 		tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC);
45455d0a513SHarald Freudenberger 		if (!tmpbuf) {
45555d0a513SHarald Freudenberger 			rc = -ENOMEM;
45655d0a513SHarald Freudenberger 			goto out;
45755d0a513SHarald Freudenberger 		}
458888edbc4SHarald Freudenberger 		/* try direct way with the PCKMO instruction */
459*f370f45cSHarald Freudenberger 		rc = pkey_clr2protkey(t->keytype, ckey.clrkey,
460*f370f45cSHarald Freudenberger 				      protkey, protkeylen, protkeytype);
461888edbc4SHarald Freudenberger 		if (rc == 0)
462888edbc4SHarald Freudenberger 			break;
463888edbc4SHarald Freudenberger 		/* PCKMO failed, so try the CCA secure key way */
46443cb5a7cSHarald Freudenberger 		zcrypt_wait_api_operational();
465888edbc4SHarald Freudenberger 		rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype,
46655d0a513SHarald Freudenberger 				    ckey.clrkey, tmpbuf);
467888edbc4SHarald Freudenberger 		if (rc == 0)
468*f370f45cSHarald Freudenberger 			rc = pkey_skey2pkey(tmpbuf,
469*f370f45cSHarald Freudenberger 					    protkey, protkeylen, protkeytype);
470888edbc4SHarald Freudenberger 		if (rc == 0)
471888edbc4SHarald Freudenberger 			break;
47255d0a513SHarald Freudenberger 		/* if the CCA way also failed, let's try via EP11 */
47355d0a513SHarald Freudenberger 		rc = pkey_clr2ep11key(ckey.clrkey, t->len,
47455d0a513SHarald Freudenberger 				      tmpbuf, &tmpbuflen);
47555d0a513SHarald Freudenberger 		if (rc == 0)
476*f370f45cSHarald Freudenberger 			rc = pkey_ep11key2pkey(tmpbuf,
477*f370f45cSHarald Freudenberger 					       protkey, protkeylen, protkeytype);
47855d0a513SHarald Freudenberger 		/* now we should really have an protected key */
479888edbc4SHarald Freudenberger 		DEBUG_ERR("%s unable to build protected key from clear",
480888edbc4SHarald Freudenberger 			  __func__);
481888edbc4SHarald Freudenberger 		break;
482888edbc4SHarald Freudenberger 	}
48355d0a513SHarald Freudenberger 	case TOKVER_EP11_AES: {
48455d0a513SHarald Freudenberger 		/* check ep11 key for exportable as protected key */
485fa6999e3SHarald Freudenberger 		rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1);
48655d0a513SHarald Freudenberger 		if (rc)
48755d0a513SHarald Freudenberger 			goto out;
488*f370f45cSHarald Freudenberger 		rc = pkey_ep11key2pkey(key,
489*f370f45cSHarald Freudenberger 				       protkey, protkeylen, protkeytype);
49055d0a513SHarald Freudenberger 		break;
49155d0a513SHarald Freudenberger 	}
492fa6999e3SHarald Freudenberger 	case TOKVER_EP11_AES_WITH_HEADER:
493fa6999e3SHarald Freudenberger 		/* check ep11 key with header for exportable as protected key */
494fa6999e3SHarald Freudenberger 		rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1);
495fa6999e3SHarald Freudenberger 		if (rc)
496fa6999e3SHarald Freudenberger 			goto out;
497fa6999e3SHarald Freudenberger 		rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header),
498*f370f45cSHarald Freudenberger 				       protkey, protkeylen, protkeytype);
499fa6999e3SHarald Freudenberger 		break;
500fb1136d6SIngo Franzki 	default:
501fb1136d6SIngo Franzki 		DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n",
502fb1136d6SIngo Franzki 			  __func__, hdr->version);
503888edbc4SHarald Freudenberger 		rc = -EINVAL;
504fb1136d6SIngo Franzki 	}
505888edbc4SHarald Freudenberger 
506888edbc4SHarald Freudenberger out:
50755d0a513SHarald Freudenberger 	kfree(tmpbuf);
508888edbc4SHarald Freudenberger 	return rc;
509fb1136d6SIngo Franzki }
510fb1136d6SIngo Franzki 
511fb1136d6SIngo Franzki /*
512fb1136d6SIngo Franzki  * Transform a CCA internal key token into a protected key
513fb1136d6SIngo Franzki  */
514183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen,
515*f370f45cSHarald Freudenberger 			       u8 *protkey, u32 *protkeylen, u32 *protkeytype)
516fb1136d6SIngo Franzki {
517fb1136d6SIngo Franzki 	struct keytoken_header *hdr = (struct keytoken_header *)key;
518fb1136d6SIngo Franzki 
519fb1136d6SIngo Franzki 	switch (hdr->version) {
520fb1136d6SIngo Franzki 	case TOKVER_CCA_AES:
521fb1136d6SIngo Franzki 		if (keylen != sizeof(struct secaeskeytoken))
522fb1136d6SIngo Franzki 			return -EINVAL;
523f2bbc96eSHarald Freudenberger 		break;
524f2bbc96eSHarald Freudenberger 	case TOKVER_CCA_VLSC:
525f2bbc96eSHarald Freudenberger 		if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
526f2bbc96eSHarald Freudenberger 			return -EINVAL;
527f2bbc96eSHarald Freudenberger 		break;
528fb1136d6SIngo Franzki 	default:
529fb1136d6SIngo Franzki 		DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n",
530fb1136d6SIngo Franzki 			  __func__, hdr->version);
531fb1136d6SIngo Franzki 		return -EINVAL;
532fb1136d6SIngo Franzki 	}
533f2bbc96eSHarald Freudenberger 
534*f370f45cSHarald Freudenberger 	return pkey_skey2pkey(key, protkey, protkeylen, protkeytype);
535fb1136d6SIngo Franzki }
536fb1136d6SIngo Franzki 
537fb1136d6SIngo Franzki /*
538fb1136d6SIngo Franzki  * Transform a key blob (of any type) into a protected key
539fb1136d6SIngo Franzki  */
540183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen,
541*f370f45cSHarald Freudenberger 		      u8 *protkey, u32 *protkeylen, u32 *protkeytype)
542fb1136d6SIngo Franzki {
543fb1136d6SIngo Franzki 	struct keytoken_header *hdr = (struct keytoken_header *)key;
54446a29b03SHarald Freudenberger 	int rc;
545fb1136d6SIngo Franzki 
546f2bbc96eSHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header)) {
547f2bbc96eSHarald Freudenberger 		DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen);
548f2bbc96eSHarald Freudenberger 		return -EINVAL;
549f2bbc96eSHarald Freudenberger 	}
550f2bbc96eSHarald Freudenberger 
551f2bbc96eSHarald Freudenberger 	switch (hdr->type) {
552f2bbc96eSHarald Freudenberger 	case TOKTYPE_NON_CCA:
553*f370f45cSHarald Freudenberger 		rc = pkey_nonccatok2pkey(key, keylen,
554*f370f45cSHarald Freudenberger 					 protkey, protkeylen, protkeytype);
555f2bbc96eSHarald Freudenberger 		break;
556f2bbc96eSHarald Freudenberger 	case TOKTYPE_CCA_INTERNAL:
557*f370f45cSHarald Freudenberger 		rc = pkey_ccainttok2pkey(key, keylen,
558*f370f45cSHarald Freudenberger 					 protkey, protkeylen, protkeytype);
559f2bbc96eSHarald Freudenberger 		break;
560f2bbc96eSHarald Freudenberger 	default:
561f2bbc96eSHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported blob type %d\n",
562f2bbc96eSHarald Freudenberger 			  __func__, hdr->type);
563f2bbc96eSHarald Freudenberger 		return -EINVAL;
564f2bbc96eSHarald Freudenberger 	}
565f2bbc96eSHarald Freudenberger 
566f2bbc96eSHarald Freudenberger 	DEBUG_DBG("%s rc=%d\n", __func__, rc);
567f2bbc96eSHarald Freudenberger 	return rc;
568f2bbc96eSHarald Freudenberger }
569f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey);
570f2bbc96eSHarald Freudenberger 
571f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns,
572f2bbc96eSHarald Freudenberger 			   enum pkey_key_type ktype, enum pkey_key_size ksize,
573f2bbc96eSHarald Freudenberger 			   u32 kflags, u8 *keybuf, size_t *keybufsize)
574f2bbc96eSHarald Freudenberger {
575f2bbc96eSHarald Freudenberger 	int i, card, dom, rc;
576f2bbc96eSHarald Freudenberger 
577f2bbc96eSHarald Freudenberger 	/* check for at least one apqn given */
578f2bbc96eSHarald Freudenberger 	if (!apqns || !nr_apqns)
579f2bbc96eSHarald Freudenberger 		return -EINVAL;
580f2bbc96eSHarald Freudenberger 
581f2bbc96eSHarald Freudenberger 	/* check key type and size */
582f2bbc96eSHarald Freudenberger 	switch (ktype) {
583f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_DATA:
584f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_CIPHER:
585f2bbc96eSHarald Freudenberger 		if (*keybufsize < SECKEYBLOBSIZE)
586f2bbc96eSHarald Freudenberger 			return -EINVAL;
587f2bbc96eSHarald Freudenberger 		break;
58855d0a513SHarald Freudenberger 	case PKEY_TYPE_EP11:
58955d0a513SHarald Freudenberger 		if (*keybufsize < MINEP11AESKEYBLOBSIZE)
59055d0a513SHarald Freudenberger 			return -EINVAL;
59155d0a513SHarald Freudenberger 		break;
592f2bbc96eSHarald Freudenberger 	default:
593f2bbc96eSHarald Freudenberger 		return -EINVAL;
594f2bbc96eSHarald Freudenberger 	}
595f2bbc96eSHarald Freudenberger 	switch (ksize) {
596f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_128:
597f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_192:
598f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_256:
599f2bbc96eSHarald Freudenberger 		break;
600f2bbc96eSHarald Freudenberger 	default:
601f2bbc96eSHarald Freudenberger 		return -EINVAL;
602f2bbc96eSHarald Freudenberger 	}
603f2bbc96eSHarald Freudenberger 
604f2bbc96eSHarald Freudenberger 	/* simple try all apqns from the list */
605f2bbc96eSHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
606f2bbc96eSHarald Freudenberger 		card = apqns[i].card;
607f2bbc96eSHarald Freudenberger 		dom = apqns[i].domain;
60855d0a513SHarald Freudenberger 		if (ktype == PKEY_TYPE_EP11) {
60955d0a513SHarald Freudenberger 			rc = ep11_genaeskey(card, dom, ksize, kflags,
61055d0a513SHarald Freudenberger 					    keybuf, keybufsize);
61155d0a513SHarald Freudenberger 		} else if (ktype == PKEY_TYPE_CCA_DATA) {
612f2bbc96eSHarald Freudenberger 			rc = cca_genseckey(card, dom, ksize, keybuf);
613f2bbc96eSHarald Freudenberger 			*keybufsize = (rc ? 0 : SECKEYBLOBSIZE);
6142004b57cSHarald Freudenberger 		} else {
6152004b57cSHarald Freudenberger 			/* TOKVER_CCA_VLSC */
616f2bbc96eSHarald Freudenberger 			rc = cca_gencipherkey(card, dom, ksize, kflags,
617f2bbc96eSHarald Freudenberger 					      keybuf, keybufsize);
6182004b57cSHarald Freudenberger 		}
619f2bbc96eSHarald Freudenberger 		if (rc == 0)
620f2bbc96eSHarald Freudenberger 			break;
621f2bbc96eSHarald Freudenberger 	}
622f2bbc96eSHarald Freudenberger 
623f2bbc96eSHarald Freudenberger 	return rc;
624f2bbc96eSHarald Freudenberger }
625f2bbc96eSHarald Freudenberger 
626f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns,
627f2bbc96eSHarald Freudenberger 			    enum pkey_key_type ktype, enum pkey_key_size ksize,
628f2bbc96eSHarald Freudenberger 			    u32 kflags, const u8 *clrkey,
629f2bbc96eSHarald Freudenberger 			    u8 *keybuf, size_t *keybufsize)
630f2bbc96eSHarald Freudenberger {
631f2bbc96eSHarald Freudenberger 	int i, card, dom, rc;
632f2bbc96eSHarald Freudenberger 
633f2bbc96eSHarald Freudenberger 	/* check for at least one apqn given */
634f2bbc96eSHarald Freudenberger 	if (!apqns || !nr_apqns)
635f2bbc96eSHarald Freudenberger 		return -EINVAL;
636f2bbc96eSHarald Freudenberger 
637f2bbc96eSHarald Freudenberger 	/* check key type and size */
638f2bbc96eSHarald Freudenberger 	switch (ktype) {
639f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_DATA:
640f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_CIPHER:
641f2bbc96eSHarald Freudenberger 		if (*keybufsize < SECKEYBLOBSIZE)
642f2bbc96eSHarald Freudenberger 			return -EINVAL;
643f2bbc96eSHarald Freudenberger 		break;
64455d0a513SHarald Freudenberger 	case PKEY_TYPE_EP11:
64555d0a513SHarald Freudenberger 		if (*keybufsize < MINEP11AESKEYBLOBSIZE)
64655d0a513SHarald Freudenberger 			return -EINVAL;
64755d0a513SHarald Freudenberger 		break;
648f2bbc96eSHarald Freudenberger 	default:
649f2bbc96eSHarald Freudenberger 		return -EINVAL;
650f2bbc96eSHarald Freudenberger 	}
651f2bbc96eSHarald Freudenberger 	switch (ksize) {
652f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_128:
653f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_192:
654f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_256:
655f2bbc96eSHarald Freudenberger 		break;
656f2bbc96eSHarald Freudenberger 	default:
657f2bbc96eSHarald Freudenberger 		return -EINVAL;
658f2bbc96eSHarald Freudenberger 	}
659f2bbc96eSHarald Freudenberger 
66043cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
66143cb5a7cSHarald Freudenberger 
662f2bbc96eSHarald Freudenberger 	/* simple try all apqns from the list */
663f2bbc96eSHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
664f2bbc96eSHarald Freudenberger 		card = apqns[i].card;
665f2bbc96eSHarald Freudenberger 		dom = apqns[i].domain;
66655d0a513SHarald Freudenberger 		if (ktype == PKEY_TYPE_EP11) {
66755d0a513SHarald Freudenberger 			rc = ep11_clr2keyblob(card, dom, ksize, kflags,
66855d0a513SHarald Freudenberger 					      clrkey, keybuf, keybufsize);
66955d0a513SHarald Freudenberger 		} else if (ktype == PKEY_TYPE_CCA_DATA) {
670f2bbc96eSHarald Freudenberger 			rc = cca_clr2seckey(card, dom, ksize,
671f2bbc96eSHarald Freudenberger 					    clrkey, keybuf);
672f2bbc96eSHarald Freudenberger 			*keybufsize = (rc ? 0 : SECKEYBLOBSIZE);
6732004b57cSHarald Freudenberger 		} else {
6742004b57cSHarald Freudenberger 			/* TOKVER_CCA_VLSC */
675f2bbc96eSHarald Freudenberger 			rc = cca_clr2cipherkey(card, dom, ksize, kflags,
676f2bbc96eSHarald Freudenberger 					       clrkey, keybuf, keybufsize);
6772004b57cSHarald Freudenberger 		}
678f2bbc96eSHarald Freudenberger 		if (rc == 0)
679f2bbc96eSHarald Freudenberger 			break;
680f2bbc96eSHarald Freudenberger 	}
681f2bbc96eSHarald Freudenberger 
682f2bbc96eSHarald Freudenberger 	return rc;
683f2bbc96eSHarald Freudenberger }
684f2bbc96eSHarald Freudenberger 
685f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen,
686f2bbc96eSHarald Freudenberger 			   u16 *cardnr, u16 *domain,
687f2bbc96eSHarald Freudenberger 			   enum pkey_key_type *ktype,
688f2bbc96eSHarald Freudenberger 			   enum pkey_key_size *ksize, u32 *flags)
689f2bbc96eSHarald Freudenberger {
690f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
69146a29b03SHarald Freudenberger 	u32 _nr_apqns, *_apqns = NULL;
69246a29b03SHarald Freudenberger 	int rc;
693f2bbc96eSHarald Freudenberger 
69455d0a513SHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header))
695f2bbc96eSHarald Freudenberger 		return -EINVAL;
696f2bbc96eSHarald Freudenberger 
6972004b57cSHarald Freudenberger 	if (hdr->type == TOKTYPE_CCA_INTERNAL &&
6982004b57cSHarald Freudenberger 	    hdr->version == TOKVER_CCA_AES) {
699f2bbc96eSHarald Freudenberger 		struct secaeskeytoken *t = (struct secaeskeytoken *)key;
700f2bbc96eSHarald Freudenberger 
701f2bbc96eSHarald Freudenberger 		rc = cca_check_secaeskeytoken(debug_info, 3, key, 0);
702f2bbc96eSHarald Freudenberger 		if (rc)
703f2bbc96eSHarald Freudenberger 			goto out;
704f2bbc96eSHarald Freudenberger 		if (ktype)
705f2bbc96eSHarald Freudenberger 			*ktype = PKEY_TYPE_CCA_DATA;
706f2bbc96eSHarald Freudenberger 		if (ksize)
707f2bbc96eSHarald Freudenberger 			*ksize = (enum pkey_key_size)t->bitsize;
708f2bbc96eSHarald Freudenberger 
709f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
71032ca04bbSHarald Freudenberger 				   ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1);
711f2bbc96eSHarald Freudenberger 		if (rc == 0 && flags)
712f2bbc96eSHarald Freudenberger 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
713f2bbc96eSHarald Freudenberger 		if (rc == -ENODEV) {
714f2bbc96eSHarald Freudenberger 			rc = cca_findcard2(&_apqns, &_nr_apqns,
715f2bbc96eSHarald Freudenberger 					   *cardnr, *domain,
71632ca04bbSHarald Freudenberger 					   ZCRYPT_CEX3C, AES_MK_SET,
71732ca04bbSHarald Freudenberger 					   0, t->mkvp, 1);
718f2bbc96eSHarald Freudenberger 			if (rc == 0 && flags)
719f2bbc96eSHarald Freudenberger 				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
720f2bbc96eSHarald Freudenberger 		}
721f2bbc96eSHarald Freudenberger 		if (rc)
722f2bbc96eSHarald Freudenberger 			goto out;
723f2bbc96eSHarald Freudenberger 
724f2bbc96eSHarald Freudenberger 		*cardnr = ((struct pkey_apqn *)_apqns)->card;
725f2bbc96eSHarald Freudenberger 		*domain = ((struct pkey_apqn *)_apqns)->domain;
726f2bbc96eSHarald Freudenberger 
7272004b57cSHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
7282004b57cSHarald Freudenberger 		   hdr->version == TOKVER_CCA_VLSC) {
729f2bbc96eSHarald Freudenberger 		struct cipherkeytoken *t = (struct cipherkeytoken *)key;
730f2bbc96eSHarald Freudenberger 
731f2bbc96eSHarald Freudenberger 		rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1);
732f2bbc96eSHarald Freudenberger 		if (rc)
733f2bbc96eSHarald Freudenberger 			goto out;
734f2bbc96eSHarald Freudenberger 		if (ktype)
735f2bbc96eSHarald Freudenberger 			*ktype = PKEY_TYPE_CCA_CIPHER;
736f2bbc96eSHarald Freudenberger 		if (ksize) {
737f2bbc96eSHarald Freudenberger 			*ksize = PKEY_SIZE_UNKNOWN;
738f2bbc96eSHarald Freudenberger 			if (!t->plfver && t->wpllen == 512)
739f2bbc96eSHarald Freudenberger 				*ksize = PKEY_SIZE_AES_128;
740f2bbc96eSHarald Freudenberger 			else if (!t->plfver && t->wpllen == 576)
741f2bbc96eSHarald Freudenberger 				*ksize = PKEY_SIZE_AES_192;
742f2bbc96eSHarald Freudenberger 			else if (!t->plfver && t->wpllen == 640)
743f2bbc96eSHarald Freudenberger 				*ksize = PKEY_SIZE_AES_256;
744f2bbc96eSHarald Freudenberger 		}
745f2bbc96eSHarald Freudenberger 
746f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
74732ca04bbSHarald Freudenberger 				   ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1);
748f2bbc96eSHarald Freudenberger 		if (rc == 0 && flags)
749f2bbc96eSHarald Freudenberger 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
750f2bbc96eSHarald Freudenberger 		if (rc == -ENODEV) {
751f2bbc96eSHarald Freudenberger 			rc = cca_findcard2(&_apqns, &_nr_apqns,
752f2bbc96eSHarald Freudenberger 					   *cardnr, *domain,
75332ca04bbSHarald Freudenberger 					   ZCRYPT_CEX6, AES_MK_SET,
75432ca04bbSHarald Freudenberger 					   0, t->mkvp0, 1);
755f2bbc96eSHarald Freudenberger 			if (rc == 0 && flags)
756f2bbc96eSHarald Freudenberger 				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
757f2bbc96eSHarald Freudenberger 		}
758f2bbc96eSHarald Freudenberger 		if (rc)
759f2bbc96eSHarald Freudenberger 			goto out;
760f2bbc96eSHarald Freudenberger 
761f2bbc96eSHarald Freudenberger 		*cardnr = ((struct pkey_apqn *)_apqns)->card;
762f2bbc96eSHarald Freudenberger 		*domain = ((struct pkey_apqn *)_apqns)->domain;
763f2bbc96eSHarald Freudenberger 
7642004b57cSHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA &&
7652004b57cSHarald Freudenberger 		   hdr->version == TOKVER_EP11_AES) {
76655d0a513SHarald Freudenberger 		struct ep11keyblob *kb = (struct ep11keyblob *)key;
76755d0a513SHarald Freudenberger 
768fa6999e3SHarald Freudenberger 		rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1);
76955d0a513SHarald Freudenberger 		if (rc)
77055d0a513SHarald Freudenberger 			goto out;
77155d0a513SHarald Freudenberger 		if (ktype)
77255d0a513SHarald Freudenberger 			*ktype = PKEY_TYPE_EP11;
77355d0a513SHarald Freudenberger 		if (ksize)
77455d0a513SHarald Freudenberger 			*ksize = kb->head.keybitlen;
77555d0a513SHarald Freudenberger 
77655d0a513SHarald Freudenberger 		rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
77755d0a513SHarald Freudenberger 				    ZCRYPT_CEX7, EP11_API_V, kb->wkvp);
77855d0a513SHarald Freudenberger 		if (rc)
77955d0a513SHarald Freudenberger 			goto out;
78055d0a513SHarald Freudenberger 
78155d0a513SHarald Freudenberger 		if (flags)
78255d0a513SHarald Freudenberger 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
78355d0a513SHarald Freudenberger 
78455d0a513SHarald Freudenberger 		*cardnr = ((struct pkey_apqn *)_apqns)->card;
78555d0a513SHarald Freudenberger 		*domain = ((struct pkey_apqn *)_apqns)->domain;
78655d0a513SHarald Freudenberger 
7872004b57cSHarald Freudenberger 	} else {
788f2bbc96eSHarald Freudenberger 		rc = -EINVAL;
7892004b57cSHarald Freudenberger 	}
790f2bbc96eSHarald Freudenberger 
791f2bbc96eSHarald Freudenberger out:
792f2bbc96eSHarald Freudenberger 	kfree(_apqns);
793f2bbc96eSHarald Freudenberger 	return rc;
794f2bbc96eSHarald Freudenberger }
795f2bbc96eSHarald Freudenberger 
796f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns,
797f2bbc96eSHarald Freudenberger 			      const u8 *key, size_t keylen,
798*f370f45cSHarald Freudenberger 			      u8 *protkey, u32 *protkeylen, u32 *protkeytype)
799f2bbc96eSHarald Freudenberger {
800f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
80146a29b03SHarald Freudenberger 	int i, card, dom, rc;
802f2bbc96eSHarald Freudenberger 
803f2bbc96eSHarald Freudenberger 	/* check for at least one apqn given */
804f2bbc96eSHarald Freudenberger 	if (!apqns || !nr_apqns)
805f2bbc96eSHarald Freudenberger 		return -EINVAL;
806f2bbc96eSHarald Freudenberger 
807fb1136d6SIngo Franzki 	if (keylen < sizeof(struct keytoken_header))
808fb1136d6SIngo Franzki 		return -EINVAL;
809fb1136d6SIngo Franzki 
81055d0a513SHarald Freudenberger 	if (hdr->type == TOKTYPE_CCA_INTERNAL) {
81155d0a513SHarald Freudenberger 		if (hdr->version == TOKVER_CCA_AES) {
812f2bbc96eSHarald Freudenberger 			if (keylen != sizeof(struct secaeskeytoken))
813f2bbc96eSHarald Freudenberger 				return -EINVAL;
814f2bbc96eSHarald Freudenberger 			if (cca_check_secaeskeytoken(debug_info, 3, key, 0))
815f2bbc96eSHarald Freudenberger 				return -EINVAL;
81655d0a513SHarald Freudenberger 		} else if (hdr->version == TOKVER_CCA_VLSC) {
817f2bbc96eSHarald Freudenberger 			if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
818f2bbc96eSHarald Freudenberger 				return -EINVAL;
819f2bbc96eSHarald Freudenberger 			if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1))
820f2bbc96eSHarald Freudenberger 				return -EINVAL;
82155d0a513SHarald Freudenberger 		} else {
822f2bbc96eSHarald Freudenberger 			DEBUG_ERR("%s unknown CCA internal token version %d\n",
823f2bbc96eSHarald Freudenberger 				  __func__, hdr->version);
824fb1136d6SIngo Franzki 			return -EINVAL;
825fb1136d6SIngo Franzki 		}
82655d0a513SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA) {
82755d0a513SHarald Freudenberger 		if (hdr->version == TOKVER_EP11_AES) {
82855d0a513SHarald Freudenberger 			if (keylen < sizeof(struct ep11keyblob))
82955d0a513SHarald Freudenberger 				return -EINVAL;
830fa6999e3SHarald Freudenberger 			if (ep11_check_aes_key(debug_info, 3, key, keylen, 1))
83155d0a513SHarald Freudenberger 				return -EINVAL;
83255d0a513SHarald Freudenberger 		} else {
833*f370f45cSHarald Freudenberger 			return pkey_nonccatok2pkey(key, keylen,
834*f370f45cSHarald Freudenberger 						   protkey, protkeylen,
835*f370f45cSHarald Freudenberger 						   protkeytype);
83655d0a513SHarald Freudenberger 		}
83755d0a513SHarald Freudenberger 	} else {
838f2bbc96eSHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported blob type %d\n",
839f2bbc96eSHarald Freudenberger 			  __func__, hdr->type);
840f2bbc96eSHarald Freudenberger 		return -EINVAL;
841fb1136d6SIngo Franzki 	}
842f2bbc96eSHarald Freudenberger 
84343cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
84443cb5a7cSHarald Freudenberger 
845f2bbc96eSHarald Freudenberger 	/* simple try all apqns from the list */
846f2bbc96eSHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
847f2bbc96eSHarald Freudenberger 		card = apqns[i].card;
848f2bbc96eSHarald Freudenberger 		dom = apqns[i].domain;
8492004b57cSHarald Freudenberger 		if (hdr->type == TOKTYPE_CCA_INTERNAL &&
8502004b57cSHarald Freudenberger 		    hdr->version == TOKVER_CCA_AES) {
851*f370f45cSHarald Freudenberger 			rc = cca_sec2protkey(card, dom, key,
852*f370f45cSHarald Freudenberger 					     protkey, protkeylen, protkeytype);
8532004b57cSHarald Freudenberger 		} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
8542004b57cSHarald Freudenberger 			   hdr->version == TOKVER_CCA_VLSC) {
855*f370f45cSHarald Freudenberger 			rc = cca_cipher2protkey(card, dom, key,
856*f370f45cSHarald Freudenberger 						protkey, protkeylen,
857*f370f45cSHarald Freudenberger 						protkeytype);
8582004b57cSHarald Freudenberger 		} else {
8592004b57cSHarald Freudenberger 			/* EP11 AES secure key blob */
86055d0a513SHarald Freudenberger 			struct ep11keyblob *kb = (struct ep11keyblob *)key;
86155d0a513SHarald Freudenberger 
862fa6999e3SHarald Freudenberger 			rc = ep11_kblob2protkey(card, dom, key, kb->head.len,
863*f370f45cSHarald Freudenberger 						protkey, protkeylen,
864*f370f45cSHarald Freudenberger 						protkeytype);
86555d0a513SHarald Freudenberger 		}
866f2bbc96eSHarald Freudenberger 		if (rc == 0)
867f2bbc96eSHarald Freudenberger 			break;
868f2bbc96eSHarald Freudenberger 	}
869f2bbc96eSHarald Freudenberger 
870f2bbc96eSHarald Freudenberger 	return rc;
871f2bbc96eSHarald Freudenberger }
872f2bbc96eSHarald Freudenberger 
873f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
874f2bbc96eSHarald Freudenberger 			  struct pkey_apqn *apqns, size_t *nr_apqns)
875f2bbc96eSHarald Freudenberger {
876f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
87746a29b03SHarald Freudenberger 	u32 _nr_apqns, *_apqns = NULL;
87846a29b03SHarald Freudenberger 	int rc;
879f2bbc96eSHarald Freudenberger 
88055d0a513SHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header) || flags == 0)
881f2bbc96eSHarald Freudenberger 		return -EINVAL;
882f2bbc96eSHarald Freudenberger 
88343cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
88443cb5a7cSHarald Freudenberger 
8852004b57cSHarald Freudenberger 	if (hdr->type == TOKTYPE_NON_CCA &&
8862004b57cSHarald Freudenberger 	    (hdr->version == TOKVER_EP11_AES_WITH_HEADER ||
8872004b57cSHarald Freudenberger 	     hdr->version == TOKVER_EP11_ECC_WITH_HEADER) &&
8882004b57cSHarald Freudenberger 	    is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
889fa6999e3SHarald Freudenberger 		struct ep11keyblob *kb = (struct ep11keyblob *)
890fa6999e3SHarald Freudenberger 			(key + sizeof(struct ep11kblob_header));
89146a29b03SHarald Freudenberger 		int minhwtype = 0, api = 0;
892fa6999e3SHarald Freudenberger 
893fa6999e3SHarald Freudenberger 		if (flags != PKEY_FLAGS_MATCH_CUR_MKVP)
894fa6999e3SHarald Freudenberger 			return -EINVAL;
895fa6999e3SHarald Freudenberger 		if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) {
896fa6999e3SHarald Freudenberger 			minhwtype = ZCRYPT_CEX7;
897fa6999e3SHarald Freudenberger 			api = EP11_API_V;
898fa6999e3SHarald Freudenberger 		}
899fa6999e3SHarald Freudenberger 		rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
900fa6999e3SHarald Freudenberger 				    minhwtype, api, kb->wkvp);
901fa6999e3SHarald Freudenberger 		if (rc)
902fa6999e3SHarald Freudenberger 			goto out;
9032004b57cSHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA &&
9042004b57cSHarald Freudenberger 		   hdr->version == TOKVER_EP11_AES &&
9052004b57cSHarald Freudenberger 		   is_ep11_keyblob(key)) {
90655d0a513SHarald Freudenberger 		struct ep11keyblob *kb = (struct ep11keyblob *)key;
90746a29b03SHarald Freudenberger 		int minhwtype = 0, api = 0;
90855d0a513SHarald Freudenberger 
90955d0a513SHarald Freudenberger 		if (flags != PKEY_FLAGS_MATCH_CUR_MKVP)
91055d0a513SHarald Freudenberger 			return -EINVAL;
91155d0a513SHarald Freudenberger 		if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) {
91255d0a513SHarald Freudenberger 			minhwtype = ZCRYPT_CEX7;
91355d0a513SHarald Freudenberger 			api = EP11_API_V;
91455d0a513SHarald Freudenberger 		}
91555d0a513SHarald Freudenberger 		rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
91655d0a513SHarald Freudenberger 				    minhwtype, api, kb->wkvp);
91755d0a513SHarald Freudenberger 		if (rc)
91855d0a513SHarald Freudenberger 			goto out;
91955d0a513SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL) {
920f2bbc96eSHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
92146a29b03SHarald Freudenberger 		int minhwtype = ZCRYPT_CEX3C;
922f2bbc96eSHarald Freudenberger 
923f2bbc96eSHarald Freudenberger 		if (hdr->version == TOKVER_CCA_AES) {
924f2bbc96eSHarald Freudenberger 			struct secaeskeytoken *t = (struct secaeskeytoken *)key;
925f2bbc96eSHarald Freudenberger 
926f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
927f2bbc96eSHarald Freudenberger 				cur_mkvp = t->mkvp;
928f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
929f2bbc96eSHarald Freudenberger 				old_mkvp = t->mkvp;
93055d0a513SHarald Freudenberger 		} else if (hdr->version == TOKVER_CCA_VLSC) {
931f2bbc96eSHarald Freudenberger 			struct cipherkeytoken *t = (struct cipherkeytoken *)key;
932f2bbc96eSHarald Freudenberger 
933f2bbc96eSHarald Freudenberger 			minhwtype = ZCRYPT_CEX6;
934f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
935f2bbc96eSHarald Freudenberger 				cur_mkvp = t->mkvp0;
936f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
937f2bbc96eSHarald Freudenberger 				old_mkvp = t->mkvp0;
93855d0a513SHarald Freudenberger 		} else {
93955d0a513SHarald Freudenberger 			/* unknown cca internal token type */
94055d0a513SHarald Freudenberger 			return -EINVAL;
941f2bbc96eSHarald Freudenberger 		}
942f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
94332ca04bbSHarald Freudenberger 				   minhwtype, AES_MK_SET,
94432ca04bbSHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
945f2bbc96eSHarald Freudenberger 		if (rc)
946f2bbc96eSHarald Freudenberger 			goto out;
947fa6999e3SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
948fa6999e3SHarald Freudenberger 		struct eccprivkeytoken *t = (struct eccprivkeytoken *)key;
94946a29b03SHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
950fa6999e3SHarald Freudenberger 
951fa6999e3SHarald Freudenberger 		if (t->secid == 0x20) {
952fa6999e3SHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
953fa6999e3SHarald Freudenberger 				cur_mkvp = t->mkvp;
954fa6999e3SHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
955fa6999e3SHarald Freudenberger 				old_mkvp = t->mkvp;
956fa6999e3SHarald Freudenberger 		} else {
957fa6999e3SHarald Freudenberger 			/* unknown cca internal 2 token type */
958fa6999e3SHarald Freudenberger 			return -EINVAL;
959fa6999e3SHarald Freudenberger 		}
960fa6999e3SHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
961fa6999e3SHarald Freudenberger 				   ZCRYPT_CEX7, APKA_MK_SET,
962fa6999e3SHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
963fa6999e3SHarald Freudenberger 		if (rc)
964fa6999e3SHarald Freudenberger 			goto out;
9652004b57cSHarald Freudenberger 	} else {
96655d0a513SHarald Freudenberger 		return -EINVAL;
9672004b57cSHarald Freudenberger 	}
96855d0a513SHarald Freudenberger 
969f2bbc96eSHarald Freudenberger 	if (apqns) {
970f2bbc96eSHarald Freudenberger 		if (*nr_apqns < _nr_apqns)
971f2bbc96eSHarald Freudenberger 			rc = -ENOSPC;
972f2bbc96eSHarald Freudenberger 		else
973f2bbc96eSHarald Freudenberger 			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
974f2bbc96eSHarald Freudenberger 	}
975f2bbc96eSHarald Freudenberger 	*nr_apqns = _nr_apqns;
976f2bbc96eSHarald Freudenberger 
977f2bbc96eSHarald Freudenberger out:
978f2bbc96eSHarald Freudenberger 	kfree(_apqns);
979f2bbc96eSHarald Freudenberger 	return rc;
980f2bbc96eSHarald Freudenberger }
981f2bbc96eSHarald Freudenberger 
982f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype,
983f2bbc96eSHarald Freudenberger 			      u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
984f2bbc96eSHarald Freudenberger 			      struct pkey_apqn *apqns, size_t *nr_apqns)
985f2bbc96eSHarald Freudenberger {
986f2bbc96eSHarald Freudenberger 	u32 _nr_apqns, *_apqns = NULL;
98746a29b03SHarald Freudenberger 	int rc;
988f2bbc96eSHarald Freudenberger 
98943cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
99043cb5a7cSHarald Freudenberger 
991f2bbc96eSHarald Freudenberger 	if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) {
992f2bbc96eSHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
993f2bbc96eSHarald Freudenberger 		int minhwtype = ZCRYPT_CEX3C;
994f2bbc96eSHarald Freudenberger 
995f2bbc96eSHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
996f2bbc96eSHarald Freudenberger 			cur_mkvp = *((u64 *)cur_mkvp);
997f2bbc96eSHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
998f2bbc96eSHarald Freudenberger 			old_mkvp = *((u64 *)alt_mkvp);
999f2bbc96eSHarald Freudenberger 		if (ktype == PKEY_TYPE_CCA_CIPHER)
1000f2bbc96eSHarald Freudenberger 			minhwtype = ZCRYPT_CEX6;
1001f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
100232ca04bbSHarald Freudenberger 				   minhwtype, AES_MK_SET,
100332ca04bbSHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
1004f2bbc96eSHarald Freudenberger 		if (rc)
1005f2bbc96eSHarald Freudenberger 			goto out;
1006fa6999e3SHarald Freudenberger 	} else if (ktype == PKEY_TYPE_CCA_ECC) {
1007fa6999e3SHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
1008fa6999e3SHarald Freudenberger 
1009fa6999e3SHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
1010fa6999e3SHarald Freudenberger 			cur_mkvp = *((u64 *)cur_mkvp);
1011fa6999e3SHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
1012fa6999e3SHarald Freudenberger 			old_mkvp = *((u64 *)alt_mkvp);
1013fa6999e3SHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
1014fa6999e3SHarald Freudenberger 				   ZCRYPT_CEX7, APKA_MK_SET,
1015fa6999e3SHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
1016fa6999e3SHarald Freudenberger 		if (rc)
1017fa6999e3SHarald Freudenberger 			goto out;
1018fa6999e3SHarald Freudenberger 
1019fa6999e3SHarald Freudenberger 	} else if (ktype == PKEY_TYPE_EP11 ||
1020fa6999e3SHarald Freudenberger 		   ktype == PKEY_TYPE_EP11_AES ||
1021fa6999e3SHarald Freudenberger 		   ktype == PKEY_TYPE_EP11_ECC) {
102255d0a513SHarald Freudenberger 		u8 *wkvp = NULL;
102355d0a513SHarald Freudenberger 
102455d0a513SHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
102555d0a513SHarald Freudenberger 			wkvp = cur_mkvp;
102655d0a513SHarald Freudenberger 		rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
102755d0a513SHarald Freudenberger 				    ZCRYPT_CEX7, EP11_API_V, wkvp);
102855d0a513SHarald Freudenberger 		if (rc)
102955d0a513SHarald Freudenberger 			goto out;
103055d0a513SHarald Freudenberger 
10312004b57cSHarald Freudenberger 	} else {
103255d0a513SHarald Freudenberger 		return -EINVAL;
10332004b57cSHarald Freudenberger 	}
103455d0a513SHarald Freudenberger 
1035f2bbc96eSHarald Freudenberger 	if (apqns) {
1036f2bbc96eSHarald Freudenberger 		if (*nr_apqns < _nr_apqns)
1037f2bbc96eSHarald Freudenberger 			rc = -ENOSPC;
1038f2bbc96eSHarald Freudenberger 		else
1039f2bbc96eSHarald Freudenberger 			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
1040f2bbc96eSHarald Freudenberger 	}
1041f2bbc96eSHarald Freudenberger 	*nr_apqns = _nr_apqns;
1042f2bbc96eSHarald Freudenberger 
1043f2bbc96eSHarald Freudenberger out:
1044f2bbc96eSHarald Freudenberger 	kfree(_apqns);
1045f2bbc96eSHarald Freudenberger 	return rc;
1046f2bbc96eSHarald Freudenberger }
1047fb1136d6SIngo Franzki 
1048fa6999e3SHarald Freudenberger static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns,
1049*f370f45cSHarald Freudenberger 			      const u8 *key, size_t keylen,
1050*f370f45cSHarald Freudenberger 			      u8 *protkey, u32 *protkeylen, u32 *protkeytype)
1051fa6999e3SHarald Freudenberger {
1052fa6999e3SHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
105346a29b03SHarald Freudenberger 	int i, card, dom, rc;
1054fa6999e3SHarald Freudenberger 
1055fa6999e3SHarald Freudenberger 	/* check for at least one apqn given */
1056fa6999e3SHarald Freudenberger 	if (!apqns || !nr_apqns)
1057fa6999e3SHarald Freudenberger 		return -EINVAL;
1058fa6999e3SHarald Freudenberger 
1059fa6999e3SHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header))
1060fa6999e3SHarald Freudenberger 		return -EINVAL;
1061fa6999e3SHarald Freudenberger 
10622004b57cSHarald Freudenberger 	if (hdr->type == TOKTYPE_NON_CCA &&
10632004b57cSHarald Freudenberger 	    hdr->version == TOKVER_EP11_AES_WITH_HEADER &&
10642004b57cSHarald Freudenberger 	    is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
1065fa6999e3SHarald Freudenberger 		/* EP11 AES key blob with header */
1066fa6999e3SHarald Freudenberger 		if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1))
1067fa6999e3SHarald Freudenberger 			return -EINVAL;
10682004b57cSHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA &&
10692004b57cSHarald Freudenberger 		   hdr->version == TOKVER_EP11_ECC_WITH_HEADER &&
10702004b57cSHarald Freudenberger 		   is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
1071fa6999e3SHarald Freudenberger 		/* EP11 ECC key blob with header */
1072fa6999e3SHarald Freudenberger 		if (ep11_check_ecc_key_with_hdr(debug_info, 3, key, keylen, 1))
1073fa6999e3SHarald Freudenberger 			return -EINVAL;
10742004b57cSHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA &&
10752004b57cSHarald Freudenberger 		   hdr->version == TOKVER_EP11_AES &&
10762004b57cSHarald Freudenberger 		   is_ep11_keyblob(key)) {
1077fa6999e3SHarald Freudenberger 		/* EP11 AES key blob with header in session field */
1078fa6999e3SHarald Freudenberger 		if (ep11_check_aes_key(debug_info, 3, key, keylen, 1))
1079fa6999e3SHarald Freudenberger 			return -EINVAL;
1080fa6999e3SHarald Freudenberger 	} else	if (hdr->type == TOKTYPE_CCA_INTERNAL) {
1081fa6999e3SHarald Freudenberger 		if (hdr->version == TOKVER_CCA_AES) {
1082fa6999e3SHarald Freudenberger 			/* CCA AES data key */
1083fa6999e3SHarald Freudenberger 			if (keylen != sizeof(struct secaeskeytoken))
1084fa6999e3SHarald Freudenberger 				return -EINVAL;
1085fa6999e3SHarald Freudenberger 			if (cca_check_secaeskeytoken(debug_info, 3, key, 0))
1086fa6999e3SHarald Freudenberger 				return -EINVAL;
1087fa6999e3SHarald Freudenberger 		} else if (hdr->version == TOKVER_CCA_VLSC) {
1088fa6999e3SHarald Freudenberger 			/* CCA AES cipher key */
1089fa6999e3SHarald Freudenberger 			if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
1090fa6999e3SHarald Freudenberger 				return -EINVAL;
1091fa6999e3SHarald Freudenberger 			if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1))
1092fa6999e3SHarald Freudenberger 				return -EINVAL;
1093fa6999e3SHarald Freudenberger 		} else {
1094fa6999e3SHarald Freudenberger 			DEBUG_ERR("%s unknown CCA internal token version %d\n",
1095fa6999e3SHarald Freudenberger 				  __func__, hdr->version);
1096fa6999e3SHarald Freudenberger 			return -EINVAL;
1097fa6999e3SHarald Freudenberger 		}
1098fa6999e3SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
1099fa6999e3SHarald Freudenberger 		/* CCA ECC (private) key */
1100fa6999e3SHarald Freudenberger 		if (keylen < sizeof(struct eccprivkeytoken))
1101fa6999e3SHarald Freudenberger 			return -EINVAL;
1102fa6999e3SHarald Freudenberger 		if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1))
1103fa6999e3SHarald Freudenberger 			return -EINVAL;
1104fa6999e3SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA) {
1105*f370f45cSHarald Freudenberger 		return pkey_nonccatok2pkey(key, keylen,
1106*f370f45cSHarald Freudenberger 					   protkey, protkeylen, protkeytype);
1107fa6999e3SHarald Freudenberger 	} else {
1108fa6999e3SHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported blob type %d\n",
1109fa6999e3SHarald Freudenberger 			  __func__, hdr->type);
1110fa6999e3SHarald Freudenberger 		return -EINVAL;
1111fa6999e3SHarald Freudenberger 	}
1112fa6999e3SHarald Freudenberger 
1113fa6999e3SHarald Freudenberger 	/* simple try all apqns from the list */
1114fa6999e3SHarald Freudenberger 	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
1115fa6999e3SHarald Freudenberger 		card = apqns[i].card;
1116fa6999e3SHarald Freudenberger 		dom = apqns[i].domain;
11172004b57cSHarald Freudenberger 		if (hdr->type == TOKTYPE_NON_CCA &&
11182004b57cSHarald Freudenberger 		    (hdr->version == TOKVER_EP11_AES_WITH_HEADER ||
11192004b57cSHarald Freudenberger 		     hdr->version == TOKVER_EP11_ECC_WITH_HEADER) &&
11202004b57cSHarald Freudenberger 		    is_ep11_keyblob(key + sizeof(struct ep11kblob_header)))
1121fa6999e3SHarald Freudenberger 			rc = ep11_kblob2protkey(card, dom, key, hdr->len,
1122fa6999e3SHarald Freudenberger 						protkey, protkeylen, protkeytype);
11232004b57cSHarald Freudenberger 		else if (hdr->type == TOKTYPE_NON_CCA &&
11242004b57cSHarald Freudenberger 			 hdr->version == TOKVER_EP11_AES &&
11252004b57cSHarald Freudenberger 			 is_ep11_keyblob(key))
1126fa6999e3SHarald Freudenberger 			rc = ep11_kblob2protkey(card, dom, key, hdr->len,
1127fa6999e3SHarald Freudenberger 						protkey, protkeylen, protkeytype);
1128fa6999e3SHarald Freudenberger 		else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
1129fa6999e3SHarald Freudenberger 			 hdr->version == TOKVER_CCA_AES)
1130fa6999e3SHarald Freudenberger 			rc = cca_sec2protkey(card, dom, key, protkey,
1131fa6999e3SHarald Freudenberger 					     protkeylen, protkeytype);
1132fa6999e3SHarald Freudenberger 		else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
1133fa6999e3SHarald Freudenberger 			 hdr->version == TOKVER_CCA_VLSC)
1134fa6999e3SHarald Freudenberger 			rc = cca_cipher2protkey(card, dom, key, protkey,
1135fa6999e3SHarald Freudenberger 						protkeylen, protkeytype);
1136fa6999e3SHarald Freudenberger 		else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA)
1137fa6999e3SHarald Freudenberger 			rc = cca_ecc2protkey(card, dom, key, protkey,
1138fa6999e3SHarald Freudenberger 					     protkeylen, protkeytype);
1139fa6999e3SHarald Freudenberger 		else
1140fa6999e3SHarald Freudenberger 			return -EINVAL;
1141fa6999e3SHarald Freudenberger 	}
1142fa6999e3SHarald Freudenberger 
1143fa6999e3SHarald Freudenberger 	return rc;
1144fa6999e3SHarald Freudenberger }
1145fa6999e3SHarald Freudenberger 
1146fb1136d6SIngo Franzki /*
1147e80d4af0SHarald Freudenberger  * File io functions
1148e80d4af0SHarald Freudenberger  */
1149e80d4af0SHarald Freudenberger 
1150f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen)
1151f2bbc96eSHarald Freudenberger {
1152f2bbc96eSHarald Freudenberger 	if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE)
1153f2bbc96eSHarald Freudenberger 		return ERR_PTR(-EINVAL);
1154f2bbc96eSHarald Freudenberger 
11558b57e7c8SMarkus Elfring 	return memdup_user(ukey, keylen);
1156f2bbc96eSHarald Freudenberger }
1157f2bbc96eSHarald Freudenberger 
1158f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns)
1159f2bbc96eSHarald Freudenberger {
11608b57e7c8SMarkus Elfring 	if (!uapqns || nr_apqns == 0)
11618b57e7c8SMarkus Elfring 		return NULL;
1162f2bbc96eSHarald Freudenberger 
11638b57e7c8SMarkus Elfring 	return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn));
1164f2bbc96eSHarald Freudenberger }
1165f2bbc96eSHarald Freudenberger 
1166e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
1167e80d4af0SHarald Freudenberger 				unsigned long arg)
1168e80d4af0SHarald Freudenberger {
1169e80d4af0SHarald Freudenberger 	int rc;
1170e80d4af0SHarald Freudenberger 
1171e80d4af0SHarald Freudenberger 	switch (cmd) {
1172e80d4af0SHarald Freudenberger 	case PKEY_GENSECK: {
1173e80d4af0SHarald Freudenberger 		struct pkey_genseck __user *ugs = (void __user *)arg;
1174e80d4af0SHarald Freudenberger 		struct pkey_genseck kgs;
1175e80d4af0SHarald Freudenberger 
1176e80d4af0SHarald Freudenberger 		if (copy_from_user(&kgs, ugs, sizeof(kgs)))
1177e80d4af0SHarald Freudenberger 			return -EFAULT;
1178efc598e6SHarald Freudenberger 		rc = cca_genseckey(kgs.cardnr, kgs.domain,
1179efc598e6SHarald Freudenberger 				   kgs.keytype, kgs.seckey.seckey);
1180efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc);
1181e80d4af0SHarald Freudenberger 		if (rc)
1182e80d4af0SHarald Freudenberger 			break;
1183e80d4af0SHarald Freudenberger 		if (copy_to_user(ugs, &kgs, sizeof(kgs)))
1184e80d4af0SHarald Freudenberger 			return -EFAULT;
1185e80d4af0SHarald Freudenberger 		break;
1186e80d4af0SHarald Freudenberger 	}
1187e80d4af0SHarald Freudenberger 	case PKEY_CLR2SECK: {
1188e80d4af0SHarald Freudenberger 		struct pkey_clr2seck __user *ucs = (void __user *)arg;
1189e80d4af0SHarald Freudenberger 		struct pkey_clr2seck kcs;
1190e80d4af0SHarald Freudenberger 
1191e80d4af0SHarald Freudenberger 		if (copy_from_user(&kcs, ucs, sizeof(kcs)))
1192e80d4af0SHarald Freudenberger 			return -EFAULT;
1193efc598e6SHarald Freudenberger 		rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype,
1194efc598e6SHarald Freudenberger 				    kcs.clrkey.clrkey, kcs.seckey.seckey);
1195efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc);
1196e80d4af0SHarald Freudenberger 		if (rc)
1197e80d4af0SHarald Freudenberger 			break;
1198e80d4af0SHarald Freudenberger 		if (copy_to_user(ucs, &kcs, sizeof(kcs)))
1199e80d4af0SHarald Freudenberger 			return -EFAULT;
1200e80d4af0SHarald Freudenberger 		memzero_explicit(&kcs, sizeof(kcs));
1201e80d4af0SHarald Freudenberger 		break;
1202e80d4af0SHarald Freudenberger 	}
1203e80d4af0SHarald Freudenberger 	case PKEY_SEC2PROTK: {
1204e80d4af0SHarald Freudenberger 		struct pkey_sec2protk __user *usp = (void __user *)arg;
1205e80d4af0SHarald Freudenberger 		struct pkey_sec2protk ksp;
1206e80d4af0SHarald Freudenberger 
1207e80d4af0SHarald Freudenberger 		if (copy_from_user(&ksp, usp, sizeof(ksp)))
1208e80d4af0SHarald Freudenberger 			return -EFAULT;
1209*f370f45cSHarald Freudenberger 		ksp.protkey.len = sizeof(ksp.protkey.protkey);
1210efc598e6SHarald Freudenberger 		rc = cca_sec2protkey(ksp.cardnr, ksp.domain,
1211efc598e6SHarald Freudenberger 				     ksp.seckey.seckey, ksp.protkey.protkey,
1212aab73d27SHarald Freudenberger 				     &ksp.protkey.len, &ksp.protkey.type);
1213efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc);
1214e80d4af0SHarald Freudenberger 		if (rc)
1215e80d4af0SHarald Freudenberger 			break;
1216e80d4af0SHarald Freudenberger 		if (copy_to_user(usp, &ksp, sizeof(ksp)))
1217e80d4af0SHarald Freudenberger 			return -EFAULT;
1218e80d4af0SHarald Freudenberger 		break;
1219e80d4af0SHarald Freudenberger 	}
1220e80d4af0SHarald Freudenberger 	case PKEY_CLR2PROTK: {
1221e80d4af0SHarald Freudenberger 		struct pkey_clr2protk __user *ucp = (void __user *)arg;
1222e80d4af0SHarald Freudenberger 		struct pkey_clr2protk kcp;
1223e80d4af0SHarald Freudenberger 
1224e80d4af0SHarald Freudenberger 		if (copy_from_user(&kcp, ucp, sizeof(kcp)))
1225e80d4af0SHarald Freudenberger 			return -EFAULT;
1226*f370f45cSHarald Freudenberger 		kcp.protkey.len = sizeof(kcp.protkey.protkey);
1227*f370f45cSHarald Freudenberger 		rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey,
1228*f370f45cSHarald Freudenberger 				      kcp.protkey.protkey,
1229*f370f45cSHarald Freudenberger 				      &kcp.protkey.len, &kcp.protkey.type);
1230ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc);
1231e80d4af0SHarald Freudenberger 		if (rc)
1232e80d4af0SHarald Freudenberger 			break;
1233e80d4af0SHarald Freudenberger 		if (copy_to_user(ucp, &kcp, sizeof(kcp)))
1234e80d4af0SHarald Freudenberger 			return -EFAULT;
1235e80d4af0SHarald Freudenberger 		memzero_explicit(&kcp, sizeof(kcp));
1236e80d4af0SHarald Freudenberger 		break;
1237e80d4af0SHarald Freudenberger 	}
1238e80d4af0SHarald Freudenberger 	case PKEY_FINDCARD: {
1239e80d4af0SHarald Freudenberger 		struct pkey_findcard __user *ufc = (void __user *)arg;
1240e80d4af0SHarald Freudenberger 		struct pkey_findcard kfc;
1241e80d4af0SHarald Freudenberger 
1242e80d4af0SHarald Freudenberger 		if (copy_from_user(&kfc, ufc, sizeof(kfc)))
1243e80d4af0SHarald Freudenberger 			return -EFAULT;
1244efc598e6SHarald Freudenberger 		rc = cca_findcard(kfc.seckey.seckey,
1245e80d4af0SHarald Freudenberger 				  &kfc.cardnr, &kfc.domain, 1);
1246efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc);
1247efc598e6SHarald Freudenberger 		if (rc < 0)
1248e80d4af0SHarald Freudenberger 			break;
1249e80d4af0SHarald Freudenberger 		if (copy_to_user(ufc, &kfc, sizeof(kfc)))
1250e80d4af0SHarald Freudenberger 			return -EFAULT;
1251e80d4af0SHarald Freudenberger 		break;
1252e80d4af0SHarald Freudenberger 	}
1253e80d4af0SHarald Freudenberger 	case PKEY_SKEY2PKEY: {
1254e80d4af0SHarald Freudenberger 		struct pkey_skey2pkey __user *usp = (void __user *)arg;
1255e80d4af0SHarald Freudenberger 		struct pkey_skey2pkey ksp;
1256e80d4af0SHarald Freudenberger 
1257e80d4af0SHarald Freudenberger 		if (copy_from_user(&ksp, usp, sizeof(ksp)))
1258e80d4af0SHarald Freudenberger 			return -EFAULT;
1259*f370f45cSHarald Freudenberger 		ksp.protkey.len = sizeof(ksp.protkey.protkey);
1260*f370f45cSHarald Freudenberger 		rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey,
1261*f370f45cSHarald Freudenberger 				    &ksp.protkey.len, &ksp.protkey.type);
1262ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc);
1263e80d4af0SHarald Freudenberger 		if (rc)
1264e80d4af0SHarald Freudenberger 			break;
1265e80d4af0SHarald Freudenberger 		if (copy_to_user(usp, &ksp, sizeof(ksp)))
1266e80d4af0SHarald Freudenberger 			return -EFAULT;
1267e80d4af0SHarald Freudenberger 		break;
1268e80d4af0SHarald Freudenberger 	}
1269e61a6134SHarald Freudenberger 	case PKEY_VERIFYKEY: {
1270e61a6134SHarald Freudenberger 		struct pkey_verifykey __user *uvk = (void __user *)arg;
1271e61a6134SHarald Freudenberger 		struct pkey_verifykey kvk;
1272e61a6134SHarald Freudenberger 
1273e61a6134SHarald Freudenberger 		if (copy_from_user(&kvk, uvk, sizeof(kvk)))
1274e61a6134SHarald Freudenberger 			return -EFAULT;
1275e61a6134SHarald Freudenberger 		rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain,
1276e61a6134SHarald Freudenberger 				    &kvk.keysize, &kvk.attributes);
1277ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc);
1278e61a6134SHarald Freudenberger 		if (rc)
1279e61a6134SHarald Freudenberger 			break;
1280e61a6134SHarald Freudenberger 		if (copy_to_user(uvk, &kvk, sizeof(kvk)))
1281e61a6134SHarald Freudenberger 			return -EFAULT;
1282e61a6134SHarald Freudenberger 		break;
1283e61a6134SHarald Freudenberger 	}
1284a45a5c7dSIngo Franzki 	case PKEY_GENPROTK: {
1285a45a5c7dSIngo Franzki 		struct pkey_genprotk __user *ugp = (void __user *)arg;
1286a45a5c7dSIngo Franzki 		struct pkey_genprotk kgp;
1287a45a5c7dSIngo Franzki 
1288a45a5c7dSIngo Franzki 		if (copy_from_user(&kgp, ugp, sizeof(kgp)))
1289a45a5c7dSIngo Franzki 			return -EFAULT;
1290*f370f45cSHarald Freudenberger 		kgp.protkey.len = sizeof(kgp.protkey.protkey);
1291*f370f45cSHarald Freudenberger 		rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey,
1292*f370f45cSHarald Freudenberger 				     &kgp.protkey.len, &kgp.protkey.type);
1293a45a5c7dSIngo Franzki 		DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc);
1294a45a5c7dSIngo Franzki 		if (rc)
1295a45a5c7dSIngo Franzki 			break;
1296a45a5c7dSIngo Franzki 		if (copy_to_user(ugp, &kgp, sizeof(kgp)))
1297a45a5c7dSIngo Franzki 			return -EFAULT;
1298a45a5c7dSIngo Franzki 		break;
1299a45a5c7dSIngo Franzki 	}
1300cb26b9ffSIngo Franzki 	case PKEY_VERIFYPROTK: {
1301cb26b9ffSIngo Franzki 		struct pkey_verifyprotk __user *uvp = (void __user *)arg;
1302cb26b9ffSIngo Franzki 		struct pkey_verifyprotk kvp;
1303cb26b9ffSIngo Franzki 
1304cb26b9ffSIngo Franzki 		if (copy_from_user(&kvp, uvp, sizeof(kvp)))
1305cb26b9ffSIngo Franzki 			return -EFAULT;
1306*f370f45cSHarald Freudenberger 		rc = pkey_verifyprotkey(kvp.protkey.protkey,
1307*f370f45cSHarald Freudenberger 					kvp.protkey.len, kvp.protkey.type);
1308cb26b9ffSIngo Franzki 		DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc);
1309cb26b9ffSIngo Franzki 		break;
1310cb26b9ffSIngo Franzki 	}
1311fb1136d6SIngo Franzki 	case PKEY_KBLOB2PROTK: {
1312fb1136d6SIngo Franzki 		struct pkey_kblob2pkey __user *utp = (void __user *)arg;
1313fb1136d6SIngo Franzki 		struct pkey_kblob2pkey ktp;
1314183cb469SHarald Freudenberger 		u8 *kkey;
1315fb1136d6SIngo Franzki 
1316fb1136d6SIngo Franzki 		if (copy_from_user(&ktp, utp, sizeof(ktp)))
1317fb1136d6SIngo Franzki 			return -EFAULT;
1318f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(ktp.key, ktp.keylen);
1319f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey))
1320f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
1321*f370f45cSHarald Freudenberger 		ktp.protkey.len = sizeof(ktp.protkey.protkey);
1322*f370f45cSHarald Freudenberger 		rc = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey,
1323*f370f45cSHarald Freudenberger 				       &ktp.protkey.len, &ktp.protkey.type);
1324fb1136d6SIngo Franzki 		DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc);
1325844cf829SHolger Dengler 		memzero_explicit(kkey, ktp.keylen);
1326fb1136d6SIngo Franzki 		kfree(kkey);
1327fb1136d6SIngo Franzki 		if (rc)
1328fb1136d6SIngo Franzki 			break;
1329fb1136d6SIngo Franzki 		if (copy_to_user(utp, &ktp, sizeof(ktp)))
1330fb1136d6SIngo Franzki 			return -EFAULT;
1331fb1136d6SIngo Franzki 		break;
1332fb1136d6SIngo Franzki 	}
1333f2bbc96eSHarald Freudenberger 	case PKEY_GENSECK2: {
1334f2bbc96eSHarald Freudenberger 		struct pkey_genseck2 __user *ugs = (void __user *)arg;
133546a29b03SHarald Freudenberger 		size_t klen = KEYBLOBBUFSIZE;
1336f2bbc96eSHarald Freudenberger 		struct pkey_genseck2 kgs;
1337f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns;
1338f2bbc96eSHarald Freudenberger 		u8 *kkey;
1339f2bbc96eSHarald Freudenberger 
1340f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kgs, ugs, sizeof(kgs)))
1341f2bbc96eSHarald Freudenberger 			return -EFAULT;
1342f2bbc96eSHarald Freudenberger 		apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries);
1343f2bbc96eSHarald Freudenberger 		if (IS_ERR(apqns))
1344f2bbc96eSHarald Freudenberger 			return PTR_ERR(apqns);
1345f2bbc96eSHarald Freudenberger 		kkey = kmalloc(klen, GFP_KERNEL);
1346f2bbc96eSHarald Freudenberger 		if (!kkey) {
1347f2bbc96eSHarald Freudenberger 			kfree(apqns);
1348f2bbc96eSHarald Freudenberger 			return -ENOMEM;
1349f2bbc96eSHarald Freudenberger 		}
1350f2bbc96eSHarald Freudenberger 		rc = pkey_genseckey2(apqns, kgs.apqn_entries,
1351f2bbc96eSHarald Freudenberger 				     kgs.type, kgs.size, kgs.keygenflags,
1352f2bbc96eSHarald Freudenberger 				     kkey, &klen);
1353f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc);
1354f2bbc96eSHarald Freudenberger 		kfree(apqns);
1355f2bbc96eSHarald Freudenberger 		if (rc) {
1356f2bbc96eSHarald Freudenberger 			kfree(kkey);
1357f2bbc96eSHarald Freudenberger 			break;
1358f2bbc96eSHarald Freudenberger 		}
1359f2bbc96eSHarald Freudenberger 		if (kgs.key) {
1360f2bbc96eSHarald Freudenberger 			if (kgs.keylen < klen) {
1361f2bbc96eSHarald Freudenberger 				kfree(kkey);
1362f2bbc96eSHarald Freudenberger 				return -EINVAL;
1363f2bbc96eSHarald Freudenberger 			}
1364f2bbc96eSHarald Freudenberger 			if (copy_to_user(kgs.key, kkey, klen)) {
1365f2bbc96eSHarald Freudenberger 				kfree(kkey);
1366f2bbc96eSHarald Freudenberger 				return -EFAULT;
1367f2bbc96eSHarald Freudenberger 			}
1368f2bbc96eSHarald Freudenberger 		}
1369f2bbc96eSHarald Freudenberger 		kgs.keylen = klen;
1370f2bbc96eSHarald Freudenberger 		if (copy_to_user(ugs, &kgs, sizeof(kgs)))
1371f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
1372f2bbc96eSHarald Freudenberger 		kfree(kkey);
1373f2bbc96eSHarald Freudenberger 		break;
1374f2bbc96eSHarald Freudenberger 	}
1375f2bbc96eSHarald Freudenberger 	case PKEY_CLR2SECK2: {
1376f2bbc96eSHarald Freudenberger 		struct pkey_clr2seck2 __user *ucs = (void __user *)arg;
137746a29b03SHarald Freudenberger 		size_t klen = KEYBLOBBUFSIZE;
1378f2bbc96eSHarald Freudenberger 		struct pkey_clr2seck2 kcs;
1379f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns;
1380f2bbc96eSHarald Freudenberger 		u8 *kkey;
1381f2bbc96eSHarald Freudenberger 
1382f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kcs, ucs, sizeof(kcs)))
1383f2bbc96eSHarald Freudenberger 			return -EFAULT;
1384f2bbc96eSHarald Freudenberger 		apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries);
1385f2bbc96eSHarald Freudenberger 		if (IS_ERR(apqns))
1386f2bbc96eSHarald Freudenberger 			return PTR_ERR(apqns);
1387f2bbc96eSHarald Freudenberger 		kkey = kmalloc(klen, GFP_KERNEL);
1388f2bbc96eSHarald Freudenberger 		if (!kkey) {
1389f2bbc96eSHarald Freudenberger 			kfree(apqns);
1390f2bbc96eSHarald Freudenberger 			return -ENOMEM;
1391f2bbc96eSHarald Freudenberger 		}
1392f2bbc96eSHarald Freudenberger 		rc = pkey_clr2seckey2(apqns, kcs.apqn_entries,
1393f2bbc96eSHarald Freudenberger 				      kcs.type, kcs.size, kcs.keygenflags,
1394f2bbc96eSHarald Freudenberger 				      kcs.clrkey.clrkey, kkey, &klen);
1395f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc);
1396f2bbc96eSHarald Freudenberger 		kfree(apqns);
1397f2bbc96eSHarald Freudenberger 		if (rc) {
1398f2bbc96eSHarald Freudenberger 			kfree(kkey);
1399f2bbc96eSHarald Freudenberger 			break;
1400f2bbc96eSHarald Freudenberger 		}
1401f2bbc96eSHarald Freudenberger 		if (kcs.key) {
1402f2bbc96eSHarald Freudenberger 			if (kcs.keylen < klen) {
1403f2bbc96eSHarald Freudenberger 				kfree(kkey);
1404f2bbc96eSHarald Freudenberger 				return -EINVAL;
1405f2bbc96eSHarald Freudenberger 			}
1406f2bbc96eSHarald Freudenberger 			if (copy_to_user(kcs.key, kkey, klen)) {
1407f2bbc96eSHarald Freudenberger 				kfree(kkey);
1408f2bbc96eSHarald Freudenberger 				return -EFAULT;
1409f2bbc96eSHarald Freudenberger 			}
1410f2bbc96eSHarald Freudenberger 		}
1411f2bbc96eSHarald Freudenberger 		kcs.keylen = klen;
1412f2bbc96eSHarald Freudenberger 		if (copy_to_user(ucs, &kcs, sizeof(kcs)))
1413f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
1414f2bbc96eSHarald Freudenberger 		memzero_explicit(&kcs, sizeof(kcs));
1415f2bbc96eSHarald Freudenberger 		kfree(kkey);
1416f2bbc96eSHarald Freudenberger 		break;
1417f2bbc96eSHarald Freudenberger 	}
1418f2bbc96eSHarald Freudenberger 	case PKEY_VERIFYKEY2: {
1419f2bbc96eSHarald Freudenberger 		struct pkey_verifykey2 __user *uvk = (void __user *)arg;
1420f2bbc96eSHarald Freudenberger 		struct pkey_verifykey2 kvk;
1421f2bbc96eSHarald Freudenberger 		u8 *kkey;
1422f2bbc96eSHarald Freudenberger 
1423f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kvk, uvk, sizeof(kvk)))
1424f2bbc96eSHarald Freudenberger 			return -EFAULT;
1425f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(kvk.key, kvk.keylen);
1426f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey))
1427f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
1428f2bbc96eSHarald Freudenberger 		rc = pkey_verifykey2(kkey, kvk.keylen,
1429f2bbc96eSHarald Freudenberger 				     &kvk.cardnr, &kvk.domain,
1430f2bbc96eSHarald Freudenberger 				     &kvk.type, &kvk.size, &kvk.flags);
1431f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc);
1432f2bbc96eSHarald Freudenberger 		kfree(kkey);
1433f2bbc96eSHarald Freudenberger 		if (rc)
1434f2bbc96eSHarald Freudenberger 			break;
1435f2bbc96eSHarald Freudenberger 		if (copy_to_user(uvk, &kvk, sizeof(kvk)))
1436f2bbc96eSHarald Freudenberger 			return -EFAULT;
1437f2bbc96eSHarald Freudenberger 		break;
1438f2bbc96eSHarald Freudenberger 	}
1439f2bbc96eSHarald Freudenberger 	case PKEY_KBLOB2PROTK2: {
1440f2bbc96eSHarald Freudenberger 		struct pkey_kblob2pkey2 __user *utp = (void __user *)arg;
1441f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns = NULL;
144246a29b03SHarald Freudenberger 		struct pkey_kblob2pkey2 ktp;
1443f2bbc96eSHarald Freudenberger 		u8 *kkey;
1444f2bbc96eSHarald Freudenberger 
1445f2bbc96eSHarald Freudenberger 		if (copy_from_user(&ktp, utp, sizeof(ktp)))
1446f2bbc96eSHarald Freudenberger 			return -EFAULT;
1447f2bbc96eSHarald Freudenberger 		apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);
1448f2bbc96eSHarald Freudenberger 		if (IS_ERR(apqns))
1449f2bbc96eSHarald Freudenberger 			return PTR_ERR(apqns);
1450f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(ktp.key, ktp.keylen);
1451f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey)) {
1452f2bbc96eSHarald Freudenberger 			kfree(apqns);
1453f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
1454f2bbc96eSHarald Freudenberger 		}
1455*f370f45cSHarald Freudenberger 		ktp.protkey.len = sizeof(ktp.protkey.protkey);
1456f2bbc96eSHarald Freudenberger 		rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries,
1457*f370f45cSHarald Freudenberger 					kkey, ktp.keylen,
1458*f370f45cSHarald Freudenberger 					ktp.protkey.protkey, &ktp.protkey.len,
1459*f370f45cSHarald Freudenberger 					&ktp.protkey.type);
1460f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc);
1461f2bbc96eSHarald Freudenberger 		kfree(apqns);
1462844cf829SHolger Dengler 		memzero_explicit(kkey, ktp.keylen);
1463f2bbc96eSHarald Freudenberger 		kfree(kkey);
1464f2bbc96eSHarald Freudenberger 		if (rc)
1465f2bbc96eSHarald Freudenberger 			break;
1466f2bbc96eSHarald Freudenberger 		if (copy_to_user(utp, &ktp, sizeof(ktp)))
1467f2bbc96eSHarald Freudenberger 			return -EFAULT;
1468f2bbc96eSHarald Freudenberger 		break;
1469f2bbc96eSHarald Freudenberger 	}
1470f2bbc96eSHarald Freudenberger 	case PKEY_APQNS4K: {
1471f2bbc96eSHarald Freudenberger 		struct pkey_apqns4key __user *uak = (void __user *)arg;
1472f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns = NULL;
147346a29b03SHarald Freudenberger 		struct pkey_apqns4key kak;
1474f2bbc96eSHarald Freudenberger 		size_t nr_apqns, len;
1475f2bbc96eSHarald Freudenberger 		u8 *kkey;
1476f2bbc96eSHarald Freudenberger 
1477f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kak, uak, sizeof(kak)))
1478f2bbc96eSHarald Freudenberger 			return -EFAULT;
1479f2bbc96eSHarald Freudenberger 		nr_apqns = kak.apqn_entries;
1480f2bbc96eSHarald Freudenberger 		if (nr_apqns) {
1481f2bbc96eSHarald Freudenberger 			apqns = kmalloc_array(nr_apqns,
1482f2bbc96eSHarald Freudenberger 					      sizeof(struct pkey_apqn),
1483f2bbc96eSHarald Freudenberger 					      GFP_KERNEL);
1484f2bbc96eSHarald Freudenberger 			if (!apqns)
1485f2bbc96eSHarald Freudenberger 				return -ENOMEM;
1486f2bbc96eSHarald Freudenberger 		}
1487f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(kak.key, kak.keylen);
1488f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey)) {
1489f2bbc96eSHarald Freudenberger 			kfree(apqns);
1490f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
1491f2bbc96eSHarald Freudenberger 		}
1492f2bbc96eSHarald Freudenberger 		rc = pkey_apqns4key(kkey, kak.keylen, kak.flags,
1493f2bbc96eSHarald Freudenberger 				    apqns, &nr_apqns);
1494f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc);
1495f2bbc96eSHarald Freudenberger 		kfree(kkey);
1496f2bbc96eSHarald Freudenberger 		if (rc && rc != -ENOSPC) {
1497f2bbc96eSHarald Freudenberger 			kfree(apqns);
1498f2bbc96eSHarald Freudenberger 			break;
1499f2bbc96eSHarald Freudenberger 		}
1500f2bbc96eSHarald Freudenberger 		if (!rc && kak.apqns) {
1501f2bbc96eSHarald Freudenberger 			if (nr_apqns > kak.apqn_entries) {
1502f2bbc96eSHarald Freudenberger 				kfree(apqns);
1503f2bbc96eSHarald Freudenberger 				return -EINVAL;
1504f2bbc96eSHarald Freudenberger 			}
1505f2bbc96eSHarald Freudenberger 			len = nr_apqns * sizeof(struct pkey_apqn);
1506f2bbc96eSHarald Freudenberger 			if (len) {
1507f2bbc96eSHarald Freudenberger 				if (copy_to_user(kak.apqns, apqns, len)) {
1508f2bbc96eSHarald Freudenberger 					kfree(apqns);
1509f2bbc96eSHarald Freudenberger 					return -EFAULT;
1510f2bbc96eSHarald Freudenberger 				}
1511f2bbc96eSHarald Freudenberger 			}
1512f2bbc96eSHarald Freudenberger 		}
1513f2bbc96eSHarald Freudenberger 		kak.apqn_entries = nr_apqns;
1514f2bbc96eSHarald Freudenberger 		if (copy_to_user(uak, &kak, sizeof(kak)))
1515f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
1516f2bbc96eSHarald Freudenberger 		kfree(apqns);
1517f2bbc96eSHarald Freudenberger 		break;
1518f2bbc96eSHarald Freudenberger 	}
1519f2bbc96eSHarald Freudenberger 	case PKEY_APQNS4KT: {
1520f2bbc96eSHarald Freudenberger 		struct pkey_apqns4keytype __user *uat = (void __user *)arg;
1521f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns = NULL;
152246a29b03SHarald Freudenberger 		struct pkey_apqns4keytype kat;
1523f2bbc96eSHarald Freudenberger 		size_t nr_apqns, len;
1524f2bbc96eSHarald Freudenberger 
1525f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kat, uat, sizeof(kat)))
1526f2bbc96eSHarald Freudenberger 			return -EFAULT;
1527f2bbc96eSHarald Freudenberger 		nr_apqns = kat.apqn_entries;
1528f2bbc96eSHarald Freudenberger 		if (nr_apqns) {
1529f2bbc96eSHarald Freudenberger 			apqns = kmalloc_array(nr_apqns,
1530f2bbc96eSHarald Freudenberger 					      sizeof(struct pkey_apqn),
1531f2bbc96eSHarald Freudenberger 					      GFP_KERNEL);
1532f2bbc96eSHarald Freudenberger 			if (!apqns)
1533f2bbc96eSHarald Freudenberger 				return -ENOMEM;
1534f2bbc96eSHarald Freudenberger 		}
1535f2bbc96eSHarald Freudenberger 		rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp,
1536f2bbc96eSHarald Freudenberger 					kat.flags, apqns, &nr_apqns);
1537f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc);
1538f2bbc96eSHarald Freudenberger 		if (rc && rc != -ENOSPC) {
1539f2bbc96eSHarald Freudenberger 			kfree(apqns);
1540f2bbc96eSHarald Freudenberger 			break;
1541f2bbc96eSHarald Freudenberger 		}
1542f2bbc96eSHarald Freudenberger 		if (!rc && kat.apqns) {
1543f2bbc96eSHarald Freudenberger 			if (nr_apqns > kat.apqn_entries) {
1544f2bbc96eSHarald Freudenberger 				kfree(apqns);
1545f2bbc96eSHarald Freudenberger 				return -EINVAL;
1546f2bbc96eSHarald Freudenberger 			}
1547f2bbc96eSHarald Freudenberger 			len = nr_apqns * sizeof(struct pkey_apqn);
1548f2bbc96eSHarald Freudenberger 			if (len) {
1549f2bbc96eSHarald Freudenberger 				if (copy_to_user(kat.apqns, apqns, len)) {
1550f2bbc96eSHarald Freudenberger 					kfree(apqns);
1551f2bbc96eSHarald Freudenberger 					return -EFAULT;
1552f2bbc96eSHarald Freudenberger 				}
1553f2bbc96eSHarald Freudenberger 			}
1554f2bbc96eSHarald Freudenberger 		}
1555f2bbc96eSHarald Freudenberger 		kat.apqn_entries = nr_apqns;
1556f2bbc96eSHarald Freudenberger 		if (copy_to_user(uat, &kat, sizeof(kat)))
1557f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
1558f2bbc96eSHarald Freudenberger 		kfree(apqns);
1559f2bbc96eSHarald Freudenberger 		break;
1560f2bbc96eSHarald Freudenberger 	}
1561fa6999e3SHarald Freudenberger 	case PKEY_KBLOB2PROTK3: {
1562fa6999e3SHarald Freudenberger 		struct pkey_kblob2pkey3 __user *utp = (void __user *)arg;
1563fa6999e3SHarald Freudenberger 		u32 protkeylen = PROTKEYBLOBBUFSIZE;
156446a29b03SHarald Freudenberger 		struct pkey_apqn *apqns = NULL;
156546a29b03SHarald Freudenberger 		struct pkey_kblob2pkey3 ktp;
1566fa6999e3SHarald Freudenberger 		u8 *kkey, *protkey;
1567fa6999e3SHarald Freudenberger 
1568fa6999e3SHarald Freudenberger 		if (copy_from_user(&ktp, utp, sizeof(ktp)))
1569fa6999e3SHarald Freudenberger 			return -EFAULT;
1570fa6999e3SHarald Freudenberger 		apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);
1571fa6999e3SHarald Freudenberger 		if (IS_ERR(apqns))
1572fa6999e3SHarald Freudenberger 			return PTR_ERR(apqns);
1573fa6999e3SHarald Freudenberger 		kkey = _copy_key_from_user(ktp.key, ktp.keylen);
1574fa6999e3SHarald Freudenberger 		if (IS_ERR(kkey)) {
1575fa6999e3SHarald Freudenberger 			kfree(apqns);
1576fa6999e3SHarald Freudenberger 			return PTR_ERR(kkey);
1577fa6999e3SHarald Freudenberger 		}
1578fa6999e3SHarald Freudenberger 		protkey = kmalloc(protkeylen, GFP_KERNEL);
1579fa6999e3SHarald Freudenberger 		if (!protkey) {
1580fa6999e3SHarald Freudenberger 			kfree(apqns);
1581fa6999e3SHarald Freudenberger 			kfree(kkey);
1582fa6999e3SHarald Freudenberger 			return -ENOMEM;
1583fa6999e3SHarald Freudenberger 		}
1584*f370f45cSHarald Freudenberger 		rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries,
1585*f370f45cSHarald Freudenberger 					kkey, ktp.keylen,
1586*f370f45cSHarald Freudenberger 					protkey, &protkeylen, &ktp.pkeytype);
1587fa6999e3SHarald Freudenberger 		DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc);
1588fa6999e3SHarald Freudenberger 		kfree(apqns);
1589844cf829SHolger Dengler 		memzero_explicit(kkey, ktp.keylen);
1590fa6999e3SHarald Freudenberger 		kfree(kkey);
1591fa6999e3SHarald Freudenberger 		if (rc) {
1592fa6999e3SHarald Freudenberger 			kfree(protkey);
1593fa6999e3SHarald Freudenberger 			break;
1594fa6999e3SHarald Freudenberger 		}
1595fa6999e3SHarald Freudenberger 		if (ktp.pkey && ktp.pkeylen) {
1596fa6999e3SHarald Freudenberger 			if (protkeylen > ktp.pkeylen) {
1597fa6999e3SHarald Freudenberger 				kfree(protkey);
1598fa6999e3SHarald Freudenberger 				return -EINVAL;
1599fa6999e3SHarald Freudenberger 			}
1600fa6999e3SHarald Freudenberger 			if (copy_to_user(ktp.pkey, protkey, protkeylen)) {
1601fa6999e3SHarald Freudenberger 				kfree(protkey);
1602fa6999e3SHarald Freudenberger 				return -EFAULT;
1603fa6999e3SHarald Freudenberger 			}
1604fa6999e3SHarald Freudenberger 		}
1605fa6999e3SHarald Freudenberger 		kfree(protkey);
1606fa6999e3SHarald Freudenberger 		ktp.pkeylen = protkeylen;
1607fa6999e3SHarald Freudenberger 		if (copy_to_user(utp, &ktp, sizeof(ktp)))
1608fa6999e3SHarald Freudenberger 			return -EFAULT;
1609fa6999e3SHarald Freudenberger 		break;
1610fa6999e3SHarald Freudenberger 	}
1611e80d4af0SHarald Freudenberger 	default:
1612e80d4af0SHarald Freudenberger 		/* unknown/unsupported ioctl cmd */
1613e80d4af0SHarald Freudenberger 		return -ENOTTY;
1614e80d4af0SHarald Freudenberger 	}
1615e80d4af0SHarald Freudenberger 
1616e80d4af0SHarald Freudenberger 	return rc;
1617e80d4af0SHarald Freudenberger }
1618e80d4af0SHarald Freudenberger 
1619e80d4af0SHarald Freudenberger /*
1620e80d4af0SHarald Freudenberger  * Sysfs and file io operations
1621e80d4af0SHarald Freudenberger  */
1622d632c047SIngo Franzki 
1623d632c047SIngo Franzki /*
1624d632c047SIngo Franzki  * Sysfs attribute read function for all protected key binary attributes.
1625d632c047SIngo Franzki  * The implementation can not deal with partial reads, because a new random
1626d632c047SIngo Franzki  * protected key blob is generated with each read. In case of partial reads
1627d632c047SIngo Franzki  * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
1628d632c047SIngo Franzki  */
1629d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf,
1630d632c047SIngo Franzki 					  loff_t off, size_t count)
1631d632c047SIngo Franzki {
1632d632c047SIngo Franzki 	struct protaeskeytoken protkeytoken;
1633d632c047SIngo Franzki 	struct pkey_protkey protkey;
1634d632c047SIngo Franzki 	int rc;
1635d632c047SIngo Franzki 
1636d632c047SIngo Franzki 	if (off != 0 || count < sizeof(protkeytoken))
1637d632c047SIngo Franzki 		return -EINVAL;
1638d632c047SIngo Franzki 	if (is_xts)
1639d632c047SIngo Franzki 		if (count < 2 * sizeof(protkeytoken))
1640d632c047SIngo Franzki 			return -EINVAL;
1641d632c047SIngo Franzki 
1642d632c047SIngo Franzki 	memset(&protkeytoken, 0, sizeof(protkeytoken));
1643d632c047SIngo Franzki 	protkeytoken.type = TOKTYPE_NON_CCA;
1644d632c047SIngo Franzki 	protkeytoken.version = TOKVER_PROTECTED_KEY;
1645d632c047SIngo Franzki 	protkeytoken.keytype = keytype;
1646d632c047SIngo Franzki 
1647*f370f45cSHarald Freudenberger 	protkey.len = sizeof(protkey.protkey);
1648*f370f45cSHarald Freudenberger 	rc = pkey_genprotkey(protkeytoken.keytype,
1649*f370f45cSHarald Freudenberger 			     protkey.protkey, &protkey.len, &protkey.type);
1650d632c047SIngo Franzki 	if (rc)
1651d632c047SIngo Franzki 		return rc;
1652d632c047SIngo Franzki 
1653d632c047SIngo Franzki 	protkeytoken.len = protkey.len;
1654d632c047SIngo Franzki 	memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len);
1655d632c047SIngo Franzki 
1656d632c047SIngo Franzki 	memcpy(buf, &protkeytoken, sizeof(protkeytoken));
1657d632c047SIngo Franzki 
1658d632c047SIngo Franzki 	if (is_xts) {
1659*f370f45cSHarald Freudenberger 		/* xts needs a second protected key, reuse protkey struct */
1660*f370f45cSHarald Freudenberger 		protkey.len = sizeof(protkey.protkey);
1661*f370f45cSHarald Freudenberger 		rc = pkey_genprotkey(protkeytoken.keytype,
1662*f370f45cSHarald Freudenberger 				     protkey.protkey, &protkey.len, &protkey.type);
1663d632c047SIngo Franzki 		if (rc)
1664d632c047SIngo Franzki 			return rc;
1665d632c047SIngo Franzki 
1666d632c047SIngo Franzki 		protkeytoken.len = protkey.len;
1667d632c047SIngo Franzki 		memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len);
1668d632c047SIngo Franzki 
1669d632c047SIngo Franzki 		memcpy(buf + sizeof(protkeytoken), &protkeytoken,
1670d632c047SIngo Franzki 		       sizeof(protkeytoken));
1671d632c047SIngo Franzki 
1672d632c047SIngo Franzki 		return 2 * sizeof(protkeytoken);
1673d632c047SIngo Franzki 	}
1674d632c047SIngo Franzki 
1675d632c047SIngo Franzki 	return sizeof(protkeytoken);
1676d632c047SIngo Franzki }
1677d632c047SIngo Franzki 
1678d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp,
1679d632c047SIngo Franzki 				    struct kobject *kobj,
1680d632c047SIngo Franzki 				    struct bin_attribute *attr,
1681d632c047SIngo Franzki 				    char *buf, loff_t off,
1682d632c047SIngo Franzki 				    size_t count)
1683d632c047SIngo Franzki {
1684d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf,
1685d632c047SIngo Franzki 					  off, count);
1686d632c047SIngo Franzki }
1687d632c047SIngo Franzki 
1688d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp,
1689d632c047SIngo Franzki 				    struct kobject *kobj,
1690d632c047SIngo Franzki 				    struct bin_attribute *attr,
1691d632c047SIngo Franzki 				    char *buf, loff_t off,
1692d632c047SIngo Franzki 				    size_t count)
1693d632c047SIngo Franzki {
1694d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf,
1695d632c047SIngo Franzki 					  off, count);
1696d632c047SIngo Franzki }
1697d632c047SIngo Franzki 
1698d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp,
1699d632c047SIngo Franzki 				    struct kobject *kobj,
1700d632c047SIngo Franzki 				    struct bin_attribute *attr,
1701d632c047SIngo Franzki 				    char *buf, loff_t off,
1702d632c047SIngo Franzki 				    size_t count)
1703d632c047SIngo Franzki {
1704d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf,
1705d632c047SIngo Franzki 					  off, count);
1706d632c047SIngo Franzki }
1707d632c047SIngo Franzki 
1708d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp,
1709d632c047SIngo Franzki 					struct kobject *kobj,
1710d632c047SIngo Franzki 					struct bin_attribute *attr,
1711d632c047SIngo Franzki 					char *buf, loff_t off,
1712d632c047SIngo Franzki 					size_t count)
1713d632c047SIngo Franzki {
1714d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf,
1715d632c047SIngo Franzki 					  off, count);
1716d632c047SIngo Franzki }
1717d632c047SIngo Franzki 
1718d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp,
1719d632c047SIngo Franzki 					struct kobject *kobj,
1720d632c047SIngo Franzki 					struct bin_attribute *attr,
1721d632c047SIngo Franzki 					char *buf, loff_t off,
1722d632c047SIngo Franzki 					size_t count)
1723d632c047SIngo Franzki {
1724d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf,
1725d632c047SIngo Franzki 					  off, count);
1726d632c047SIngo Franzki }
1727d632c047SIngo Franzki 
1728d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken));
1729d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken));
1730d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken));
1731d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken));
1732d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken));
1733d632c047SIngo Franzki 
1734d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = {
1735d632c047SIngo Franzki 	&bin_attr_protkey_aes_128,
1736d632c047SIngo Franzki 	&bin_attr_protkey_aes_192,
1737d632c047SIngo Franzki 	&bin_attr_protkey_aes_256,
1738d632c047SIngo Franzki 	&bin_attr_protkey_aes_128_xts,
1739d632c047SIngo Franzki 	&bin_attr_protkey_aes_256_xts,
1740d632c047SIngo Franzki 	NULL
1741d632c047SIngo Franzki };
1742d632c047SIngo Franzki 
1743d632c047SIngo Franzki static struct attribute_group protkey_attr_group = {
1744d632c047SIngo Franzki 	.name	   = "protkey",
1745d632c047SIngo Franzki 	.bin_attrs = protkey_attrs,
1746d632c047SIngo Franzki };
1747d632c047SIngo Franzki 
1748af504452SIngo Franzki /*
1749af504452SIngo Franzki  * Sysfs attribute read function for all secure key ccadata binary attributes.
1750af504452SIngo Franzki  * The implementation can not deal with partial reads, because a new random
1751af504452SIngo Franzki  * protected key blob is generated with each read. In case of partial reads
1752af504452SIngo Franzki  * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
1753af504452SIngo Franzki  */
1754af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf,
1755af504452SIngo Franzki 					  loff_t off, size_t count)
1756af504452SIngo Franzki {
1757efc598e6SHarald Freudenberger 	struct pkey_seckey *seckey = (struct pkey_seckey *)buf;
175846a29b03SHarald Freudenberger 	int rc;
1759af504452SIngo Franzki 
1760af504452SIngo Franzki 	if (off != 0 || count < sizeof(struct secaeskeytoken))
1761af504452SIngo Franzki 		return -EINVAL;
1762af504452SIngo Franzki 	if (is_xts)
1763af504452SIngo Franzki 		if (count < 2 * sizeof(struct secaeskeytoken))
1764af504452SIngo Franzki 			return -EINVAL;
1765af504452SIngo Franzki 
1766efc598e6SHarald Freudenberger 	rc = cca_genseckey(-1, -1, keytype, seckey->seckey);
1767af504452SIngo Franzki 	if (rc)
1768af504452SIngo Franzki 		return rc;
1769af504452SIngo Franzki 
1770af504452SIngo Franzki 	if (is_xts) {
1771efc598e6SHarald Freudenberger 		seckey++;
1772efc598e6SHarald Freudenberger 		rc = cca_genseckey(-1, -1, keytype, seckey->seckey);
1773af504452SIngo Franzki 		if (rc)
1774af504452SIngo Franzki 			return rc;
1775af504452SIngo Franzki 
1776af504452SIngo Franzki 		return 2 * sizeof(struct secaeskeytoken);
1777af504452SIngo Franzki 	}
1778af504452SIngo Franzki 
1779af504452SIngo Franzki 	return sizeof(struct secaeskeytoken);
1780af504452SIngo Franzki }
1781af504452SIngo Franzki 
1782af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp,
1783af504452SIngo Franzki 				    struct kobject *kobj,
1784af504452SIngo Franzki 				    struct bin_attribute *attr,
1785af504452SIngo Franzki 				    char *buf, loff_t off,
1786af504452SIngo Franzki 				    size_t count)
1787af504452SIngo Franzki {
1788af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf,
1789af504452SIngo Franzki 					  off, count);
1790af504452SIngo Franzki }
1791af504452SIngo Franzki 
1792af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp,
1793af504452SIngo Franzki 				    struct kobject *kobj,
1794af504452SIngo Franzki 				    struct bin_attribute *attr,
1795af504452SIngo Franzki 				    char *buf, loff_t off,
1796af504452SIngo Franzki 				    size_t count)
1797af504452SIngo Franzki {
1798af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf,
1799af504452SIngo Franzki 					  off, count);
1800af504452SIngo Franzki }
1801af504452SIngo Franzki 
1802af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp,
1803af504452SIngo Franzki 				    struct kobject *kobj,
1804af504452SIngo Franzki 				    struct bin_attribute *attr,
1805af504452SIngo Franzki 				    char *buf, loff_t off,
1806af504452SIngo Franzki 				    size_t count)
1807af504452SIngo Franzki {
1808af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf,
1809af504452SIngo Franzki 					  off, count);
1810af504452SIngo Franzki }
1811af504452SIngo Franzki 
1812af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp,
1813af504452SIngo Franzki 					struct kobject *kobj,
1814af504452SIngo Franzki 					struct bin_attribute *attr,
1815af504452SIngo Franzki 					char *buf, loff_t off,
1816af504452SIngo Franzki 					size_t count)
1817af504452SIngo Franzki {
1818af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf,
1819af504452SIngo Franzki 					  off, count);
1820af504452SIngo Franzki }
1821af504452SIngo Franzki 
1822af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp,
1823af504452SIngo Franzki 					struct kobject *kobj,
1824af504452SIngo Franzki 					struct bin_attribute *attr,
1825af504452SIngo Franzki 					char *buf, loff_t off,
1826af504452SIngo Franzki 					size_t count)
1827af504452SIngo Franzki {
1828af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf,
1829af504452SIngo Franzki 					  off, count);
1830af504452SIngo Franzki }
1831af504452SIngo Franzki 
1832af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken));
1833af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken));
1834af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken));
1835af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken));
1836af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken));
1837af504452SIngo Franzki 
1838af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = {
1839af504452SIngo Franzki 	&bin_attr_ccadata_aes_128,
1840af504452SIngo Franzki 	&bin_attr_ccadata_aes_192,
1841af504452SIngo Franzki 	&bin_attr_ccadata_aes_256,
1842af504452SIngo Franzki 	&bin_attr_ccadata_aes_128_xts,
1843af504452SIngo Franzki 	&bin_attr_ccadata_aes_256_xts,
1844af504452SIngo Franzki 	NULL
1845af504452SIngo Franzki };
1846af504452SIngo Franzki 
1847af504452SIngo Franzki static struct attribute_group ccadata_attr_group = {
1848af504452SIngo Franzki 	.name	   = "ccadata",
1849af504452SIngo Franzki 	.bin_attrs = ccadata_attrs,
1850af504452SIngo Franzki };
1851af504452SIngo Franzki 
1852f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE	(sizeof(struct cipherkeytoken) + 80)
1853f71fee27SIngo Franzki 
1854f71fee27SIngo Franzki /*
1855f71fee27SIngo Franzki  * Sysfs attribute read function for all secure key ccacipher binary attributes.
1856f71fee27SIngo Franzki  * The implementation can not deal with partial reads, because a new random
1857f71fee27SIngo Franzki  * secure key blob is generated with each read. In case of partial reads
1858f71fee27SIngo Franzki  * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
1859f71fee27SIngo Franzki  */
1860f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits,
1861f71fee27SIngo Franzki 					    bool is_xts, char *buf, loff_t off,
1862f71fee27SIngo Franzki 					    size_t count)
1863f71fee27SIngo Franzki {
186455d0a513SHarald Freudenberger 	size_t keysize = CCACIPHERTOKENSIZE;
186546a29b03SHarald Freudenberger 	u32 nr_apqns, *apqns = NULL;
186646a29b03SHarald Freudenberger 	int i, rc, card, dom;
1867f71fee27SIngo Franzki 
1868f71fee27SIngo Franzki 	if (off != 0 || count < CCACIPHERTOKENSIZE)
1869f71fee27SIngo Franzki 		return -EINVAL;
1870f71fee27SIngo Franzki 	if (is_xts)
1871f71fee27SIngo Franzki 		if (count < 2 * CCACIPHERTOKENSIZE)
1872f71fee27SIngo Franzki 			return -EINVAL;
1873f71fee27SIngo Franzki 
187455d0a513SHarald Freudenberger 	/* build a list of apqns able to generate an cipher key */
187555d0a513SHarald Freudenberger 	rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
187632ca04bbSHarald Freudenberger 			   ZCRYPT_CEX6, 0, 0, 0, 0);
1877f71fee27SIngo Franzki 	if (rc)
1878f71fee27SIngo Franzki 		return rc;
187955d0a513SHarald Freudenberger 
188055d0a513SHarald Freudenberger 	memset(buf, 0, is_xts ? 2 * keysize : keysize);
188155d0a513SHarald Freudenberger 
188255d0a513SHarald Freudenberger 	/* simple try all apqns from the list */
188355d0a513SHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
188455d0a513SHarald Freudenberger 		card = apqns[i] >> 16;
188555d0a513SHarald Freudenberger 		dom = apqns[i] & 0xFFFF;
188655d0a513SHarald Freudenberger 		rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize);
188755d0a513SHarald Freudenberger 		if (rc == 0)
188855d0a513SHarald Freudenberger 			break;
188955d0a513SHarald Freudenberger 	}
189055d0a513SHarald Freudenberger 	if (rc)
189155d0a513SHarald Freudenberger 		return rc;
1892f71fee27SIngo Franzki 
1893f71fee27SIngo Franzki 	if (is_xts) {
1894f71fee27SIngo Franzki 		keysize = CCACIPHERTOKENSIZE;
189555d0a513SHarald Freudenberger 		buf += CCACIPHERTOKENSIZE;
189655d0a513SHarald Freudenberger 		rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize);
189755d0a513SHarald Freudenberger 		if (rc == 0)
1898f71fee27SIngo Franzki 			return 2 * CCACIPHERTOKENSIZE;
1899f71fee27SIngo Franzki 	}
1900f71fee27SIngo Franzki 
1901f71fee27SIngo Franzki 	return CCACIPHERTOKENSIZE;
1902f71fee27SIngo Franzki }
1903f71fee27SIngo Franzki 
1904f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp,
1905f71fee27SIngo Franzki 				      struct kobject *kobj,
1906f71fee27SIngo Franzki 				      struct bin_attribute *attr,
1907f71fee27SIngo Franzki 				      char *buf, loff_t off,
1908f71fee27SIngo Franzki 				      size_t count)
1909f71fee27SIngo Franzki {
1910f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf,
1911f71fee27SIngo Franzki 					    off, count);
1912f71fee27SIngo Franzki }
1913f71fee27SIngo Franzki 
1914f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp,
1915f71fee27SIngo Franzki 				      struct kobject *kobj,
1916f71fee27SIngo Franzki 				      struct bin_attribute *attr,
1917f71fee27SIngo Franzki 				      char *buf, loff_t off,
1918f71fee27SIngo Franzki 				      size_t count)
1919f71fee27SIngo Franzki {
1920f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf,
1921f71fee27SIngo Franzki 					    off, count);
1922f71fee27SIngo Franzki }
1923f71fee27SIngo Franzki 
1924f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp,
1925f71fee27SIngo Franzki 				      struct kobject *kobj,
1926f71fee27SIngo Franzki 				      struct bin_attribute *attr,
1927f71fee27SIngo Franzki 				      char *buf, loff_t off,
1928f71fee27SIngo Franzki 				      size_t count)
1929f71fee27SIngo Franzki {
1930f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf,
1931f71fee27SIngo Franzki 					    off, count);
1932f71fee27SIngo Franzki }
1933f71fee27SIngo Franzki 
1934f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp,
1935f71fee27SIngo Franzki 					  struct kobject *kobj,
1936f71fee27SIngo Franzki 					  struct bin_attribute *attr,
1937f71fee27SIngo Franzki 					  char *buf, loff_t off,
1938f71fee27SIngo Franzki 					  size_t count)
1939f71fee27SIngo Franzki {
1940f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf,
1941f71fee27SIngo Franzki 					    off, count);
1942f71fee27SIngo Franzki }
1943f71fee27SIngo Franzki 
1944f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_read(struct file *filp,
1945f71fee27SIngo Franzki 					  struct kobject *kobj,
1946f71fee27SIngo Franzki 					  struct bin_attribute *attr,
1947f71fee27SIngo Franzki 					  char *buf, loff_t off,
1948f71fee27SIngo Franzki 					  size_t count)
1949f71fee27SIngo Franzki {
1950f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf,
1951f71fee27SIngo Franzki 					    off, count);
1952f71fee27SIngo Franzki }
1953f71fee27SIngo Franzki 
1954f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE);
1955f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE);
1956f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE);
1957f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE);
1958f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE);
1959f71fee27SIngo Franzki 
1960f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = {
1961f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_128,
1962f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_192,
1963f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_256,
1964f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_128_xts,
1965f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_256_xts,
1966f71fee27SIngo Franzki 	NULL
1967f71fee27SIngo Franzki };
1968f71fee27SIngo Franzki 
1969f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = {
1970f71fee27SIngo Franzki 	.name	   = "ccacipher",
1971f71fee27SIngo Franzki 	.bin_attrs = ccacipher_attrs,
1972f71fee27SIngo Franzki };
1973f71fee27SIngo Franzki 
197455d0a513SHarald Freudenberger /*
197555d0a513SHarald Freudenberger  * Sysfs attribute read function for all ep11 aes key binary attributes.
197655d0a513SHarald Freudenberger  * The implementation can not deal with partial reads, because a new random
197755d0a513SHarald Freudenberger  * secure key blob is generated with each read. In case of partial reads
197855d0a513SHarald Freudenberger  * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
197955d0a513SHarald Freudenberger  * This function and the sysfs attributes using it provide EP11 key blobs
198055d0a513SHarald Freudenberger  * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently
198155d0a513SHarald Freudenberger  * 320 bytes.
198255d0a513SHarald Freudenberger  */
198355d0a513SHarald Freudenberger static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits,
198455d0a513SHarald Freudenberger 				       bool is_xts, char *buf, loff_t off,
198555d0a513SHarald Freudenberger 				       size_t count)
198655d0a513SHarald Freudenberger {
198755d0a513SHarald Freudenberger 	size_t keysize = MAXEP11AESKEYBLOBSIZE;
198846a29b03SHarald Freudenberger 	u32 nr_apqns, *apqns = NULL;
198946a29b03SHarald Freudenberger 	int i, rc, card, dom;
199055d0a513SHarald Freudenberger 
199155d0a513SHarald Freudenberger 	if (off != 0 || count < MAXEP11AESKEYBLOBSIZE)
199255d0a513SHarald Freudenberger 		return -EINVAL;
199355d0a513SHarald Freudenberger 	if (is_xts)
199455d0a513SHarald Freudenberger 		if (count < 2 * MAXEP11AESKEYBLOBSIZE)
199555d0a513SHarald Freudenberger 			return -EINVAL;
199655d0a513SHarald Freudenberger 
199755d0a513SHarald Freudenberger 	/* build a list of apqns able to generate an cipher key */
199855d0a513SHarald Freudenberger 	rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
199955d0a513SHarald Freudenberger 			    ZCRYPT_CEX7, EP11_API_V, NULL);
200055d0a513SHarald Freudenberger 	if (rc)
200155d0a513SHarald Freudenberger 		return rc;
200255d0a513SHarald Freudenberger 
200355d0a513SHarald Freudenberger 	memset(buf, 0, is_xts ? 2 * keysize : keysize);
200455d0a513SHarald Freudenberger 
200555d0a513SHarald Freudenberger 	/* simple try all apqns from the list */
200655d0a513SHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
200755d0a513SHarald Freudenberger 		card = apqns[i] >> 16;
200855d0a513SHarald Freudenberger 		dom = apqns[i] & 0xFFFF;
200955d0a513SHarald Freudenberger 		rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize);
201055d0a513SHarald Freudenberger 		if (rc == 0)
201155d0a513SHarald Freudenberger 			break;
201255d0a513SHarald Freudenberger 	}
201355d0a513SHarald Freudenberger 	if (rc)
201455d0a513SHarald Freudenberger 		return rc;
201555d0a513SHarald Freudenberger 
201655d0a513SHarald Freudenberger 	if (is_xts) {
201755d0a513SHarald Freudenberger 		keysize = MAXEP11AESKEYBLOBSIZE;
201855d0a513SHarald Freudenberger 		buf += MAXEP11AESKEYBLOBSIZE;
201955d0a513SHarald Freudenberger 		rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize);
202055d0a513SHarald Freudenberger 		if (rc == 0)
202155d0a513SHarald Freudenberger 			return 2 * MAXEP11AESKEYBLOBSIZE;
202255d0a513SHarald Freudenberger 	}
202355d0a513SHarald Freudenberger 
202455d0a513SHarald Freudenberger 	return MAXEP11AESKEYBLOBSIZE;
202555d0a513SHarald Freudenberger }
202655d0a513SHarald Freudenberger 
202755d0a513SHarald Freudenberger static ssize_t ep11_aes_128_read(struct file *filp,
202855d0a513SHarald Freudenberger 				 struct kobject *kobj,
202955d0a513SHarald Freudenberger 				 struct bin_attribute *attr,
203055d0a513SHarald Freudenberger 				 char *buf, loff_t off,
203155d0a513SHarald Freudenberger 				 size_t count)
203255d0a513SHarald Freudenberger {
203355d0a513SHarald Freudenberger 	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf,
203455d0a513SHarald Freudenberger 				       off, count);
203555d0a513SHarald Freudenberger }
203655d0a513SHarald Freudenberger 
203755d0a513SHarald Freudenberger static ssize_t ep11_aes_192_read(struct file *filp,
203855d0a513SHarald Freudenberger 				 struct kobject *kobj,
203955d0a513SHarald Freudenberger 				 struct bin_attribute *attr,
204055d0a513SHarald Freudenberger 				 char *buf, loff_t off,
204155d0a513SHarald Freudenberger 				 size_t count)
204255d0a513SHarald Freudenberger {
204355d0a513SHarald Freudenberger 	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf,
204455d0a513SHarald Freudenberger 				       off, count);
204555d0a513SHarald Freudenberger }
204655d0a513SHarald Freudenberger 
204755d0a513SHarald Freudenberger static ssize_t ep11_aes_256_read(struct file *filp,
204855d0a513SHarald Freudenberger 				 struct kobject *kobj,
204955d0a513SHarald Freudenberger 				 struct bin_attribute *attr,
205055d0a513SHarald Freudenberger 				 char *buf, loff_t off,
205155d0a513SHarald Freudenberger 				 size_t count)
205255d0a513SHarald Freudenberger {
205355d0a513SHarald Freudenberger 	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf,
205455d0a513SHarald Freudenberger 				       off, count);
205555d0a513SHarald Freudenberger }
205655d0a513SHarald Freudenberger 
205755d0a513SHarald Freudenberger static ssize_t ep11_aes_128_xts_read(struct file *filp,
205855d0a513SHarald Freudenberger 				     struct kobject *kobj,
205955d0a513SHarald Freudenberger 				     struct bin_attribute *attr,
206055d0a513SHarald Freudenberger 				     char *buf, loff_t off,
206155d0a513SHarald Freudenberger 				     size_t count)
206255d0a513SHarald Freudenberger {
206355d0a513SHarald Freudenberger 	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf,
206455d0a513SHarald Freudenberger 				       off, count);
206555d0a513SHarald Freudenberger }
206655d0a513SHarald Freudenberger 
206755d0a513SHarald Freudenberger static ssize_t ep11_aes_256_xts_read(struct file *filp,
206855d0a513SHarald Freudenberger 				     struct kobject *kobj,
206955d0a513SHarald Freudenberger 				     struct bin_attribute *attr,
207055d0a513SHarald Freudenberger 				     char *buf, loff_t off,
207155d0a513SHarald Freudenberger 				     size_t count)
207255d0a513SHarald Freudenberger {
207355d0a513SHarald Freudenberger 	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf,
207455d0a513SHarald Freudenberger 				       off, count);
207555d0a513SHarald Freudenberger }
207655d0a513SHarald Freudenberger 
207755d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE);
207855d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE);
207955d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE);
208055d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE);
208155d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE);
208255d0a513SHarald Freudenberger 
208355d0a513SHarald Freudenberger static struct bin_attribute *ep11_attrs[] = {
208455d0a513SHarald Freudenberger 	&bin_attr_ep11_aes_128,
208555d0a513SHarald Freudenberger 	&bin_attr_ep11_aes_192,
208655d0a513SHarald Freudenberger 	&bin_attr_ep11_aes_256,
208755d0a513SHarald Freudenberger 	&bin_attr_ep11_aes_128_xts,
208855d0a513SHarald Freudenberger 	&bin_attr_ep11_aes_256_xts,
208955d0a513SHarald Freudenberger 	NULL
209055d0a513SHarald Freudenberger };
209155d0a513SHarald Freudenberger 
209255d0a513SHarald Freudenberger static struct attribute_group ep11_attr_group = {
209355d0a513SHarald Freudenberger 	.name	   = "ep11",
209455d0a513SHarald Freudenberger 	.bin_attrs = ep11_attrs,
209555d0a513SHarald Freudenberger };
209655d0a513SHarald Freudenberger 
2097d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = {
2098d632c047SIngo Franzki 	&protkey_attr_group,
2099af504452SIngo Franzki 	&ccadata_attr_group,
2100f71fee27SIngo Franzki 	&ccacipher_attr_group,
210155d0a513SHarald Freudenberger 	&ep11_attr_group,
2102d632c047SIngo Franzki 	NULL,
2103d632c047SIngo Franzki };
2104d632c047SIngo Franzki 
2105e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = {
2106e80d4af0SHarald Freudenberger 	.owner		= THIS_MODULE,
2107e80d4af0SHarald Freudenberger 	.open		= nonseekable_open,
2108e80d4af0SHarald Freudenberger 	.llseek		= no_llseek,
2109e80d4af0SHarald Freudenberger 	.unlocked_ioctl = pkey_unlocked_ioctl,
2110e80d4af0SHarald Freudenberger };
2111e80d4af0SHarald Freudenberger 
2112e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = {
2113e80d4af0SHarald Freudenberger 	.name	= "pkey",
2114e80d4af0SHarald Freudenberger 	.minor	= MISC_DYNAMIC_MINOR,
2115e80d4af0SHarald Freudenberger 	.mode	= 0666,
2116e80d4af0SHarald Freudenberger 	.fops	= &pkey_fops,
2117d632c047SIngo Franzki 	.groups = pkey_attr_groups,
2118e80d4af0SHarald Freudenberger };
2119e80d4af0SHarald Freudenberger 
2120e80d4af0SHarald Freudenberger /*
2121e80d4af0SHarald Freudenberger  * Module init
2122e80d4af0SHarald Freudenberger  */
2123cb4ef3c2SHeiko Carstens static int __init pkey_init(void)
2124e80d4af0SHarald Freudenberger {
21255b35047eSHarald Freudenberger 	cpacf_mask_t func_mask;
2126e80d4af0SHarald Freudenberger 
2127f822ad2cSHarald Freudenberger 	/*
2128f822ad2cSHarald Freudenberger 	 * The pckmo instruction should be available - even if we don't
2129f822ad2cSHarald Freudenberger 	 * actually invoke it. This instruction comes with MSA 3 which
2130f822ad2cSHarald Freudenberger 	 * is also the minimum level for the kmc instructions which
2131f822ad2cSHarald Freudenberger 	 * are able to work with protected keys.
2132f822ad2cSHarald Freudenberger 	 */
21335b35047eSHarald Freudenberger 	if (!cpacf_query(CPACF_PCKMO, &func_mask))
213458443b67SDavid Hildenbrand 		return -ENODEV;
2135e80d4af0SHarald Freudenberger 
2136cb26b9ffSIngo Franzki 	/* check for kmc instructions available */
21375b35047eSHarald Freudenberger 	if (!cpacf_query(CPACF_KMC, &func_mask))
213858443b67SDavid Hildenbrand 		return -ENODEV;
21395b35047eSHarald Freudenberger 	if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) ||
21405b35047eSHarald Freudenberger 	    !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) ||
21415b35047eSHarald Freudenberger 	    !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256))
214258443b67SDavid Hildenbrand 		return -ENODEV;
2143cb26b9ffSIngo Franzki 
2144e80d4af0SHarald Freudenberger 	pkey_debug_init();
2145e80d4af0SHarald Freudenberger 
2146e80d4af0SHarald Freudenberger 	return misc_register(&pkey_dev);
2147e80d4af0SHarald Freudenberger }
2148e80d4af0SHarald Freudenberger 
2149e80d4af0SHarald Freudenberger /*
2150e80d4af0SHarald Freudenberger  * Module exit
2151e80d4af0SHarald Freudenberger  */
2152e80d4af0SHarald Freudenberger static void __exit pkey_exit(void)
2153e80d4af0SHarald Freudenberger {
2154e80d4af0SHarald Freudenberger 	misc_deregister(&pkey_dev);
2155e80d4af0SHarald Freudenberger 	pkey_debug_exit();
2156e80d4af0SHarald Freudenberger }
2157e80d4af0SHarald Freudenberger 
21580a5f9b38SHeiko Carstens module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init);
2159e80d4af0SHarald Freudenberger module_exit(pkey_exit);
2160