xref: /openbmc/linux/drivers/s390/crypto/pkey_api.c (revision 8b57e7c852fc58a62e668a83c0fa8d9246131803)
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"
28e80d4af0SHarald Freudenberger 
29e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL");
30e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation");
31e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface");
32e80d4af0SHarald Freudenberger 
33f2bbc96eSHarald Freudenberger #define KEYBLOBBUFSIZE 8192  /* key buffer size used for internal processing */
34f2bbc96eSHarald Freudenberger #define MAXAPQNSINLIST 64    /* max 64 apqns within a apqn list */
35f2bbc96eSHarald Freudenberger 
36f822ad2cSHarald Freudenberger /* mask of available pckmo subfunctions, fetched once at module init */
37f822ad2cSHarald Freudenberger static cpacf_mask_t pckmo_functions;
38f822ad2cSHarald 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 
74e80d4af0SHarald Freudenberger /*
75e80d4af0SHarald Freudenberger  * Create a protected key from a clear key value.
76e80d4af0SHarald Freudenberger  */
77183cb469SHarald Freudenberger static int pkey_clr2protkey(u32 keytype,
78e80d4af0SHarald Freudenberger 			    const struct pkey_clrkey *clrkey,
79e80d4af0SHarald Freudenberger 			    struct pkey_protkey *protkey)
80e80d4af0SHarald Freudenberger {
81e80d4af0SHarald Freudenberger 	long fc;
82e80d4af0SHarald Freudenberger 	int keysize;
83e80d4af0SHarald Freudenberger 	u8 paramblock[64];
84e80d4af0SHarald Freudenberger 
85e80d4af0SHarald Freudenberger 	switch (keytype) {
86e80d4af0SHarald Freudenberger 	case PKEY_KEYTYPE_AES_128:
87e80d4af0SHarald Freudenberger 		keysize = 16;
88e80d4af0SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_AES_128_KEY;
89e80d4af0SHarald Freudenberger 		break;
90e80d4af0SHarald Freudenberger 	case PKEY_KEYTYPE_AES_192:
91e80d4af0SHarald Freudenberger 		keysize = 24;
92e80d4af0SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_AES_192_KEY;
93e80d4af0SHarald Freudenberger 		break;
94e80d4af0SHarald Freudenberger 	case PKEY_KEYTYPE_AES_256:
95e80d4af0SHarald Freudenberger 		keysize = 32;
96e80d4af0SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_AES_256_KEY;
97e80d4af0SHarald Freudenberger 		break;
98e80d4af0SHarald Freudenberger 	default:
99ac2b96f3SHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported keytype %d\n",
100ac2b96f3SHarald Freudenberger 			  __func__, keytype);
101e80d4af0SHarald Freudenberger 		return -EINVAL;
102e80d4af0SHarald Freudenberger 	}
103e80d4af0SHarald Freudenberger 
104f822ad2cSHarald Freudenberger 	/*
105f822ad2cSHarald Freudenberger 	 * Check if the needed pckmo subfunction is available.
106f822ad2cSHarald Freudenberger 	 * These subfunctions can be enabled/disabled by customers
107f822ad2cSHarald Freudenberger 	 * in the LPAR profile or may even change on the fly.
108f822ad2cSHarald Freudenberger 	 */
109f822ad2cSHarald Freudenberger 	if (!cpacf_test_func(&pckmo_functions, fc)) {
110f822ad2cSHarald Freudenberger 		DEBUG_ERR("%s pckmo functions not available\n", __func__);
11158443b67SDavid Hildenbrand 		return -ENODEV;
112f822ad2cSHarald Freudenberger 	}
113f822ad2cSHarald Freudenberger 
114e80d4af0SHarald Freudenberger 	/* prepare param block */
115e80d4af0SHarald Freudenberger 	memset(paramblock, 0, sizeof(paramblock));
116e80d4af0SHarald Freudenberger 	memcpy(paramblock, clrkey->clrkey, keysize);
117e80d4af0SHarald Freudenberger 
118e80d4af0SHarald Freudenberger 	/* call the pckmo instruction */
119e80d4af0SHarald Freudenberger 	cpacf_pckmo(fc, paramblock);
120e80d4af0SHarald Freudenberger 
121e80d4af0SHarald Freudenberger 	/* copy created protected key */
122e80d4af0SHarald Freudenberger 	protkey->type = keytype;
123e80d4af0SHarald Freudenberger 	protkey->len = keysize + 32;
124e80d4af0SHarald Freudenberger 	memcpy(protkey->protkey, paramblock, keysize + 32);
125e80d4af0SHarald Freudenberger 
126e80d4af0SHarald Freudenberger 	return 0;
127e80d4af0SHarald Freudenberger }
128e80d4af0SHarald Freudenberger 
129e80d4af0SHarald Freudenberger /*
130e80d4af0SHarald Freudenberger  * Find card and transform secure key into protected key.
131e80d4af0SHarald Freudenberger  */
132f2bbc96eSHarald Freudenberger static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey)
133e80d4af0SHarald Freudenberger {
134e80d4af0SHarald Freudenberger 	int rc, verify;
135f2bbc96eSHarald Freudenberger 	u16 cardnr, domain;
136f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
137e80d4af0SHarald Freudenberger 
138e80d4af0SHarald Freudenberger 	/*
139f2bbc96eSHarald Freudenberger 	 * The cca_xxx2protkey call may fail when a card has been
140e80d4af0SHarald Freudenberger 	 * addressed where the master key was changed after last fetch
141efc598e6SHarald Freudenberger 	 * of the mkvp into the cache. Try 3 times: First witout verify
142efc598e6SHarald Freudenberger 	 * then with verify and last round with verify and old master
143efc598e6SHarald Freudenberger 	 * key verification pattern match not ignored.
144e80d4af0SHarald Freudenberger 	 */
145efc598e6SHarald Freudenberger 	for (verify = 0; verify < 3; verify++) {
146f2bbc96eSHarald Freudenberger 		rc = cca_findcard(key, &cardnr, &domain, verify);
147efc598e6SHarald Freudenberger 		if (rc < 0)
148e80d4af0SHarald Freudenberger 			continue;
149efc598e6SHarald Freudenberger 		if (rc > 0 && verify < 2)
150efc598e6SHarald Freudenberger 			continue;
151f2bbc96eSHarald Freudenberger 		switch (hdr->version) {
152f2bbc96eSHarald Freudenberger 		case TOKVER_CCA_AES:
153f2bbc96eSHarald Freudenberger 			rc = cca_sec2protkey(cardnr, domain,
154f2bbc96eSHarald Freudenberger 					     key, pkey->protkey,
155f2bbc96eSHarald Freudenberger 					     &pkey->len, &pkey->type);
156f2bbc96eSHarald Freudenberger 			break;
157f2bbc96eSHarald Freudenberger 		case TOKVER_CCA_VLSC:
158f2bbc96eSHarald Freudenberger 			rc = cca_cipher2protkey(cardnr, domain,
159f2bbc96eSHarald Freudenberger 						key, pkey->protkey,
160f2bbc96eSHarald Freudenberger 						&pkey->len, &pkey->type);
161f2bbc96eSHarald Freudenberger 			break;
162f2bbc96eSHarald Freudenberger 		default:
163f2bbc96eSHarald Freudenberger 			return -EINVAL;
164f2bbc96eSHarald Freudenberger 		}
165e80d4af0SHarald Freudenberger 		if (rc == 0)
166e80d4af0SHarald Freudenberger 			break;
167e80d4af0SHarald Freudenberger 	}
168e80d4af0SHarald Freudenberger 
169e80d4af0SHarald Freudenberger 	if (rc)
170ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s failed rc=%d\n", __func__, rc);
171e80d4af0SHarald Freudenberger 
172e80d4af0SHarald Freudenberger 	return rc;
173e80d4af0SHarald Freudenberger }
174e80d4af0SHarald Freudenberger 
175e80d4af0SHarald Freudenberger /*
176e61a6134SHarald Freudenberger  * Verify key and give back some info about the key.
177e61a6134SHarald Freudenberger  */
178183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey,
179e61a6134SHarald Freudenberger 			  u16 *pcardnr, u16 *pdomain,
180e61a6134SHarald Freudenberger 			  u16 *pkeysize, u32 *pattributes)
181e61a6134SHarald Freudenberger {
182e61a6134SHarald Freudenberger 	struct secaeskeytoken *t = (struct secaeskeytoken *) seckey;
183e61a6134SHarald Freudenberger 	u16 cardnr, domain;
184e61a6134SHarald Freudenberger 	int rc;
185e61a6134SHarald Freudenberger 
186e61a6134SHarald Freudenberger 	/* check the secure key for valid AES secure key */
187efc598e6SHarald Freudenberger 	rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *) seckey, 0);
188e61a6134SHarald Freudenberger 	if (rc)
189e61a6134SHarald Freudenberger 		goto out;
190e61a6134SHarald Freudenberger 	if (pattributes)
191e61a6134SHarald Freudenberger 		*pattributes = PKEY_VERIFY_ATTR_AES;
192e61a6134SHarald Freudenberger 	if (pkeysize)
193e61a6134SHarald Freudenberger 		*pkeysize = t->bitsize;
194e61a6134SHarald Freudenberger 
195e61a6134SHarald Freudenberger 	/* try to find a card which can handle this key */
196efc598e6SHarald Freudenberger 	rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1);
197efc598e6SHarald Freudenberger 	if (rc < 0)
198e61a6134SHarald Freudenberger 		goto out;
199e61a6134SHarald Freudenberger 
200efc598e6SHarald Freudenberger 	if (rc > 0) {
201efc598e6SHarald Freudenberger 		/* key mkvp matches to old master key mkvp */
202ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s secure key has old mkvp\n", __func__);
203e61a6134SHarald Freudenberger 		if (pattributes)
204e61a6134SHarald Freudenberger 			*pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP;
205efc598e6SHarald Freudenberger 		rc = 0;
206e61a6134SHarald Freudenberger 	}
207e61a6134SHarald Freudenberger 
208e61a6134SHarald Freudenberger 	if (pcardnr)
209e61a6134SHarald Freudenberger 		*pcardnr = cardnr;
210e61a6134SHarald Freudenberger 	if (pdomain)
211e61a6134SHarald Freudenberger 		*pdomain = domain;
212e61a6134SHarald Freudenberger 
213e61a6134SHarald Freudenberger out:
214ac2b96f3SHarald Freudenberger 	DEBUG_DBG("%s rc=%d\n", __func__, rc);
215e61a6134SHarald Freudenberger 	return rc;
216e61a6134SHarald Freudenberger }
217e61a6134SHarald Freudenberger 
218e61a6134SHarald Freudenberger /*
219a45a5c7dSIngo Franzki  * Generate a random protected key
220a45a5c7dSIngo Franzki  */
221183cb469SHarald Freudenberger static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey)
222a45a5c7dSIngo Franzki {
223a45a5c7dSIngo Franzki 	struct pkey_clrkey clrkey;
224a45a5c7dSIngo Franzki 	int keysize;
225a45a5c7dSIngo Franzki 	int rc;
226a45a5c7dSIngo Franzki 
227a45a5c7dSIngo Franzki 	switch (keytype) {
228a45a5c7dSIngo Franzki 	case PKEY_KEYTYPE_AES_128:
229a45a5c7dSIngo Franzki 		keysize = 16;
230a45a5c7dSIngo Franzki 		break;
231a45a5c7dSIngo Franzki 	case PKEY_KEYTYPE_AES_192:
232a45a5c7dSIngo Franzki 		keysize = 24;
233a45a5c7dSIngo Franzki 		break;
234a45a5c7dSIngo Franzki 	case PKEY_KEYTYPE_AES_256:
235a45a5c7dSIngo Franzki 		keysize = 32;
236a45a5c7dSIngo Franzki 		break;
237a45a5c7dSIngo Franzki 	default:
238a45a5c7dSIngo Franzki 		DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__,
239a45a5c7dSIngo Franzki 			  keytype);
240a45a5c7dSIngo Franzki 		return -EINVAL;
241a45a5c7dSIngo Franzki 	}
242a45a5c7dSIngo Franzki 
243a45a5c7dSIngo Franzki 	/* generate a dummy random clear key */
244a45a5c7dSIngo Franzki 	get_random_bytes(clrkey.clrkey, keysize);
245a45a5c7dSIngo Franzki 
246a45a5c7dSIngo Franzki 	/* convert it to a dummy protected key */
247a45a5c7dSIngo Franzki 	rc = pkey_clr2protkey(keytype, &clrkey, protkey);
248a45a5c7dSIngo Franzki 	if (rc)
249a45a5c7dSIngo Franzki 		return rc;
250a45a5c7dSIngo Franzki 
251a45a5c7dSIngo Franzki 	/* replace the key part of the protected key with random bytes */
252a45a5c7dSIngo Franzki 	get_random_bytes(protkey->protkey, keysize);
253a45a5c7dSIngo Franzki 
254a45a5c7dSIngo Franzki 	return 0;
255a45a5c7dSIngo Franzki }
256a45a5c7dSIngo Franzki 
257a45a5c7dSIngo Franzki /*
258cb26b9ffSIngo Franzki  * Verify if a protected key is still valid
259cb26b9ffSIngo Franzki  */
260183cb469SHarald Freudenberger static int pkey_verifyprotkey(const struct pkey_protkey *protkey)
261cb26b9ffSIngo Franzki {
262cb26b9ffSIngo Franzki 	unsigned long fc;
263cb26b9ffSIngo Franzki 	struct {
264cb26b9ffSIngo Franzki 		u8 iv[AES_BLOCK_SIZE];
265cb26b9ffSIngo Franzki 		u8 key[MAXPROTKEYSIZE];
266cb26b9ffSIngo Franzki 	} param;
267cb26b9ffSIngo Franzki 	u8 null_msg[AES_BLOCK_SIZE];
268cb26b9ffSIngo Franzki 	u8 dest_buf[AES_BLOCK_SIZE];
269cb26b9ffSIngo Franzki 	unsigned int k;
270cb26b9ffSIngo Franzki 
271cb26b9ffSIngo Franzki 	switch (protkey->type) {
272cb26b9ffSIngo Franzki 	case PKEY_KEYTYPE_AES_128:
273cb26b9ffSIngo Franzki 		fc = CPACF_KMC_PAES_128;
274cb26b9ffSIngo Franzki 		break;
275cb26b9ffSIngo Franzki 	case PKEY_KEYTYPE_AES_192:
276cb26b9ffSIngo Franzki 		fc = CPACF_KMC_PAES_192;
277cb26b9ffSIngo Franzki 		break;
278cb26b9ffSIngo Franzki 	case PKEY_KEYTYPE_AES_256:
279cb26b9ffSIngo Franzki 		fc = CPACF_KMC_PAES_256;
280cb26b9ffSIngo Franzki 		break;
281cb26b9ffSIngo Franzki 	default:
282cb26b9ffSIngo Franzki 		DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__,
283cb26b9ffSIngo Franzki 			  protkey->type);
284cb26b9ffSIngo Franzki 		return -EINVAL;
285cb26b9ffSIngo Franzki 	}
286cb26b9ffSIngo Franzki 
287cb26b9ffSIngo Franzki 	memset(null_msg, 0, sizeof(null_msg));
288cb26b9ffSIngo Franzki 
289cb26b9ffSIngo Franzki 	memset(param.iv, 0, sizeof(param.iv));
290cb26b9ffSIngo Franzki 	memcpy(param.key, protkey->protkey, sizeof(param.key));
291cb26b9ffSIngo Franzki 
292cb26b9ffSIngo Franzki 	k = cpacf_kmc(fc | CPACF_ENCRYPT, &param, null_msg, dest_buf,
293cb26b9ffSIngo Franzki 		      sizeof(null_msg));
294cb26b9ffSIngo Franzki 	if (k != sizeof(null_msg)) {
295cb26b9ffSIngo Franzki 		DEBUG_ERR("%s protected key is not valid\n", __func__);
296cb26b9ffSIngo Franzki 		return -EKEYREJECTED;
297cb26b9ffSIngo Franzki 	}
298cb26b9ffSIngo Franzki 
299cb26b9ffSIngo Franzki 	return 0;
300cb26b9ffSIngo Franzki }
301cb26b9ffSIngo Franzki 
302cb26b9ffSIngo Franzki /*
303fb1136d6SIngo Franzki  * Transform a non-CCA key token into a protected key
304fb1136d6SIngo Franzki  */
305183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
306fb1136d6SIngo Franzki 			       struct pkey_protkey *protkey)
307fb1136d6SIngo Franzki {
308fb1136d6SIngo Franzki 	struct keytoken_header *hdr = (struct keytoken_header *)key;
309fb1136d6SIngo Franzki 	struct protaeskeytoken *t;
310fb1136d6SIngo Franzki 
311fb1136d6SIngo Franzki 	switch (hdr->version) {
312fb1136d6SIngo Franzki 	case TOKVER_PROTECTED_KEY:
313fb1136d6SIngo Franzki 		if (keylen != sizeof(struct protaeskeytoken))
314fb1136d6SIngo Franzki 			return -EINVAL;
315fb1136d6SIngo Franzki 
316fb1136d6SIngo Franzki 		t = (struct protaeskeytoken *)key;
317fb1136d6SIngo Franzki 		protkey->len = t->len;
318fb1136d6SIngo Franzki 		protkey->type = t->keytype;
319fb1136d6SIngo Franzki 		memcpy(protkey->protkey, t->protkey,
320fb1136d6SIngo Franzki 		       sizeof(protkey->protkey));
321fb1136d6SIngo Franzki 
322fb1136d6SIngo Franzki 		return pkey_verifyprotkey(protkey);
323fb1136d6SIngo Franzki 	default:
324fb1136d6SIngo Franzki 		DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n",
325fb1136d6SIngo Franzki 			  __func__, hdr->version);
326fb1136d6SIngo Franzki 		return -EINVAL;
327fb1136d6SIngo Franzki 	}
328fb1136d6SIngo Franzki }
329fb1136d6SIngo Franzki 
330fb1136d6SIngo Franzki /*
331fb1136d6SIngo Franzki  * Transform a CCA internal key token into a protected key
332fb1136d6SIngo Franzki  */
333183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen,
334fb1136d6SIngo Franzki 			       struct pkey_protkey *protkey)
335fb1136d6SIngo Franzki {
336fb1136d6SIngo Franzki 	struct keytoken_header *hdr = (struct keytoken_header *)key;
337fb1136d6SIngo Franzki 
338fb1136d6SIngo Franzki 	switch (hdr->version) {
339fb1136d6SIngo Franzki 	case TOKVER_CCA_AES:
340fb1136d6SIngo Franzki 		if (keylen != sizeof(struct secaeskeytoken))
341fb1136d6SIngo Franzki 			return -EINVAL;
342f2bbc96eSHarald Freudenberger 		break;
343f2bbc96eSHarald Freudenberger 	case TOKVER_CCA_VLSC:
344f2bbc96eSHarald Freudenberger 		if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
345f2bbc96eSHarald Freudenberger 			return -EINVAL;
346f2bbc96eSHarald Freudenberger 		break;
347fb1136d6SIngo Franzki 	default:
348fb1136d6SIngo Franzki 		DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n",
349fb1136d6SIngo Franzki 			  __func__, hdr->version);
350fb1136d6SIngo Franzki 		return -EINVAL;
351fb1136d6SIngo Franzki 	}
352f2bbc96eSHarald Freudenberger 
353f2bbc96eSHarald Freudenberger 	return pkey_skey2pkey(key, protkey);
354fb1136d6SIngo Franzki }
355fb1136d6SIngo Franzki 
356fb1136d6SIngo Franzki /*
357fb1136d6SIngo Franzki  * Transform a key blob (of any type) into a protected key
358fb1136d6SIngo Franzki  */
359183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen,
360fb1136d6SIngo Franzki 		      struct pkey_protkey *protkey)
361fb1136d6SIngo Franzki {
362f2bbc96eSHarald Freudenberger 	int rc;
363fb1136d6SIngo Franzki 	struct keytoken_header *hdr = (struct keytoken_header *)key;
364fb1136d6SIngo Franzki 
365f2bbc96eSHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header)) {
366f2bbc96eSHarald Freudenberger 		DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen);
367f2bbc96eSHarald Freudenberger 		return -EINVAL;
368f2bbc96eSHarald Freudenberger 	}
369f2bbc96eSHarald Freudenberger 
370f2bbc96eSHarald Freudenberger 	switch (hdr->type) {
371f2bbc96eSHarald Freudenberger 	case TOKTYPE_NON_CCA:
372f2bbc96eSHarald Freudenberger 		rc = pkey_nonccatok2pkey(key, keylen, protkey);
373f2bbc96eSHarald Freudenberger 		break;
374f2bbc96eSHarald Freudenberger 	case TOKTYPE_CCA_INTERNAL:
375f2bbc96eSHarald Freudenberger 		rc = pkey_ccainttok2pkey(key, keylen, protkey);
376f2bbc96eSHarald Freudenberger 		break;
377f2bbc96eSHarald Freudenberger 	default:
378f2bbc96eSHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported blob type %d\n",
379f2bbc96eSHarald Freudenberger 			  __func__, hdr->type);
380f2bbc96eSHarald Freudenberger 		return -EINVAL;
381f2bbc96eSHarald Freudenberger 	}
382f2bbc96eSHarald Freudenberger 
383f2bbc96eSHarald Freudenberger 	DEBUG_DBG("%s rc=%d\n", __func__, rc);
384f2bbc96eSHarald Freudenberger 	return rc;
385f2bbc96eSHarald Freudenberger 
386f2bbc96eSHarald Freudenberger }
387f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey);
388f2bbc96eSHarald Freudenberger 
389f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns,
390f2bbc96eSHarald Freudenberger 			   enum pkey_key_type ktype, enum pkey_key_size ksize,
391f2bbc96eSHarald Freudenberger 			   u32 kflags, u8 *keybuf, size_t *keybufsize)
392f2bbc96eSHarald Freudenberger {
393f2bbc96eSHarald Freudenberger 	int i, card, dom, rc;
394f2bbc96eSHarald Freudenberger 
395f2bbc96eSHarald Freudenberger 	/* check for at least one apqn given */
396f2bbc96eSHarald Freudenberger 	if (!apqns || !nr_apqns)
397f2bbc96eSHarald Freudenberger 		return -EINVAL;
398f2bbc96eSHarald Freudenberger 
399f2bbc96eSHarald Freudenberger 	/* check key type and size */
400f2bbc96eSHarald Freudenberger 	switch (ktype) {
401f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_DATA:
402f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_CIPHER:
403f2bbc96eSHarald Freudenberger 		if (*keybufsize < SECKEYBLOBSIZE)
404f2bbc96eSHarald Freudenberger 			return -EINVAL;
405f2bbc96eSHarald Freudenberger 		break;
406f2bbc96eSHarald Freudenberger 	default:
407f2bbc96eSHarald Freudenberger 		return -EINVAL;
408f2bbc96eSHarald Freudenberger 	}
409f2bbc96eSHarald Freudenberger 	switch (ksize) {
410f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_128:
411f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_192:
412f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_256:
413f2bbc96eSHarald Freudenberger 		break;
414f2bbc96eSHarald Freudenberger 	default:
415f2bbc96eSHarald Freudenberger 		return -EINVAL;
416f2bbc96eSHarald Freudenberger 	}
417f2bbc96eSHarald Freudenberger 
418f2bbc96eSHarald Freudenberger 	/* simple try all apqns from the list */
419f2bbc96eSHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
420f2bbc96eSHarald Freudenberger 		card = apqns[i].card;
421f2bbc96eSHarald Freudenberger 		dom = apqns[i].domain;
422f2bbc96eSHarald Freudenberger 		if (ktype == PKEY_TYPE_CCA_DATA) {
423f2bbc96eSHarald Freudenberger 			rc = cca_genseckey(card, dom, ksize, keybuf);
424f2bbc96eSHarald Freudenberger 			*keybufsize = (rc ? 0 : SECKEYBLOBSIZE);
425f2bbc96eSHarald Freudenberger 		} else /* TOKVER_CCA_VLSC */
426f2bbc96eSHarald Freudenberger 			rc = cca_gencipherkey(card, dom, ksize, kflags,
427f2bbc96eSHarald Freudenberger 					      keybuf, keybufsize);
428f2bbc96eSHarald Freudenberger 		if (rc == 0)
429f2bbc96eSHarald Freudenberger 			break;
430f2bbc96eSHarald Freudenberger 	}
431f2bbc96eSHarald Freudenberger 
432f2bbc96eSHarald Freudenberger 	return rc;
433f2bbc96eSHarald Freudenberger }
434f2bbc96eSHarald Freudenberger 
435f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns,
436f2bbc96eSHarald Freudenberger 			    enum pkey_key_type ktype, enum pkey_key_size ksize,
437f2bbc96eSHarald Freudenberger 			    u32 kflags, const u8 *clrkey,
438f2bbc96eSHarald Freudenberger 			    u8 *keybuf, size_t *keybufsize)
439f2bbc96eSHarald Freudenberger {
440f2bbc96eSHarald Freudenberger 	int i, card, dom, rc;
441f2bbc96eSHarald Freudenberger 
442f2bbc96eSHarald Freudenberger 	/* check for at least one apqn given */
443f2bbc96eSHarald Freudenberger 	if (!apqns || !nr_apqns)
444f2bbc96eSHarald Freudenberger 		return -EINVAL;
445f2bbc96eSHarald Freudenberger 
446f2bbc96eSHarald Freudenberger 	/* check key type and size */
447f2bbc96eSHarald Freudenberger 	switch (ktype) {
448f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_DATA:
449f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_CIPHER:
450f2bbc96eSHarald Freudenberger 		if (*keybufsize < SECKEYBLOBSIZE)
451f2bbc96eSHarald Freudenberger 			return -EINVAL;
452f2bbc96eSHarald Freudenberger 		break;
453f2bbc96eSHarald Freudenberger 	default:
454f2bbc96eSHarald Freudenberger 		return -EINVAL;
455f2bbc96eSHarald Freudenberger 	}
456f2bbc96eSHarald Freudenberger 	switch (ksize) {
457f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_128:
458f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_192:
459f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_256:
460f2bbc96eSHarald Freudenberger 		break;
461f2bbc96eSHarald Freudenberger 	default:
462f2bbc96eSHarald Freudenberger 		return -EINVAL;
463f2bbc96eSHarald Freudenberger 	}
464f2bbc96eSHarald Freudenberger 
465f2bbc96eSHarald Freudenberger 	/* simple try all apqns from the list */
466f2bbc96eSHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
467f2bbc96eSHarald Freudenberger 		card = apqns[i].card;
468f2bbc96eSHarald Freudenberger 		dom = apqns[i].domain;
469f2bbc96eSHarald Freudenberger 		if (ktype == PKEY_TYPE_CCA_DATA) {
470f2bbc96eSHarald Freudenberger 			rc = cca_clr2seckey(card, dom, ksize,
471f2bbc96eSHarald Freudenberger 					    clrkey, keybuf);
472f2bbc96eSHarald Freudenberger 			*keybufsize = (rc ? 0 : SECKEYBLOBSIZE);
473f2bbc96eSHarald Freudenberger 		} else /* TOKVER_CCA_VLSC */
474f2bbc96eSHarald Freudenberger 			rc = cca_clr2cipherkey(card, dom, ksize, kflags,
475f2bbc96eSHarald Freudenberger 					       clrkey, keybuf, keybufsize);
476f2bbc96eSHarald Freudenberger 		if (rc == 0)
477f2bbc96eSHarald Freudenberger 			break;
478f2bbc96eSHarald Freudenberger 	}
479f2bbc96eSHarald Freudenberger 
480f2bbc96eSHarald Freudenberger 	return rc;
481f2bbc96eSHarald Freudenberger }
482f2bbc96eSHarald Freudenberger 
483f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen,
484f2bbc96eSHarald Freudenberger 			   u16 *cardnr, u16 *domain,
485f2bbc96eSHarald Freudenberger 			   enum pkey_key_type *ktype,
486f2bbc96eSHarald Freudenberger 			   enum pkey_key_size *ksize, u32 *flags)
487f2bbc96eSHarald Freudenberger {
488f2bbc96eSHarald Freudenberger 	int rc;
489f2bbc96eSHarald Freudenberger 	u32 _nr_apqns, *_apqns = NULL;
490f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
491f2bbc96eSHarald Freudenberger 
492f2bbc96eSHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header) ||
493f2bbc96eSHarald Freudenberger 	    hdr->type != TOKTYPE_CCA_INTERNAL)
494f2bbc96eSHarald Freudenberger 		return -EINVAL;
495f2bbc96eSHarald Freudenberger 
496f2bbc96eSHarald Freudenberger 	if (hdr->version == TOKVER_CCA_AES) {
497f2bbc96eSHarald Freudenberger 		struct secaeskeytoken *t = (struct secaeskeytoken *)key;
498f2bbc96eSHarald Freudenberger 
499f2bbc96eSHarald Freudenberger 		rc = cca_check_secaeskeytoken(debug_info, 3, key, 0);
500f2bbc96eSHarald Freudenberger 		if (rc)
501f2bbc96eSHarald Freudenberger 			goto out;
502f2bbc96eSHarald Freudenberger 		if (ktype)
503f2bbc96eSHarald Freudenberger 			*ktype = PKEY_TYPE_CCA_DATA;
504f2bbc96eSHarald Freudenberger 		if (ksize)
505f2bbc96eSHarald Freudenberger 			*ksize = (enum pkey_key_size) t->bitsize;
506f2bbc96eSHarald Freudenberger 
507f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
508f2bbc96eSHarald Freudenberger 				   ZCRYPT_CEX3C, t->mkvp, 0, 1);
509f2bbc96eSHarald Freudenberger 		if (rc == 0 && flags)
510f2bbc96eSHarald Freudenberger 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
511f2bbc96eSHarald Freudenberger 		if (rc == -ENODEV) {
512f2bbc96eSHarald Freudenberger 			rc = cca_findcard2(&_apqns, &_nr_apqns,
513f2bbc96eSHarald Freudenberger 					   *cardnr, *domain,
514f2bbc96eSHarald Freudenberger 					   ZCRYPT_CEX3C, 0, t->mkvp, 1);
515f2bbc96eSHarald Freudenberger 			if (rc == 0 && flags)
516f2bbc96eSHarald Freudenberger 				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
517f2bbc96eSHarald Freudenberger 		}
518f2bbc96eSHarald Freudenberger 		if (rc)
519f2bbc96eSHarald Freudenberger 			goto out;
520f2bbc96eSHarald Freudenberger 
521f2bbc96eSHarald Freudenberger 		*cardnr = ((struct pkey_apqn *)_apqns)->card;
522f2bbc96eSHarald Freudenberger 		*domain = ((struct pkey_apqn *)_apqns)->domain;
523f2bbc96eSHarald Freudenberger 
524f2bbc96eSHarald Freudenberger 	} else if (hdr->version == TOKVER_CCA_VLSC) {
525f2bbc96eSHarald Freudenberger 		struct cipherkeytoken *t = (struct cipherkeytoken *)key;
526f2bbc96eSHarald Freudenberger 
527f2bbc96eSHarald Freudenberger 		rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1);
528f2bbc96eSHarald Freudenberger 		if (rc)
529f2bbc96eSHarald Freudenberger 			goto out;
530f2bbc96eSHarald Freudenberger 		if (ktype)
531f2bbc96eSHarald Freudenberger 			*ktype = PKEY_TYPE_CCA_CIPHER;
532f2bbc96eSHarald Freudenberger 		if (ksize) {
533f2bbc96eSHarald Freudenberger 			*ksize = PKEY_SIZE_UNKNOWN;
534f2bbc96eSHarald Freudenberger 			if (!t->plfver && t->wpllen == 512)
535f2bbc96eSHarald Freudenberger 				*ksize = PKEY_SIZE_AES_128;
536f2bbc96eSHarald Freudenberger 			else if (!t->plfver && t->wpllen == 576)
537f2bbc96eSHarald Freudenberger 				*ksize = PKEY_SIZE_AES_192;
538f2bbc96eSHarald Freudenberger 			else if (!t->plfver && t->wpllen == 640)
539f2bbc96eSHarald Freudenberger 				*ksize = PKEY_SIZE_AES_256;
540f2bbc96eSHarald Freudenberger 		}
541f2bbc96eSHarald Freudenberger 
542f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
543f2bbc96eSHarald Freudenberger 				   ZCRYPT_CEX6, t->mkvp0, 0, 1);
544f2bbc96eSHarald Freudenberger 		if (rc == 0 && flags)
545f2bbc96eSHarald Freudenberger 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
546f2bbc96eSHarald Freudenberger 		if (rc == -ENODEV) {
547f2bbc96eSHarald Freudenberger 			rc = cca_findcard2(&_apqns, &_nr_apqns,
548f2bbc96eSHarald Freudenberger 					   *cardnr, *domain,
549f2bbc96eSHarald Freudenberger 					   ZCRYPT_CEX6, 0, t->mkvp0, 1);
550f2bbc96eSHarald Freudenberger 			if (rc == 0 && flags)
551f2bbc96eSHarald Freudenberger 				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
552f2bbc96eSHarald Freudenberger 		}
553f2bbc96eSHarald Freudenberger 		if (rc)
554f2bbc96eSHarald Freudenberger 			goto out;
555f2bbc96eSHarald Freudenberger 
556f2bbc96eSHarald Freudenberger 		*cardnr = ((struct pkey_apqn *)_apqns)->card;
557f2bbc96eSHarald Freudenberger 		*domain = ((struct pkey_apqn *)_apqns)->domain;
558f2bbc96eSHarald Freudenberger 
559f2bbc96eSHarald Freudenberger 	} else
560f2bbc96eSHarald Freudenberger 		rc = -EINVAL;
561f2bbc96eSHarald Freudenberger 
562f2bbc96eSHarald Freudenberger out:
563f2bbc96eSHarald Freudenberger 	kfree(_apqns);
564f2bbc96eSHarald Freudenberger 	return rc;
565f2bbc96eSHarald Freudenberger }
566f2bbc96eSHarald Freudenberger 
567f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns,
568f2bbc96eSHarald Freudenberger 			      const u8 *key, size_t keylen,
569f2bbc96eSHarald Freudenberger 			      struct pkey_protkey *pkey)
570f2bbc96eSHarald Freudenberger {
571f2bbc96eSHarald Freudenberger 	int i, card, dom, rc;
572f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
573f2bbc96eSHarald Freudenberger 
574f2bbc96eSHarald Freudenberger 	/* check for at least one apqn given */
575f2bbc96eSHarald Freudenberger 	if (!apqns || !nr_apqns)
576f2bbc96eSHarald Freudenberger 		return -EINVAL;
577f2bbc96eSHarald Freudenberger 
578fb1136d6SIngo Franzki 	if (keylen < sizeof(struct keytoken_header))
579fb1136d6SIngo Franzki 		return -EINVAL;
580fb1136d6SIngo Franzki 
581fb1136d6SIngo Franzki 	switch (hdr->type) {
582fb1136d6SIngo Franzki 	case TOKTYPE_NON_CCA:
583f2bbc96eSHarald Freudenberger 		return pkey_nonccatok2pkey(key, keylen, pkey);
584fb1136d6SIngo Franzki 	case TOKTYPE_CCA_INTERNAL:
585f2bbc96eSHarald Freudenberger 		switch (hdr->version) {
586f2bbc96eSHarald Freudenberger 		case TOKVER_CCA_AES:
587f2bbc96eSHarald Freudenberger 			if (keylen != sizeof(struct secaeskeytoken))
588f2bbc96eSHarald Freudenberger 				return -EINVAL;
589f2bbc96eSHarald Freudenberger 			if (cca_check_secaeskeytoken(debug_info, 3, key, 0))
590f2bbc96eSHarald Freudenberger 				return -EINVAL;
591f2bbc96eSHarald Freudenberger 			break;
592f2bbc96eSHarald Freudenberger 		case TOKVER_CCA_VLSC:
593f2bbc96eSHarald Freudenberger 			if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
594f2bbc96eSHarald Freudenberger 				return -EINVAL;
595f2bbc96eSHarald Freudenberger 			if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1))
596f2bbc96eSHarald Freudenberger 				return -EINVAL;
597f2bbc96eSHarald Freudenberger 			break;
598fb1136d6SIngo Franzki 		default:
599f2bbc96eSHarald Freudenberger 			DEBUG_ERR("%s unknown CCA internal token version %d\n",
600f2bbc96eSHarald Freudenberger 				  __func__, hdr->version);
601fb1136d6SIngo Franzki 			return -EINVAL;
602fb1136d6SIngo Franzki 		}
603f2bbc96eSHarald Freudenberger 		break;
604f2bbc96eSHarald Freudenberger 	default:
605f2bbc96eSHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported blob type %d\n",
606f2bbc96eSHarald Freudenberger 			  __func__, hdr->type);
607f2bbc96eSHarald Freudenberger 		return -EINVAL;
608fb1136d6SIngo Franzki 	}
609f2bbc96eSHarald Freudenberger 
610f2bbc96eSHarald Freudenberger 	/* simple try all apqns from the list */
611f2bbc96eSHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
612f2bbc96eSHarald Freudenberger 		card = apqns[i].card;
613f2bbc96eSHarald Freudenberger 		dom = apqns[i].domain;
614f2bbc96eSHarald Freudenberger 		if (hdr->version == TOKVER_CCA_AES)
615f2bbc96eSHarald Freudenberger 			rc = cca_sec2protkey(card, dom, key, pkey->protkey,
616f2bbc96eSHarald Freudenberger 					     &pkey->len, &pkey->type);
617f2bbc96eSHarald Freudenberger 		else /* TOKVER_CCA_VLSC */
618f2bbc96eSHarald Freudenberger 			rc = cca_cipher2protkey(card, dom, key, pkey->protkey,
619f2bbc96eSHarald Freudenberger 						&pkey->len, &pkey->type);
620f2bbc96eSHarald Freudenberger 		if (rc == 0)
621f2bbc96eSHarald Freudenberger 			break;
622f2bbc96eSHarald Freudenberger 	}
623f2bbc96eSHarald Freudenberger 
624f2bbc96eSHarald Freudenberger 	return rc;
625f2bbc96eSHarald Freudenberger }
626f2bbc96eSHarald Freudenberger 
627f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
628f2bbc96eSHarald Freudenberger 			  struct pkey_apqn *apqns, size_t *nr_apqns)
629f2bbc96eSHarald Freudenberger {
630f2bbc96eSHarald Freudenberger 	int rc = EINVAL;
631f2bbc96eSHarald Freudenberger 	u32 _nr_apqns, *_apqns = NULL;
632f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
633f2bbc96eSHarald Freudenberger 
634f2bbc96eSHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header) ||
635f2bbc96eSHarald Freudenberger 	    hdr->type != TOKTYPE_CCA_INTERNAL ||
636f2bbc96eSHarald Freudenberger 	    flags == 0)
637f2bbc96eSHarald Freudenberger 		return -EINVAL;
638f2bbc96eSHarald Freudenberger 
639f2bbc96eSHarald Freudenberger 	if (hdr->version == TOKVER_CCA_AES || hdr->version == TOKVER_CCA_VLSC) {
640f2bbc96eSHarald Freudenberger 		int minhwtype = ZCRYPT_CEX3C;
641f2bbc96eSHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
642f2bbc96eSHarald Freudenberger 
643f2bbc96eSHarald Freudenberger 		if (hdr->version == TOKVER_CCA_AES) {
644f2bbc96eSHarald Freudenberger 			struct secaeskeytoken *t = (struct secaeskeytoken *)key;
645f2bbc96eSHarald Freudenberger 
646f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
647f2bbc96eSHarald Freudenberger 				cur_mkvp = t->mkvp;
648f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
649f2bbc96eSHarald Freudenberger 				old_mkvp = t->mkvp;
650f2bbc96eSHarald Freudenberger 		} else {
651f2bbc96eSHarald Freudenberger 			struct cipherkeytoken *t = (struct cipherkeytoken *)key;
652f2bbc96eSHarald Freudenberger 
653f2bbc96eSHarald Freudenberger 			minhwtype = ZCRYPT_CEX6;
654f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
655f2bbc96eSHarald Freudenberger 				cur_mkvp = t->mkvp0;
656f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
657f2bbc96eSHarald Freudenberger 				old_mkvp = t->mkvp0;
658f2bbc96eSHarald Freudenberger 		}
659f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
660f2bbc96eSHarald Freudenberger 				   minhwtype, cur_mkvp, old_mkvp, 1);
661f2bbc96eSHarald Freudenberger 		if (rc)
662f2bbc96eSHarald Freudenberger 			goto out;
663f2bbc96eSHarald Freudenberger 		if (apqns) {
664f2bbc96eSHarald Freudenberger 			if (*nr_apqns < _nr_apqns)
665f2bbc96eSHarald Freudenberger 				rc = -ENOSPC;
666f2bbc96eSHarald Freudenberger 			else
667f2bbc96eSHarald Freudenberger 				memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
668f2bbc96eSHarald Freudenberger 		}
669f2bbc96eSHarald Freudenberger 		*nr_apqns = _nr_apqns;
670f2bbc96eSHarald Freudenberger 	}
671f2bbc96eSHarald Freudenberger 
672f2bbc96eSHarald Freudenberger out:
673f2bbc96eSHarald Freudenberger 	kfree(_apqns);
674f2bbc96eSHarald Freudenberger 	return rc;
675f2bbc96eSHarald Freudenberger }
676f2bbc96eSHarald Freudenberger 
677f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype,
678f2bbc96eSHarald Freudenberger 			      u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
679f2bbc96eSHarald Freudenberger 			      struct pkey_apqn *apqns, size_t *nr_apqns)
680f2bbc96eSHarald Freudenberger {
681f2bbc96eSHarald Freudenberger 	int rc = -EINVAL;
682f2bbc96eSHarald Freudenberger 	u32 _nr_apqns, *_apqns = NULL;
683f2bbc96eSHarald Freudenberger 
684f2bbc96eSHarald Freudenberger 	if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) {
685f2bbc96eSHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
686f2bbc96eSHarald Freudenberger 		int minhwtype = ZCRYPT_CEX3C;
687f2bbc96eSHarald Freudenberger 
688f2bbc96eSHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
689f2bbc96eSHarald Freudenberger 			cur_mkvp = *((u64 *) cur_mkvp);
690f2bbc96eSHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
691f2bbc96eSHarald Freudenberger 			old_mkvp = *((u64 *) alt_mkvp);
692f2bbc96eSHarald Freudenberger 		if (ktype == PKEY_TYPE_CCA_CIPHER)
693f2bbc96eSHarald Freudenberger 			minhwtype = ZCRYPT_CEX6;
694f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
695f2bbc96eSHarald Freudenberger 				   minhwtype, cur_mkvp, old_mkvp, 1);
696f2bbc96eSHarald Freudenberger 		if (rc)
697f2bbc96eSHarald Freudenberger 			goto out;
698f2bbc96eSHarald Freudenberger 		if (apqns) {
699f2bbc96eSHarald Freudenberger 			if (*nr_apqns < _nr_apqns)
700f2bbc96eSHarald Freudenberger 				rc = -ENOSPC;
701f2bbc96eSHarald Freudenberger 			else
702f2bbc96eSHarald Freudenberger 				memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
703f2bbc96eSHarald Freudenberger 		}
704f2bbc96eSHarald Freudenberger 		*nr_apqns = _nr_apqns;
705f2bbc96eSHarald Freudenberger 	}
706f2bbc96eSHarald Freudenberger 
707f2bbc96eSHarald Freudenberger out:
708f2bbc96eSHarald Freudenberger 	kfree(_apqns);
709f2bbc96eSHarald Freudenberger 	return rc;
710f2bbc96eSHarald Freudenberger }
711fb1136d6SIngo Franzki 
712fb1136d6SIngo Franzki /*
713e80d4af0SHarald Freudenberger  * File io functions
714e80d4af0SHarald Freudenberger  */
715e80d4af0SHarald Freudenberger 
716f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen)
717f2bbc96eSHarald Freudenberger {
718f2bbc96eSHarald Freudenberger 	if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE)
719f2bbc96eSHarald Freudenberger 		return ERR_PTR(-EINVAL);
720f2bbc96eSHarald Freudenberger 
721*8b57e7c8SMarkus Elfring 	return memdup_user(ukey, keylen);
722f2bbc96eSHarald Freudenberger }
723f2bbc96eSHarald Freudenberger 
724f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns)
725f2bbc96eSHarald Freudenberger {
726*8b57e7c8SMarkus Elfring 	if (!uapqns || nr_apqns == 0)
727*8b57e7c8SMarkus Elfring 		return NULL;
728f2bbc96eSHarald Freudenberger 
729*8b57e7c8SMarkus Elfring 	return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn));
730f2bbc96eSHarald Freudenberger }
731f2bbc96eSHarald Freudenberger 
732e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
733e80d4af0SHarald Freudenberger 				unsigned long arg)
734e80d4af0SHarald Freudenberger {
735e80d4af0SHarald Freudenberger 	int rc;
736e80d4af0SHarald Freudenberger 
737e80d4af0SHarald Freudenberger 	switch (cmd) {
738e80d4af0SHarald Freudenberger 	case PKEY_GENSECK: {
739e80d4af0SHarald Freudenberger 		struct pkey_genseck __user *ugs = (void __user *) arg;
740e80d4af0SHarald Freudenberger 		struct pkey_genseck kgs;
741e80d4af0SHarald Freudenberger 
742e80d4af0SHarald Freudenberger 		if (copy_from_user(&kgs, ugs, sizeof(kgs)))
743e80d4af0SHarald Freudenberger 			return -EFAULT;
744efc598e6SHarald Freudenberger 		rc = cca_genseckey(kgs.cardnr, kgs.domain,
745efc598e6SHarald Freudenberger 				   kgs.keytype, kgs.seckey.seckey);
746efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc);
747e80d4af0SHarald Freudenberger 		if (rc)
748e80d4af0SHarald Freudenberger 			break;
749e80d4af0SHarald Freudenberger 		if (copy_to_user(ugs, &kgs, sizeof(kgs)))
750e80d4af0SHarald Freudenberger 			return -EFAULT;
751e80d4af0SHarald Freudenberger 		break;
752e80d4af0SHarald Freudenberger 	}
753e80d4af0SHarald Freudenberger 	case PKEY_CLR2SECK: {
754e80d4af0SHarald Freudenberger 		struct pkey_clr2seck __user *ucs = (void __user *) arg;
755e80d4af0SHarald Freudenberger 		struct pkey_clr2seck kcs;
756e80d4af0SHarald Freudenberger 
757e80d4af0SHarald Freudenberger 		if (copy_from_user(&kcs, ucs, sizeof(kcs)))
758e80d4af0SHarald Freudenberger 			return -EFAULT;
759efc598e6SHarald Freudenberger 		rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype,
760efc598e6SHarald Freudenberger 				    kcs.clrkey.clrkey, kcs.seckey.seckey);
761efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc);
762e80d4af0SHarald Freudenberger 		if (rc)
763e80d4af0SHarald Freudenberger 			break;
764e80d4af0SHarald Freudenberger 		if (copy_to_user(ucs, &kcs, sizeof(kcs)))
765e80d4af0SHarald Freudenberger 			return -EFAULT;
766e80d4af0SHarald Freudenberger 		memzero_explicit(&kcs, sizeof(kcs));
767e80d4af0SHarald Freudenberger 		break;
768e80d4af0SHarald Freudenberger 	}
769e80d4af0SHarald Freudenberger 	case PKEY_SEC2PROTK: {
770e80d4af0SHarald Freudenberger 		struct pkey_sec2protk __user *usp = (void __user *) arg;
771e80d4af0SHarald Freudenberger 		struct pkey_sec2protk ksp;
772e80d4af0SHarald Freudenberger 
773e80d4af0SHarald Freudenberger 		if (copy_from_user(&ksp, usp, sizeof(ksp)))
774e80d4af0SHarald Freudenberger 			return -EFAULT;
775efc598e6SHarald Freudenberger 		rc = cca_sec2protkey(ksp.cardnr, ksp.domain,
776efc598e6SHarald Freudenberger 				     ksp.seckey.seckey, ksp.protkey.protkey,
777efc598e6SHarald Freudenberger 				     NULL, &ksp.protkey.type);
778efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc);
779e80d4af0SHarald Freudenberger 		if (rc)
780e80d4af0SHarald Freudenberger 			break;
781e80d4af0SHarald Freudenberger 		if (copy_to_user(usp, &ksp, sizeof(ksp)))
782e80d4af0SHarald Freudenberger 			return -EFAULT;
783e80d4af0SHarald Freudenberger 		break;
784e80d4af0SHarald Freudenberger 	}
785e80d4af0SHarald Freudenberger 	case PKEY_CLR2PROTK: {
786e80d4af0SHarald Freudenberger 		struct pkey_clr2protk __user *ucp = (void __user *) arg;
787e80d4af0SHarald Freudenberger 		struct pkey_clr2protk kcp;
788e80d4af0SHarald Freudenberger 
789e80d4af0SHarald Freudenberger 		if (copy_from_user(&kcp, ucp, sizeof(kcp)))
790e80d4af0SHarald Freudenberger 			return -EFAULT;
791e80d4af0SHarald Freudenberger 		rc = pkey_clr2protkey(kcp.keytype,
792e80d4af0SHarald Freudenberger 				      &kcp.clrkey, &kcp.protkey);
793ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc);
794e80d4af0SHarald Freudenberger 		if (rc)
795e80d4af0SHarald Freudenberger 			break;
796e80d4af0SHarald Freudenberger 		if (copy_to_user(ucp, &kcp, sizeof(kcp)))
797e80d4af0SHarald Freudenberger 			return -EFAULT;
798e80d4af0SHarald Freudenberger 		memzero_explicit(&kcp, sizeof(kcp));
799e80d4af0SHarald Freudenberger 		break;
800e80d4af0SHarald Freudenberger 	}
801e80d4af0SHarald Freudenberger 	case PKEY_FINDCARD: {
802e80d4af0SHarald Freudenberger 		struct pkey_findcard __user *ufc = (void __user *) arg;
803e80d4af0SHarald Freudenberger 		struct pkey_findcard kfc;
804e80d4af0SHarald Freudenberger 
805e80d4af0SHarald Freudenberger 		if (copy_from_user(&kfc, ufc, sizeof(kfc)))
806e80d4af0SHarald Freudenberger 			return -EFAULT;
807efc598e6SHarald Freudenberger 		rc = cca_findcard(kfc.seckey.seckey,
808e80d4af0SHarald Freudenberger 				  &kfc.cardnr, &kfc.domain, 1);
809efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc);
810efc598e6SHarald Freudenberger 		if (rc < 0)
811e80d4af0SHarald Freudenberger 			break;
812e80d4af0SHarald Freudenberger 		if (copy_to_user(ufc, &kfc, sizeof(kfc)))
813e80d4af0SHarald Freudenberger 			return -EFAULT;
814e80d4af0SHarald Freudenberger 		break;
815e80d4af0SHarald Freudenberger 	}
816e80d4af0SHarald Freudenberger 	case PKEY_SKEY2PKEY: {
817e80d4af0SHarald Freudenberger 		struct pkey_skey2pkey __user *usp = (void __user *) arg;
818e80d4af0SHarald Freudenberger 		struct pkey_skey2pkey ksp;
819e80d4af0SHarald Freudenberger 
820e80d4af0SHarald Freudenberger 		if (copy_from_user(&ksp, usp, sizeof(ksp)))
821e80d4af0SHarald Freudenberger 			return -EFAULT;
822f2bbc96eSHarald Freudenberger 		rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey);
823ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc);
824e80d4af0SHarald Freudenberger 		if (rc)
825e80d4af0SHarald Freudenberger 			break;
826e80d4af0SHarald Freudenberger 		if (copy_to_user(usp, &ksp, sizeof(ksp)))
827e80d4af0SHarald Freudenberger 			return -EFAULT;
828e80d4af0SHarald Freudenberger 		break;
829e80d4af0SHarald Freudenberger 	}
830e61a6134SHarald Freudenberger 	case PKEY_VERIFYKEY: {
831e61a6134SHarald Freudenberger 		struct pkey_verifykey __user *uvk = (void __user *) arg;
832e61a6134SHarald Freudenberger 		struct pkey_verifykey kvk;
833e61a6134SHarald Freudenberger 
834e61a6134SHarald Freudenberger 		if (copy_from_user(&kvk, uvk, sizeof(kvk)))
835e61a6134SHarald Freudenberger 			return -EFAULT;
836e61a6134SHarald Freudenberger 		rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain,
837e61a6134SHarald Freudenberger 				    &kvk.keysize, &kvk.attributes);
838ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc);
839e61a6134SHarald Freudenberger 		if (rc)
840e61a6134SHarald Freudenberger 			break;
841e61a6134SHarald Freudenberger 		if (copy_to_user(uvk, &kvk, sizeof(kvk)))
842e61a6134SHarald Freudenberger 			return -EFAULT;
843e61a6134SHarald Freudenberger 		break;
844e61a6134SHarald Freudenberger 	}
845a45a5c7dSIngo Franzki 	case PKEY_GENPROTK: {
846a45a5c7dSIngo Franzki 		struct pkey_genprotk __user *ugp = (void __user *) arg;
847a45a5c7dSIngo Franzki 		struct pkey_genprotk kgp;
848a45a5c7dSIngo Franzki 
849a45a5c7dSIngo Franzki 		if (copy_from_user(&kgp, ugp, sizeof(kgp)))
850a45a5c7dSIngo Franzki 			return -EFAULT;
851a45a5c7dSIngo Franzki 		rc = pkey_genprotkey(kgp.keytype, &kgp.protkey);
852a45a5c7dSIngo Franzki 		DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc);
853a45a5c7dSIngo Franzki 		if (rc)
854a45a5c7dSIngo Franzki 			break;
855a45a5c7dSIngo Franzki 		if (copy_to_user(ugp, &kgp, sizeof(kgp)))
856a45a5c7dSIngo Franzki 			return -EFAULT;
857a45a5c7dSIngo Franzki 		break;
858a45a5c7dSIngo Franzki 	}
859cb26b9ffSIngo Franzki 	case PKEY_VERIFYPROTK: {
860cb26b9ffSIngo Franzki 		struct pkey_verifyprotk __user *uvp = (void __user *) arg;
861cb26b9ffSIngo Franzki 		struct pkey_verifyprotk kvp;
862cb26b9ffSIngo Franzki 
863cb26b9ffSIngo Franzki 		if (copy_from_user(&kvp, uvp, sizeof(kvp)))
864cb26b9ffSIngo Franzki 			return -EFAULT;
865cb26b9ffSIngo Franzki 		rc = pkey_verifyprotkey(&kvp.protkey);
866cb26b9ffSIngo Franzki 		DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc);
867cb26b9ffSIngo Franzki 		break;
868cb26b9ffSIngo Franzki 	}
869fb1136d6SIngo Franzki 	case PKEY_KBLOB2PROTK: {
870fb1136d6SIngo Franzki 		struct pkey_kblob2pkey __user *utp = (void __user *) arg;
871fb1136d6SIngo Franzki 		struct pkey_kblob2pkey ktp;
872183cb469SHarald Freudenberger 		u8 *kkey;
873fb1136d6SIngo Franzki 
874fb1136d6SIngo Franzki 		if (copy_from_user(&ktp, utp, sizeof(ktp)))
875fb1136d6SIngo Franzki 			return -EFAULT;
876f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(ktp.key, ktp.keylen);
877f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey))
878f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
879fb1136d6SIngo Franzki 		rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey);
880fb1136d6SIngo Franzki 		DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc);
881fb1136d6SIngo Franzki 		kfree(kkey);
882fb1136d6SIngo Franzki 		if (rc)
883fb1136d6SIngo Franzki 			break;
884fb1136d6SIngo Franzki 		if (copy_to_user(utp, &ktp, sizeof(ktp)))
885fb1136d6SIngo Franzki 			return -EFAULT;
886fb1136d6SIngo Franzki 		break;
887fb1136d6SIngo Franzki 	}
888f2bbc96eSHarald Freudenberger 	case PKEY_GENSECK2: {
889f2bbc96eSHarald Freudenberger 		struct pkey_genseck2 __user *ugs = (void __user *) arg;
890f2bbc96eSHarald Freudenberger 		struct pkey_genseck2 kgs;
891f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns;
892f2bbc96eSHarald Freudenberger 		size_t klen = KEYBLOBBUFSIZE;
893f2bbc96eSHarald Freudenberger 		u8 *kkey;
894f2bbc96eSHarald Freudenberger 
895f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kgs, ugs, sizeof(kgs)))
896f2bbc96eSHarald Freudenberger 			return -EFAULT;
897f2bbc96eSHarald Freudenberger 		apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries);
898f2bbc96eSHarald Freudenberger 		if (IS_ERR(apqns))
899f2bbc96eSHarald Freudenberger 			return PTR_ERR(apqns);
900f2bbc96eSHarald Freudenberger 		kkey = kmalloc(klen, GFP_KERNEL);
901f2bbc96eSHarald Freudenberger 		if (!kkey) {
902f2bbc96eSHarald Freudenberger 			kfree(apqns);
903f2bbc96eSHarald Freudenberger 			return -ENOMEM;
904f2bbc96eSHarald Freudenberger 		}
905f2bbc96eSHarald Freudenberger 		rc = pkey_genseckey2(apqns, kgs.apqn_entries,
906f2bbc96eSHarald Freudenberger 				     kgs.type, kgs.size, kgs.keygenflags,
907f2bbc96eSHarald Freudenberger 				     kkey, &klen);
908f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc);
909f2bbc96eSHarald Freudenberger 		kfree(apqns);
910f2bbc96eSHarald Freudenberger 		if (rc) {
911f2bbc96eSHarald Freudenberger 			kfree(kkey);
912f2bbc96eSHarald Freudenberger 			break;
913f2bbc96eSHarald Freudenberger 		}
914f2bbc96eSHarald Freudenberger 		if (kgs.key) {
915f2bbc96eSHarald Freudenberger 			if (kgs.keylen < klen) {
916f2bbc96eSHarald Freudenberger 				kfree(kkey);
917f2bbc96eSHarald Freudenberger 				return -EINVAL;
918f2bbc96eSHarald Freudenberger 			}
919f2bbc96eSHarald Freudenberger 			if (copy_to_user(kgs.key, kkey, klen)) {
920f2bbc96eSHarald Freudenberger 				kfree(kkey);
921f2bbc96eSHarald Freudenberger 				return -EFAULT;
922f2bbc96eSHarald Freudenberger 			}
923f2bbc96eSHarald Freudenberger 		}
924f2bbc96eSHarald Freudenberger 		kgs.keylen = klen;
925f2bbc96eSHarald Freudenberger 		if (copy_to_user(ugs, &kgs, sizeof(kgs)))
926f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
927f2bbc96eSHarald Freudenberger 		kfree(kkey);
928f2bbc96eSHarald Freudenberger 		break;
929f2bbc96eSHarald Freudenberger 	}
930f2bbc96eSHarald Freudenberger 	case PKEY_CLR2SECK2: {
931f2bbc96eSHarald Freudenberger 		struct pkey_clr2seck2 __user *ucs = (void __user *) arg;
932f2bbc96eSHarald Freudenberger 		struct pkey_clr2seck2 kcs;
933f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns;
934f2bbc96eSHarald Freudenberger 		size_t klen = KEYBLOBBUFSIZE;
935f2bbc96eSHarald Freudenberger 		u8 *kkey;
936f2bbc96eSHarald Freudenberger 
937f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kcs, ucs, sizeof(kcs)))
938f2bbc96eSHarald Freudenberger 			return -EFAULT;
939f2bbc96eSHarald Freudenberger 		apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries);
940f2bbc96eSHarald Freudenberger 		if (IS_ERR(apqns))
941f2bbc96eSHarald Freudenberger 			return PTR_ERR(apqns);
942f2bbc96eSHarald Freudenberger 		kkey = kmalloc(klen, GFP_KERNEL);
943f2bbc96eSHarald Freudenberger 		if (!kkey) {
944f2bbc96eSHarald Freudenberger 			kfree(apqns);
945f2bbc96eSHarald Freudenberger 			return -ENOMEM;
946f2bbc96eSHarald Freudenberger 		}
947f2bbc96eSHarald Freudenberger 		rc = pkey_clr2seckey2(apqns, kcs.apqn_entries,
948f2bbc96eSHarald Freudenberger 				      kcs.type, kcs.size, kcs.keygenflags,
949f2bbc96eSHarald Freudenberger 				      kcs.clrkey.clrkey, kkey, &klen);
950f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc);
951f2bbc96eSHarald Freudenberger 		kfree(apqns);
952f2bbc96eSHarald Freudenberger 		if (rc) {
953f2bbc96eSHarald Freudenberger 			kfree(kkey);
954f2bbc96eSHarald Freudenberger 			break;
955f2bbc96eSHarald Freudenberger 		}
956f2bbc96eSHarald Freudenberger 		if (kcs.key) {
957f2bbc96eSHarald Freudenberger 			if (kcs.keylen < klen) {
958f2bbc96eSHarald Freudenberger 				kfree(kkey);
959f2bbc96eSHarald Freudenberger 				return -EINVAL;
960f2bbc96eSHarald Freudenberger 			}
961f2bbc96eSHarald Freudenberger 			if (copy_to_user(kcs.key, kkey, klen)) {
962f2bbc96eSHarald Freudenberger 				kfree(kkey);
963f2bbc96eSHarald Freudenberger 				return -EFAULT;
964f2bbc96eSHarald Freudenberger 			}
965f2bbc96eSHarald Freudenberger 		}
966f2bbc96eSHarald Freudenberger 		kcs.keylen = klen;
967f2bbc96eSHarald Freudenberger 		if (copy_to_user(ucs, &kcs, sizeof(kcs)))
968f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
969f2bbc96eSHarald Freudenberger 		memzero_explicit(&kcs, sizeof(kcs));
970f2bbc96eSHarald Freudenberger 		kfree(kkey);
971f2bbc96eSHarald Freudenberger 		break;
972f2bbc96eSHarald Freudenberger 	}
973f2bbc96eSHarald Freudenberger 	case PKEY_VERIFYKEY2: {
974f2bbc96eSHarald Freudenberger 		struct pkey_verifykey2 __user *uvk = (void __user *) arg;
975f2bbc96eSHarald Freudenberger 		struct pkey_verifykey2 kvk;
976f2bbc96eSHarald Freudenberger 		u8 *kkey;
977f2bbc96eSHarald Freudenberger 
978f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kvk, uvk, sizeof(kvk)))
979f2bbc96eSHarald Freudenberger 			return -EFAULT;
980f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(kvk.key, kvk.keylen);
981f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey))
982f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
983f2bbc96eSHarald Freudenberger 		rc = pkey_verifykey2(kkey, kvk.keylen,
984f2bbc96eSHarald Freudenberger 				     &kvk.cardnr, &kvk.domain,
985f2bbc96eSHarald Freudenberger 				     &kvk.type, &kvk.size, &kvk.flags);
986f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc);
987f2bbc96eSHarald Freudenberger 		kfree(kkey);
988f2bbc96eSHarald Freudenberger 		if (rc)
989f2bbc96eSHarald Freudenberger 			break;
990f2bbc96eSHarald Freudenberger 		if (copy_to_user(uvk, &kvk, sizeof(kvk)))
991f2bbc96eSHarald Freudenberger 			return -EFAULT;
992f2bbc96eSHarald Freudenberger 		break;
993f2bbc96eSHarald Freudenberger 	}
994f2bbc96eSHarald Freudenberger 	case PKEY_KBLOB2PROTK2: {
995f2bbc96eSHarald Freudenberger 		struct pkey_kblob2pkey2 __user *utp = (void __user *) arg;
996f2bbc96eSHarald Freudenberger 		struct pkey_kblob2pkey2 ktp;
997f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns = NULL;
998f2bbc96eSHarald Freudenberger 		u8 *kkey;
999f2bbc96eSHarald Freudenberger 
1000f2bbc96eSHarald Freudenberger 		if (copy_from_user(&ktp, utp, sizeof(ktp)))
1001f2bbc96eSHarald Freudenberger 			return -EFAULT;
1002f2bbc96eSHarald Freudenberger 		apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);
1003f2bbc96eSHarald Freudenberger 		if (IS_ERR(apqns))
1004f2bbc96eSHarald Freudenberger 			return PTR_ERR(apqns);
1005f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(ktp.key, ktp.keylen);
1006f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey)) {
1007f2bbc96eSHarald Freudenberger 			kfree(apqns);
1008f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
1009f2bbc96eSHarald Freudenberger 		}
1010f2bbc96eSHarald Freudenberger 		rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries,
1011f2bbc96eSHarald Freudenberger 					kkey, ktp.keylen, &ktp.protkey);
1012f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc);
1013f2bbc96eSHarald Freudenberger 		kfree(apqns);
1014f2bbc96eSHarald Freudenberger 		kfree(kkey);
1015f2bbc96eSHarald Freudenberger 		if (rc)
1016f2bbc96eSHarald Freudenberger 			break;
1017f2bbc96eSHarald Freudenberger 		if (copy_to_user(utp, &ktp, sizeof(ktp)))
1018f2bbc96eSHarald Freudenberger 			return -EFAULT;
1019f2bbc96eSHarald Freudenberger 		break;
1020f2bbc96eSHarald Freudenberger 	}
1021f2bbc96eSHarald Freudenberger 	case PKEY_APQNS4K: {
1022f2bbc96eSHarald Freudenberger 		struct pkey_apqns4key __user *uak = (void __user *) arg;
1023f2bbc96eSHarald Freudenberger 		struct pkey_apqns4key kak;
1024f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns = NULL;
1025f2bbc96eSHarald Freudenberger 		size_t nr_apqns, len;
1026f2bbc96eSHarald Freudenberger 		u8 *kkey;
1027f2bbc96eSHarald Freudenberger 
1028f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kak, uak, sizeof(kak)))
1029f2bbc96eSHarald Freudenberger 			return -EFAULT;
1030f2bbc96eSHarald Freudenberger 		nr_apqns = kak.apqn_entries;
1031f2bbc96eSHarald Freudenberger 		if (nr_apqns) {
1032f2bbc96eSHarald Freudenberger 			apqns = kmalloc_array(nr_apqns,
1033f2bbc96eSHarald Freudenberger 					      sizeof(struct pkey_apqn),
1034f2bbc96eSHarald Freudenberger 					      GFP_KERNEL);
1035f2bbc96eSHarald Freudenberger 			if (!apqns)
1036f2bbc96eSHarald Freudenberger 				return -ENOMEM;
1037f2bbc96eSHarald Freudenberger 		}
1038f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(kak.key, kak.keylen);
1039f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey)) {
1040f2bbc96eSHarald Freudenberger 			kfree(apqns);
1041f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
1042f2bbc96eSHarald Freudenberger 		}
1043f2bbc96eSHarald Freudenberger 		rc = pkey_apqns4key(kkey, kak.keylen, kak.flags,
1044f2bbc96eSHarald Freudenberger 				    apqns, &nr_apqns);
1045f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc);
1046f2bbc96eSHarald Freudenberger 		kfree(kkey);
1047f2bbc96eSHarald Freudenberger 		if (rc && rc != -ENOSPC) {
1048f2bbc96eSHarald Freudenberger 			kfree(apqns);
1049f2bbc96eSHarald Freudenberger 			break;
1050f2bbc96eSHarald Freudenberger 		}
1051f2bbc96eSHarald Freudenberger 		if (!rc && kak.apqns) {
1052f2bbc96eSHarald Freudenberger 			if (nr_apqns > kak.apqn_entries) {
1053f2bbc96eSHarald Freudenberger 				kfree(apqns);
1054f2bbc96eSHarald Freudenberger 				return -EINVAL;
1055f2bbc96eSHarald Freudenberger 			}
1056f2bbc96eSHarald Freudenberger 			len = nr_apqns * sizeof(struct pkey_apqn);
1057f2bbc96eSHarald Freudenberger 			if (len) {
1058f2bbc96eSHarald Freudenberger 				if (copy_to_user(kak.apqns, apqns, len)) {
1059f2bbc96eSHarald Freudenberger 					kfree(apqns);
1060f2bbc96eSHarald Freudenberger 					return -EFAULT;
1061f2bbc96eSHarald Freudenberger 				}
1062f2bbc96eSHarald Freudenberger 			}
1063f2bbc96eSHarald Freudenberger 		}
1064f2bbc96eSHarald Freudenberger 		kak.apqn_entries = nr_apqns;
1065f2bbc96eSHarald Freudenberger 		if (copy_to_user(uak, &kak, sizeof(kak)))
1066f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
1067f2bbc96eSHarald Freudenberger 		kfree(apqns);
1068f2bbc96eSHarald Freudenberger 		break;
1069f2bbc96eSHarald Freudenberger 	}
1070f2bbc96eSHarald Freudenberger 	case PKEY_APQNS4KT: {
1071f2bbc96eSHarald Freudenberger 		struct pkey_apqns4keytype __user *uat = (void __user *) arg;
1072f2bbc96eSHarald Freudenberger 		struct pkey_apqns4keytype kat;
1073f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns = NULL;
1074f2bbc96eSHarald Freudenberger 		size_t nr_apqns, len;
1075f2bbc96eSHarald Freudenberger 
1076f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kat, uat, sizeof(kat)))
1077f2bbc96eSHarald Freudenberger 			return -EFAULT;
1078f2bbc96eSHarald Freudenberger 		nr_apqns = kat.apqn_entries;
1079f2bbc96eSHarald Freudenberger 		if (nr_apqns) {
1080f2bbc96eSHarald Freudenberger 			apqns = kmalloc_array(nr_apqns,
1081f2bbc96eSHarald Freudenberger 					      sizeof(struct pkey_apqn),
1082f2bbc96eSHarald Freudenberger 					      GFP_KERNEL);
1083f2bbc96eSHarald Freudenberger 			if (!apqns)
1084f2bbc96eSHarald Freudenberger 				return -ENOMEM;
1085f2bbc96eSHarald Freudenberger 		}
1086f2bbc96eSHarald Freudenberger 		rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp,
1087f2bbc96eSHarald Freudenberger 					kat.flags, apqns, &nr_apqns);
1088f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc);
1089f2bbc96eSHarald Freudenberger 		if (rc && rc != -ENOSPC) {
1090f2bbc96eSHarald Freudenberger 			kfree(apqns);
1091f2bbc96eSHarald Freudenberger 			break;
1092f2bbc96eSHarald Freudenberger 		}
1093f2bbc96eSHarald Freudenberger 		if (!rc && kat.apqns) {
1094f2bbc96eSHarald Freudenberger 			if (nr_apqns > kat.apqn_entries) {
1095f2bbc96eSHarald Freudenberger 				kfree(apqns);
1096f2bbc96eSHarald Freudenberger 				return -EINVAL;
1097f2bbc96eSHarald Freudenberger 			}
1098f2bbc96eSHarald Freudenberger 			len = nr_apqns * sizeof(struct pkey_apqn);
1099f2bbc96eSHarald Freudenberger 			if (len) {
1100f2bbc96eSHarald Freudenberger 				if (copy_to_user(kat.apqns, apqns, len)) {
1101f2bbc96eSHarald Freudenberger 					kfree(apqns);
1102f2bbc96eSHarald Freudenberger 					return -EFAULT;
1103f2bbc96eSHarald Freudenberger 				}
1104f2bbc96eSHarald Freudenberger 			}
1105f2bbc96eSHarald Freudenberger 		}
1106f2bbc96eSHarald Freudenberger 		kat.apqn_entries = nr_apqns;
1107f2bbc96eSHarald Freudenberger 		if (copy_to_user(uat, &kat, sizeof(kat)))
1108f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
1109f2bbc96eSHarald Freudenberger 		kfree(apqns);
1110f2bbc96eSHarald Freudenberger 		break;
1111f2bbc96eSHarald Freudenberger 	}
1112e80d4af0SHarald Freudenberger 	default:
1113e80d4af0SHarald Freudenberger 		/* unknown/unsupported ioctl cmd */
1114e80d4af0SHarald Freudenberger 		return -ENOTTY;
1115e80d4af0SHarald Freudenberger 	}
1116e80d4af0SHarald Freudenberger 
1117e80d4af0SHarald Freudenberger 	return rc;
1118e80d4af0SHarald Freudenberger }
1119e80d4af0SHarald Freudenberger 
1120e80d4af0SHarald Freudenberger /*
1121e80d4af0SHarald Freudenberger  * Sysfs and file io operations
1122e80d4af0SHarald Freudenberger  */
1123d632c047SIngo Franzki 
1124d632c047SIngo Franzki /*
1125d632c047SIngo Franzki  * Sysfs attribute read function for all protected key binary attributes.
1126d632c047SIngo Franzki  * The implementation can not deal with partial reads, because a new random
1127d632c047SIngo Franzki  * protected key blob is generated with each read. In case of partial reads
1128d632c047SIngo Franzki  * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
1129d632c047SIngo Franzki  */
1130d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf,
1131d632c047SIngo Franzki 					  loff_t off, size_t count)
1132d632c047SIngo Franzki {
1133d632c047SIngo Franzki 	struct protaeskeytoken protkeytoken;
1134d632c047SIngo Franzki 	struct pkey_protkey protkey;
1135d632c047SIngo Franzki 	int rc;
1136d632c047SIngo Franzki 
1137d632c047SIngo Franzki 	if (off != 0 || count < sizeof(protkeytoken))
1138d632c047SIngo Franzki 		return -EINVAL;
1139d632c047SIngo Franzki 	if (is_xts)
1140d632c047SIngo Franzki 		if (count < 2 * sizeof(protkeytoken))
1141d632c047SIngo Franzki 			return -EINVAL;
1142d632c047SIngo Franzki 
1143d632c047SIngo Franzki 	memset(&protkeytoken, 0, sizeof(protkeytoken));
1144d632c047SIngo Franzki 	protkeytoken.type = TOKTYPE_NON_CCA;
1145d632c047SIngo Franzki 	protkeytoken.version = TOKVER_PROTECTED_KEY;
1146d632c047SIngo Franzki 	protkeytoken.keytype = keytype;
1147d632c047SIngo Franzki 
1148d632c047SIngo Franzki 	rc = pkey_genprotkey(protkeytoken.keytype, &protkey);
1149d632c047SIngo Franzki 	if (rc)
1150d632c047SIngo Franzki 		return rc;
1151d632c047SIngo Franzki 
1152d632c047SIngo Franzki 	protkeytoken.len = protkey.len;
1153d632c047SIngo Franzki 	memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len);
1154d632c047SIngo Franzki 
1155d632c047SIngo Franzki 	memcpy(buf, &protkeytoken, sizeof(protkeytoken));
1156d632c047SIngo Franzki 
1157d632c047SIngo Franzki 	if (is_xts) {
1158d632c047SIngo Franzki 		rc = pkey_genprotkey(protkeytoken.keytype, &protkey);
1159d632c047SIngo Franzki 		if (rc)
1160d632c047SIngo Franzki 			return rc;
1161d632c047SIngo Franzki 
1162d632c047SIngo Franzki 		protkeytoken.len = protkey.len;
1163d632c047SIngo Franzki 		memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len);
1164d632c047SIngo Franzki 
1165d632c047SIngo Franzki 		memcpy(buf + sizeof(protkeytoken), &protkeytoken,
1166d632c047SIngo Franzki 		       sizeof(protkeytoken));
1167d632c047SIngo Franzki 
1168d632c047SIngo Franzki 		return 2 * sizeof(protkeytoken);
1169d632c047SIngo Franzki 	}
1170d632c047SIngo Franzki 
1171d632c047SIngo Franzki 	return sizeof(protkeytoken);
1172d632c047SIngo Franzki }
1173d632c047SIngo Franzki 
1174d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp,
1175d632c047SIngo Franzki 				    struct kobject *kobj,
1176d632c047SIngo Franzki 				    struct bin_attribute *attr,
1177d632c047SIngo Franzki 				    char *buf, loff_t off,
1178d632c047SIngo Franzki 				    size_t count)
1179d632c047SIngo Franzki {
1180d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf,
1181d632c047SIngo Franzki 					  off, count);
1182d632c047SIngo Franzki }
1183d632c047SIngo Franzki 
1184d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp,
1185d632c047SIngo Franzki 				    struct kobject *kobj,
1186d632c047SIngo Franzki 				    struct bin_attribute *attr,
1187d632c047SIngo Franzki 				    char *buf, loff_t off,
1188d632c047SIngo Franzki 				    size_t count)
1189d632c047SIngo Franzki {
1190d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf,
1191d632c047SIngo Franzki 					  off, count);
1192d632c047SIngo Franzki }
1193d632c047SIngo Franzki 
1194d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp,
1195d632c047SIngo Franzki 				    struct kobject *kobj,
1196d632c047SIngo Franzki 				    struct bin_attribute *attr,
1197d632c047SIngo Franzki 				    char *buf, loff_t off,
1198d632c047SIngo Franzki 				    size_t count)
1199d632c047SIngo Franzki {
1200d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf,
1201d632c047SIngo Franzki 					  off, count);
1202d632c047SIngo Franzki }
1203d632c047SIngo Franzki 
1204d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp,
1205d632c047SIngo Franzki 					struct kobject *kobj,
1206d632c047SIngo Franzki 					struct bin_attribute *attr,
1207d632c047SIngo Franzki 					char *buf, loff_t off,
1208d632c047SIngo Franzki 					size_t count)
1209d632c047SIngo Franzki {
1210d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf,
1211d632c047SIngo Franzki 					  off, count);
1212d632c047SIngo Franzki }
1213d632c047SIngo Franzki 
1214d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp,
1215d632c047SIngo Franzki 					struct kobject *kobj,
1216d632c047SIngo Franzki 					struct bin_attribute *attr,
1217d632c047SIngo Franzki 					char *buf, loff_t off,
1218d632c047SIngo Franzki 					size_t count)
1219d632c047SIngo Franzki {
1220d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf,
1221d632c047SIngo Franzki 					  off, count);
1222d632c047SIngo Franzki }
1223d632c047SIngo Franzki 
1224d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken));
1225d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken));
1226d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken));
1227d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken));
1228d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken));
1229d632c047SIngo Franzki 
1230d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = {
1231d632c047SIngo Franzki 	&bin_attr_protkey_aes_128,
1232d632c047SIngo Franzki 	&bin_attr_protkey_aes_192,
1233d632c047SIngo Franzki 	&bin_attr_protkey_aes_256,
1234d632c047SIngo Franzki 	&bin_attr_protkey_aes_128_xts,
1235d632c047SIngo Franzki 	&bin_attr_protkey_aes_256_xts,
1236d632c047SIngo Franzki 	NULL
1237d632c047SIngo Franzki };
1238d632c047SIngo Franzki 
1239d632c047SIngo Franzki static struct attribute_group protkey_attr_group = {
1240d632c047SIngo Franzki 	.name	   = "protkey",
1241d632c047SIngo Franzki 	.bin_attrs = protkey_attrs,
1242d632c047SIngo Franzki };
1243d632c047SIngo Franzki 
1244af504452SIngo Franzki /*
1245af504452SIngo Franzki  * Sysfs attribute read function for all secure key ccadata binary attributes.
1246af504452SIngo Franzki  * The implementation can not deal with partial reads, because a new random
1247af504452SIngo Franzki  * protected key blob is generated with each read. In case of partial reads
1248af504452SIngo Franzki  * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
1249af504452SIngo Franzki  */
1250af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf,
1251af504452SIngo Franzki 					  loff_t off, size_t count)
1252af504452SIngo Franzki {
1253af504452SIngo Franzki 	int rc;
1254efc598e6SHarald Freudenberger 	struct pkey_seckey *seckey = (struct pkey_seckey *) buf;
1255af504452SIngo Franzki 
1256af504452SIngo Franzki 	if (off != 0 || count < sizeof(struct secaeskeytoken))
1257af504452SIngo Franzki 		return -EINVAL;
1258af504452SIngo Franzki 	if (is_xts)
1259af504452SIngo Franzki 		if (count < 2 * sizeof(struct secaeskeytoken))
1260af504452SIngo Franzki 			return -EINVAL;
1261af504452SIngo Franzki 
1262efc598e6SHarald Freudenberger 	rc = cca_genseckey(-1, -1, keytype, seckey->seckey);
1263af504452SIngo Franzki 	if (rc)
1264af504452SIngo Franzki 		return rc;
1265af504452SIngo Franzki 
1266af504452SIngo Franzki 	if (is_xts) {
1267efc598e6SHarald Freudenberger 		seckey++;
1268efc598e6SHarald Freudenberger 		rc = cca_genseckey(-1, -1, keytype, seckey->seckey);
1269af504452SIngo Franzki 		if (rc)
1270af504452SIngo Franzki 			return rc;
1271af504452SIngo Franzki 
1272af504452SIngo Franzki 		return 2 * sizeof(struct secaeskeytoken);
1273af504452SIngo Franzki 	}
1274af504452SIngo Franzki 
1275af504452SIngo Franzki 	return sizeof(struct secaeskeytoken);
1276af504452SIngo Franzki }
1277af504452SIngo Franzki 
1278af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp,
1279af504452SIngo Franzki 				    struct kobject *kobj,
1280af504452SIngo Franzki 				    struct bin_attribute *attr,
1281af504452SIngo Franzki 				    char *buf, loff_t off,
1282af504452SIngo Franzki 				    size_t count)
1283af504452SIngo Franzki {
1284af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf,
1285af504452SIngo Franzki 					  off, count);
1286af504452SIngo Franzki }
1287af504452SIngo Franzki 
1288af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp,
1289af504452SIngo Franzki 				    struct kobject *kobj,
1290af504452SIngo Franzki 				    struct bin_attribute *attr,
1291af504452SIngo Franzki 				    char *buf, loff_t off,
1292af504452SIngo Franzki 				    size_t count)
1293af504452SIngo Franzki {
1294af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf,
1295af504452SIngo Franzki 					  off, count);
1296af504452SIngo Franzki }
1297af504452SIngo Franzki 
1298af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp,
1299af504452SIngo Franzki 				    struct kobject *kobj,
1300af504452SIngo Franzki 				    struct bin_attribute *attr,
1301af504452SIngo Franzki 				    char *buf, loff_t off,
1302af504452SIngo Franzki 				    size_t count)
1303af504452SIngo Franzki {
1304af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf,
1305af504452SIngo Franzki 					  off, count);
1306af504452SIngo Franzki }
1307af504452SIngo Franzki 
1308af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp,
1309af504452SIngo Franzki 					struct kobject *kobj,
1310af504452SIngo Franzki 					struct bin_attribute *attr,
1311af504452SIngo Franzki 					char *buf, loff_t off,
1312af504452SIngo Franzki 					size_t count)
1313af504452SIngo Franzki {
1314af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf,
1315af504452SIngo Franzki 					  off, count);
1316af504452SIngo Franzki }
1317af504452SIngo Franzki 
1318af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp,
1319af504452SIngo Franzki 					struct kobject *kobj,
1320af504452SIngo Franzki 					struct bin_attribute *attr,
1321af504452SIngo Franzki 					char *buf, loff_t off,
1322af504452SIngo Franzki 					size_t count)
1323af504452SIngo Franzki {
1324af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf,
1325af504452SIngo Franzki 					  off, count);
1326af504452SIngo Franzki }
1327af504452SIngo Franzki 
1328af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken));
1329af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken));
1330af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken));
1331af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken));
1332af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken));
1333af504452SIngo Franzki 
1334af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = {
1335af504452SIngo Franzki 	&bin_attr_ccadata_aes_128,
1336af504452SIngo Franzki 	&bin_attr_ccadata_aes_192,
1337af504452SIngo Franzki 	&bin_attr_ccadata_aes_256,
1338af504452SIngo Franzki 	&bin_attr_ccadata_aes_128_xts,
1339af504452SIngo Franzki 	&bin_attr_ccadata_aes_256_xts,
1340af504452SIngo Franzki 	NULL
1341af504452SIngo Franzki };
1342af504452SIngo Franzki 
1343af504452SIngo Franzki static struct attribute_group ccadata_attr_group = {
1344af504452SIngo Franzki 	.name	   = "ccadata",
1345af504452SIngo Franzki 	.bin_attrs = ccadata_attrs,
1346af504452SIngo Franzki };
1347af504452SIngo Franzki 
1348f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE	(sizeof(struct cipherkeytoken) + 80)
1349f71fee27SIngo Franzki 
1350f71fee27SIngo Franzki /*
1351f71fee27SIngo Franzki  * Sysfs attribute read function for all secure key ccacipher binary attributes.
1352f71fee27SIngo Franzki  * The implementation can not deal with partial reads, because a new random
1353f71fee27SIngo Franzki  * secure key blob is generated with each read. In case of partial reads
1354f71fee27SIngo Franzki  * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
1355f71fee27SIngo Franzki  */
1356f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits,
1357f71fee27SIngo Franzki 					    bool is_xts, char *buf, loff_t off,
1358f71fee27SIngo Franzki 					    size_t count)
1359f71fee27SIngo Franzki {
1360f71fee27SIngo Franzki 	size_t keysize;
1361f71fee27SIngo Franzki 	int rc;
1362f71fee27SIngo Franzki 
1363f71fee27SIngo Franzki 	if (off != 0 || count < CCACIPHERTOKENSIZE)
1364f71fee27SIngo Franzki 		return -EINVAL;
1365f71fee27SIngo Franzki 	if (is_xts)
1366f71fee27SIngo Franzki 		if (count < 2 * CCACIPHERTOKENSIZE)
1367f71fee27SIngo Franzki 			return -EINVAL;
1368f71fee27SIngo Franzki 
1369f71fee27SIngo Franzki 	keysize = CCACIPHERTOKENSIZE;
1370f71fee27SIngo Franzki 	rc = cca_gencipherkey(-1, -1, keybits, 0, buf, &keysize);
1371f71fee27SIngo Franzki 	if (rc)
1372f71fee27SIngo Franzki 		return rc;
1373f71fee27SIngo Franzki 	memset(buf + keysize, 0, CCACIPHERTOKENSIZE - keysize);
1374f71fee27SIngo Franzki 
1375f71fee27SIngo Franzki 	if (is_xts) {
1376f71fee27SIngo Franzki 		keysize = CCACIPHERTOKENSIZE;
1377f71fee27SIngo Franzki 		rc = cca_gencipherkey(-1, -1, keybits, 0,
1378f71fee27SIngo Franzki 				      buf + CCACIPHERTOKENSIZE, &keysize);
1379f71fee27SIngo Franzki 		if (rc)
1380f71fee27SIngo Franzki 			return rc;
1381f71fee27SIngo Franzki 		memset(buf + CCACIPHERTOKENSIZE + keysize, 0,
1382f71fee27SIngo Franzki 		       CCACIPHERTOKENSIZE - keysize);
1383f71fee27SIngo Franzki 
1384f71fee27SIngo Franzki 		return 2 * CCACIPHERTOKENSIZE;
1385f71fee27SIngo Franzki 	}
1386f71fee27SIngo Franzki 
1387f71fee27SIngo Franzki 	return CCACIPHERTOKENSIZE;
1388f71fee27SIngo Franzki }
1389f71fee27SIngo Franzki 
1390f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp,
1391f71fee27SIngo Franzki 				      struct kobject *kobj,
1392f71fee27SIngo Franzki 				      struct bin_attribute *attr,
1393f71fee27SIngo Franzki 				      char *buf, loff_t off,
1394f71fee27SIngo Franzki 				      size_t count)
1395f71fee27SIngo Franzki {
1396f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf,
1397f71fee27SIngo Franzki 					    off, count);
1398f71fee27SIngo Franzki }
1399f71fee27SIngo Franzki 
1400f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp,
1401f71fee27SIngo Franzki 				      struct kobject *kobj,
1402f71fee27SIngo Franzki 				      struct bin_attribute *attr,
1403f71fee27SIngo Franzki 				      char *buf, loff_t off,
1404f71fee27SIngo Franzki 				      size_t count)
1405f71fee27SIngo Franzki {
1406f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf,
1407f71fee27SIngo Franzki 					    off, count);
1408f71fee27SIngo Franzki }
1409f71fee27SIngo Franzki 
1410f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp,
1411f71fee27SIngo Franzki 				      struct kobject *kobj,
1412f71fee27SIngo Franzki 				      struct bin_attribute *attr,
1413f71fee27SIngo Franzki 				      char *buf, loff_t off,
1414f71fee27SIngo Franzki 				      size_t count)
1415f71fee27SIngo Franzki {
1416f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf,
1417f71fee27SIngo Franzki 					    off, count);
1418f71fee27SIngo Franzki }
1419f71fee27SIngo Franzki 
1420f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp,
1421f71fee27SIngo Franzki 					  struct kobject *kobj,
1422f71fee27SIngo Franzki 					  struct bin_attribute *attr,
1423f71fee27SIngo Franzki 					  char *buf, loff_t off,
1424f71fee27SIngo Franzki 					  size_t count)
1425f71fee27SIngo Franzki {
1426f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf,
1427f71fee27SIngo Franzki 					    off, count);
1428f71fee27SIngo Franzki }
1429f71fee27SIngo Franzki 
1430f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_read(struct file *filp,
1431f71fee27SIngo Franzki 					  struct kobject *kobj,
1432f71fee27SIngo Franzki 					  struct bin_attribute *attr,
1433f71fee27SIngo Franzki 					  char *buf, loff_t off,
1434f71fee27SIngo Franzki 					  size_t count)
1435f71fee27SIngo Franzki {
1436f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf,
1437f71fee27SIngo Franzki 					    off, count);
1438f71fee27SIngo Franzki }
1439f71fee27SIngo Franzki 
1440f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE);
1441f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE);
1442f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE);
1443f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE);
1444f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE);
1445f71fee27SIngo Franzki 
1446f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = {
1447f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_128,
1448f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_192,
1449f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_256,
1450f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_128_xts,
1451f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_256_xts,
1452f71fee27SIngo Franzki 	NULL
1453f71fee27SIngo Franzki };
1454f71fee27SIngo Franzki 
1455f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = {
1456f71fee27SIngo Franzki 	.name	   = "ccacipher",
1457f71fee27SIngo Franzki 	.bin_attrs = ccacipher_attrs,
1458f71fee27SIngo Franzki };
1459f71fee27SIngo Franzki 
1460d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = {
1461d632c047SIngo Franzki 	&protkey_attr_group,
1462af504452SIngo Franzki 	&ccadata_attr_group,
1463f71fee27SIngo Franzki 	&ccacipher_attr_group,
1464d632c047SIngo Franzki 	NULL,
1465d632c047SIngo Franzki };
1466d632c047SIngo Franzki 
1467e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = {
1468e80d4af0SHarald Freudenberger 	.owner		= THIS_MODULE,
1469e80d4af0SHarald Freudenberger 	.open		= nonseekable_open,
1470e80d4af0SHarald Freudenberger 	.llseek		= no_llseek,
1471e80d4af0SHarald Freudenberger 	.unlocked_ioctl = pkey_unlocked_ioctl,
1472e80d4af0SHarald Freudenberger };
1473e80d4af0SHarald Freudenberger 
1474e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = {
1475e80d4af0SHarald Freudenberger 	.name	= "pkey",
1476e80d4af0SHarald Freudenberger 	.minor	= MISC_DYNAMIC_MINOR,
1477e80d4af0SHarald Freudenberger 	.mode	= 0666,
1478e80d4af0SHarald Freudenberger 	.fops	= &pkey_fops,
1479d632c047SIngo Franzki 	.groups = pkey_attr_groups,
1480e80d4af0SHarald Freudenberger };
1481e80d4af0SHarald Freudenberger 
1482e80d4af0SHarald Freudenberger /*
1483e80d4af0SHarald Freudenberger  * Module init
1484e80d4af0SHarald Freudenberger  */
1485cb4ef3c2SHeiko Carstens static int __init pkey_init(void)
1486e80d4af0SHarald Freudenberger {
1487f822ad2cSHarald Freudenberger 	cpacf_mask_t kmc_functions;
1488e80d4af0SHarald Freudenberger 
1489f822ad2cSHarald Freudenberger 	/*
1490f822ad2cSHarald Freudenberger 	 * The pckmo instruction should be available - even if we don't
1491f822ad2cSHarald Freudenberger 	 * actually invoke it. This instruction comes with MSA 3 which
1492f822ad2cSHarald Freudenberger 	 * is also the minimum level for the kmc instructions which
1493f822ad2cSHarald Freudenberger 	 * are able to work with protected keys.
1494f822ad2cSHarald Freudenberger 	 */
1495e80d4af0SHarald Freudenberger 	if (!cpacf_query(CPACF_PCKMO, &pckmo_functions))
149658443b67SDavid Hildenbrand 		return -ENODEV;
1497e80d4af0SHarald Freudenberger 
1498cb26b9ffSIngo Franzki 	/* check for kmc instructions available */
1499cb26b9ffSIngo Franzki 	if (!cpacf_query(CPACF_KMC, &kmc_functions))
150058443b67SDavid Hildenbrand 		return -ENODEV;
1501cb26b9ffSIngo Franzki 	if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) ||
1502cb26b9ffSIngo Franzki 	    !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) ||
1503cb26b9ffSIngo Franzki 	    !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256))
150458443b67SDavid Hildenbrand 		return -ENODEV;
1505cb26b9ffSIngo Franzki 
1506e80d4af0SHarald Freudenberger 	pkey_debug_init();
1507e80d4af0SHarald Freudenberger 
1508e80d4af0SHarald Freudenberger 	return misc_register(&pkey_dev);
1509e80d4af0SHarald Freudenberger }
1510e80d4af0SHarald Freudenberger 
1511e80d4af0SHarald Freudenberger /*
1512e80d4af0SHarald Freudenberger  * Module exit
1513e80d4af0SHarald Freudenberger  */
1514e80d4af0SHarald Freudenberger static void __exit pkey_exit(void)
1515e80d4af0SHarald Freudenberger {
1516e80d4af0SHarald Freudenberger 	misc_deregister(&pkey_dev);
1517e80d4af0SHarald Freudenberger 	pkey_debug_exit();
1518e80d4af0SHarald Freudenberger }
1519e80d4af0SHarald Freudenberger 
152063c19be0SIngo Franzki module_cpu_feature_match(MSA, pkey_init);
1521e80d4af0SHarald Freudenberger module_exit(pkey_exit);
1522