xref: /openbmc/linux/drivers/s390/crypto/pkey_api.c (revision 9e436c195e2d6d3a0db6921e14ef2c85e559ae5b)
1812141a9SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2e80d4af0SHarald Freudenberger /*
3e80d4af0SHarald Freudenberger  *  pkey device driver
4e80d4af0SHarald Freudenberger  *
5*9e436c19SHarald Freudenberger  *  Copyright IBM Corp. 2017, 2023
6*9e436c19SHarald Freudenberger  *
7e80d4af0SHarald Freudenberger  *  Author(s): Harald Freudenberger
8e80d4af0SHarald Freudenberger  */
9e80d4af0SHarald Freudenberger 
10e80d4af0SHarald Freudenberger #define KMSG_COMPONENT "pkey"
11e80d4af0SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
12e80d4af0SHarald Freudenberger 
13e80d4af0SHarald Freudenberger #include <linux/fs.h>
14e80d4af0SHarald Freudenberger #include <linux/init.h>
15e80d4af0SHarald Freudenberger #include <linux/miscdevice.h>
16e80d4af0SHarald Freudenberger #include <linux/module.h>
17e80d4af0SHarald Freudenberger #include <linux/slab.h>
18e80d4af0SHarald Freudenberger #include <linux/kallsyms.h>
19e80d4af0SHarald Freudenberger #include <linux/debugfs.h>
20a45a5c7dSIngo Franzki #include <linux/random.h>
2163c19be0SIngo Franzki #include <linux/cpufeature.h>
22e80d4af0SHarald Freudenberger #include <asm/zcrypt.h>
23e80d4af0SHarald Freudenberger #include <asm/cpacf.h>
24e80d4af0SHarald Freudenberger #include <asm/pkey.h>
25cb26b9ffSIngo Franzki #include <crypto/aes.h>
26e80d4af0SHarald Freudenberger 
27e80d4af0SHarald Freudenberger #include "zcrypt_api.h"
28efc598e6SHarald Freudenberger #include "zcrypt_ccamisc.h"
2955d0a513SHarald Freudenberger #include "zcrypt_ep11misc.h"
30e80d4af0SHarald Freudenberger 
31e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL");
32e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation");
33e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface");
34e80d4af0SHarald Freudenberger 
35f2bbc96eSHarald Freudenberger #define KEYBLOBBUFSIZE 8192	/* key buffer size used for internal processing */
36*9e436c19SHarald Freudenberger #define MINKEYBLOBBUFSIZE (sizeof(struct keytoken_header))
37fa6999e3SHarald Freudenberger #define PROTKEYBLOBBUFSIZE 256	/* protected key buffer size used internal */
38f2bbc96eSHarald Freudenberger #define MAXAPQNSINLIST 64	/* max 64 apqns within a apqn list */
39f370f45cSHarald Freudenberger #define AES_WK_VP_SIZE 32	/* Size of WK VP block appended to a prot key */
40f2bbc96eSHarald Freudenberger 
41e80d4af0SHarald Freudenberger /*
42e80d4af0SHarald Freudenberger  * debug feature data and functions
43e80d4af0SHarald Freudenberger  */
44e80d4af0SHarald Freudenberger 
45e80d4af0SHarald Freudenberger static debug_info_t *debug_info;
46e80d4af0SHarald Freudenberger 
47e80d4af0SHarald Freudenberger #define DEBUG_DBG(...)	debug_sprintf_event(debug_info, 6, ##__VA_ARGS__)
48e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__)
49e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__)
50e80d4af0SHarald Freudenberger #define DEBUG_ERR(...)	debug_sprintf_event(debug_info, 3, ##__VA_ARGS__)
51e80d4af0SHarald Freudenberger 
52e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void)
53e80d4af0SHarald Freudenberger {
546b1f16baSHarald Freudenberger 	/* 5 arguments per dbf entry (including the format string ptr) */
556b1f16baSHarald Freudenberger 	debug_info = debug_register("pkey", 1, 1, 5 * sizeof(long));
56e80d4af0SHarald Freudenberger 	debug_register_view(debug_info, &debug_sprintf_view);
57e80d4af0SHarald Freudenberger 	debug_set_level(debug_info, 3);
58e80d4af0SHarald Freudenberger }
59e80d4af0SHarald Freudenberger 
60e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void)
61e80d4af0SHarald Freudenberger {
62e80d4af0SHarald Freudenberger 	debug_unregister(debug_info);
63e80d4af0SHarald Freudenberger }
64e80d4af0SHarald Freudenberger 
650534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */
660534bde7SIngo Franzki struct protaeskeytoken {
670534bde7SIngo Franzki 	u8  type;     /* 0x00 for PAES specific key tokens */
680534bde7SIngo Franzki 	u8  res0[3];
690534bde7SIngo Franzki 	u8  version;  /* should be 0x01 for protected AES key token */
700534bde7SIngo Franzki 	u8  res1[3];
710534bde7SIngo Franzki 	u32 keytype;  /* key type, one of the PKEY_KEYTYPE values */
720534bde7SIngo Franzki 	u32 len;      /* bytes actually stored in protkey[] */
730534bde7SIngo Franzki 	u8  protkey[MAXPROTKEYSIZE]; /* the protected key blob */
740534bde7SIngo Franzki } __packed;
750534bde7SIngo Franzki 
76888edbc4SHarald Freudenberger /* inside view of a clear key token (type 0x00 version 0x02) */
77*9e436c19SHarald Freudenberger struct clearkeytoken {
78888edbc4SHarald Freudenberger 	u8  type;	/* 0x00 for PAES specific key tokens */
79888edbc4SHarald Freudenberger 	u8  res0[3];
80*9e436c19SHarald Freudenberger 	u8  version;	/* 0x02 for clear key token */
81888edbc4SHarald Freudenberger 	u8  res1[3];
82*9e436c19SHarald Freudenberger 	u32 keytype;	/* key type, one of the PKEY_KEYTYPE_* values */
83888edbc4SHarald Freudenberger 	u32 len;	/* bytes actually stored in clearkey[] */
84fa226f1dSGustavo A. R. Silva 	u8  clearkey[]; /* clear key value */
85888edbc4SHarald Freudenberger } __packed;
86888edbc4SHarald Freudenberger 
87*9e436c19SHarald Freudenberger /* helper function which translates the PKEY_KEYTYPE_AES_* to their keysize */
88*9e436c19SHarald Freudenberger static inline u32 pkey_keytype_aes_to_size(u32 keytype)
89*9e436c19SHarald Freudenberger {
90*9e436c19SHarald Freudenberger 	switch (keytype) {
91*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_AES_128:
92*9e436c19SHarald Freudenberger 		return 16;
93*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_AES_192:
94*9e436c19SHarald Freudenberger 		return 24;
95*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_AES_256:
96*9e436c19SHarald Freudenberger 		return 32;
97*9e436c19SHarald Freudenberger 	default:
98*9e436c19SHarald Freudenberger 		return 0;
99*9e436c19SHarald Freudenberger 	}
100*9e436c19SHarald Freudenberger }
101*9e436c19SHarald Freudenberger 
102e80d4af0SHarald Freudenberger /*
103f370f45cSHarald Freudenberger  * Create a protected key from a clear key value via PCKMO instruction.
104e80d4af0SHarald Freudenberger  */
105f370f45cSHarald Freudenberger static int pkey_clr2protkey(u32 keytype, const u8 *clrkey,
106f370f45cSHarald Freudenberger 			    u8 *protkey, u32 *protkeylen, u32 *protkeytype)
107e80d4af0SHarald Freudenberger {
1085b35047eSHarald Freudenberger 	/* mask of available pckmo subfunctions */
1095b35047eSHarald Freudenberger 	static cpacf_mask_t pckmo_functions;
1105b35047eSHarald Freudenberger 
111*9e436c19SHarald Freudenberger 	u8 paramblock[112];
112*9e436c19SHarald Freudenberger 	u32 pkeytype;
11346a29b03SHarald Freudenberger 	int keysize;
11446a29b03SHarald Freudenberger 	long fc;
115e80d4af0SHarald Freudenberger 
116e80d4af0SHarald Freudenberger 	switch (keytype) {
117e80d4af0SHarald Freudenberger 	case PKEY_KEYTYPE_AES_128:
118*9e436c19SHarald Freudenberger 		/* 16 byte key, 32 byte aes wkvp, total 48 bytes */
119e80d4af0SHarald Freudenberger 		keysize = 16;
120*9e436c19SHarald Freudenberger 		pkeytype = keytype;
121e80d4af0SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_AES_128_KEY;
122e80d4af0SHarald Freudenberger 		break;
123e80d4af0SHarald Freudenberger 	case PKEY_KEYTYPE_AES_192:
124*9e436c19SHarald Freudenberger 		/* 24 byte key, 32 byte aes wkvp, total 56 bytes */
125e80d4af0SHarald Freudenberger 		keysize = 24;
126*9e436c19SHarald Freudenberger 		pkeytype = keytype;
127e80d4af0SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_AES_192_KEY;
128e80d4af0SHarald Freudenberger 		break;
129e80d4af0SHarald Freudenberger 	case PKEY_KEYTYPE_AES_256:
130*9e436c19SHarald Freudenberger 		/* 32 byte key, 32 byte aes wkvp, total 64 bytes */
131e80d4af0SHarald Freudenberger 		keysize = 32;
132*9e436c19SHarald Freudenberger 		pkeytype = keytype;
133e80d4af0SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_AES_256_KEY;
134e80d4af0SHarald Freudenberger 		break;
135*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_ECC_P256:
136*9e436c19SHarald Freudenberger 		/* 32 byte key, 32 byte aes wkvp, total 64 bytes */
137*9e436c19SHarald Freudenberger 		keysize = 32;
138*9e436c19SHarald Freudenberger 		pkeytype = PKEY_KEYTYPE_ECC;
139*9e436c19SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_ECC_P256_KEY;
140*9e436c19SHarald Freudenberger 		break;
141*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_ECC_P384:
142*9e436c19SHarald Freudenberger 		/* 48 byte key, 32 byte aes wkvp, total 80 bytes */
143*9e436c19SHarald Freudenberger 		keysize = 48;
144*9e436c19SHarald Freudenberger 		pkeytype = PKEY_KEYTYPE_ECC;
145*9e436c19SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_ECC_P384_KEY;
146*9e436c19SHarald Freudenberger 		break;
147*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_ECC_P521:
148*9e436c19SHarald Freudenberger 		/* 80 byte key, 32 byte aes wkvp, total 112 bytes */
149*9e436c19SHarald Freudenberger 		keysize = 80;
150*9e436c19SHarald Freudenberger 		pkeytype = PKEY_KEYTYPE_ECC;
151*9e436c19SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_ECC_P521_KEY;
152*9e436c19SHarald Freudenberger 		break;
153*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_ECC_ED25519:
154*9e436c19SHarald Freudenberger 		/* 32 byte key, 32 byte aes wkvp, total 64 bytes */
155*9e436c19SHarald Freudenberger 		keysize = 32;
156*9e436c19SHarald Freudenberger 		pkeytype = PKEY_KEYTYPE_ECC;
157*9e436c19SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_ECC_ED25519_KEY;
158*9e436c19SHarald Freudenberger 		break;
159*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_ECC_ED448:
160*9e436c19SHarald Freudenberger 		/* 64 byte key, 32 byte aes wkvp, total 96 bytes */
161*9e436c19SHarald Freudenberger 		keysize = 64;
162*9e436c19SHarald Freudenberger 		pkeytype = PKEY_KEYTYPE_ECC;
163*9e436c19SHarald Freudenberger 		fc = CPACF_PCKMO_ENC_ECC_ED448_KEY;
164*9e436c19SHarald Freudenberger 		break;
165e80d4af0SHarald Freudenberger 	default:
166f370f45cSHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported keytype %u\n",
167ac2b96f3SHarald Freudenberger 			  __func__, keytype);
168e80d4af0SHarald Freudenberger 		return -EINVAL;
169e80d4af0SHarald Freudenberger 	}
170e80d4af0SHarald Freudenberger 
171f370f45cSHarald Freudenberger 	if (*protkeylen < keysize + AES_WK_VP_SIZE) {
172f370f45cSHarald Freudenberger 		DEBUG_ERR("%s prot key buffer size too small: %u < %d\n",
173f370f45cSHarald Freudenberger 			  __func__, *protkeylen, keysize + AES_WK_VP_SIZE);
174f370f45cSHarald Freudenberger 		return -EINVAL;
175f370f45cSHarald Freudenberger 	}
176f370f45cSHarald Freudenberger 
1775b35047eSHarald Freudenberger 	/* Did we already check for PCKMO ? */
1785b35047eSHarald Freudenberger 	if (!pckmo_functions.bytes[0]) {
1795b35047eSHarald Freudenberger 		/* no, so check now */
1805b35047eSHarald Freudenberger 		if (!cpacf_query(CPACF_PCKMO, &pckmo_functions))
1815b35047eSHarald Freudenberger 			return -ENODEV;
1825b35047eSHarald Freudenberger 	}
1835b35047eSHarald Freudenberger 	/* check for the pckmo subfunction we need now */
184f822ad2cSHarald Freudenberger 	if (!cpacf_test_func(&pckmo_functions, fc)) {
185f822ad2cSHarald Freudenberger 		DEBUG_ERR("%s pckmo functions not available\n", __func__);
18658443b67SDavid Hildenbrand 		return -ENODEV;
187f822ad2cSHarald Freudenberger 	}
188f822ad2cSHarald Freudenberger 
189e80d4af0SHarald Freudenberger 	/* prepare param block */
190e80d4af0SHarald Freudenberger 	memset(paramblock, 0, sizeof(paramblock));
191f370f45cSHarald Freudenberger 	memcpy(paramblock, clrkey, keysize);
192e80d4af0SHarald Freudenberger 
193e80d4af0SHarald Freudenberger 	/* call the pckmo instruction */
194e80d4af0SHarald Freudenberger 	cpacf_pckmo(fc, paramblock);
195e80d4af0SHarald Freudenberger 
196f370f45cSHarald Freudenberger 	/* copy created protected key to key buffer including the wkvp block */
197f370f45cSHarald Freudenberger 	*protkeylen = keysize + AES_WK_VP_SIZE;
198f370f45cSHarald Freudenberger 	memcpy(protkey, paramblock, *protkeylen);
199*9e436c19SHarald Freudenberger 	*protkeytype = pkeytype;
200e80d4af0SHarald Freudenberger 
201e80d4af0SHarald Freudenberger 	return 0;
202e80d4af0SHarald Freudenberger }
203e80d4af0SHarald Freudenberger 
204e80d4af0SHarald Freudenberger /*
205e80d4af0SHarald Freudenberger  * Find card and transform secure key into protected key.
206e80d4af0SHarald Freudenberger  */
207f370f45cSHarald Freudenberger static int pkey_skey2pkey(const u8 *key, u8 *protkey,
208f370f45cSHarald Freudenberger 			  u32 *protkeylen, u32 *protkeytype)
209e80d4af0SHarald Freudenberger {
210f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
21146a29b03SHarald Freudenberger 	u16 cardnr, domain;
21246a29b03SHarald Freudenberger 	int rc, verify;
213e80d4af0SHarald Freudenberger 
21443cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
21543cb5a7cSHarald Freudenberger 
216e80d4af0SHarald Freudenberger 	/*
217f2bbc96eSHarald Freudenberger 	 * The cca_xxx2protkey call may fail when a card has been
218e80d4af0SHarald Freudenberger 	 * addressed where the master key was changed after last fetch
219f4272c03SJulia Lawall 	 * of the mkvp into the cache. Try 3 times: First without verify
220efc598e6SHarald Freudenberger 	 * then with verify and last round with verify and old master
221efc598e6SHarald Freudenberger 	 * key verification pattern match not ignored.
222e80d4af0SHarald Freudenberger 	 */
223efc598e6SHarald Freudenberger 	for (verify = 0; verify < 3; verify++) {
224f2bbc96eSHarald Freudenberger 		rc = cca_findcard(key, &cardnr, &domain, verify);
225efc598e6SHarald Freudenberger 		if (rc < 0)
226e80d4af0SHarald Freudenberger 			continue;
227efc598e6SHarald Freudenberger 		if (rc > 0 && verify < 2)
228efc598e6SHarald Freudenberger 			continue;
229f2bbc96eSHarald Freudenberger 		switch (hdr->version) {
230f2bbc96eSHarald Freudenberger 		case TOKVER_CCA_AES:
231f370f45cSHarald Freudenberger 			rc = cca_sec2protkey(cardnr, domain, key,
232f370f45cSHarald Freudenberger 					     protkey, protkeylen, protkeytype);
233f2bbc96eSHarald Freudenberger 			break;
234f2bbc96eSHarald Freudenberger 		case TOKVER_CCA_VLSC:
235f370f45cSHarald Freudenberger 			rc = cca_cipher2protkey(cardnr, domain, key,
236f370f45cSHarald Freudenberger 						protkey, protkeylen,
237f370f45cSHarald Freudenberger 						protkeytype);
238f2bbc96eSHarald Freudenberger 			break;
239f2bbc96eSHarald Freudenberger 		default:
240f2bbc96eSHarald Freudenberger 			return -EINVAL;
241f2bbc96eSHarald Freudenberger 		}
242e80d4af0SHarald Freudenberger 		if (rc == 0)
243e80d4af0SHarald Freudenberger 			break;
244e80d4af0SHarald Freudenberger 	}
245e80d4af0SHarald Freudenberger 
246e80d4af0SHarald Freudenberger 	if (rc)
247ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s failed rc=%d\n", __func__, rc);
248e80d4af0SHarald Freudenberger 
249e80d4af0SHarald Freudenberger 	return rc;
250e80d4af0SHarald Freudenberger }
251e80d4af0SHarald Freudenberger 
252e80d4af0SHarald Freudenberger /*
25355d0a513SHarald Freudenberger  * Construct EP11 key with given clear key value.
25455d0a513SHarald Freudenberger  */
25555d0a513SHarald Freudenberger static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen,
25655d0a513SHarald Freudenberger 			    u8 *keybuf, size_t *keybuflen)
25755d0a513SHarald Freudenberger {
25855d0a513SHarald Freudenberger 	u32 nr_apqns, *apqns = NULL;
25946a29b03SHarald Freudenberger 	u16 card, dom;
26046a29b03SHarald Freudenberger 	int i, rc;
26155d0a513SHarald Freudenberger 
26243cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
26343cb5a7cSHarald Freudenberger 
26455d0a513SHarald Freudenberger 	/* build a list of apqns suitable for ep11 keys with cpacf support */
26555d0a513SHarald Freudenberger 	rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
26655d0a513SHarald Freudenberger 			    ZCRYPT_CEX7, EP11_API_V, NULL);
26755d0a513SHarald Freudenberger 	if (rc)
26855d0a513SHarald Freudenberger 		goto out;
26955d0a513SHarald Freudenberger 
27055d0a513SHarald Freudenberger 	/* go through the list of apqns and try to bild an ep11 key */
27155d0a513SHarald Freudenberger 	for (rc = -ENODEV, i = 0; i < nr_apqns; i++) {
27255d0a513SHarald Freudenberger 		card = apqns[i] >> 16;
27355d0a513SHarald Freudenberger 		dom = apqns[i] & 0xFFFF;
27455d0a513SHarald Freudenberger 		rc = ep11_clr2keyblob(card, dom, clrkeylen * 8,
27555d0a513SHarald Freudenberger 				      0, clrkey, keybuf, keybuflen);
27655d0a513SHarald Freudenberger 		if (rc == 0)
27755d0a513SHarald Freudenberger 			break;
27855d0a513SHarald Freudenberger 	}
27955d0a513SHarald Freudenberger 
28055d0a513SHarald Freudenberger out:
28155d0a513SHarald Freudenberger 	kfree(apqns);
28255d0a513SHarald Freudenberger 	if (rc)
28355d0a513SHarald Freudenberger 		DEBUG_DBG("%s failed rc=%d\n", __func__, rc);
28455d0a513SHarald Freudenberger 	return rc;
28555d0a513SHarald Freudenberger }
28655d0a513SHarald Freudenberger 
28755d0a513SHarald Freudenberger /*
28855d0a513SHarald Freudenberger  * Find card and transform EP11 secure key into protected key.
28955d0a513SHarald Freudenberger  */
290f370f45cSHarald Freudenberger static int pkey_ep11key2pkey(const u8 *key, u8 *protkey,
291f370f45cSHarald Freudenberger 			     u32 *protkeylen, u32 *protkeytype)
29255d0a513SHarald Freudenberger {
29355d0a513SHarald Freudenberger 	struct ep11keyblob *kb = (struct ep11keyblob *)key;
29446a29b03SHarald Freudenberger 	u32 nr_apqns, *apqns = NULL;
29546a29b03SHarald Freudenberger 	u16 card, dom;
29646a29b03SHarald Freudenberger 	int i, rc;
29755d0a513SHarald Freudenberger 
29843cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
29943cb5a7cSHarald Freudenberger 
30055d0a513SHarald Freudenberger 	/* build a list of apqns suitable for this key */
30155d0a513SHarald Freudenberger 	rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
30255d0a513SHarald Freudenberger 			    ZCRYPT_CEX7, EP11_API_V, kb->wkvp);
30355d0a513SHarald Freudenberger 	if (rc)
30455d0a513SHarald Freudenberger 		goto out;
30555d0a513SHarald Freudenberger 
30655d0a513SHarald Freudenberger 	/* go through the list of apqns and try to derive an pkey */
30755d0a513SHarald Freudenberger 	for (rc = -ENODEV, i = 0; i < nr_apqns; i++) {
30855d0a513SHarald Freudenberger 		card = apqns[i] >> 16;
30955d0a513SHarald Freudenberger 		dom = apqns[i] & 0xFFFF;
310fa6999e3SHarald Freudenberger 		rc = ep11_kblob2protkey(card, dom, key, kb->head.len,
311f370f45cSHarald Freudenberger 					protkey, protkeylen, protkeytype);
31255d0a513SHarald Freudenberger 		if (rc == 0)
31355d0a513SHarald Freudenberger 			break;
31455d0a513SHarald Freudenberger 	}
31555d0a513SHarald Freudenberger 
31655d0a513SHarald Freudenberger out:
31755d0a513SHarald Freudenberger 	kfree(apqns);
31855d0a513SHarald Freudenberger 	if (rc)
31955d0a513SHarald Freudenberger 		DEBUG_DBG("%s failed rc=%d\n", __func__, rc);
32055d0a513SHarald Freudenberger 	return rc;
32155d0a513SHarald Freudenberger }
32255d0a513SHarald Freudenberger 
32355d0a513SHarald Freudenberger /*
324e61a6134SHarald Freudenberger  * Verify key and give back some info about the key.
325e61a6134SHarald Freudenberger  */
326183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey,
327e61a6134SHarald Freudenberger 			  u16 *pcardnr, u16 *pdomain,
328e61a6134SHarald Freudenberger 			  u16 *pkeysize, u32 *pattributes)
329e61a6134SHarald Freudenberger {
330e61a6134SHarald Freudenberger 	struct secaeskeytoken *t = (struct secaeskeytoken *)seckey;
331e61a6134SHarald Freudenberger 	u16 cardnr, domain;
332e61a6134SHarald Freudenberger 	int rc;
333e61a6134SHarald Freudenberger 
334e61a6134SHarald Freudenberger 	/* check the secure key for valid AES secure key */
335efc598e6SHarald Freudenberger 	rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *)seckey, 0);
336e61a6134SHarald Freudenberger 	if (rc)
337e61a6134SHarald Freudenberger 		goto out;
338e61a6134SHarald Freudenberger 	if (pattributes)
339e61a6134SHarald Freudenberger 		*pattributes = PKEY_VERIFY_ATTR_AES;
340e61a6134SHarald Freudenberger 	if (pkeysize)
341e61a6134SHarald Freudenberger 		*pkeysize = t->bitsize;
342e61a6134SHarald Freudenberger 
343e61a6134SHarald Freudenberger 	/* try to find a card which can handle this key */
344efc598e6SHarald Freudenberger 	rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1);
345efc598e6SHarald Freudenberger 	if (rc < 0)
346e61a6134SHarald Freudenberger 		goto out;
347e61a6134SHarald Freudenberger 
348efc598e6SHarald Freudenberger 	if (rc > 0) {
349efc598e6SHarald Freudenberger 		/* key mkvp matches to old master key mkvp */
350ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s secure key has old mkvp\n", __func__);
351e61a6134SHarald Freudenberger 		if (pattributes)
352e61a6134SHarald Freudenberger 			*pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP;
353efc598e6SHarald Freudenberger 		rc = 0;
354e61a6134SHarald Freudenberger 	}
355e61a6134SHarald Freudenberger 
356e61a6134SHarald Freudenberger 	if (pcardnr)
357e61a6134SHarald Freudenberger 		*pcardnr = cardnr;
358e61a6134SHarald Freudenberger 	if (pdomain)
359e61a6134SHarald Freudenberger 		*pdomain = domain;
360e61a6134SHarald Freudenberger 
361e61a6134SHarald Freudenberger out:
362ac2b96f3SHarald Freudenberger 	DEBUG_DBG("%s rc=%d\n", __func__, rc);
363e61a6134SHarald Freudenberger 	return rc;
364e61a6134SHarald Freudenberger }
365e61a6134SHarald Freudenberger 
366e61a6134SHarald Freudenberger /*
367a45a5c7dSIngo Franzki  * Generate a random protected key
368a45a5c7dSIngo Franzki  */
369f370f45cSHarald Freudenberger static int pkey_genprotkey(u32 keytype, u8 *protkey,
370f370f45cSHarald Freudenberger 			   u32 *protkeylen, u32 *protkeytype)
371a45a5c7dSIngo Franzki {
372f370f45cSHarald Freudenberger 	u8 clrkey[32];
373a45a5c7dSIngo Franzki 	int keysize;
374a45a5c7dSIngo Franzki 	int rc;
375a45a5c7dSIngo Franzki 
376*9e436c19SHarald Freudenberger 	keysize = pkey_keytype_aes_to_size(keytype);
377*9e436c19SHarald Freudenberger 	if (!keysize) {
378a45a5c7dSIngo Franzki 		DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__,
379a45a5c7dSIngo Franzki 			  keytype);
380a45a5c7dSIngo Franzki 		return -EINVAL;
381a45a5c7dSIngo Franzki 	}
382a45a5c7dSIngo Franzki 
383a45a5c7dSIngo Franzki 	/* generate a dummy random clear key */
384f370f45cSHarald Freudenberger 	get_random_bytes(clrkey, keysize);
385a45a5c7dSIngo Franzki 
386a45a5c7dSIngo Franzki 	/* convert it to a dummy protected key */
387f370f45cSHarald Freudenberger 	rc = pkey_clr2protkey(keytype, clrkey,
388f370f45cSHarald Freudenberger 			      protkey, protkeylen, protkeytype);
389a45a5c7dSIngo Franzki 	if (rc)
390a45a5c7dSIngo Franzki 		return rc;
391a45a5c7dSIngo Franzki 
392a45a5c7dSIngo Franzki 	/* replace the key part of the protected key with random bytes */
393f370f45cSHarald Freudenberger 	get_random_bytes(protkey, keysize);
394a45a5c7dSIngo Franzki 
395a45a5c7dSIngo Franzki 	return 0;
396a45a5c7dSIngo Franzki }
397a45a5c7dSIngo Franzki 
398a45a5c7dSIngo Franzki /*
399cb26b9ffSIngo Franzki  * Verify if a protected key is still valid
400cb26b9ffSIngo Franzki  */
401f370f45cSHarald Freudenberger static int pkey_verifyprotkey(const u8 *protkey, u32 protkeylen,
402f370f45cSHarald Freudenberger 			      u32 protkeytype)
403cb26b9ffSIngo Franzki {
404cb26b9ffSIngo Franzki 	struct {
405cb26b9ffSIngo Franzki 		u8 iv[AES_BLOCK_SIZE];
406cb26b9ffSIngo Franzki 		u8 key[MAXPROTKEYSIZE];
407cb26b9ffSIngo Franzki 	} param;
408cb26b9ffSIngo Franzki 	u8 null_msg[AES_BLOCK_SIZE];
409cb26b9ffSIngo Franzki 	u8 dest_buf[AES_BLOCK_SIZE];
410f370f45cSHarald Freudenberger 	unsigned int k, pkeylen;
41146a29b03SHarald Freudenberger 	unsigned long fc;
412cb26b9ffSIngo Franzki 
413f370f45cSHarald Freudenberger 	switch (protkeytype) {
414cb26b9ffSIngo Franzki 	case PKEY_KEYTYPE_AES_128:
415f370f45cSHarald Freudenberger 		pkeylen = 16 + AES_WK_VP_SIZE;
416cb26b9ffSIngo Franzki 		fc = CPACF_KMC_PAES_128;
417cb26b9ffSIngo Franzki 		break;
418cb26b9ffSIngo Franzki 	case PKEY_KEYTYPE_AES_192:
419f370f45cSHarald Freudenberger 		pkeylen = 24 + AES_WK_VP_SIZE;
420cb26b9ffSIngo Franzki 		fc = CPACF_KMC_PAES_192;
421cb26b9ffSIngo Franzki 		break;
422cb26b9ffSIngo Franzki 	case PKEY_KEYTYPE_AES_256:
423f370f45cSHarald Freudenberger 		pkeylen = 32 + AES_WK_VP_SIZE;
424cb26b9ffSIngo Franzki 		fc = CPACF_KMC_PAES_256;
425cb26b9ffSIngo Franzki 		break;
426cb26b9ffSIngo Franzki 	default:
427f370f45cSHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported keytype %u\n", __func__,
428f370f45cSHarald Freudenberger 			  protkeytype);
429f370f45cSHarald Freudenberger 		return -EINVAL;
430f370f45cSHarald Freudenberger 	}
431f370f45cSHarald Freudenberger 	if (protkeylen != pkeylen) {
432f370f45cSHarald Freudenberger 		DEBUG_ERR("%s invalid protected key size %u for keytype %u\n",
433f370f45cSHarald Freudenberger 			  __func__, protkeylen, protkeytype);
434cb26b9ffSIngo Franzki 		return -EINVAL;
435cb26b9ffSIngo Franzki 	}
436cb26b9ffSIngo Franzki 
437cb26b9ffSIngo Franzki 	memset(null_msg, 0, sizeof(null_msg));
438cb26b9ffSIngo Franzki 
439cb26b9ffSIngo Franzki 	memset(param.iv, 0, sizeof(param.iv));
440f370f45cSHarald Freudenberger 	memcpy(param.key, protkey, protkeylen);
441cb26b9ffSIngo Franzki 
442cb26b9ffSIngo Franzki 	k = cpacf_kmc(fc | CPACF_ENCRYPT, &param, null_msg, dest_buf,
443cb26b9ffSIngo Franzki 		      sizeof(null_msg));
444cb26b9ffSIngo Franzki 	if (k != sizeof(null_msg)) {
445cb26b9ffSIngo Franzki 		DEBUG_ERR("%s protected key is not valid\n", __func__);
446cb26b9ffSIngo Franzki 		return -EKEYREJECTED;
447cb26b9ffSIngo Franzki 	}
448cb26b9ffSIngo Franzki 
449cb26b9ffSIngo Franzki 	return 0;
450cb26b9ffSIngo Franzki }
451cb26b9ffSIngo Franzki 
452*9e436c19SHarald Freudenberger /* Helper for pkey_nonccatok2pkey, handles aes clear key token */
453*9e436c19SHarald Freudenberger static int nonccatokaes2pkey(const struct clearkeytoken *t,
454*9e436c19SHarald Freudenberger 			     u8 *protkey, u32 *protkeylen, u32 *protkeytype)
455*9e436c19SHarald Freudenberger {
456*9e436c19SHarald Freudenberger 	size_t tmpbuflen = max_t(size_t, SECKEYBLOBSIZE, MAXEP11AESKEYBLOBSIZE);
457*9e436c19SHarald Freudenberger 	u8 *tmpbuf = NULL;
458*9e436c19SHarald Freudenberger 	u32 keysize;
459*9e436c19SHarald Freudenberger 	int rc;
460*9e436c19SHarald Freudenberger 
461*9e436c19SHarald Freudenberger 	keysize = pkey_keytype_aes_to_size(t->keytype);
462*9e436c19SHarald Freudenberger 	if (!keysize) {
463*9e436c19SHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported keytype %u\n",
464*9e436c19SHarald Freudenberger 			  __func__, t->keytype);
465*9e436c19SHarald Freudenberger 		return -EINVAL;
466*9e436c19SHarald Freudenberger 	}
467*9e436c19SHarald Freudenberger 	if (t->len != keysize) {
468*9e436c19SHarald Freudenberger 		DEBUG_ERR("%s non clear key aes token: invalid key len %u\n",
469*9e436c19SHarald Freudenberger 			  __func__, t->len);
470*9e436c19SHarald Freudenberger 		return -EINVAL;
471*9e436c19SHarald Freudenberger 	}
472*9e436c19SHarald Freudenberger 
473*9e436c19SHarald Freudenberger 	/* try direct way with the PCKMO instruction */
474*9e436c19SHarald Freudenberger 	rc = pkey_clr2protkey(t->keytype, t->clearkey,
475*9e436c19SHarald Freudenberger 			      protkey, protkeylen, protkeytype);
476*9e436c19SHarald Freudenberger 	if (!rc)
477*9e436c19SHarald Freudenberger 		goto out;
478*9e436c19SHarald Freudenberger 
479*9e436c19SHarald Freudenberger 	/* PCKMO failed, so try the CCA secure key way */
480*9e436c19SHarald Freudenberger 	tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC);
481*9e436c19SHarald Freudenberger 	if (!tmpbuf)
482*9e436c19SHarald Freudenberger 		return -ENOMEM;
483*9e436c19SHarald Freudenberger 	zcrypt_wait_api_operational();
484*9e436c19SHarald Freudenberger 	rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, t->clearkey, tmpbuf);
485*9e436c19SHarald Freudenberger 	if (rc)
486*9e436c19SHarald Freudenberger 		goto try_via_ep11;
487*9e436c19SHarald Freudenberger 	rc = pkey_skey2pkey(tmpbuf,
488*9e436c19SHarald Freudenberger 			    protkey, protkeylen, protkeytype);
489*9e436c19SHarald Freudenberger 	if (!rc)
490*9e436c19SHarald Freudenberger 		goto out;
491*9e436c19SHarald Freudenberger 
492*9e436c19SHarald Freudenberger try_via_ep11:
493*9e436c19SHarald Freudenberger 	/* if the CCA way also failed, let's try via EP11 */
494*9e436c19SHarald Freudenberger 	rc = pkey_clr2ep11key(t->clearkey, t->len,
495*9e436c19SHarald Freudenberger 			      tmpbuf, &tmpbuflen);
496*9e436c19SHarald Freudenberger 	if (rc)
497*9e436c19SHarald Freudenberger 		goto failure;
498*9e436c19SHarald Freudenberger 	rc = pkey_ep11key2pkey(tmpbuf,
499*9e436c19SHarald Freudenberger 			       protkey, protkeylen, protkeytype);
500*9e436c19SHarald Freudenberger 	if (!rc)
501*9e436c19SHarald Freudenberger 		goto out;
502*9e436c19SHarald Freudenberger 
503*9e436c19SHarald Freudenberger failure:
504*9e436c19SHarald Freudenberger 	DEBUG_ERR("%s unable to build protected key from clear", __func__);
505*9e436c19SHarald Freudenberger 
506*9e436c19SHarald Freudenberger out:
507*9e436c19SHarald Freudenberger 	kfree(tmpbuf);
508*9e436c19SHarald Freudenberger 	return rc;
509*9e436c19SHarald Freudenberger }
510*9e436c19SHarald Freudenberger 
511*9e436c19SHarald Freudenberger /* Helper for pkey_nonccatok2pkey, handles ecc clear key token */
512*9e436c19SHarald Freudenberger static int nonccatokecc2pkey(const struct clearkeytoken *t,
513*9e436c19SHarald Freudenberger 			     u8 *protkey, u32 *protkeylen, u32 *protkeytype)
514*9e436c19SHarald Freudenberger {
515*9e436c19SHarald Freudenberger 	u32 keylen;
516*9e436c19SHarald Freudenberger 	int rc;
517*9e436c19SHarald Freudenberger 
518*9e436c19SHarald Freudenberger 	switch (t->keytype) {
519*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_ECC_P256:
520*9e436c19SHarald Freudenberger 		keylen = 32;
521*9e436c19SHarald Freudenberger 		break;
522*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_ECC_P384:
523*9e436c19SHarald Freudenberger 		keylen = 48;
524*9e436c19SHarald Freudenberger 		break;
525*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_ECC_P521:
526*9e436c19SHarald Freudenberger 		keylen = 80;
527*9e436c19SHarald Freudenberger 		break;
528*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_ECC_ED25519:
529*9e436c19SHarald Freudenberger 		keylen = 32;
530*9e436c19SHarald Freudenberger 		break;
531*9e436c19SHarald Freudenberger 	case PKEY_KEYTYPE_ECC_ED448:
532*9e436c19SHarald Freudenberger 		keylen = 64;
533*9e436c19SHarald Freudenberger 		break;
534*9e436c19SHarald Freudenberger 	default:
535*9e436c19SHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported keytype %u\n",
536*9e436c19SHarald Freudenberger 			  __func__, t->keytype);
537*9e436c19SHarald Freudenberger 		return -EINVAL;
538*9e436c19SHarald Freudenberger 	}
539*9e436c19SHarald Freudenberger 
540*9e436c19SHarald Freudenberger 	if (t->len != keylen) {
541*9e436c19SHarald Freudenberger 		DEBUG_ERR("%s non clear key ecc token: invalid key len %u\n",
542*9e436c19SHarald Freudenberger 			  __func__, t->len);
543*9e436c19SHarald Freudenberger 		return -EINVAL;
544*9e436c19SHarald Freudenberger 	}
545*9e436c19SHarald Freudenberger 
546*9e436c19SHarald Freudenberger 	/* only one path possible: via PCKMO instruction */
547*9e436c19SHarald Freudenberger 	rc = pkey_clr2protkey(t->keytype, t->clearkey,
548*9e436c19SHarald Freudenberger 			      protkey, protkeylen, protkeytype);
549*9e436c19SHarald Freudenberger 	if (rc) {
550*9e436c19SHarald Freudenberger 		DEBUG_ERR("%s unable to build protected key from clear",
551*9e436c19SHarald Freudenberger 			  __func__);
552*9e436c19SHarald Freudenberger 	}
553*9e436c19SHarald Freudenberger 
554*9e436c19SHarald Freudenberger 	return rc;
555*9e436c19SHarald Freudenberger }
556*9e436c19SHarald Freudenberger 
557cb26b9ffSIngo Franzki /*
558fb1136d6SIngo Franzki  * Transform a non-CCA key token into a protected key
559fb1136d6SIngo Franzki  */
560183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
561f370f45cSHarald Freudenberger 			       u8 *protkey, u32 *protkeylen, u32 *protkeytype)
562fb1136d6SIngo Franzki {
563fb1136d6SIngo Franzki 	struct keytoken_header *hdr = (struct keytoken_header *)key;
56446a29b03SHarald Freudenberger 	int rc = -EINVAL;
565fb1136d6SIngo Franzki 
566fb1136d6SIngo Franzki 	switch (hdr->version) {
567888edbc4SHarald Freudenberger 	case TOKVER_PROTECTED_KEY: {
568888edbc4SHarald Freudenberger 		struct protaeskeytoken *t;
569fb1136d6SIngo Franzki 
570888edbc4SHarald Freudenberger 		if (keylen != sizeof(struct protaeskeytoken))
571888edbc4SHarald Freudenberger 			goto out;
572fb1136d6SIngo Franzki 		t = (struct protaeskeytoken *)key;
573f370f45cSHarald Freudenberger 		rc = pkey_verifyprotkey(t->protkey, t->len, t->keytype);
574f370f45cSHarald Freudenberger 		if (rc)
575f370f45cSHarald Freudenberger 			goto out;
576f370f45cSHarald Freudenberger 		memcpy(protkey, t->protkey, t->len);
577f370f45cSHarald Freudenberger 		*protkeylen = t->len;
578f370f45cSHarald Freudenberger 		*protkeytype = t->keytype;
579888edbc4SHarald Freudenberger 		break;
580888edbc4SHarald Freudenberger 	}
581888edbc4SHarald Freudenberger 	case TOKVER_CLEAR_KEY: {
582*9e436c19SHarald Freudenberger 		struct clearkeytoken *t = (struct clearkeytoken *)key;
583fb1136d6SIngo Franzki 
584*9e436c19SHarald Freudenberger 		if (keylen < sizeof(struct clearkeytoken) ||
585*9e436c19SHarald Freudenberger 		    keylen != sizeof(*t) + t->len)
586888edbc4SHarald Freudenberger 			goto out;
587*9e436c19SHarald Freudenberger 		switch (t->keytype) {
588*9e436c19SHarald Freudenberger 		case PKEY_KEYTYPE_AES_128:
589*9e436c19SHarald Freudenberger 		case PKEY_KEYTYPE_AES_192:
590*9e436c19SHarald Freudenberger 		case PKEY_KEYTYPE_AES_256:
591*9e436c19SHarald Freudenberger 			rc = nonccatokaes2pkey(t, protkey,
592*9e436c19SHarald Freudenberger 					       protkeylen, protkeytype);
593*9e436c19SHarald Freudenberger 			break;
594*9e436c19SHarald Freudenberger 		case PKEY_KEYTYPE_ECC_P256:
595*9e436c19SHarald Freudenberger 		case PKEY_KEYTYPE_ECC_P384:
596*9e436c19SHarald Freudenberger 		case PKEY_KEYTYPE_ECC_P521:
597*9e436c19SHarald Freudenberger 		case PKEY_KEYTYPE_ECC_ED25519:
598*9e436c19SHarald Freudenberger 		case PKEY_KEYTYPE_ECC_ED448:
599*9e436c19SHarald Freudenberger 			rc = nonccatokecc2pkey(t, protkey,
600*9e436c19SHarald Freudenberger 					       protkeylen, protkeytype);
601*9e436c19SHarald Freudenberger 			break;
602*9e436c19SHarald Freudenberger 		default:
603*9e436c19SHarald Freudenberger 			DEBUG_ERR("%s unknown/unsupported non cca clear key type %u\n",
604*9e436c19SHarald Freudenberger 				  __func__, t->keytype);
605*9e436c19SHarald Freudenberger 			return -EINVAL;
60655d0a513SHarald Freudenberger 		}
607888edbc4SHarald Freudenberger 		break;
608888edbc4SHarald Freudenberger 	}
60955d0a513SHarald Freudenberger 	case TOKVER_EP11_AES: {
61055d0a513SHarald Freudenberger 		/* check ep11 key for exportable as protected key */
611fa6999e3SHarald Freudenberger 		rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1);
61255d0a513SHarald Freudenberger 		if (rc)
61355d0a513SHarald Freudenberger 			goto out;
614f370f45cSHarald Freudenberger 		rc = pkey_ep11key2pkey(key,
615f370f45cSHarald Freudenberger 				       protkey, protkeylen, protkeytype);
61655d0a513SHarald Freudenberger 		break;
61755d0a513SHarald Freudenberger 	}
618fa6999e3SHarald Freudenberger 	case TOKVER_EP11_AES_WITH_HEADER:
619fa6999e3SHarald Freudenberger 		/* check ep11 key with header for exportable as protected key */
620fa6999e3SHarald Freudenberger 		rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1);
621fa6999e3SHarald Freudenberger 		if (rc)
622fa6999e3SHarald Freudenberger 			goto out;
623fa6999e3SHarald Freudenberger 		rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header),
624f370f45cSHarald Freudenberger 				       protkey, protkeylen, protkeytype);
625fa6999e3SHarald Freudenberger 		break;
626fb1136d6SIngo Franzki 	default:
627fb1136d6SIngo Franzki 		DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n",
628fb1136d6SIngo Franzki 			  __func__, hdr->version);
629fb1136d6SIngo Franzki 	}
630888edbc4SHarald Freudenberger 
631888edbc4SHarald Freudenberger out:
632888edbc4SHarald Freudenberger 	return rc;
633fb1136d6SIngo Franzki }
634fb1136d6SIngo Franzki 
635fb1136d6SIngo Franzki /*
636fb1136d6SIngo Franzki  * Transform a CCA internal key token into a protected key
637fb1136d6SIngo Franzki  */
638183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen,
639f370f45cSHarald Freudenberger 			       u8 *protkey, u32 *protkeylen, u32 *protkeytype)
640fb1136d6SIngo Franzki {
641fb1136d6SIngo Franzki 	struct keytoken_header *hdr = (struct keytoken_header *)key;
642fb1136d6SIngo Franzki 
643fb1136d6SIngo Franzki 	switch (hdr->version) {
644fb1136d6SIngo Franzki 	case TOKVER_CCA_AES:
645fb1136d6SIngo Franzki 		if (keylen != sizeof(struct secaeskeytoken))
646fb1136d6SIngo Franzki 			return -EINVAL;
647f2bbc96eSHarald Freudenberger 		break;
648f2bbc96eSHarald Freudenberger 	case TOKVER_CCA_VLSC:
649f2bbc96eSHarald Freudenberger 		if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
650f2bbc96eSHarald Freudenberger 			return -EINVAL;
651f2bbc96eSHarald Freudenberger 		break;
652fb1136d6SIngo Franzki 	default:
653fb1136d6SIngo Franzki 		DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n",
654fb1136d6SIngo Franzki 			  __func__, hdr->version);
655fb1136d6SIngo Franzki 		return -EINVAL;
656fb1136d6SIngo Franzki 	}
657f2bbc96eSHarald Freudenberger 
658f370f45cSHarald Freudenberger 	return pkey_skey2pkey(key, protkey, protkeylen, protkeytype);
659fb1136d6SIngo Franzki }
660fb1136d6SIngo Franzki 
661fb1136d6SIngo Franzki /*
662fb1136d6SIngo Franzki  * Transform a key blob (of any type) into a protected key
663fb1136d6SIngo Franzki  */
664183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen,
665f370f45cSHarald Freudenberger 		      u8 *protkey, u32 *protkeylen, u32 *protkeytype)
666fb1136d6SIngo Franzki {
667fb1136d6SIngo Franzki 	struct keytoken_header *hdr = (struct keytoken_header *)key;
66846a29b03SHarald Freudenberger 	int rc;
669fb1136d6SIngo Franzki 
670f2bbc96eSHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header)) {
671f2bbc96eSHarald Freudenberger 		DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen);
672f2bbc96eSHarald Freudenberger 		return -EINVAL;
673f2bbc96eSHarald Freudenberger 	}
674f2bbc96eSHarald Freudenberger 
675f2bbc96eSHarald Freudenberger 	switch (hdr->type) {
676f2bbc96eSHarald Freudenberger 	case TOKTYPE_NON_CCA:
677f370f45cSHarald Freudenberger 		rc = pkey_nonccatok2pkey(key, keylen,
678f370f45cSHarald Freudenberger 					 protkey, protkeylen, protkeytype);
679f2bbc96eSHarald Freudenberger 		break;
680f2bbc96eSHarald Freudenberger 	case TOKTYPE_CCA_INTERNAL:
681f370f45cSHarald Freudenberger 		rc = pkey_ccainttok2pkey(key, keylen,
682f370f45cSHarald Freudenberger 					 protkey, protkeylen, protkeytype);
683f2bbc96eSHarald Freudenberger 		break;
684f2bbc96eSHarald Freudenberger 	default:
685f2bbc96eSHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported blob type %d\n",
686f2bbc96eSHarald Freudenberger 			  __func__, hdr->type);
687f2bbc96eSHarald Freudenberger 		return -EINVAL;
688f2bbc96eSHarald Freudenberger 	}
689f2bbc96eSHarald Freudenberger 
690f2bbc96eSHarald Freudenberger 	DEBUG_DBG("%s rc=%d\n", __func__, rc);
691f2bbc96eSHarald Freudenberger 	return rc;
692f2bbc96eSHarald Freudenberger }
693f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey);
694f2bbc96eSHarald Freudenberger 
695f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns,
696f2bbc96eSHarald Freudenberger 			   enum pkey_key_type ktype, enum pkey_key_size ksize,
697f2bbc96eSHarald Freudenberger 			   u32 kflags, u8 *keybuf, size_t *keybufsize)
698f2bbc96eSHarald Freudenberger {
699f2bbc96eSHarald Freudenberger 	int i, card, dom, rc;
700f2bbc96eSHarald Freudenberger 
701f2bbc96eSHarald Freudenberger 	/* check for at least one apqn given */
702f2bbc96eSHarald Freudenberger 	if (!apqns || !nr_apqns)
703f2bbc96eSHarald Freudenberger 		return -EINVAL;
704f2bbc96eSHarald Freudenberger 
705f2bbc96eSHarald Freudenberger 	/* check key type and size */
706f2bbc96eSHarald Freudenberger 	switch (ktype) {
707f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_DATA:
708f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_CIPHER:
709f2bbc96eSHarald Freudenberger 		if (*keybufsize < SECKEYBLOBSIZE)
710f2bbc96eSHarald Freudenberger 			return -EINVAL;
711f2bbc96eSHarald Freudenberger 		break;
71255d0a513SHarald Freudenberger 	case PKEY_TYPE_EP11:
71355d0a513SHarald Freudenberger 		if (*keybufsize < MINEP11AESKEYBLOBSIZE)
71455d0a513SHarald Freudenberger 			return -EINVAL;
71555d0a513SHarald Freudenberger 		break;
716f2bbc96eSHarald Freudenberger 	default:
717f2bbc96eSHarald Freudenberger 		return -EINVAL;
718f2bbc96eSHarald Freudenberger 	}
719f2bbc96eSHarald Freudenberger 	switch (ksize) {
720f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_128:
721f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_192:
722f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_256:
723f2bbc96eSHarald Freudenberger 		break;
724f2bbc96eSHarald Freudenberger 	default:
725f2bbc96eSHarald Freudenberger 		return -EINVAL;
726f2bbc96eSHarald Freudenberger 	}
727f2bbc96eSHarald Freudenberger 
728f2bbc96eSHarald Freudenberger 	/* simple try all apqns from the list */
729f2bbc96eSHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
730f2bbc96eSHarald Freudenberger 		card = apqns[i].card;
731f2bbc96eSHarald Freudenberger 		dom = apqns[i].domain;
73255d0a513SHarald Freudenberger 		if (ktype == PKEY_TYPE_EP11) {
73355d0a513SHarald Freudenberger 			rc = ep11_genaeskey(card, dom, ksize, kflags,
73455d0a513SHarald Freudenberger 					    keybuf, keybufsize);
73555d0a513SHarald Freudenberger 		} else if (ktype == PKEY_TYPE_CCA_DATA) {
736f2bbc96eSHarald Freudenberger 			rc = cca_genseckey(card, dom, ksize, keybuf);
737f2bbc96eSHarald Freudenberger 			*keybufsize = (rc ? 0 : SECKEYBLOBSIZE);
7382004b57cSHarald Freudenberger 		} else {
7392004b57cSHarald Freudenberger 			/* TOKVER_CCA_VLSC */
740f2bbc96eSHarald Freudenberger 			rc = cca_gencipherkey(card, dom, ksize, kflags,
741f2bbc96eSHarald Freudenberger 					      keybuf, keybufsize);
7422004b57cSHarald Freudenberger 		}
743f2bbc96eSHarald Freudenberger 		if (rc == 0)
744f2bbc96eSHarald Freudenberger 			break;
745f2bbc96eSHarald Freudenberger 	}
746f2bbc96eSHarald Freudenberger 
747f2bbc96eSHarald Freudenberger 	return rc;
748f2bbc96eSHarald Freudenberger }
749f2bbc96eSHarald Freudenberger 
750f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns,
751f2bbc96eSHarald Freudenberger 			    enum pkey_key_type ktype, enum pkey_key_size ksize,
752f2bbc96eSHarald Freudenberger 			    u32 kflags, const u8 *clrkey,
753f2bbc96eSHarald Freudenberger 			    u8 *keybuf, size_t *keybufsize)
754f2bbc96eSHarald Freudenberger {
755f2bbc96eSHarald Freudenberger 	int i, card, dom, rc;
756f2bbc96eSHarald Freudenberger 
757f2bbc96eSHarald Freudenberger 	/* check for at least one apqn given */
758f2bbc96eSHarald Freudenberger 	if (!apqns || !nr_apqns)
759f2bbc96eSHarald Freudenberger 		return -EINVAL;
760f2bbc96eSHarald Freudenberger 
761f2bbc96eSHarald Freudenberger 	/* check key type and size */
762f2bbc96eSHarald Freudenberger 	switch (ktype) {
763f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_DATA:
764f2bbc96eSHarald Freudenberger 	case PKEY_TYPE_CCA_CIPHER:
765f2bbc96eSHarald Freudenberger 		if (*keybufsize < SECKEYBLOBSIZE)
766f2bbc96eSHarald Freudenberger 			return -EINVAL;
767f2bbc96eSHarald Freudenberger 		break;
76855d0a513SHarald Freudenberger 	case PKEY_TYPE_EP11:
76955d0a513SHarald Freudenberger 		if (*keybufsize < MINEP11AESKEYBLOBSIZE)
77055d0a513SHarald Freudenberger 			return -EINVAL;
77155d0a513SHarald Freudenberger 		break;
772f2bbc96eSHarald Freudenberger 	default:
773f2bbc96eSHarald Freudenberger 		return -EINVAL;
774f2bbc96eSHarald Freudenberger 	}
775f2bbc96eSHarald Freudenberger 	switch (ksize) {
776f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_128:
777f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_192:
778f2bbc96eSHarald Freudenberger 	case PKEY_SIZE_AES_256:
779f2bbc96eSHarald Freudenberger 		break;
780f2bbc96eSHarald Freudenberger 	default:
781f2bbc96eSHarald Freudenberger 		return -EINVAL;
782f2bbc96eSHarald Freudenberger 	}
783f2bbc96eSHarald Freudenberger 
78443cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
78543cb5a7cSHarald Freudenberger 
786f2bbc96eSHarald Freudenberger 	/* simple try all apqns from the list */
787f2bbc96eSHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
788f2bbc96eSHarald Freudenberger 		card = apqns[i].card;
789f2bbc96eSHarald Freudenberger 		dom = apqns[i].domain;
79055d0a513SHarald Freudenberger 		if (ktype == PKEY_TYPE_EP11) {
79155d0a513SHarald Freudenberger 			rc = ep11_clr2keyblob(card, dom, ksize, kflags,
79255d0a513SHarald Freudenberger 					      clrkey, keybuf, keybufsize);
79355d0a513SHarald Freudenberger 		} else if (ktype == PKEY_TYPE_CCA_DATA) {
794f2bbc96eSHarald Freudenberger 			rc = cca_clr2seckey(card, dom, ksize,
795f2bbc96eSHarald Freudenberger 					    clrkey, keybuf);
796f2bbc96eSHarald Freudenberger 			*keybufsize = (rc ? 0 : SECKEYBLOBSIZE);
7972004b57cSHarald Freudenberger 		} else {
7982004b57cSHarald Freudenberger 			/* TOKVER_CCA_VLSC */
799f2bbc96eSHarald Freudenberger 			rc = cca_clr2cipherkey(card, dom, ksize, kflags,
800f2bbc96eSHarald Freudenberger 					       clrkey, keybuf, keybufsize);
8012004b57cSHarald Freudenberger 		}
802f2bbc96eSHarald Freudenberger 		if (rc == 0)
803f2bbc96eSHarald Freudenberger 			break;
804f2bbc96eSHarald Freudenberger 	}
805f2bbc96eSHarald Freudenberger 
806f2bbc96eSHarald Freudenberger 	return rc;
807f2bbc96eSHarald Freudenberger }
808f2bbc96eSHarald Freudenberger 
809f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen,
810f2bbc96eSHarald Freudenberger 			   u16 *cardnr, u16 *domain,
811f2bbc96eSHarald Freudenberger 			   enum pkey_key_type *ktype,
812f2bbc96eSHarald Freudenberger 			   enum pkey_key_size *ksize, u32 *flags)
813f2bbc96eSHarald Freudenberger {
814f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
81546a29b03SHarald Freudenberger 	u32 _nr_apqns, *_apqns = NULL;
81646a29b03SHarald Freudenberger 	int rc;
817f2bbc96eSHarald Freudenberger 
81855d0a513SHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header))
819f2bbc96eSHarald Freudenberger 		return -EINVAL;
820f2bbc96eSHarald Freudenberger 
8212004b57cSHarald Freudenberger 	if (hdr->type == TOKTYPE_CCA_INTERNAL &&
8222004b57cSHarald Freudenberger 	    hdr->version == TOKVER_CCA_AES) {
823f2bbc96eSHarald Freudenberger 		struct secaeskeytoken *t = (struct secaeskeytoken *)key;
824f2bbc96eSHarald Freudenberger 
825f2bbc96eSHarald Freudenberger 		rc = cca_check_secaeskeytoken(debug_info, 3, key, 0);
826f2bbc96eSHarald Freudenberger 		if (rc)
827f2bbc96eSHarald Freudenberger 			goto out;
828f2bbc96eSHarald Freudenberger 		if (ktype)
829f2bbc96eSHarald Freudenberger 			*ktype = PKEY_TYPE_CCA_DATA;
830f2bbc96eSHarald Freudenberger 		if (ksize)
831f2bbc96eSHarald Freudenberger 			*ksize = (enum pkey_key_size)t->bitsize;
832f2bbc96eSHarald Freudenberger 
833f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
83432ca04bbSHarald Freudenberger 				   ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1);
835f2bbc96eSHarald Freudenberger 		if (rc == 0 && flags)
836f2bbc96eSHarald Freudenberger 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
837f2bbc96eSHarald Freudenberger 		if (rc == -ENODEV) {
838f2bbc96eSHarald Freudenberger 			rc = cca_findcard2(&_apqns, &_nr_apqns,
839f2bbc96eSHarald Freudenberger 					   *cardnr, *domain,
84032ca04bbSHarald Freudenberger 					   ZCRYPT_CEX3C, AES_MK_SET,
84132ca04bbSHarald Freudenberger 					   0, t->mkvp, 1);
842f2bbc96eSHarald Freudenberger 			if (rc == 0 && flags)
843f2bbc96eSHarald Freudenberger 				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
844f2bbc96eSHarald Freudenberger 		}
845f2bbc96eSHarald Freudenberger 		if (rc)
846f2bbc96eSHarald Freudenberger 			goto out;
847f2bbc96eSHarald Freudenberger 
848f2bbc96eSHarald Freudenberger 		*cardnr = ((struct pkey_apqn *)_apqns)->card;
849f2bbc96eSHarald Freudenberger 		*domain = ((struct pkey_apqn *)_apqns)->domain;
850f2bbc96eSHarald Freudenberger 
8512004b57cSHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
8522004b57cSHarald Freudenberger 		   hdr->version == TOKVER_CCA_VLSC) {
853f2bbc96eSHarald Freudenberger 		struct cipherkeytoken *t = (struct cipherkeytoken *)key;
854f2bbc96eSHarald Freudenberger 
855f2bbc96eSHarald Freudenberger 		rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1);
856f2bbc96eSHarald Freudenberger 		if (rc)
857f2bbc96eSHarald Freudenberger 			goto out;
858f2bbc96eSHarald Freudenberger 		if (ktype)
859f2bbc96eSHarald Freudenberger 			*ktype = PKEY_TYPE_CCA_CIPHER;
860f2bbc96eSHarald Freudenberger 		if (ksize) {
861f2bbc96eSHarald Freudenberger 			*ksize = PKEY_SIZE_UNKNOWN;
862f2bbc96eSHarald Freudenberger 			if (!t->plfver && t->wpllen == 512)
863f2bbc96eSHarald Freudenberger 				*ksize = PKEY_SIZE_AES_128;
864f2bbc96eSHarald Freudenberger 			else if (!t->plfver && t->wpllen == 576)
865f2bbc96eSHarald Freudenberger 				*ksize = PKEY_SIZE_AES_192;
866f2bbc96eSHarald Freudenberger 			else if (!t->plfver && t->wpllen == 640)
867f2bbc96eSHarald Freudenberger 				*ksize = PKEY_SIZE_AES_256;
868f2bbc96eSHarald Freudenberger 		}
869f2bbc96eSHarald Freudenberger 
870f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
87132ca04bbSHarald Freudenberger 				   ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1);
872f2bbc96eSHarald Freudenberger 		if (rc == 0 && flags)
873f2bbc96eSHarald Freudenberger 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
874f2bbc96eSHarald Freudenberger 		if (rc == -ENODEV) {
875f2bbc96eSHarald Freudenberger 			rc = cca_findcard2(&_apqns, &_nr_apqns,
876f2bbc96eSHarald Freudenberger 					   *cardnr, *domain,
87732ca04bbSHarald Freudenberger 					   ZCRYPT_CEX6, AES_MK_SET,
87832ca04bbSHarald Freudenberger 					   0, t->mkvp0, 1);
879f2bbc96eSHarald Freudenberger 			if (rc == 0 && flags)
880f2bbc96eSHarald Freudenberger 				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
881f2bbc96eSHarald Freudenberger 		}
882f2bbc96eSHarald Freudenberger 		if (rc)
883f2bbc96eSHarald Freudenberger 			goto out;
884f2bbc96eSHarald Freudenberger 
885f2bbc96eSHarald Freudenberger 		*cardnr = ((struct pkey_apqn *)_apqns)->card;
886f2bbc96eSHarald Freudenberger 		*domain = ((struct pkey_apqn *)_apqns)->domain;
887f2bbc96eSHarald Freudenberger 
8882004b57cSHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA &&
8892004b57cSHarald Freudenberger 		   hdr->version == TOKVER_EP11_AES) {
89055d0a513SHarald Freudenberger 		struct ep11keyblob *kb = (struct ep11keyblob *)key;
89155d0a513SHarald Freudenberger 
892fa6999e3SHarald Freudenberger 		rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1);
89355d0a513SHarald Freudenberger 		if (rc)
89455d0a513SHarald Freudenberger 			goto out;
89555d0a513SHarald Freudenberger 		if (ktype)
89655d0a513SHarald Freudenberger 			*ktype = PKEY_TYPE_EP11;
89755d0a513SHarald Freudenberger 		if (ksize)
89855d0a513SHarald Freudenberger 			*ksize = kb->head.keybitlen;
89955d0a513SHarald Freudenberger 
90055d0a513SHarald Freudenberger 		rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
90155d0a513SHarald Freudenberger 				    ZCRYPT_CEX7, EP11_API_V, kb->wkvp);
90255d0a513SHarald Freudenberger 		if (rc)
90355d0a513SHarald Freudenberger 			goto out;
90455d0a513SHarald Freudenberger 
90555d0a513SHarald Freudenberger 		if (flags)
90655d0a513SHarald Freudenberger 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
90755d0a513SHarald Freudenberger 
90855d0a513SHarald Freudenberger 		*cardnr = ((struct pkey_apqn *)_apqns)->card;
90955d0a513SHarald Freudenberger 		*domain = ((struct pkey_apqn *)_apqns)->domain;
91055d0a513SHarald Freudenberger 
9112004b57cSHarald Freudenberger 	} else {
912f2bbc96eSHarald Freudenberger 		rc = -EINVAL;
9132004b57cSHarald Freudenberger 	}
914f2bbc96eSHarald Freudenberger 
915f2bbc96eSHarald Freudenberger out:
916f2bbc96eSHarald Freudenberger 	kfree(_apqns);
917f2bbc96eSHarald Freudenberger 	return rc;
918f2bbc96eSHarald Freudenberger }
919f2bbc96eSHarald Freudenberger 
920f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns,
921f2bbc96eSHarald Freudenberger 			      const u8 *key, size_t keylen,
922f370f45cSHarald Freudenberger 			      u8 *protkey, u32 *protkeylen, u32 *protkeytype)
923f2bbc96eSHarald Freudenberger {
924f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
92546a29b03SHarald Freudenberger 	int i, card, dom, rc;
926f2bbc96eSHarald Freudenberger 
927f2bbc96eSHarald Freudenberger 	/* check for at least one apqn given */
928f2bbc96eSHarald Freudenberger 	if (!apqns || !nr_apqns)
929f2bbc96eSHarald Freudenberger 		return -EINVAL;
930f2bbc96eSHarald Freudenberger 
931fb1136d6SIngo Franzki 	if (keylen < sizeof(struct keytoken_header))
932fb1136d6SIngo Franzki 		return -EINVAL;
933fb1136d6SIngo Franzki 
93455d0a513SHarald Freudenberger 	if (hdr->type == TOKTYPE_CCA_INTERNAL) {
93555d0a513SHarald Freudenberger 		if (hdr->version == TOKVER_CCA_AES) {
936f2bbc96eSHarald Freudenberger 			if (keylen != sizeof(struct secaeskeytoken))
937f2bbc96eSHarald Freudenberger 				return -EINVAL;
938f2bbc96eSHarald Freudenberger 			if (cca_check_secaeskeytoken(debug_info, 3, key, 0))
939f2bbc96eSHarald Freudenberger 				return -EINVAL;
94055d0a513SHarald Freudenberger 		} else if (hdr->version == TOKVER_CCA_VLSC) {
941f2bbc96eSHarald Freudenberger 			if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
942f2bbc96eSHarald Freudenberger 				return -EINVAL;
943f2bbc96eSHarald Freudenberger 			if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1))
944f2bbc96eSHarald Freudenberger 				return -EINVAL;
94555d0a513SHarald Freudenberger 		} else {
946f2bbc96eSHarald Freudenberger 			DEBUG_ERR("%s unknown CCA internal token version %d\n",
947f2bbc96eSHarald Freudenberger 				  __func__, hdr->version);
948fb1136d6SIngo Franzki 			return -EINVAL;
949fb1136d6SIngo Franzki 		}
95055d0a513SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA) {
95155d0a513SHarald Freudenberger 		if (hdr->version == TOKVER_EP11_AES) {
95255d0a513SHarald Freudenberger 			if (keylen < sizeof(struct ep11keyblob))
95355d0a513SHarald Freudenberger 				return -EINVAL;
954fa6999e3SHarald Freudenberger 			if (ep11_check_aes_key(debug_info, 3, key, keylen, 1))
95555d0a513SHarald Freudenberger 				return -EINVAL;
95655d0a513SHarald Freudenberger 		} else {
957f370f45cSHarald Freudenberger 			return pkey_nonccatok2pkey(key, keylen,
958f370f45cSHarald Freudenberger 						   protkey, protkeylen,
959f370f45cSHarald Freudenberger 						   protkeytype);
96055d0a513SHarald Freudenberger 		}
96155d0a513SHarald Freudenberger 	} else {
962f2bbc96eSHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported blob type %d\n",
963f2bbc96eSHarald Freudenberger 			  __func__, hdr->type);
964f2bbc96eSHarald Freudenberger 		return -EINVAL;
965fb1136d6SIngo Franzki 	}
966f2bbc96eSHarald Freudenberger 
96743cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
96843cb5a7cSHarald Freudenberger 
969f2bbc96eSHarald Freudenberger 	/* simple try all apqns from the list */
970f2bbc96eSHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
971f2bbc96eSHarald Freudenberger 		card = apqns[i].card;
972f2bbc96eSHarald Freudenberger 		dom = apqns[i].domain;
9732004b57cSHarald Freudenberger 		if (hdr->type == TOKTYPE_CCA_INTERNAL &&
9742004b57cSHarald Freudenberger 		    hdr->version == TOKVER_CCA_AES) {
975f370f45cSHarald Freudenberger 			rc = cca_sec2protkey(card, dom, key,
976f370f45cSHarald Freudenberger 					     protkey, protkeylen, protkeytype);
9772004b57cSHarald Freudenberger 		} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
9782004b57cSHarald Freudenberger 			   hdr->version == TOKVER_CCA_VLSC) {
979f370f45cSHarald Freudenberger 			rc = cca_cipher2protkey(card, dom, key,
980f370f45cSHarald Freudenberger 						protkey, protkeylen,
981f370f45cSHarald Freudenberger 						protkeytype);
9822004b57cSHarald Freudenberger 		} else {
9832004b57cSHarald Freudenberger 			/* EP11 AES secure key blob */
98455d0a513SHarald Freudenberger 			struct ep11keyblob *kb = (struct ep11keyblob *)key;
98555d0a513SHarald Freudenberger 
986fa6999e3SHarald Freudenberger 			rc = ep11_kblob2protkey(card, dom, key, kb->head.len,
987f370f45cSHarald Freudenberger 						protkey, protkeylen,
988f370f45cSHarald Freudenberger 						protkeytype);
98955d0a513SHarald Freudenberger 		}
990f2bbc96eSHarald Freudenberger 		if (rc == 0)
991f2bbc96eSHarald Freudenberger 			break;
992f2bbc96eSHarald Freudenberger 	}
993f2bbc96eSHarald Freudenberger 
994f2bbc96eSHarald Freudenberger 	return rc;
995f2bbc96eSHarald Freudenberger }
996f2bbc96eSHarald Freudenberger 
997f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags,
998f2bbc96eSHarald Freudenberger 			  struct pkey_apqn *apqns, size_t *nr_apqns)
999f2bbc96eSHarald Freudenberger {
1000f2bbc96eSHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
100146a29b03SHarald Freudenberger 	u32 _nr_apqns, *_apqns = NULL;
100246a29b03SHarald Freudenberger 	int rc;
1003f2bbc96eSHarald Freudenberger 
100455d0a513SHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header) || flags == 0)
1005f2bbc96eSHarald Freudenberger 		return -EINVAL;
1006f2bbc96eSHarald Freudenberger 
100743cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
100843cb5a7cSHarald Freudenberger 
10092004b57cSHarald Freudenberger 	if (hdr->type == TOKTYPE_NON_CCA &&
10102004b57cSHarald Freudenberger 	    (hdr->version == TOKVER_EP11_AES_WITH_HEADER ||
10112004b57cSHarald Freudenberger 	     hdr->version == TOKVER_EP11_ECC_WITH_HEADER) &&
10122004b57cSHarald Freudenberger 	    is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
1013fa6999e3SHarald Freudenberger 		struct ep11keyblob *kb = (struct ep11keyblob *)
1014fa6999e3SHarald Freudenberger 			(key + sizeof(struct ep11kblob_header));
101546a29b03SHarald Freudenberger 		int minhwtype = 0, api = 0;
1016fa6999e3SHarald Freudenberger 
1017fa6999e3SHarald Freudenberger 		if (flags != PKEY_FLAGS_MATCH_CUR_MKVP)
1018fa6999e3SHarald Freudenberger 			return -EINVAL;
1019fa6999e3SHarald Freudenberger 		if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) {
1020fa6999e3SHarald Freudenberger 			minhwtype = ZCRYPT_CEX7;
1021fa6999e3SHarald Freudenberger 			api = EP11_API_V;
1022fa6999e3SHarald Freudenberger 		}
1023fa6999e3SHarald Freudenberger 		rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
1024fa6999e3SHarald Freudenberger 				    minhwtype, api, kb->wkvp);
1025fa6999e3SHarald Freudenberger 		if (rc)
1026fa6999e3SHarald Freudenberger 			goto out;
10272004b57cSHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA &&
10282004b57cSHarald Freudenberger 		   hdr->version == TOKVER_EP11_AES &&
10292004b57cSHarald Freudenberger 		   is_ep11_keyblob(key)) {
103055d0a513SHarald Freudenberger 		struct ep11keyblob *kb = (struct ep11keyblob *)key;
103146a29b03SHarald Freudenberger 		int minhwtype = 0, api = 0;
103255d0a513SHarald Freudenberger 
103355d0a513SHarald Freudenberger 		if (flags != PKEY_FLAGS_MATCH_CUR_MKVP)
103455d0a513SHarald Freudenberger 			return -EINVAL;
103555d0a513SHarald Freudenberger 		if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) {
103655d0a513SHarald Freudenberger 			minhwtype = ZCRYPT_CEX7;
103755d0a513SHarald Freudenberger 			api = EP11_API_V;
103855d0a513SHarald Freudenberger 		}
103955d0a513SHarald Freudenberger 		rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
104055d0a513SHarald Freudenberger 				    minhwtype, api, kb->wkvp);
104155d0a513SHarald Freudenberger 		if (rc)
104255d0a513SHarald Freudenberger 			goto out;
104355d0a513SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL) {
1044f2bbc96eSHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
104546a29b03SHarald Freudenberger 		int minhwtype = ZCRYPT_CEX3C;
1046f2bbc96eSHarald Freudenberger 
1047f2bbc96eSHarald Freudenberger 		if (hdr->version == TOKVER_CCA_AES) {
1048f2bbc96eSHarald Freudenberger 			struct secaeskeytoken *t = (struct secaeskeytoken *)key;
1049f2bbc96eSHarald Freudenberger 
1050f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
1051f2bbc96eSHarald Freudenberger 				cur_mkvp = t->mkvp;
1052f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
1053f2bbc96eSHarald Freudenberger 				old_mkvp = t->mkvp;
105455d0a513SHarald Freudenberger 		} else if (hdr->version == TOKVER_CCA_VLSC) {
1055f2bbc96eSHarald Freudenberger 			struct cipherkeytoken *t = (struct cipherkeytoken *)key;
1056f2bbc96eSHarald Freudenberger 
1057f2bbc96eSHarald Freudenberger 			minhwtype = ZCRYPT_CEX6;
1058f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
1059f2bbc96eSHarald Freudenberger 				cur_mkvp = t->mkvp0;
1060f2bbc96eSHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
1061f2bbc96eSHarald Freudenberger 				old_mkvp = t->mkvp0;
106255d0a513SHarald Freudenberger 		} else {
106355d0a513SHarald Freudenberger 			/* unknown cca internal token type */
106455d0a513SHarald Freudenberger 			return -EINVAL;
1065f2bbc96eSHarald Freudenberger 		}
1066f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
106732ca04bbSHarald Freudenberger 				   minhwtype, AES_MK_SET,
106832ca04bbSHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
1069f2bbc96eSHarald Freudenberger 		if (rc)
1070f2bbc96eSHarald Freudenberger 			goto out;
1071fa6999e3SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
1072fa6999e3SHarald Freudenberger 		struct eccprivkeytoken *t = (struct eccprivkeytoken *)key;
107346a29b03SHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
1074fa6999e3SHarald Freudenberger 
1075fa6999e3SHarald Freudenberger 		if (t->secid == 0x20) {
1076fa6999e3SHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
1077fa6999e3SHarald Freudenberger 				cur_mkvp = t->mkvp;
1078fa6999e3SHarald Freudenberger 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
1079fa6999e3SHarald Freudenberger 				old_mkvp = t->mkvp;
1080fa6999e3SHarald Freudenberger 		} else {
1081fa6999e3SHarald Freudenberger 			/* unknown cca internal 2 token type */
1082fa6999e3SHarald Freudenberger 			return -EINVAL;
1083fa6999e3SHarald Freudenberger 		}
1084fa6999e3SHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
1085fa6999e3SHarald Freudenberger 				   ZCRYPT_CEX7, APKA_MK_SET,
1086fa6999e3SHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
1087fa6999e3SHarald Freudenberger 		if (rc)
1088fa6999e3SHarald Freudenberger 			goto out;
10892004b57cSHarald Freudenberger 	} else {
109055d0a513SHarald Freudenberger 		return -EINVAL;
10912004b57cSHarald Freudenberger 	}
109255d0a513SHarald Freudenberger 
1093f2bbc96eSHarald Freudenberger 	if (apqns) {
1094f2bbc96eSHarald Freudenberger 		if (*nr_apqns < _nr_apqns)
1095f2bbc96eSHarald Freudenberger 			rc = -ENOSPC;
1096f2bbc96eSHarald Freudenberger 		else
1097f2bbc96eSHarald Freudenberger 			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
1098f2bbc96eSHarald Freudenberger 	}
1099f2bbc96eSHarald Freudenberger 	*nr_apqns = _nr_apqns;
1100f2bbc96eSHarald Freudenberger 
1101f2bbc96eSHarald Freudenberger out:
1102f2bbc96eSHarald Freudenberger 	kfree(_apqns);
1103f2bbc96eSHarald Freudenberger 	return rc;
1104f2bbc96eSHarald Freudenberger }
1105f2bbc96eSHarald Freudenberger 
1106f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype,
1107f2bbc96eSHarald Freudenberger 			      u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
1108f2bbc96eSHarald Freudenberger 			      struct pkey_apqn *apqns, size_t *nr_apqns)
1109f2bbc96eSHarald Freudenberger {
1110f2bbc96eSHarald Freudenberger 	u32 _nr_apqns, *_apqns = NULL;
111146a29b03SHarald Freudenberger 	int rc;
1112f2bbc96eSHarald Freudenberger 
111343cb5a7cSHarald Freudenberger 	zcrypt_wait_api_operational();
111443cb5a7cSHarald Freudenberger 
1115f2bbc96eSHarald Freudenberger 	if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) {
1116f2bbc96eSHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
1117f2bbc96eSHarald Freudenberger 		int minhwtype = ZCRYPT_CEX3C;
1118f2bbc96eSHarald Freudenberger 
1119f2bbc96eSHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
1120f2bbc96eSHarald Freudenberger 			cur_mkvp = *((u64 *)cur_mkvp);
1121f2bbc96eSHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
1122f2bbc96eSHarald Freudenberger 			old_mkvp = *((u64 *)alt_mkvp);
1123f2bbc96eSHarald Freudenberger 		if (ktype == PKEY_TYPE_CCA_CIPHER)
1124f2bbc96eSHarald Freudenberger 			minhwtype = ZCRYPT_CEX6;
1125f2bbc96eSHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
112632ca04bbSHarald Freudenberger 				   minhwtype, AES_MK_SET,
112732ca04bbSHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
1128f2bbc96eSHarald Freudenberger 		if (rc)
1129f2bbc96eSHarald Freudenberger 			goto out;
1130fa6999e3SHarald Freudenberger 	} else if (ktype == PKEY_TYPE_CCA_ECC) {
1131fa6999e3SHarald Freudenberger 		u64 cur_mkvp = 0, old_mkvp = 0;
1132fa6999e3SHarald Freudenberger 
1133fa6999e3SHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
1134fa6999e3SHarald Freudenberger 			cur_mkvp = *((u64 *)cur_mkvp);
1135fa6999e3SHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
1136fa6999e3SHarald Freudenberger 			old_mkvp = *((u64 *)alt_mkvp);
1137fa6999e3SHarald Freudenberger 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
1138fa6999e3SHarald Freudenberger 				   ZCRYPT_CEX7, APKA_MK_SET,
1139fa6999e3SHarald Freudenberger 				   cur_mkvp, old_mkvp, 1);
1140fa6999e3SHarald Freudenberger 		if (rc)
1141fa6999e3SHarald Freudenberger 			goto out;
1142fa6999e3SHarald Freudenberger 
1143fa6999e3SHarald Freudenberger 	} else if (ktype == PKEY_TYPE_EP11 ||
1144fa6999e3SHarald Freudenberger 		   ktype == PKEY_TYPE_EP11_AES ||
1145fa6999e3SHarald Freudenberger 		   ktype == PKEY_TYPE_EP11_ECC) {
114655d0a513SHarald Freudenberger 		u8 *wkvp = NULL;
114755d0a513SHarald Freudenberger 
114855d0a513SHarald Freudenberger 		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
114955d0a513SHarald Freudenberger 			wkvp = cur_mkvp;
115055d0a513SHarald Freudenberger 		rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
115155d0a513SHarald Freudenberger 				    ZCRYPT_CEX7, EP11_API_V, wkvp);
115255d0a513SHarald Freudenberger 		if (rc)
115355d0a513SHarald Freudenberger 			goto out;
115455d0a513SHarald Freudenberger 
11552004b57cSHarald Freudenberger 	} else {
115655d0a513SHarald Freudenberger 		return -EINVAL;
11572004b57cSHarald Freudenberger 	}
115855d0a513SHarald Freudenberger 
1159f2bbc96eSHarald Freudenberger 	if (apqns) {
1160f2bbc96eSHarald Freudenberger 		if (*nr_apqns < _nr_apqns)
1161f2bbc96eSHarald Freudenberger 			rc = -ENOSPC;
1162f2bbc96eSHarald Freudenberger 		else
1163f2bbc96eSHarald Freudenberger 			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
1164f2bbc96eSHarald Freudenberger 	}
1165f2bbc96eSHarald Freudenberger 	*nr_apqns = _nr_apqns;
1166f2bbc96eSHarald Freudenberger 
1167f2bbc96eSHarald Freudenberger out:
1168f2bbc96eSHarald Freudenberger 	kfree(_apqns);
1169f2bbc96eSHarald Freudenberger 	return rc;
1170f2bbc96eSHarald Freudenberger }
1171fb1136d6SIngo Franzki 
1172fa6999e3SHarald Freudenberger static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns,
1173f370f45cSHarald Freudenberger 			      const u8 *key, size_t keylen,
1174f370f45cSHarald Freudenberger 			      u8 *protkey, u32 *protkeylen, u32 *protkeytype)
1175fa6999e3SHarald Freudenberger {
1176fa6999e3SHarald Freudenberger 	struct keytoken_header *hdr = (struct keytoken_header *)key;
117746a29b03SHarald Freudenberger 	int i, card, dom, rc;
1178fa6999e3SHarald Freudenberger 
1179fa6999e3SHarald Freudenberger 	/* check for at least one apqn given */
1180fa6999e3SHarald Freudenberger 	if (!apqns || !nr_apqns)
1181fa6999e3SHarald Freudenberger 		return -EINVAL;
1182fa6999e3SHarald Freudenberger 
1183fa6999e3SHarald Freudenberger 	if (keylen < sizeof(struct keytoken_header))
1184fa6999e3SHarald Freudenberger 		return -EINVAL;
1185fa6999e3SHarald Freudenberger 
11862004b57cSHarald Freudenberger 	if (hdr->type == TOKTYPE_NON_CCA &&
11872004b57cSHarald Freudenberger 	    hdr->version == TOKVER_EP11_AES_WITH_HEADER &&
11882004b57cSHarald Freudenberger 	    is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
1189fa6999e3SHarald Freudenberger 		/* EP11 AES key blob with header */
1190fa6999e3SHarald Freudenberger 		if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1))
1191fa6999e3SHarald Freudenberger 			return -EINVAL;
11922004b57cSHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA &&
11932004b57cSHarald Freudenberger 		   hdr->version == TOKVER_EP11_ECC_WITH_HEADER &&
11942004b57cSHarald Freudenberger 		   is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
1195fa6999e3SHarald Freudenberger 		/* EP11 ECC key blob with header */
1196fa6999e3SHarald Freudenberger 		if (ep11_check_ecc_key_with_hdr(debug_info, 3, key, keylen, 1))
1197fa6999e3SHarald Freudenberger 			return -EINVAL;
11982004b57cSHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA &&
11992004b57cSHarald Freudenberger 		   hdr->version == TOKVER_EP11_AES &&
12002004b57cSHarald Freudenberger 		   is_ep11_keyblob(key)) {
1201fa6999e3SHarald Freudenberger 		/* EP11 AES key blob with header in session field */
1202fa6999e3SHarald Freudenberger 		if (ep11_check_aes_key(debug_info, 3, key, keylen, 1))
1203fa6999e3SHarald Freudenberger 			return -EINVAL;
1204fa6999e3SHarald Freudenberger 	} else	if (hdr->type == TOKTYPE_CCA_INTERNAL) {
1205fa6999e3SHarald Freudenberger 		if (hdr->version == TOKVER_CCA_AES) {
1206fa6999e3SHarald Freudenberger 			/* CCA AES data key */
1207fa6999e3SHarald Freudenberger 			if (keylen != sizeof(struct secaeskeytoken))
1208fa6999e3SHarald Freudenberger 				return -EINVAL;
1209fa6999e3SHarald Freudenberger 			if (cca_check_secaeskeytoken(debug_info, 3, key, 0))
1210fa6999e3SHarald Freudenberger 				return -EINVAL;
1211fa6999e3SHarald Freudenberger 		} else if (hdr->version == TOKVER_CCA_VLSC) {
1212fa6999e3SHarald Freudenberger 			/* CCA AES cipher key */
1213fa6999e3SHarald Freudenberger 			if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
1214fa6999e3SHarald Freudenberger 				return -EINVAL;
1215fa6999e3SHarald Freudenberger 			if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1))
1216fa6999e3SHarald Freudenberger 				return -EINVAL;
1217fa6999e3SHarald Freudenberger 		} else {
1218fa6999e3SHarald Freudenberger 			DEBUG_ERR("%s unknown CCA internal token version %d\n",
1219fa6999e3SHarald Freudenberger 				  __func__, hdr->version);
1220fa6999e3SHarald Freudenberger 			return -EINVAL;
1221fa6999e3SHarald Freudenberger 		}
1222fa6999e3SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
1223fa6999e3SHarald Freudenberger 		/* CCA ECC (private) key */
1224fa6999e3SHarald Freudenberger 		if (keylen < sizeof(struct eccprivkeytoken))
1225fa6999e3SHarald Freudenberger 			return -EINVAL;
1226fa6999e3SHarald Freudenberger 		if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1))
1227fa6999e3SHarald Freudenberger 			return -EINVAL;
1228fa6999e3SHarald Freudenberger 	} else if (hdr->type == TOKTYPE_NON_CCA) {
1229f370f45cSHarald Freudenberger 		return pkey_nonccatok2pkey(key, keylen,
1230f370f45cSHarald Freudenberger 					   protkey, protkeylen, protkeytype);
1231fa6999e3SHarald Freudenberger 	} else {
1232fa6999e3SHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported blob type %d\n",
1233fa6999e3SHarald Freudenberger 			  __func__, hdr->type);
1234fa6999e3SHarald Freudenberger 		return -EINVAL;
1235fa6999e3SHarald Freudenberger 	}
1236fa6999e3SHarald Freudenberger 
1237fa6999e3SHarald Freudenberger 	/* simple try all apqns from the list */
1238fa6999e3SHarald Freudenberger 	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
1239fa6999e3SHarald Freudenberger 		card = apqns[i].card;
1240fa6999e3SHarald Freudenberger 		dom = apqns[i].domain;
12412004b57cSHarald Freudenberger 		if (hdr->type == TOKTYPE_NON_CCA &&
12422004b57cSHarald Freudenberger 		    (hdr->version == TOKVER_EP11_AES_WITH_HEADER ||
12432004b57cSHarald Freudenberger 		     hdr->version == TOKVER_EP11_ECC_WITH_HEADER) &&
12442004b57cSHarald Freudenberger 		    is_ep11_keyblob(key + sizeof(struct ep11kblob_header)))
1245fa6999e3SHarald Freudenberger 			rc = ep11_kblob2protkey(card, dom, key, hdr->len,
1246fa6999e3SHarald Freudenberger 						protkey, protkeylen, protkeytype);
12472004b57cSHarald Freudenberger 		else if (hdr->type == TOKTYPE_NON_CCA &&
12482004b57cSHarald Freudenberger 			 hdr->version == TOKVER_EP11_AES &&
12492004b57cSHarald Freudenberger 			 is_ep11_keyblob(key))
1250fa6999e3SHarald Freudenberger 			rc = ep11_kblob2protkey(card, dom, key, hdr->len,
1251fa6999e3SHarald Freudenberger 						protkey, protkeylen, protkeytype);
1252fa6999e3SHarald Freudenberger 		else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
1253fa6999e3SHarald Freudenberger 			 hdr->version == TOKVER_CCA_AES)
1254fa6999e3SHarald Freudenberger 			rc = cca_sec2protkey(card, dom, key, protkey,
1255fa6999e3SHarald Freudenberger 					     protkeylen, protkeytype);
1256fa6999e3SHarald Freudenberger 		else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
1257fa6999e3SHarald Freudenberger 			 hdr->version == TOKVER_CCA_VLSC)
1258fa6999e3SHarald Freudenberger 			rc = cca_cipher2protkey(card, dom, key, protkey,
1259fa6999e3SHarald Freudenberger 						protkeylen, protkeytype);
1260fa6999e3SHarald Freudenberger 		else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA)
1261fa6999e3SHarald Freudenberger 			rc = cca_ecc2protkey(card, dom, key, protkey,
1262fa6999e3SHarald Freudenberger 					     protkeylen, protkeytype);
1263fa6999e3SHarald Freudenberger 		else
1264fa6999e3SHarald Freudenberger 			return -EINVAL;
1265fa6999e3SHarald Freudenberger 	}
1266fa6999e3SHarald Freudenberger 
1267fa6999e3SHarald Freudenberger 	return rc;
1268fa6999e3SHarald Freudenberger }
1269fa6999e3SHarald Freudenberger 
1270fb1136d6SIngo Franzki /*
1271e80d4af0SHarald Freudenberger  * File io functions
1272e80d4af0SHarald Freudenberger  */
1273e80d4af0SHarald Freudenberger 
1274f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen)
1275f2bbc96eSHarald Freudenberger {
1276*9e436c19SHarald Freudenberger 	if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE)
1277f2bbc96eSHarald Freudenberger 		return ERR_PTR(-EINVAL);
1278f2bbc96eSHarald Freudenberger 
12798b57e7c8SMarkus Elfring 	return memdup_user(ukey, keylen);
1280f2bbc96eSHarald Freudenberger }
1281f2bbc96eSHarald Freudenberger 
1282f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns)
1283f2bbc96eSHarald Freudenberger {
12848b57e7c8SMarkus Elfring 	if (!uapqns || nr_apqns == 0)
12858b57e7c8SMarkus Elfring 		return NULL;
1286f2bbc96eSHarald Freudenberger 
12878b57e7c8SMarkus Elfring 	return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn));
1288f2bbc96eSHarald Freudenberger }
1289f2bbc96eSHarald Freudenberger 
1290e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
1291e80d4af0SHarald Freudenberger 				unsigned long arg)
1292e80d4af0SHarald Freudenberger {
1293e80d4af0SHarald Freudenberger 	int rc;
1294e80d4af0SHarald Freudenberger 
1295e80d4af0SHarald Freudenberger 	switch (cmd) {
1296e80d4af0SHarald Freudenberger 	case PKEY_GENSECK: {
1297e80d4af0SHarald Freudenberger 		struct pkey_genseck __user *ugs = (void __user *)arg;
1298e80d4af0SHarald Freudenberger 		struct pkey_genseck kgs;
1299e80d4af0SHarald Freudenberger 
1300e80d4af0SHarald Freudenberger 		if (copy_from_user(&kgs, ugs, sizeof(kgs)))
1301e80d4af0SHarald Freudenberger 			return -EFAULT;
1302efc598e6SHarald Freudenberger 		rc = cca_genseckey(kgs.cardnr, kgs.domain,
1303efc598e6SHarald Freudenberger 				   kgs.keytype, kgs.seckey.seckey);
1304efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc);
1305e80d4af0SHarald Freudenberger 		if (rc)
1306e80d4af0SHarald Freudenberger 			break;
1307e80d4af0SHarald Freudenberger 		if (copy_to_user(ugs, &kgs, sizeof(kgs)))
1308e80d4af0SHarald Freudenberger 			return -EFAULT;
1309e80d4af0SHarald Freudenberger 		break;
1310e80d4af0SHarald Freudenberger 	}
1311e80d4af0SHarald Freudenberger 	case PKEY_CLR2SECK: {
1312e80d4af0SHarald Freudenberger 		struct pkey_clr2seck __user *ucs = (void __user *)arg;
1313e80d4af0SHarald Freudenberger 		struct pkey_clr2seck kcs;
1314e80d4af0SHarald Freudenberger 
1315e80d4af0SHarald Freudenberger 		if (copy_from_user(&kcs, ucs, sizeof(kcs)))
1316e80d4af0SHarald Freudenberger 			return -EFAULT;
1317efc598e6SHarald Freudenberger 		rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype,
1318efc598e6SHarald Freudenberger 				    kcs.clrkey.clrkey, kcs.seckey.seckey);
1319efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc);
1320e80d4af0SHarald Freudenberger 		if (rc)
1321e80d4af0SHarald Freudenberger 			break;
1322e80d4af0SHarald Freudenberger 		if (copy_to_user(ucs, &kcs, sizeof(kcs)))
1323e80d4af0SHarald Freudenberger 			return -EFAULT;
1324e80d4af0SHarald Freudenberger 		memzero_explicit(&kcs, sizeof(kcs));
1325e80d4af0SHarald Freudenberger 		break;
1326e80d4af0SHarald Freudenberger 	}
1327e80d4af0SHarald Freudenberger 	case PKEY_SEC2PROTK: {
1328e80d4af0SHarald Freudenberger 		struct pkey_sec2protk __user *usp = (void __user *)arg;
1329e80d4af0SHarald Freudenberger 		struct pkey_sec2protk ksp;
1330e80d4af0SHarald Freudenberger 
1331e80d4af0SHarald Freudenberger 		if (copy_from_user(&ksp, usp, sizeof(ksp)))
1332e80d4af0SHarald Freudenberger 			return -EFAULT;
1333f370f45cSHarald Freudenberger 		ksp.protkey.len = sizeof(ksp.protkey.protkey);
1334efc598e6SHarald Freudenberger 		rc = cca_sec2protkey(ksp.cardnr, ksp.domain,
1335efc598e6SHarald Freudenberger 				     ksp.seckey.seckey, ksp.protkey.protkey,
1336aab73d27SHarald Freudenberger 				     &ksp.protkey.len, &ksp.protkey.type);
1337efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc);
1338e80d4af0SHarald Freudenberger 		if (rc)
1339e80d4af0SHarald Freudenberger 			break;
1340e80d4af0SHarald Freudenberger 		if (copy_to_user(usp, &ksp, sizeof(ksp)))
1341e80d4af0SHarald Freudenberger 			return -EFAULT;
1342e80d4af0SHarald Freudenberger 		break;
1343e80d4af0SHarald Freudenberger 	}
1344e80d4af0SHarald Freudenberger 	case PKEY_CLR2PROTK: {
1345e80d4af0SHarald Freudenberger 		struct pkey_clr2protk __user *ucp = (void __user *)arg;
1346e80d4af0SHarald Freudenberger 		struct pkey_clr2protk kcp;
1347e80d4af0SHarald Freudenberger 
1348e80d4af0SHarald Freudenberger 		if (copy_from_user(&kcp, ucp, sizeof(kcp)))
1349e80d4af0SHarald Freudenberger 			return -EFAULT;
1350f370f45cSHarald Freudenberger 		kcp.protkey.len = sizeof(kcp.protkey.protkey);
1351f370f45cSHarald Freudenberger 		rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey,
1352f370f45cSHarald Freudenberger 				      kcp.protkey.protkey,
1353f370f45cSHarald Freudenberger 				      &kcp.protkey.len, &kcp.protkey.type);
1354ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc);
1355e80d4af0SHarald Freudenberger 		if (rc)
1356e80d4af0SHarald Freudenberger 			break;
1357e80d4af0SHarald Freudenberger 		if (copy_to_user(ucp, &kcp, sizeof(kcp)))
1358e80d4af0SHarald Freudenberger 			return -EFAULT;
1359e80d4af0SHarald Freudenberger 		memzero_explicit(&kcp, sizeof(kcp));
1360e80d4af0SHarald Freudenberger 		break;
1361e80d4af0SHarald Freudenberger 	}
1362e80d4af0SHarald Freudenberger 	case PKEY_FINDCARD: {
1363e80d4af0SHarald Freudenberger 		struct pkey_findcard __user *ufc = (void __user *)arg;
1364e80d4af0SHarald Freudenberger 		struct pkey_findcard kfc;
1365e80d4af0SHarald Freudenberger 
1366e80d4af0SHarald Freudenberger 		if (copy_from_user(&kfc, ufc, sizeof(kfc)))
1367e80d4af0SHarald Freudenberger 			return -EFAULT;
1368efc598e6SHarald Freudenberger 		rc = cca_findcard(kfc.seckey.seckey,
1369e80d4af0SHarald Freudenberger 				  &kfc.cardnr, &kfc.domain, 1);
1370efc598e6SHarald Freudenberger 		DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc);
1371efc598e6SHarald Freudenberger 		if (rc < 0)
1372e80d4af0SHarald Freudenberger 			break;
1373e80d4af0SHarald Freudenberger 		if (copy_to_user(ufc, &kfc, sizeof(kfc)))
1374e80d4af0SHarald Freudenberger 			return -EFAULT;
1375e80d4af0SHarald Freudenberger 		break;
1376e80d4af0SHarald Freudenberger 	}
1377e80d4af0SHarald Freudenberger 	case PKEY_SKEY2PKEY: {
1378e80d4af0SHarald Freudenberger 		struct pkey_skey2pkey __user *usp = (void __user *)arg;
1379e80d4af0SHarald Freudenberger 		struct pkey_skey2pkey ksp;
1380e80d4af0SHarald Freudenberger 
1381e80d4af0SHarald Freudenberger 		if (copy_from_user(&ksp, usp, sizeof(ksp)))
1382e80d4af0SHarald Freudenberger 			return -EFAULT;
1383f370f45cSHarald Freudenberger 		ksp.protkey.len = sizeof(ksp.protkey.protkey);
1384f370f45cSHarald Freudenberger 		rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey,
1385f370f45cSHarald Freudenberger 				    &ksp.protkey.len, &ksp.protkey.type);
1386ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc);
1387e80d4af0SHarald Freudenberger 		if (rc)
1388e80d4af0SHarald Freudenberger 			break;
1389e80d4af0SHarald Freudenberger 		if (copy_to_user(usp, &ksp, sizeof(ksp)))
1390e80d4af0SHarald Freudenberger 			return -EFAULT;
1391e80d4af0SHarald Freudenberger 		break;
1392e80d4af0SHarald Freudenberger 	}
1393e61a6134SHarald Freudenberger 	case PKEY_VERIFYKEY: {
1394e61a6134SHarald Freudenberger 		struct pkey_verifykey __user *uvk = (void __user *)arg;
1395e61a6134SHarald Freudenberger 		struct pkey_verifykey kvk;
1396e61a6134SHarald Freudenberger 
1397e61a6134SHarald Freudenberger 		if (copy_from_user(&kvk, uvk, sizeof(kvk)))
1398e61a6134SHarald Freudenberger 			return -EFAULT;
1399e61a6134SHarald Freudenberger 		rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain,
1400e61a6134SHarald Freudenberger 				    &kvk.keysize, &kvk.attributes);
1401ac2b96f3SHarald Freudenberger 		DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc);
1402e61a6134SHarald Freudenberger 		if (rc)
1403e61a6134SHarald Freudenberger 			break;
1404e61a6134SHarald Freudenberger 		if (copy_to_user(uvk, &kvk, sizeof(kvk)))
1405e61a6134SHarald Freudenberger 			return -EFAULT;
1406e61a6134SHarald Freudenberger 		break;
1407e61a6134SHarald Freudenberger 	}
1408a45a5c7dSIngo Franzki 	case PKEY_GENPROTK: {
1409a45a5c7dSIngo Franzki 		struct pkey_genprotk __user *ugp = (void __user *)arg;
1410a45a5c7dSIngo Franzki 		struct pkey_genprotk kgp;
1411a45a5c7dSIngo Franzki 
1412a45a5c7dSIngo Franzki 		if (copy_from_user(&kgp, ugp, sizeof(kgp)))
1413a45a5c7dSIngo Franzki 			return -EFAULT;
1414f370f45cSHarald Freudenberger 		kgp.protkey.len = sizeof(kgp.protkey.protkey);
1415f370f45cSHarald Freudenberger 		rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey,
1416f370f45cSHarald Freudenberger 				     &kgp.protkey.len, &kgp.protkey.type);
1417a45a5c7dSIngo Franzki 		DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc);
1418a45a5c7dSIngo Franzki 		if (rc)
1419a45a5c7dSIngo Franzki 			break;
1420a45a5c7dSIngo Franzki 		if (copy_to_user(ugp, &kgp, sizeof(kgp)))
1421a45a5c7dSIngo Franzki 			return -EFAULT;
1422a45a5c7dSIngo Franzki 		break;
1423a45a5c7dSIngo Franzki 	}
1424cb26b9ffSIngo Franzki 	case PKEY_VERIFYPROTK: {
1425cb26b9ffSIngo Franzki 		struct pkey_verifyprotk __user *uvp = (void __user *)arg;
1426cb26b9ffSIngo Franzki 		struct pkey_verifyprotk kvp;
1427cb26b9ffSIngo Franzki 
1428cb26b9ffSIngo Franzki 		if (copy_from_user(&kvp, uvp, sizeof(kvp)))
1429cb26b9ffSIngo Franzki 			return -EFAULT;
1430f370f45cSHarald Freudenberger 		rc = pkey_verifyprotkey(kvp.protkey.protkey,
1431f370f45cSHarald Freudenberger 					kvp.protkey.len, kvp.protkey.type);
1432cb26b9ffSIngo Franzki 		DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc);
1433cb26b9ffSIngo Franzki 		break;
1434cb26b9ffSIngo Franzki 	}
1435fb1136d6SIngo Franzki 	case PKEY_KBLOB2PROTK: {
1436fb1136d6SIngo Franzki 		struct pkey_kblob2pkey __user *utp = (void __user *)arg;
1437fb1136d6SIngo Franzki 		struct pkey_kblob2pkey ktp;
1438183cb469SHarald Freudenberger 		u8 *kkey;
1439fb1136d6SIngo Franzki 
1440fb1136d6SIngo Franzki 		if (copy_from_user(&ktp, utp, sizeof(ktp)))
1441fb1136d6SIngo Franzki 			return -EFAULT;
1442f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(ktp.key, ktp.keylen);
1443f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey))
1444f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
1445f370f45cSHarald Freudenberger 		ktp.protkey.len = sizeof(ktp.protkey.protkey);
1446f370f45cSHarald Freudenberger 		rc = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey,
1447f370f45cSHarald Freudenberger 				       &ktp.protkey.len, &ktp.protkey.type);
1448fb1136d6SIngo Franzki 		DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc);
1449844cf829SHolger Dengler 		memzero_explicit(kkey, ktp.keylen);
1450fb1136d6SIngo Franzki 		kfree(kkey);
1451fb1136d6SIngo Franzki 		if (rc)
1452fb1136d6SIngo Franzki 			break;
1453fb1136d6SIngo Franzki 		if (copy_to_user(utp, &ktp, sizeof(ktp)))
1454fb1136d6SIngo Franzki 			return -EFAULT;
1455fb1136d6SIngo Franzki 		break;
1456fb1136d6SIngo Franzki 	}
1457f2bbc96eSHarald Freudenberger 	case PKEY_GENSECK2: {
1458f2bbc96eSHarald Freudenberger 		struct pkey_genseck2 __user *ugs = (void __user *)arg;
145946a29b03SHarald Freudenberger 		size_t klen = KEYBLOBBUFSIZE;
1460f2bbc96eSHarald Freudenberger 		struct pkey_genseck2 kgs;
1461f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns;
1462f2bbc96eSHarald Freudenberger 		u8 *kkey;
1463f2bbc96eSHarald Freudenberger 
1464f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kgs, ugs, sizeof(kgs)))
1465f2bbc96eSHarald Freudenberger 			return -EFAULT;
1466f2bbc96eSHarald Freudenberger 		apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries);
1467f2bbc96eSHarald Freudenberger 		if (IS_ERR(apqns))
1468f2bbc96eSHarald Freudenberger 			return PTR_ERR(apqns);
1469f2bbc96eSHarald Freudenberger 		kkey = kmalloc(klen, GFP_KERNEL);
1470f2bbc96eSHarald Freudenberger 		if (!kkey) {
1471f2bbc96eSHarald Freudenberger 			kfree(apqns);
1472f2bbc96eSHarald Freudenberger 			return -ENOMEM;
1473f2bbc96eSHarald Freudenberger 		}
1474f2bbc96eSHarald Freudenberger 		rc = pkey_genseckey2(apqns, kgs.apqn_entries,
1475f2bbc96eSHarald Freudenberger 				     kgs.type, kgs.size, kgs.keygenflags,
1476f2bbc96eSHarald Freudenberger 				     kkey, &klen);
1477f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc);
1478f2bbc96eSHarald Freudenberger 		kfree(apqns);
1479f2bbc96eSHarald Freudenberger 		if (rc) {
1480f2bbc96eSHarald Freudenberger 			kfree(kkey);
1481f2bbc96eSHarald Freudenberger 			break;
1482f2bbc96eSHarald Freudenberger 		}
1483f2bbc96eSHarald Freudenberger 		if (kgs.key) {
1484f2bbc96eSHarald Freudenberger 			if (kgs.keylen < klen) {
1485f2bbc96eSHarald Freudenberger 				kfree(kkey);
1486f2bbc96eSHarald Freudenberger 				return -EINVAL;
1487f2bbc96eSHarald Freudenberger 			}
1488f2bbc96eSHarald Freudenberger 			if (copy_to_user(kgs.key, kkey, klen)) {
1489f2bbc96eSHarald Freudenberger 				kfree(kkey);
1490f2bbc96eSHarald Freudenberger 				return -EFAULT;
1491f2bbc96eSHarald Freudenberger 			}
1492f2bbc96eSHarald Freudenberger 		}
1493f2bbc96eSHarald Freudenberger 		kgs.keylen = klen;
1494f2bbc96eSHarald Freudenberger 		if (copy_to_user(ugs, &kgs, sizeof(kgs)))
1495f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
1496f2bbc96eSHarald Freudenberger 		kfree(kkey);
1497f2bbc96eSHarald Freudenberger 		break;
1498f2bbc96eSHarald Freudenberger 	}
1499f2bbc96eSHarald Freudenberger 	case PKEY_CLR2SECK2: {
1500f2bbc96eSHarald Freudenberger 		struct pkey_clr2seck2 __user *ucs = (void __user *)arg;
150146a29b03SHarald Freudenberger 		size_t klen = KEYBLOBBUFSIZE;
1502f2bbc96eSHarald Freudenberger 		struct pkey_clr2seck2 kcs;
1503f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns;
1504f2bbc96eSHarald Freudenberger 		u8 *kkey;
1505f2bbc96eSHarald Freudenberger 
1506f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kcs, ucs, sizeof(kcs)))
1507f2bbc96eSHarald Freudenberger 			return -EFAULT;
1508f2bbc96eSHarald Freudenberger 		apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries);
1509f2bbc96eSHarald Freudenberger 		if (IS_ERR(apqns))
1510f2bbc96eSHarald Freudenberger 			return PTR_ERR(apqns);
1511f2bbc96eSHarald Freudenberger 		kkey = kmalloc(klen, GFP_KERNEL);
1512f2bbc96eSHarald Freudenberger 		if (!kkey) {
1513f2bbc96eSHarald Freudenberger 			kfree(apqns);
1514f2bbc96eSHarald Freudenberger 			return -ENOMEM;
1515f2bbc96eSHarald Freudenberger 		}
1516f2bbc96eSHarald Freudenberger 		rc = pkey_clr2seckey2(apqns, kcs.apqn_entries,
1517f2bbc96eSHarald Freudenberger 				      kcs.type, kcs.size, kcs.keygenflags,
1518f2bbc96eSHarald Freudenberger 				      kcs.clrkey.clrkey, kkey, &klen);
1519f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc);
1520f2bbc96eSHarald Freudenberger 		kfree(apqns);
1521f2bbc96eSHarald Freudenberger 		if (rc) {
1522f2bbc96eSHarald Freudenberger 			kfree(kkey);
1523f2bbc96eSHarald Freudenberger 			break;
1524f2bbc96eSHarald Freudenberger 		}
1525f2bbc96eSHarald Freudenberger 		if (kcs.key) {
1526f2bbc96eSHarald Freudenberger 			if (kcs.keylen < klen) {
1527f2bbc96eSHarald Freudenberger 				kfree(kkey);
1528f2bbc96eSHarald Freudenberger 				return -EINVAL;
1529f2bbc96eSHarald Freudenberger 			}
1530f2bbc96eSHarald Freudenberger 			if (copy_to_user(kcs.key, kkey, klen)) {
1531f2bbc96eSHarald Freudenberger 				kfree(kkey);
1532f2bbc96eSHarald Freudenberger 				return -EFAULT;
1533f2bbc96eSHarald Freudenberger 			}
1534f2bbc96eSHarald Freudenberger 		}
1535f2bbc96eSHarald Freudenberger 		kcs.keylen = klen;
1536f2bbc96eSHarald Freudenberger 		if (copy_to_user(ucs, &kcs, sizeof(kcs)))
1537f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
1538f2bbc96eSHarald Freudenberger 		memzero_explicit(&kcs, sizeof(kcs));
1539f2bbc96eSHarald Freudenberger 		kfree(kkey);
1540f2bbc96eSHarald Freudenberger 		break;
1541f2bbc96eSHarald Freudenberger 	}
1542f2bbc96eSHarald Freudenberger 	case PKEY_VERIFYKEY2: {
1543f2bbc96eSHarald Freudenberger 		struct pkey_verifykey2 __user *uvk = (void __user *)arg;
1544f2bbc96eSHarald Freudenberger 		struct pkey_verifykey2 kvk;
1545f2bbc96eSHarald Freudenberger 		u8 *kkey;
1546f2bbc96eSHarald Freudenberger 
1547f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kvk, uvk, sizeof(kvk)))
1548f2bbc96eSHarald Freudenberger 			return -EFAULT;
1549f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(kvk.key, kvk.keylen);
1550f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey))
1551f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
1552f2bbc96eSHarald Freudenberger 		rc = pkey_verifykey2(kkey, kvk.keylen,
1553f2bbc96eSHarald Freudenberger 				     &kvk.cardnr, &kvk.domain,
1554f2bbc96eSHarald Freudenberger 				     &kvk.type, &kvk.size, &kvk.flags);
1555f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc);
1556f2bbc96eSHarald Freudenberger 		kfree(kkey);
1557f2bbc96eSHarald Freudenberger 		if (rc)
1558f2bbc96eSHarald Freudenberger 			break;
1559f2bbc96eSHarald Freudenberger 		if (copy_to_user(uvk, &kvk, sizeof(kvk)))
1560f2bbc96eSHarald Freudenberger 			return -EFAULT;
1561f2bbc96eSHarald Freudenberger 		break;
1562f2bbc96eSHarald Freudenberger 	}
1563f2bbc96eSHarald Freudenberger 	case PKEY_KBLOB2PROTK2: {
1564f2bbc96eSHarald Freudenberger 		struct pkey_kblob2pkey2 __user *utp = (void __user *)arg;
1565f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns = NULL;
156646a29b03SHarald Freudenberger 		struct pkey_kblob2pkey2 ktp;
1567f2bbc96eSHarald Freudenberger 		u8 *kkey;
1568f2bbc96eSHarald Freudenberger 
1569f2bbc96eSHarald Freudenberger 		if (copy_from_user(&ktp, utp, sizeof(ktp)))
1570f2bbc96eSHarald Freudenberger 			return -EFAULT;
1571f2bbc96eSHarald Freudenberger 		apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);
1572f2bbc96eSHarald Freudenberger 		if (IS_ERR(apqns))
1573f2bbc96eSHarald Freudenberger 			return PTR_ERR(apqns);
1574f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(ktp.key, ktp.keylen);
1575f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey)) {
1576f2bbc96eSHarald Freudenberger 			kfree(apqns);
1577f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
1578f2bbc96eSHarald Freudenberger 		}
1579f370f45cSHarald Freudenberger 		ktp.protkey.len = sizeof(ktp.protkey.protkey);
1580f2bbc96eSHarald Freudenberger 		rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries,
1581f370f45cSHarald Freudenberger 					kkey, ktp.keylen,
1582f370f45cSHarald Freudenberger 					ktp.protkey.protkey, &ktp.protkey.len,
1583f370f45cSHarald Freudenberger 					&ktp.protkey.type);
1584f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc);
1585f2bbc96eSHarald Freudenberger 		kfree(apqns);
1586844cf829SHolger Dengler 		memzero_explicit(kkey, ktp.keylen);
1587f2bbc96eSHarald Freudenberger 		kfree(kkey);
1588f2bbc96eSHarald Freudenberger 		if (rc)
1589f2bbc96eSHarald Freudenberger 			break;
1590f2bbc96eSHarald Freudenberger 		if (copy_to_user(utp, &ktp, sizeof(ktp)))
1591f2bbc96eSHarald Freudenberger 			return -EFAULT;
1592f2bbc96eSHarald Freudenberger 		break;
1593f2bbc96eSHarald Freudenberger 	}
1594f2bbc96eSHarald Freudenberger 	case PKEY_APQNS4K: {
1595f2bbc96eSHarald Freudenberger 		struct pkey_apqns4key __user *uak = (void __user *)arg;
1596f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns = NULL;
159746a29b03SHarald Freudenberger 		struct pkey_apqns4key kak;
1598f2bbc96eSHarald Freudenberger 		size_t nr_apqns, len;
1599f2bbc96eSHarald Freudenberger 		u8 *kkey;
1600f2bbc96eSHarald Freudenberger 
1601f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kak, uak, sizeof(kak)))
1602f2bbc96eSHarald Freudenberger 			return -EFAULT;
1603f2bbc96eSHarald Freudenberger 		nr_apqns = kak.apqn_entries;
1604f2bbc96eSHarald Freudenberger 		if (nr_apqns) {
1605f2bbc96eSHarald Freudenberger 			apqns = kmalloc_array(nr_apqns,
1606f2bbc96eSHarald Freudenberger 					      sizeof(struct pkey_apqn),
1607f2bbc96eSHarald Freudenberger 					      GFP_KERNEL);
1608f2bbc96eSHarald Freudenberger 			if (!apqns)
1609f2bbc96eSHarald Freudenberger 				return -ENOMEM;
1610f2bbc96eSHarald Freudenberger 		}
1611f2bbc96eSHarald Freudenberger 		kkey = _copy_key_from_user(kak.key, kak.keylen);
1612f2bbc96eSHarald Freudenberger 		if (IS_ERR(kkey)) {
1613f2bbc96eSHarald Freudenberger 			kfree(apqns);
1614f2bbc96eSHarald Freudenberger 			return PTR_ERR(kkey);
1615f2bbc96eSHarald Freudenberger 		}
1616f2bbc96eSHarald Freudenberger 		rc = pkey_apqns4key(kkey, kak.keylen, kak.flags,
1617f2bbc96eSHarald Freudenberger 				    apqns, &nr_apqns);
1618f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc);
1619f2bbc96eSHarald Freudenberger 		kfree(kkey);
1620f2bbc96eSHarald Freudenberger 		if (rc && rc != -ENOSPC) {
1621f2bbc96eSHarald Freudenberger 			kfree(apqns);
1622f2bbc96eSHarald Freudenberger 			break;
1623f2bbc96eSHarald Freudenberger 		}
1624f2bbc96eSHarald Freudenberger 		if (!rc && kak.apqns) {
1625f2bbc96eSHarald Freudenberger 			if (nr_apqns > kak.apqn_entries) {
1626f2bbc96eSHarald Freudenberger 				kfree(apqns);
1627f2bbc96eSHarald Freudenberger 				return -EINVAL;
1628f2bbc96eSHarald Freudenberger 			}
1629f2bbc96eSHarald Freudenberger 			len = nr_apqns * sizeof(struct pkey_apqn);
1630f2bbc96eSHarald Freudenberger 			if (len) {
1631f2bbc96eSHarald Freudenberger 				if (copy_to_user(kak.apqns, apqns, len)) {
1632f2bbc96eSHarald Freudenberger 					kfree(apqns);
1633f2bbc96eSHarald Freudenberger 					return -EFAULT;
1634f2bbc96eSHarald Freudenberger 				}
1635f2bbc96eSHarald Freudenberger 			}
1636f2bbc96eSHarald Freudenberger 		}
1637f2bbc96eSHarald Freudenberger 		kak.apqn_entries = nr_apqns;
1638f2bbc96eSHarald Freudenberger 		if (copy_to_user(uak, &kak, sizeof(kak)))
1639f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
1640f2bbc96eSHarald Freudenberger 		kfree(apqns);
1641f2bbc96eSHarald Freudenberger 		break;
1642f2bbc96eSHarald Freudenberger 	}
1643f2bbc96eSHarald Freudenberger 	case PKEY_APQNS4KT: {
1644f2bbc96eSHarald Freudenberger 		struct pkey_apqns4keytype __user *uat = (void __user *)arg;
1645f2bbc96eSHarald Freudenberger 		struct pkey_apqn *apqns = NULL;
164646a29b03SHarald Freudenberger 		struct pkey_apqns4keytype kat;
1647f2bbc96eSHarald Freudenberger 		size_t nr_apqns, len;
1648f2bbc96eSHarald Freudenberger 
1649f2bbc96eSHarald Freudenberger 		if (copy_from_user(&kat, uat, sizeof(kat)))
1650f2bbc96eSHarald Freudenberger 			return -EFAULT;
1651f2bbc96eSHarald Freudenberger 		nr_apqns = kat.apqn_entries;
1652f2bbc96eSHarald Freudenberger 		if (nr_apqns) {
1653f2bbc96eSHarald Freudenberger 			apqns = kmalloc_array(nr_apqns,
1654f2bbc96eSHarald Freudenberger 					      sizeof(struct pkey_apqn),
1655f2bbc96eSHarald Freudenberger 					      GFP_KERNEL);
1656f2bbc96eSHarald Freudenberger 			if (!apqns)
1657f2bbc96eSHarald Freudenberger 				return -ENOMEM;
1658f2bbc96eSHarald Freudenberger 		}
1659f2bbc96eSHarald Freudenberger 		rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp,
1660f2bbc96eSHarald Freudenberger 					kat.flags, apqns, &nr_apqns);
1661f2bbc96eSHarald Freudenberger 		DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc);
1662f2bbc96eSHarald Freudenberger 		if (rc && rc != -ENOSPC) {
1663f2bbc96eSHarald Freudenberger 			kfree(apqns);
1664f2bbc96eSHarald Freudenberger 			break;
1665f2bbc96eSHarald Freudenberger 		}
1666f2bbc96eSHarald Freudenberger 		if (!rc && kat.apqns) {
1667f2bbc96eSHarald Freudenberger 			if (nr_apqns > kat.apqn_entries) {
1668f2bbc96eSHarald Freudenberger 				kfree(apqns);
1669f2bbc96eSHarald Freudenberger 				return -EINVAL;
1670f2bbc96eSHarald Freudenberger 			}
1671f2bbc96eSHarald Freudenberger 			len = nr_apqns * sizeof(struct pkey_apqn);
1672f2bbc96eSHarald Freudenberger 			if (len) {
1673f2bbc96eSHarald Freudenberger 				if (copy_to_user(kat.apqns, apqns, len)) {
1674f2bbc96eSHarald Freudenberger 					kfree(apqns);
1675f2bbc96eSHarald Freudenberger 					return -EFAULT;
1676f2bbc96eSHarald Freudenberger 				}
1677f2bbc96eSHarald Freudenberger 			}
1678f2bbc96eSHarald Freudenberger 		}
1679f2bbc96eSHarald Freudenberger 		kat.apqn_entries = nr_apqns;
1680f2bbc96eSHarald Freudenberger 		if (copy_to_user(uat, &kat, sizeof(kat)))
1681f2bbc96eSHarald Freudenberger 			rc = -EFAULT;
1682f2bbc96eSHarald Freudenberger 		kfree(apqns);
1683f2bbc96eSHarald Freudenberger 		break;
1684f2bbc96eSHarald Freudenberger 	}
1685fa6999e3SHarald Freudenberger 	case PKEY_KBLOB2PROTK3: {
1686fa6999e3SHarald Freudenberger 		struct pkey_kblob2pkey3 __user *utp = (void __user *)arg;
1687fa6999e3SHarald Freudenberger 		u32 protkeylen = PROTKEYBLOBBUFSIZE;
168846a29b03SHarald Freudenberger 		struct pkey_apqn *apqns = NULL;
168946a29b03SHarald Freudenberger 		struct pkey_kblob2pkey3 ktp;
1690fa6999e3SHarald Freudenberger 		u8 *kkey, *protkey;
1691fa6999e3SHarald Freudenberger 
1692fa6999e3SHarald Freudenberger 		if (copy_from_user(&ktp, utp, sizeof(ktp)))
1693fa6999e3SHarald Freudenberger 			return -EFAULT;
1694fa6999e3SHarald Freudenberger 		apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);
1695fa6999e3SHarald Freudenberger 		if (IS_ERR(apqns))
1696fa6999e3SHarald Freudenberger 			return PTR_ERR(apqns);
1697fa6999e3SHarald Freudenberger 		kkey = _copy_key_from_user(ktp.key, ktp.keylen);
1698fa6999e3SHarald Freudenberger 		if (IS_ERR(kkey)) {
1699fa6999e3SHarald Freudenberger 			kfree(apqns);
1700fa6999e3SHarald Freudenberger 			return PTR_ERR(kkey);
1701fa6999e3SHarald Freudenberger 		}
1702fa6999e3SHarald Freudenberger 		protkey = kmalloc(protkeylen, GFP_KERNEL);
1703fa6999e3SHarald Freudenberger 		if (!protkey) {
1704fa6999e3SHarald Freudenberger 			kfree(apqns);
1705fa6999e3SHarald Freudenberger 			kfree(kkey);
1706fa6999e3SHarald Freudenberger 			return -ENOMEM;
1707fa6999e3SHarald Freudenberger 		}
1708f370f45cSHarald Freudenberger 		rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries,
1709f370f45cSHarald Freudenberger 					kkey, ktp.keylen,
1710f370f45cSHarald Freudenberger 					protkey, &protkeylen, &ktp.pkeytype);
1711fa6999e3SHarald Freudenberger 		DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc);
1712fa6999e3SHarald Freudenberger 		kfree(apqns);
1713844cf829SHolger Dengler 		memzero_explicit(kkey, ktp.keylen);
1714fa6999e3SHarald Freudenberger 		kfree(kkey);
1715fa6999e3SHarald Freudenberger 		if (rc) {
1716fa6999e3SHarald Freudenberger 			kfree(protkey);
1717fa6999e3SHarald Freudenberger 			break;
1718fa6999e3SHarald Freudenberger 		}
1719fa6999e3SHarald Freudenberger 		if (ktp.pkey && ktp.pkeylen) {
1720fa6999e3SHarald Freudenberger 			if (protkeylen > ktp.pkeylen) {
1721fa6999e3SHarald Freudenberger 				kfree(protkey);
1722fa6999e3SHarald Freudenberger 				return -EINVAL;
1723fa6999e3SHarald Freudenberger 			}
1724fa6999e3SHarald Freudenberger 			if (copy_to_user(ktp.pkey, protkey, protkeylen)) {
1725fa6999e3SHarald Freudenberger 				kfree(protkey);
1726fa6999e3SHarald Freudenberger 				return -EFAULT;
1727fa6999e3SHarald Freudenberger 			}
1728fa6999e3SHarald Freudenberger 		}
1729fa6999e3SHarald Freudenberger 		kfree(protkey);
1730fa6999e3SHarald Freudenberger 		ktp.pkeylen = protkeylen;
1731fa6999e3SHarald Freudenberger 		if (copy_to_user(utp, &ktp, sizeof(ktp)))
1732fa6999e3SHarald Freudenberger 			return -EFAULT;
1733fa6999e3SHarald Freudenberger 		break;
1734fa6999e3SHarald Freudenberger 	}
1735e80d4af0SHarald Freudenberger 	default:
1736e80d4af0SHarald Freudenberger 		/* unknown/unsupported ioctl cmd */
1737e80d4af0SHarald Freudenberger 		return -ENOTTY;
1738e80d4af0SHarald Freudenberger 	}
1739e80d4af0SHarald Freudenberger 
1740e80d4af0SHarald Freudenberger 	return rc;
1741e80d4af0SHarald Freudenberger }
1742e80d4af0SHarald Freudenberger 
1743e80d4af0SHarald Freudenberger /*
1744e80d4af0SHarald Freudenberger  * Sysfs and file io operations
1745e80d4af0SHarald Freudenberger  */
1746d632c047SIngo Franzki 
1747d632c047SIngo Franzki /*
1748d632c047SIngo Franzki  * Sysfs attribute read function for all protected key binary attributes.
1749d632c047SIngo Franzki  * The implementation can not deal with partial reads, because a new random
1750d632c047SIngo Franzki  * protected key blob is generated with each read. In case of partial reads
1751d632c047SIngo Franzki  * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
1752d632c047SIngo Franzki  */
1753d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf,
1754d632c047SIngo Franzki 					  loff_t off, size_t count)
1755d632c047SIngo Franzki {
1756d632c047SIngo Franzki 	struct protaeskeytoken protkeytoken;
1757d632c047SIngo Franzki 	struct pkey_protkey protkey;
1758d632c047SIngo Franzki 	int rc;
1759d632c047SIngo Franzki 
1760d632c047SIngo Franzki 	if (off != 0 || count < sizeof(protkeytoken))
1761d632c047SIngo Franzki 		return -EINVAL;
1762d632c047SIngo Franzki 	if (is_xts)
1763d632c047SIngo Franzki 		if (count < 2 * sizeof(protkeytoken))
1764d632c047SIngo Franzki 			return -EINVAL;
1765d632c047SIngo Franzki 
1766d632c047SIngo Franzki 	memset(&protkeytoken, 0, sizeof(protkeytoken));
1767d632c047SIngo Franzki 	protkeytoken.type = TOKTYPE_NON_CCA;
1768d632c047SIngo Franzki 	protkeytoken.version = TOKVER_PROTECTED_KEY;
1769d632c047SIngo Franzki 	protkeytoken.keytype = keytype;
1770d632c047SIngo Franzki 
1771f370f45cSHarald Freudenberger 	protkey.len = sizeof(protkey.protkey);
1772f370f45cSHarald Freudenberger 	rc = pkey_genprotkey(protkeytoken.keytype,
1773f370f45cSHarald Freudenberger 			     protkey.protkey, &protkey.len, &protkey.type);
1774d632c047SIngo Franzki 	if (rc)
1775d632c047SIngo Franzki 		return rc;
1776d632c047SIngo Franzki 
1777d632c047SIngo Franzki 	protkeytoken.len = protkey.len;
1778d632c047SIngo Franzki 	memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len);
1779d632c047SIngo Franzki 
1780d632c047SIngo Franzki 	memcpy(buf, &protkeytoken, sizeof(protkeytoken));
1781d632c047SIngo Franzki 
1782d632c047SIngo Franzki 	if (is_xts) {
1783f370f45cSHarald Freudenberger 		/* xts needs a second protected key, reuse protkey struct */
1784f370f45cSHarald Freudenberger 		protkey.len = sizeof(protkey.protkey);
1785f370f45cSHarald Freudenberger 		rc = pkey_genprotkey(protkeytoken.keytype,
1786f370f45cSHarald Freudenberger 				     protkey.protkey, &protkey.len, &protkey.type);
1787d632c047SIngo Franzki 		if (rc)
1788d632c047SIngo Franzki 			return rc;
1789d632c047SIngo Franzki 
1790d632c047SIngo Franzki 		protkeytoken.len = protkey.len;
1791d632c047SIngo Franzki 		memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len);
1792d632c047SIngo Franzki 
1793d632c047SIngo Franzki 		memcpy(buf + sizeof(protkeytoken), &protkeytoken,
1794d632c047SIngo Franzki 		       sizeof(protkeytoken));
1795d632c047SIngo Franzki 
1796d632c047SIngo Franzki 		return 2 * sizeof(protkeytoken);
1797d632c047SIngo Franzki 	}
1798d632c047SIngo Franzki 
1799d632c047SIngo Franzki 	return sizeof(protkeytoken);
1800d632c047SIngo Franzki }
1801d632c047SIngo Franzki 
1802d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp,
1803d632c047SIngo Franzki 				    struct kobject *kobj,
1804d632c047SIngo Franzki 				    struct bin_attribute *attr,
1805d632c047SIngo Franzki 				    char *buf, loff_t off,
1806d632c047SIngo Franzki 				    size_t count)
1807d632c047SIngo Franzki {
1808d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf,
1809d632c047SIngo Franzki 					  off, count);
1810d632c047SIngo Franzki }
1811d632c047SIngo Franzki 
1812d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp,
1813d632c047SIngo Franzki 				    struct kobject *kobj,
1814d632c047SIngo Franzki 				    struct bin_attribute *attr,
1815d632c047SIngo Franzki 				    char *buf, loff_t off,
1816d632c047SIngo Franzki 				    size_t count)
1817d632c047SIngo Franzki {
1818d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf,
1819d632c047SIngo Franzki 					  off, count);
1820d632c047SIngo Franzki }
1821d632c047SIngo Franzki 
1822d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp,
1823d632c047SIngo Franzki 				    struct kobject *kobj,
1824d632c047SIngo Franzki 				    struct bin_attribute *attr,
1825d632c047SIngo Franzki 				    char *buf, loff_t off,
1826d632c047SIngo Franzki 				    size_t count)
1827d632c047SIngo Franzki {
1828d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf,
1829d632c047SIngo Franzki 					  off, count);
1830d632c047SIngo Franzki }
1831d632c047SIngo Franzki 
1832d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp,
1833d632c047SIngo Franzki 					struct kobject *kobj,
1834d632c047SIngo Franzki 					struct bin_attribute *attr,
1835d632c047SIngo Franzki 					char *buf, loff_t off,
1836d632c047SIngo Franzki 					size_t count)
1837d632c047SIngo Franzki {
1838d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf,
1839d632c047SIngo Franzki 					  off, count);
1840d632c047SIngo Franzki }
1841d632c047SIngo Franzki 
1842d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp,
1843d632c047SIngo Franzki 					struct kobject *kobj,
1844d632c047SIngo Franzki 					struct bin_attribute *attr,
1845d632c047SIngo Franzki 					char *buf, loff_t off,
1846d632c047SIngo Franzki 					size_t count)
1847d632c047SIngo Franzki {
1848d632c047SIngo Franzki 	return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf,
1849d632c047SIngo Franzki 					  off, count);
1850d632c047SIngo Franzki }
1851d632c047SIngo Franzki 
1852d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken));
1853d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken));
1854d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken));
1855d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken));
1856d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken));
1857d632c047SIngo Franzki 
1858d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = {
1859d632c047SIngo Franzki 	&bin_attr_protkey_aes_128,
1860d632c047SIngo Franzki 	&bin_attr_protkey_aes_192,
1861d632c047SIngo Franzki 	&bin_attr_protkey_aes_256,
1862d632c047SIngo Franzki 	&bin_attr_protkey_aes_128_xts,
1863d632c047SIngo Franzki 	&bin_attr_protkey_aes_256_xts,
1864d632c047SIngo Franzki 	NULL
1865d632c047SIngo Franzki };
1866d632c047SIngo Franzki 
1867d632c047SIngo Franzki static struct attribute_group protkey_attr_group = {
1868d632c047SIngo Franzki 	.name	   = "protkey",
1869d632c047SIngo Franzki 	.bin_attrs = protkey_attrs,
1870d632c047SIngo Franzki };
1871d632c047SIngo Franzki 
1872af504452SIngo Franzki /*
1873af504452SIngo Franzki  * Sysfs attribute read function for all secure key ccadata binary attributes.
1874af504452SIngo Franzki  * The implementation can not deal with partial reads, because a new random
1875af504452SIngo Franzki  * protected key blob is generated with each read. In case of partial reads
1876af504452SIngo Franzki  * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
1877af504452SIngo Franzki  */
1878af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf,
1879af504452SIngo Franzki 					  loff_t off, size_t count)
1880af504452SIngo Franzki {
1881efc598e6SHarald Freudenberger 	struct pkey_seckey *seckey = (struct pkey_seckey *)buf;
188246a29b03SHarald Freudenberger 	int rc;
1883af504452SIngo Franzki 
1884af504452SIngo Franzki 	if (off != 0 || count < sizeof(struct secaeskeytoken))
1885af504452SIngo Franzki 		return -EINVAL;
1886af504452SIngo Franzki 	if (is_xts)
1887af504452SIngo Franzki 		if (count < 2 * sizeof(struct secaeskeytoken))
1888af504452SIngo Franzki 			return -EINVAL;
1889af504452SIngo Franzki 
1890efc598e6SHarald Freudenberger 	rc = cca_genseckey(-1, -1, keytype, seckey->seckey);
1891af504452SIngo Franzki 	if (rc)
1892af504452SIngo Franzki 		return rc;
1893af504452SIngo Franzki 
1894af504452SIngo Franzki 	if (is_xts) {
1895efc598e6SHarald Freudenberger 		seckey++;
1896efc598e6SHarald Freudenberger 		rc = cca_genseckey(-1, -1, keytype, seckey->seckey);
1897af504452SIngo Franzki 		if (rc)
1898af504452SIngo Franzki 			return rc;
1899af504452SIngo Franzki 
1900af504452SIngo Franzki 		return 2 * sizeof(struct secaeskeytoken);
1901af504452SIngo Franzki 	}
1902af504452SIngo Franzki 
1903af504452SIngo Franzki 	return sizeof(struct secaeskeytoken);
1904af504452SIngo Franzki }
1905af504452SIngo Franzki 
1906af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp,
1907af504452SIngo Franzki 				    struct kobject *kobj,
1908af504452SIngo Franzki 				    struct bin_attribute *attr,
1909af504452SIngo Franzki 				    char *buf, loff_t off,
1910af504452SIngo Franzki 				    size_t count)
1911af504452SIngo Franzki {
1912af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf,
1913af504452SIngo Franzki 					  off, count);
1914af504452SIngo Franzki }
1915af504452SIngo Franzki 
1916af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp,
1917af504452SIngo Franzki 				    struct kobject *kobj,
1918af504452SIngo Franzki 				    struct bin_attribute *attr,
1919af504452SIngo Franzki 				    char *buf, loff_t off,
1920af504452SIngo Franzki 				    size_t count)
1921af504452SIngo Franzki {
1922af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf,
1923af504452SIngo Franzki 					  off, count);
1924af504452SIngo Franzki }
1925af504452SIngo Franzki 
1926af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp,
1927af504452SIngo Franzki 				    struct kobject *kobj,
1928af504452SIngo Franzki 				    struct bin_attribute *attr,
1929af504452SIngo Franzki 				    char *buf, loff_t off,
1930af504452SIngo Franzki 				    size_t count)
1931af504452SIngo Franzki {
1932af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf,
1933af504452SIngo Franzki 					  off, count);
1934af504452SIngo Franzki }
1935af504452SIngo Franzki 
1936af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp,
1937af504452SIngo Franzki 					struct kobject *kobj,
1938af504452SIngo Franzki 					struct bin_attribute *attr,
1939af504452SIngo Franzki 					char *buf, loff_t off,
1940af504452SIngo Franzki 					size_t count)
1941af504452SIngo Franzki {
1942af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf,
1943af504452SIngo Franzki 					  off, count);
1944af504452SIngo Franzki }
1945af504452SIngo Franzki 
1946af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp,
1947af504452SIngo Franzki 					struct kobject *kobj,
1948af504452SIngo Franzki 					struct bin_attribute *attr,
1949af504452SIngo Franzki 					char *buf, loff_t off,
1950af504452SIngo Franzki 					size_t count)
1951af504452SIngo Franzki {
1952af504452SIngo Franzki 	return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf,
1953af504452SIngo Franzki 					  off, count);
1954af504452SIngo Franzki }
1955af504452SIngo Franzki 
1956af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken));
1957af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken));
1958af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken));
1959af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken));
1960af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken));
1961af504452SIngo Franzki 
1962af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = {
1963af504452SIngo Franzki 	&bin_attr_ccadata_aes_128,
1964af504452SIngo Franzki 	&bin_attr_ccadata_aes_192,
1965af504452SIngo Franzki 	&bin_attr_ccadata_aes_256,
1966af504452SIngo Franzki 	&bin_attr_ccadata_aes_128_xts,
1967af504452SIngo Franzki 	&bin_attr_ccadata_aes_256_xts,
1968af504452SIngo Franzki 	NULL
1969af504452SIngo Franzki };
1970af504452SIngo Franzki 
1971af504452SIngo Franzki static struct attribute_group ccadata_attr_group = {
1972af504452SIngo Franzki 	.name	   = "ccadata",
1973af504452SIngo Franzki 	.bin_attrs = ccadata_attrs,
1974af504452SIngo Franzki };
1975af504452SIngo Franzki 
1976f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE	(sizeof(struct cipherkeytoken) + 80)
1977f71fee27SIngo Franzki 
1978f71fee27SIngo Franzki /*
1979f71fee27SIngo Franzki  * Sysfs attribute read function for all secure key ccacipher binary attributes.
1980f71fee27SIngo Franzki  * The implementation can not deal with partial reads, because a new random
1981f71fee27SIngo Franzki  * secure key blob is generated with each read. In case of partial reads
1982f71fee27SIngo Franzki  * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
1983f71fee27SIngo Franzki  */
1984f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits,
1985f71fee27SIngo Franzki 					    bool is_xts, char *buf, loff_t off,
1986f71fee27SIngo Franzki 					    size_t count)
1987f71fee27SIngo Franzki {
198855d0a513SHarald Freudenberger 	size_t keysize = CCACIPHERTOKENSIZE;
198946a29b03SHarald Freudenberger 	u32 nr_apqns, *apqns = NULL;
199046a29b03SHarald Freudenberger 	int i, rc, card, dom;
1991f71fee27SIngo Franzki 
1992f71fee27SIngo Franzki 	if (off != 0 || count < CCACIPHERTOKENSIZE)
1993f71fee27SIngo Franzki 		return -EINVAL;
1994f71fee27SIngo Franzki 	if (is_xts)
1995f71fee27SIngo Franzki 		if (count < 2 * CCACIPHERTOKENSIZE)
1996f71fee27SIngo Franzki 			return -EINVAL;
1997f71fee27SIngo Franzki 
199855d0a513SHarald Freudenberger 	/* build a list of apqns able to generate an cipher key */
199955d0a513SHarald Freudenberger 	rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
200032ca04bbSHarald Freudenberger 			   ZCRYPT_CEX6, 0, 0, 0, 0);
2001f71fee27SIngo Franzki 	if (rc)
2002f71fee27SIngo Franzki 		return rc;
200355d0a513SHarald Freudenberger 
200455d0a513SHarald Freudenberger 	memset(buf, 0, is_xts ? 2 * keysize : keysize);
200555d0a513SHarald Freudenberger 
200655d0a513SHarald Freudenberger 	/* simple try all apqns from the list */
200755d0a513SHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
200855d0a513SHarald Freudenberger 		card = apqns[i] >> 16;
200955d0a513SHarald Freudenberger 		dom = apqns[i] & 0xFFFF;
201055d0a513SHarald Freudenberger 		rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize);
201155d0a513SHarald Freudenberger 		if (rc == 0)
201255d0a513SHarald Freudenberger 			break;
201355d0a513SHarald Freudenberger 	}
201455d0a513SHarald Freudenberger 	if (rc)
201555d0a513SHarald Freudenberger 		return rc;
2016f71fee27SIngo Franzki 
2017f71fee27SIngo Franzki 	if (is_xts) {
2018f71fee27SIngo Franzki 		keysize = CCACIPHERTOKENSIZE;
201955d0a513SHarald Freudenberger 		buf += CCACIPHERTOKENSIZE;
202055d0a513SHarald Freudenberger 		rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize);
202155d0a513SHarald Freudenberger 		if (rc == 0)
2022f71fee27SIngo Franzki 			return 2 * CCACIPHERTOKENSIZE;
2023f71fee27SIngo Franzki 	}
2024f71fee27SIngo Franzki 
2025f71fee27SIngo Franzki 	return CCACIPHERTOKENSIZE;
2026f71fee27SIngo Franzki }
2027f71fee27SIngo Franzki 
2028f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp,
2029f71fee27SIngo Franzki 				      struct kobject *kobj,
2030f71fee27SIngo Franzki 				      struct bin_attribute *attr,
2031f71fee27SIngo Franzki 				      char *buf, loff_t off,
2032f71fee27SIngo Franzki 				      size_t count)
2033f71fee27SIngo Franzki {
2034f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf,
2035f71fee27SIngo Franzki 					    off, count);
2036f71fee27SIngo Franzki }
2037f71fee27SIngo Franzki 
2038f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp,
2039f71fee27SIngo Franzki 				      struct kobject *kobj,
2040f71fee27SIngo Franzki 				      struct bin_attribute *attr,
2041f71fee27SIngo Franzki 				      char *buf, loff_t off,
2042f71fee27SIngo Franzki 				      size_t count)
2043f71fee27SIngo Franzki {
2044f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf,
2045f71fee27SIngo Franzki 					    off, count);
2046f71fee27SIngo Franzki }
2047f71fee27SIngo Franzki 
2048f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp,
2049f71fee27SIngo Franzki 				      struct kobject *kobj,
2050f71fee27SIngo Franzki 				      struct bin_attribute *attr,
2051f71fee27SIngo Franzki 				      char *buf, loff_t off,
2052f71fee27SIngo Franzki 				      size_t count)
2053f71fee27SIngo Franzki {
2054f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf,
2055f71fee27SIngo Franzki 					    off, count);
2056f71fee27SIngo Franzki }
2057f71fee27SIngo Franzki 
2058f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp,
2059f71fee27SIngo Franzki 					  struct kobject *kobj,
2060f71fee27SIngo Franzki 					  struct bin_attribute *attr,
2061f71fee27SIngo Franzki 					  char *buf, loff_t off,
2062f71fee27SIngo Franzki 					  size_t count)
2063f71fee27SIngo Franzki {
2064f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf,
2065f71fee27SIngo Franzki 					    off, count);
2066f71fee27SIngo Franzki }
2067f71fee27SIngo Franzki 
2068f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_read(struct file *filp,
2069f71fee27SIngo Franzki 					  struct kobject *kobj,
2070f71fee27SIngo Franzki 					  struct bin_attribute *attr,
2071f71fee27SIngo Franzki 					  char *buf, loff_t off,
2072f71fee27SIngo Franzki 					  size_t count)
2073f71fee27SIngo Franzki {
2074f71fee27SIngo Franzki 	return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf,
2075f71fee27SIngo Franzki 					    off, count);
2076f71fee27SIngo Franzki }
2077f71fee27SIngo Franzki 
2078f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE);
2079f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE);
2080f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE);
2081f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE);
2082f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE);
2083f71fee27SIngo Franzki 
2084f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = {
2085f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_128,
2086f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_192,
2087f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_256,
2088f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_128_xts,
2089f71fee27SIngo Franzki 	&bin_attr_ccacipher_aes_256_xts,
2090f71fee27SIngo Franzki 	NULL
2091f71fee27SIngo Franzki };
2092f71fee27SIngo Franzki 
2093f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = {
2094f71fee27SIngo Franzki 	.name	   = "ccacipher",
2095f71fee27SIngo Franzki 	.bin_attrs = ccacipher_attrs,
2096f71fee27SIngo Franzki };
2097f71fee27SIngo Franzki 
209855d0a513SHarald Freudenberger /*
209955d0a513SHarald Freudenberger  * Sysfs attribute read function for all ep11 aes key binary attributes.
210055d0a513SHarald Freudenberger  * The implementation can not deal with partial reads, because a new random
210155d0a513SHarald Freudenberger  * secure key blob is generated with each read. In case of partial reads
210255d0a513SHarald Freudenberger  * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
210355d0a513SHarald Freudenberger  * This function and the sysfs attributes using it provide EP11 key blobs
210455d0a513SHarald Freudenberger  * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently
210555d0a513SHarald Freudenberger  * 320 bytes.
210655d0a513SHarald Freudenberger  */
210755d0a513SHarald Freudenberger static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits,
210855d0a513SHarald Freudenberger 				       bool is_xts, char *buf, loff_t off,
210955d0a513SHarald Freudenberger 				       size_t count)
211055d0a513SHarald Freudenberger {
211155d0a513SHarald Freudenberger 	size_t keysize = MAXEP11AESKEYBLOBSIZE;
211246a29b03SHarald Freudenberger 	u32 nr_apqns, *apqns = NULL;
211346a29b03SHarald Freudenberger 	int i, rc, card, dom;
211455d0a513SHarald Freudenberger 
211555d0a513SHarald Freudenberger 	if (off != 0 || count < MAXEP11AESKEYBLOBSIZE)
211655d0a513SHarald Freudenberger 		return -EINVAL;
211755d0a513SHarald Freudenberger 	if (is_xts)
211855d0a513SHarald Freudenberger 		if (count < 2 * MAXEP11AESKEYBLOBSIZE)
211955d0a513SHarald Freudenberger 			return -EINVAL;
212055d0a513SHarald Freudenberger 
212155d0a513SHarald Freudenberger 	/* build a list of apqns able to generate an cipher key */
212255d0a513SHarald Freudenberger 	rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
212355d0a513SHarald Freudenberger 			    ZCRYPT_CEX7, EP11_API_V, NULL);
212455d0a513SHarald Freudenberger 	if (rc)
212555d0a513SHarald Freudenberger 		return rc;
212655d0a513SHarald Freudenberger 
212755d0a513SHarald Freudenberger 	memset(buf, 0, is_xts ? 2 * keysize : keysize);
212855d0a513SHarald Freudenberger 
212955d0a513SHarald Freudenberger 	/* simple try all apqns from the list */
213055d0a513SHarald Freudenberger 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
213155d0a513SHarald Freudenberger 		card = apqns[i] >> 16;
213255d0a513SHarald Freudenberger 		dom = apqns[i] & 0xFFFF;
213355d0a513SHarald Freudenberger 		rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize);
213455d0a513SHarald Freudenberger 		if (rc == 0)
213555d0a513SHarald Freudenberger 			break;
213655d0a513SHarald Freudenberger 	}
213755d0a513SHarald Freudenberger 	if (rc)
213855d0a513SHarald Freudenberger 		return rc;
213955d0a513SHarald Freudenberger 
214055d0a513SHarald Freudenberger 	if (is_xts) {
214155d0a513SHarald Freudenberger 		keysize = MAXEP11AESKEYBLOBSIZE;
214255d0a513SHarald Freudenberger 		buf += MAXEP11AESKEYBLOBSIZE;
214355d0a513SHarald Freudenberger 		rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize);
214455d0a513SHarald Freudenberger 		if (rc == 0)
214555d0a513SHarald Freudenberger 			return 2 * MAXEP11AESKEYBLOBSIZE;
214655d0a513SHarald Freudenberger 	}
214755d0a513SHarald Freudenberger 
214855d0a513SHarald Freudenberger 	return MAXEP11AESKEYBLOBSIZE;
214955d0a513SHarald Freudenberger }
215055d0a513SHarald Freudenberger 
215155d0a513SHarald Freudenberger static ssize_t ep11_aes_128_read(struct file *filp,
215255d0a513SHarald Freudenberger 				 struct kobject *kobj,
215355d0a513SHarald Freudenberger 				 struct bin_attribute *attr,
215455d0a513SHarald Freudenberger 				 char *buf, loff_t off,
215555d0a513SHarald Freudenberger 				 size_t count)
215655d0a513SHarald Freudenberger {
215755d0a513SHarald Freudenberger 	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf,
215855d0a513SHarald Freudenberger 				       off, count);
215955d0a513SHarald Freudenberger }
216055d0a513SHarald Freudenberger 
216155d0a513SHarald Freudenberger static ssize_t ep11_aes_192_read(struct file *filp,
216255d0a513SHarald Freudenberger 				 struct kobject *kobj,
216355d0a513SHarald Freudenberger 				 struct bin_attribute *attr,
216455d0a513SHarald Freudenberger 				 char *buf, loff_t off,
216555d0a513SHarald Freudenberger 				 size_t count)
216655d0a513SHarald Freudenberger {
216755d0a513SHarald Freudenberger 	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf,
216855d0a513SHarald Freudenberger 				       off, count);
216955d0a513SHarald Freudenberger }
217055d0a513SHarald Freudenberger 
217155d0a513SHarald Freudenberger static ssize_t ep11_aes_256_read(struct file *filp,
217255d0a513SHarald Freudenberger 				 struct kobject *kobj,
217355d0a513SHarald Freudenberger 				 struct bin_attribute *attr,
217455d0a513SHarald Freudenberger 				 char *buf, loff_t off,
217555d0a513SHarald Freudenberger 				 size_t count)
217655d0a513SHarald Freudenberger {
217755d0a513SHarald Freudenberger 	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf,
217855d0a513SHarald Freudenberger 				       off, count);
217955d0a513SHarald Freudenberger }
218055d0a513SHarald Freudenberger 
218155d0a513SHarald Freudenberger static ssize_t ep11_aes_128_xts_read(struct file *filp,
218255d0a513SHarald Freudenberger 				     struct kobject *kobj,
218355d0a513SHarald Freudenberger 				     struct bin_attribute *attr,
218455d0a513SHarald Freudenberger 				     char *buf, loff_t off,
218555d0a513SHarald Freudenberger 				     size_t count)
218655d0a513SHarald Freudenberger {
218755d0a513SHarald Freudenberger 	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf,
218855d0a513SHarald Freudenberger 				       off, count);
218955d0a513SHarald Freudenberger }
219055d0a513SHarald Freudenberger 
219155d0a513SHarald Freudenberger static ssize_t ep11_aes_256_xts_read(struct file *filp,
219255d0a513SHarald Freudenberger 				     struct kobject *kobj,
219355d0a513SHarald Freudenberger 				     struct bin_attribute *attr,
219455d0a513SHarald Freudenberger 				     char *buf, loff_t off,
219555d0a513SHarald Freudenberger 				     size_t count)
219655d0a513SHarald Freudenberger {
219755d0a513SHarald Freudenberger 	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf,
219855d0a513SHarald Freudenberger 				       off, count);
219955d0a513SHarald Freudenberger }
220055d0a513SHarald Freudenberger 
220155d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE);
220255d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE);
220355d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE);
220455d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE);
220555d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE);
220655d0a513SHarald Freudenberger 
220755d0a513SHarald Freudenberger static struct bin_attribute *ep11_attrs[] = {
220855d0a513SHarald Freudenberger 	&bin_attr_ep11_aes_128,
220955d0a513SHarald Freudenberger 	&bin_attr_ep11_aes_192,
221055d0a513SHarald Freudenberger 	&bin_attr_ep11_aes_256,
221155d0a513SHarald Freudenberger 	&bin_attr_ep11_aes_128_xts,
221255d0a513SHarald Freudenberger 	&bin_attr_ep11_aes_256_xts,
221355d0a513SHarald Freudenberger 	NULL
221455d0a513SHarald Freudenberger };
221555d0a513SHarald Freudenberger 
221655d0a513SHarald Freudenberger static struct attribute_group ep11_attr_group = {
221755d0a513SHarald Freudenberger 	.name	   = "ep11",
221855d0a513SHarald Freudenberger 	.bin_attrs = ep11_attrs,
221955d0a513SHarald Freudenberger };
222055d0a513SHarald Freudenberger 
2221d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = {
2222d632c047SIngo Franzki 	&protkey_attr_group,
2223af504452SIngo Franzki 	&ccadata_attr_group,
2224f71fee27SIngo Franzki 	&ccacipher_attr_group,
222555d0a513SHarald Freudenberger 	&ep11_attr_group,
2226d632c047SIngo Franzki 	NULL,
2227d632c047SIngo Franzki };
2228d632c047SIngo Franzki 
2229e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = {
2230e80d4af0SHarald Freudenberger 	.owner		= THIS_MODULE,
2231e80d4af0SHarald Freudenberger 	.open		= nonseekable_open,
2232e80d4af0SHarald Freudenberger 	.llseek		= no_llseek,
2233e80d4af0SHarald Freudenberger 	.unlocked_ioctl = pkey_unlocked_ioctl,
2234e80d4af0SHarald Freudenberger };
2235e80d4af0SHarald Freudenberger 
2236e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = {
2237e80d4af0SHarald Freudenberger 	.name	= "pkey",
2238e80d4af0SHarald Freudenberger 	.minor	= MISC_DYNAMIC_MINOR,
2239e80d4af0SHarald Freudenberger 	.mode	= 0666,
2240e80d4af0SHarald Freudenberger 	.fops	= &pkey_fops,
2241d632c047SIngo Franzki 	.groups = pkey_attr_groups,
2242e80d4af0SHarald Freudenberger };
2243e80d4af0SHarald Freudenberger 
2244e80d4af0SHarald Freudenberger /*
2245e80d4af0SHarald Freudenberger  * Module init
2246e80d4af0SHarald Freudenberger  */
2247cb4ef3c2SHeiko Carstens static int __init pkey_init(void)
2248e80d4af0SHarald Freudenberger {
22495b35047eSHarald Freudenberger 	cpacf_mask_t func_mask;
2250e80d4af0SHarald Freudenberger 
2251f822ad2cSHarald Freudenberger 	/*
2252f822ad2cSHarald Freudenberger 	 * The pckmo instruction should be available - even if we don't
2253f822ad2cSHarald Freudenberger 	 * actually invoke it. This instruction comes with MSA 3 which
2254f822ad2cSHarald Freudenberger 	 * is also the minimum level for the kmc instructions which
2255f822ad2cSHarald Freudenberger 	 * are able to work with protected keys.
2256f822ad2cSHarald Freudenberger 	 */
22575b35047eSHarald Freudenberger 	if (!cpacf_query(CPACF_PCKMO, &func_mask))
225858443b67SDavid Hildenbrand 		return -ENODEV;
2259e80d4af0SHarald Freudenberger 
2260cb26b9ffSIngo Franzki 	/* check for kmc instructions available */
22615b35047eSHarald Freudenberger 	if (!cpacf_query(CPACF_KMC, &func_mask))
226258443b67SDavid Hildenbrand 		return -ENODEV;
22635b35047eSHarald Freudenberger 	if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) ||
22645b35047eSHarald Freudenberger 	    !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) ||
22655b35047eSHarald Freudenberger 	    !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256))
226658443b67SDavid Hildenbrand 		return -ENODEV;
2267cb26b9ffSIngo Franzki 
2268e80d4af0SHarald Freudenberger 	pkey_debug_init();
2269e80d4af0SHarald Freudenberger 
2270e80d4af0SHarald Freudenberger 	return misc_register(&pkey_dev);
2271e80d4af0SHarald Freudenberger }
2272e80d4af0SHarald Freudenberger 
2273e80d4af0SHarald Freudenberger /*
2274e80d4af0SHarald Freudenberger  * Module exit
2275e80d4af0SHarald Freudenberger  */
2276e80d4af0SHarald Freudenberger static void __exit pkey_exit(void)
2277e80d4af0SHarald Freudenberger {
2278e80d4af0SHarald Freudenberger 	misc_deregister(&pkey_dev);
2279e80d4af0SHarald Freudenberger 	pkey_debug_exit();
2280e80d4af0SHarald Freudenberger }
2281e80d4af0SHarald Freudenberger 
22820a5f9b38SHeiko Carstens module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init);
2283e80d4af0SHarald Freudenberger module_exit(pkey_exit);
2284