17384eb72SHarald Freudenberger // SPDX-License-Identifier: GPL-2.0+
27384eb72SHarald Freudenberger /*
37384eb72SHarald Freudenberger  *  Copyright IBM Corp. 2019
47384eb72SHarald Freudenberger  *  Author(s): Harald Freudenberger <freude@linux.ibm.com>
57384eb72SHarald Freudenberger  *
67384eb72SHarald Freudenberger  *  Collection of EP11 misc functions used by zcrypt and pkey
77384eb72SHarald Freudenberger  */
87384eb72SHarald Freudenberger 
97384eb72SHarald Freudenberger #define KMSG_COMPONENT "zcrypt"
107384eb72SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
117384eb72SHarald Freudenberger 
127384eb72SHarald Freudenberger #include <linux/init.h>
137384eb72SHarald Freudenberger #include <linux/module.h>
147384eb72SHarald Freudenberger #include <linux/slab.h>
157384eb72SHarald Freudenberger #include <linux/random.h>
167384eb72SHarald Freudenberger #include <asm/zcrypt.h>
177384eb72SHarald Freudenberger #include <asm/pkey.h>
18fa6999e3SHarald Freudenberger #include <crypto/aes.h>
197384eb72SHarald Freudenberger 
207384eb72SHarald Freudenberger #include "ap_bus.h"
217384eb72SHarald Freudenberger #include "zcrypt_api.h"
227384eb72SHarald Freudenberger #include "zcrypt_debug.h"
237384eb72SHarald Freudenberger #include "zcrypt_msgtype6.h"
247384eb72SHarald Freudenberger #include "zcrypt_ep11misc.h"
2555d0a513SHarald Freudenberger #include "zcrypt_ccamisc.h"
267384eb72SHarald Freudenberger 
277384eb72SHarald Freudenberger #define DEBUG_DBG(...)	ZCRYPT_DBF(DBF_DEBUG, ##__VA_ARGS__)
287384eb72SHarald Freudenberger #define DEBUG_INFO(...) ZCRYPT_DBF(DBF_INFO, ##__VA_ARGS__)
297384eb72SHarald Freudenberger #define DEBUG_WARN(...) ZCRYPT_DBF(DBF_WARN, ##__VA_ARGS__)
307384eb72SHarald Freudenberger #define DEBUG_ERR(...)	ZCRYPT_DBF(DBF_ERR, ##__VA_ARGS__)
317384eb72SHarald Freudenberger 
32*386cb81eSHolger Dengler #define EP11_PINBLOB_V1_BYTES 56
33*386cb81eSHolger Dengler 
3455d0a513SHarald Freudenberger /* default iv used here */
3555d0a513SHarald Freudenberger static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
3655d0a513SHarald Freudenberger 			       0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
3755d0a513SHarald Freudenberger 
387384eb72SHarald Freudenberger /* ep11 card info cache */
397384eb72SHarald Freudenberger struct card_list_entry {
407384eb72SHarald Freudenberger 	struct list_head list;
417384eb72SHarald Freudenberger 	u16 cardnr;
427384eb72SHarald Freudenberger 	struct ep11_card_info info;
437384eb72SHarald Freudenberger };
447384eb72SHarald Freudenberger static LIST_HEAD(card_list);
457384eb72SHarald Freudenberger static DEFINE_SPINLOCK(card_list_lock);
467384eb72SHarald Freudenberger 
card_cache_fetch(u16 cardnr,struct ep11_card_info * ci)477384eb72SHarald Freudenberger static int card_cache_fetch(u16 cardnr, struct ep11_card_info *ci)
487384eb72SHarald Freudenberger {
497384eb72SHarald Freudenberger 	int rc = -ENOENT;
507384eb72SHarald Freudenberger 	struct card_list_entry *ptr;
517384eb72SHarald Freudenberger 
527384eb72SHarald Freudenberger 	spin_lock_bh(&card_list_lock);
537384eb72SHarald Freudenberger 	list_for_each_entry(ptr, &card_list, list) {
547384eb72SHarald Freudenberger 		if (ptr->cardnr == cardnr) {
557384eb72SHarald Freudenberger 			memcpy(ci, &ptr->info, sizeof(*ci));
567384eb72SHarald Freudenberger 			rc = 0;
577384eb72SHarald Freudenberger 			break;
587384eb72SHarald Freudenberger 		}
597384eb72SHarald Freudenberger 	}
607384eb72SHarald Freudenberger 	spin_unlock_bh(&card_list_lock);
617384eb72SHarald Freudenberger 
627384eb72SHarald Freudenberger 	return rc;
637384eb72SHarald Freudenberger }
647384eb72SHarald Freudenberger 
card_cache_update(u16 cardnr,const struct ep11_card_info * ci)657384eb72SHarald Freudenberger static void card_cache_update(u16 cardnr, const struct ep11_card_info *ci)
667384eb72SHarald Freudenberger {
677384eb72SHarald Freudenberger 	int found = 0;
687384eb72SHarald Freudenberger 	struct card_list_entry *ptr;
697384eb72SHarald Freudenberger 
707384eb72SHarald Freudenberger 	spin_lock_bh(&card_list_lock);
717384eb72SHarald Freudenberger 	list_for_each_entry(ptr, &card_list, list) {
727384eb72SHarald Freudenberger 		if (ptr->cardnr == cardnr) {
737384eb72SHarald Freudenberger 			memcpy(&ptr->info, ci, sizeof(*ci));
747384eb72SHarald Freudenberger 			found = 1;
757384eb72SHarald Freudenberger 			break;
767384eb72SHarald Freudenberger 		}
777384eb72SHarald Freudenberger 	}
787384eb72SHarald Freudenberger 	if (!found) {
797384eb72SHarald Freudenberger 		ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC);
807384eb72SHarald Freudenberger 		if (!ptr) {
817384eb72SHarald Freudenberger 			spin_unlock_bh(&card_list_lock);
827384eb72SHarald Freudenberger 			return;
837384eb72SHarald Freudenberger 		}
847384eb72SHarald Freudenberger 		ptr->cardnr = cardnr;
857384eb72SHarald Freudenberger 		memcpy(&ptr->info, ci, sizeof(*ci));
867384eb72SHarald Freudenberger 		list_add(&ptr->list, &card_list);
877384eb72SHarald Freudenberger 	}
887384eb72SHarald Freudenberger 	spin_unlock_bh(&card_list_lock);
897384eb72SHarald Freudenberger }
907384eb72SHarald Freudenberger 
card_cache_scrub(u16 cardnr)917384eb72SHarald Freudenberger static void card_cache_scrub(u16 cardnr)
927384eb72SHarald Freudenberger {
937384eb72SHarald Freudenberger 	struct card_list_entry *ptr;
947384eb72SHarald Freudenberger 
957384eb72SHarald Freudenberger 	spin_lock_bh(&card_list_lock);
967384eb72SHarald Freudenberger 	list_for_each_entry(ptr, &card_list, list) {
977384eb72SHarald Freudenberger 		if (ptr->cardnr == cardnr) {
987384eb72SHarald Freudenberger 			list_del(&ptr->list);
997384eb72SHarald Freudenberger 			kfree(ptr);
1007384eb72SHarald Freudenberger 			break;
1017384eb72SHarald Freudenberger 		}
1027384eb72SHarald Freudenberger 	}
1037384eb72SHarald Freudenberger 	spin_unlock_bh(&card_list_lock);
1047384eb72SHarald Freudenberger }
1057384eb72SHarald Freudenberger 
card_cache_free(void)1067384eb72SHarald Freudenberger static void __exit card_cache_free(void)
1077384eb72SHarald Freudenberger {
1087384eb72SHarald Freudenberger 	struct card_list_entry *ptr, *pnext;
1097384eb72SHarald Freudenberger 
1107384eb72SHarald Freudenberger 	spin_lock_bh(&card_list_lock);
1117384eb72SHarald Freudenberger 	list_for_each_entry_safe(ptr, pnext, &card_list, list) {
1127384eb72SHarald Freudenberger 		list_del(&ptr->list);
1137384eb72SHarald Freudenberger 		kfree(ptr);
1147384eb72SHarald Freudenberger 	}
1157384eb72SHarald Freudenberger 	spin_unlock_bh(&card_list_lock);
1167384eb72SHarald Freudenberger }
1177384eb72SHarald Freudenberger 
ep11_kb_split(const u8 * kb,size_t kblen,u32 kbver,struct ep11kblob_header ** kbhdr,size_t * kbhdrsize,u8 ** kbpl,size_t * kbplsize)118fb249ce7SHolger Dengler static int ep11_kb_split(const u8 *kb, size_t kblen, u32 kbver,
119fb249ce7SHolger Dengler 			 struct ep11kblob_header **kbhdr, size_t *kbhdrsize,
120fb249ce7SHolger Dengler 			 u8 **kbpl, size_t *kbplsize)
121fb249ce7SHolger Dengler {
122fb249ce7SHolger Dengler 	struct ep11kblob_header *hdr = NULL;
123fb249ce7SHolger Dengler 	size_t hdrsize, plsize = 0;
124fb249ce7SHolger Dengler 	int rc = -EINVAL;
125fb249ce7SHolger Dengler 	u8 *pl = NULL;
126fb249ce7SHolger Dengler 
127fb249ce7SHolger Dengler 	if (kblen < sizeof(struct ep11kblob_header))
128fb249ce7SHolger Dengler 		goto out;
129fb249ce7SHolger Dengler 	hdr = (struct ep11kblob_header *)kb;
130fb249ce7SHolger Dengler 
131fb249ce7SHolger Dengler 	switch (kbver) {
132fb249ce7SHolger Dengler 	case TOKVER_EP11_AES:
133fb249ce7SHolger Dengler 		/* header overlays the payload */
134fb249ce7SHolger Dengler 		hdrsize = 0;
135fb249ce7SHolger Dengler 		break;
136fb249ce7SHolger Dengler 	case TOKVER_EP11_ECC_WITH_HEADER:
137fb249ce7SHolger Dengler 	case TOKVER_EP11_AES_WITH_HEADER:
138fb249ce7SHolger Dengler 		/* payload starts after the header */
139fb249ce7SHolger Dengler 		hdrsize = sizeof(struct ep11kblob_header);
140fb249ce7SHolger Dengler 		break;
141fb249ce7SHolger Dengler 	default:
142fb249ce7SHolger Dengler 		goto out;
143fb249ce7SHolger Dengler 	}
144fb249ce7SHolger Dengler 
145fb249ce7SHolger Dengler 	plsize = kblen - hdrsize;
146fb249ce7SHolger Dengler 	pl = (u8 *)kb + hdrsize;
147fb249ce7SHolger Dengler 
148fb249ce7SHolger Dengler 	if (kbhdr)
149fb249ce7SHolger Dengler 		*kbhdr = hdr;
150fb249ce7SHolger Dengler 	if (kbhdrsize)
151fb249ce7SHolger Dengler 		*kbhdrsize = hdrsize;
152fb249ce7SHolger Dengler 	if (kbpl)
153fb249ce7SHolger Dengler 		*kbpl = pl;
154fb249ce7SHolger Dengler 	if (kbplsize)
155fb249ce7SHolger Dengler 		*kbplsize = plsize;
156fb249ce7SHolger Dengler 
157fb249ce7SHolger Dengler 	rc = 0;
158fb249ce7SHolger Dengler out:
159fb249ce7SHolger Dengler 	return rc;
160fb249ce7SHolger Dengler }
161fb249ce7SHolger Dengler 
ep11_kb_decode(const u8 * kb,size_t kblen,struct ep11kblob_header ** kbhdr,size_t * kbhdrsize,struct ep11keyblob ** kbpl,size_t * kbplsize)162d1fdfb0bSHolger Dengler static int ep11_kb_decode(const u8 *kb, size_t kblen,
163d1fdfb0bSHolger Dengler 			  struct ep11kblob_header **kbhdr, size_t *kbhdrsize,
164d1fdfb0bSHolger Dengler 			  struct ep11keyblob **kbpl, size_t *kbplsize)
165d1fdfb0bSHolger Dengler {
166d1fdfb0bSHolger Dengler 	struct ep11kblob_header *tmph, *hdr = NULL;
167d1fdfb0bSHolger Dengler 	size_t hdrsize = 0, plsize = 0;
168d1fdfb0bSHolger Dengler 	struct ep11keyblob *pl = NULL;
169d1fdfb0bSHolger Dengler 	int rc = -EINVAL;
170d1fdfb0bSHolger Dengler 	u8 *tmpp;
171d1fdfb0bSHolger Dengler 
172d1fdfb0bSHolger Dengler 	if (kblen < sizeof(struct ep11kblob_header))
173d1fdfb0bSHolger Dengler 		goto out;
174d1fdfb0bSHolger Dengler 	tmph = (struct ep11kblob_header *)kb;
175d1fdfb0bSHolger Dengler 
176d1fdfb0bSHolger Dengler 	if (tmph->type != TOKTYPE_NON_CCA &&
177d1fdfb0bSHolger Dengler 	    tmph->len > kblen)
178d1fdfb0bSHolger Dengler 		goto out;
179d1fdfb0bSHolger Dengler 
180d1fdfb0bSHolger Dengler 	if (ep11_kb_split(kb, kblen, tmph->version,
181d1fdfb0bSHolger Dengler 			  &hdr, &hdrsize, &tmpp, &plsize))
182d1fdfb0bSHolger Dengler 		goto out;
183d1fdfb0bSHolger Dengler 
184d1fdfb0bSHolger Dengler 	if (plsize < sizeof(struct ep11keyblob))
185d1fdfb0bSHolger Dengler 		goto out;
186d1fdfb0bSHolger Dengler 
187d1fdfb0bSHolger Dengler 	if (!is_ep11_keyblob(tmpp))
188d1fdfb0bSHolger Dengler 		goto out;
189d1fdfb0bSHolger Dengler 
190d1fdfb0bSHolger Dengler 	pl = (struct ep11keyblob *)tmpp;
191d1fdfb0bSHolger Dengler 	plsize = hdr->len - hdrsize;
192d1fdfb0bSHolger Dengler 
193d1fdfb0bSHolger Dengler 	if (kbhdr)
194d1fdfb0bSHolger Dengler 		*kbhdr = hdr;
195d1fdfb0bSHolger Dengler 	if (kbhdrsize)
196d1fdfb0bSHolger Dengler 		*kbhdrsize = hdrsize;
197d1fdfb0bSHolger Dengler 	if (kbpl)
198d1fdfb0bSHolger Dengler 		*kbpl = pl;
199d1fdfb0bSHolger Dengler 	if (kbplsize)
200d1fdfb0bSHolger Dengler 		*kbplsize = plsize;
201d1fdfb0bSHolger Dengler 
202d1fdfb0bSHolger Dengler 	rc = 0;
203d1fdfb0bSHolger Dengler out:
204d1fdfb0bSHolger Dengler 	return rc;
205d1fdfb0bSHolger Dengler }
206d1fdfb0bSHolger Dengler 
207d1fdfb0bSHolger Dengler /*
208d1fdfb0bSHolger Dengler  * For valid ep11 keyblobs, returns a reference to the wrappingkey verification
209d1fdfb0bSHolger Dengler  * pattern. Otherwise NULL.
210d1fdfb0bSHolger Dengler  */
ep11_kb_wkvp(const u8 * keyblob,size_t keybloblen)211d1fdfb0bSHolger Dengler const u8 *ep11_kb_wkvp(const u8 *keyblob, size_t keybloblen)
212d1fdfb0bSHolger Dengler {
213d1fdfb0bSHolger Dengler 	struct ep11keyblob *kb;
214d1fdfb0bSHolger Dengler 
215d1fdfb0bSHolger Dengler 	if (ep11_kb_decode(keyblob, keybloblen, NULL, NULL, &kb, NULL))
216d1fdfb0bSHolger Dengler 		return NULL;
217d1fdfb0bSHolger Dengler 	return kb->wkvp;
218d1fdfb0bSHolger Dengler }
219d1fdfb0bSHolger Dengler EXPORT_SYMBOL(ep11_kb_wkvp);
220d1fdfb0bSHolger Dengler 
2217384eb72SHarald Freudenberger /*
222fa6999e3SHarald Freudenberger  * Simple check if the key blob is a valid EP11 AES key blob with header.
22355d0a513SHarald Freudenberger  */
ep11_check_aes_key_with_hdr(debug_info_t * dbg,int dbflvl,const u8 * key,size_t keylen,int checkcpacfexp)224fa6999e3SHarald Freudenberger int ep11_check_aes_key_with_hdr(debug_info_t *dbg, int dbflvl,
225fa6999e3SHarald Freudenberger 				const u8 *key, size_t keylen, int checkcpacfexp)
226fa6999e3SHarald Freudenberger {
227fa6999e3SHarald Freudenberger 	struct ep11kblob_header *hdr = (struct ep11kblob_header *)key;
228fa6999e3SHarald Freudenberger 	struct ep11keyblob *kb = (struct ep11keyblob *)(key + sizeof(*hdr));
229fa6999e3SHarald Freudenberger 
230fa6999e3SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__)
231fa6999e3SHarald Freudenberger 
232fa6999e3SHarald Freudenberger 	if (keylen < sizeof(*hdr) + sizeof(*kb)) {
233fa6999e3SHarald Freudenberger 		DBF("%s key check failed, keylen %zu < %zu\n",
234fa6999e3SHarald Freudenberger 		    __func__, keylen, sizeof(*hdr) + sizeof(*kb));
235fa6999e3SHarald Freudenberger 		return -EINVAL;
236fa6999e3SHarald Freudenberger 	}
237fa6999e3SHarald Freudenberger 
238fa6999e3SHarald Freudenberger 	if (hdr->type != TOKTYPE_NON_CCA) {
239fa6999e3SHarald Freudenberger 		if (dbg)
240fa6999e3SHarald Freudenberger 			DBF("%s key check failed, type 0x%02x != 0x%02x\n",
241fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->type, TOKTYPE_NON_CCA);
242fa6999e3SHarald Freudenberger 		return -EINVAL;
243fa6999e3SHarald Freudenberger 	}
244fa6999e3SHarald Freudenberger 	if (hdr->hver != 0x00) {
245fa6999e3SHarald Freudenberger 		if (dbg)
246fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header version 0x%02x != 0x00\n",
247fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->hver);
248fa6999e3SHarald Freudenberger 		return -EINVAL;
249fa6999e3SHarald Freudenberger 	}
250fa6999e3SHarald Freudenberger 	if (hdr->version != TOKVER_EP11_AES_WITH_HEADER) {
251fa6999e3SHarald Freudenberger 		if (dbg)
252fa6999e3SHarald Freudenberger 			DBF("%s key check failed, version 0x%02x != 0x%02x\n",
253fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->version, TOKVER_EP11_AES_WITH_HEADER);
254fa6999e3SHarald Freudenberger 		return -EINVAL;
255fa6999e3SHarald Freudenberger 	}
256fa6999e3SHarald Freudenberger 	if (hdr->len > keylen) {
257fa6999e3SHarald Freudenberger 		if (dbg)
258fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header len %d keylen %zu mismatch\n",
259fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->len, keylen);
260fa6999e3SHarald Freudenberger 		return -EINVAL;
261fa6999e3SHarald Freudenberger 	}
262fa6999e3SHarald Freudenberger 	if (hdr->len < sizeof(*hdr) + sizeof(*kb)) {
263fa6999e3SHarald Freudenberger 		if (dbg)
264fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header len %d < %zu\n",
265fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->len, sizeof(*hdr) + sizeof(*kb));
266fa6999e3SHarald Freudenberger 		return -EINVAL;
267fa6999e3SHarald Freudenberger 	}
268fa6999e3SHarald Freudenberger 
269fa6999e3SHarald Freudenberger 	if (kb->version != EP11_STRUCT_MAGIC) {
270fa6999e3SHarald Freudenberger 		if (dbg)
271fa6999e3SHarald Freudenberger 			DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n",
272fa6999e3SHarald Freudenberger 			    __func__, (int)kb->version, EP11_STRUCT_MAGIC);
273fa6999e3SHarald Freudenberger 		return -EINVAL;
274fa6999e3SHarald Freudenberger 	}
275fa6999e3SHarald Freudenberger 	if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) {
276fa6999e3SHarald Freudenberger 		if (dbg)
277fa6999e3SHarald Freudenberger 			DBF("%s key check failed, PKEY_EXTRACTABLE is off\n",
278fa6999e3SHarald Freudenberger 			    __func__);
279fa6999e3SHarald Freudenberger 		return -EINVAL;
280fa6999e3SHarald Freudenberger 	}
281fa6999e3SHarald Freudenberger 
282fa6999e3SHarald Freudenberger #undef DBF
283fa6999e3SHarald Freudenberger 
284fa6999e3SHarald Freudenberger 	return 0;
285fa6999e3SHarald Freudenberger }
286fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_aes_key_with_hdr);
287fa6999e3SHarald Freudenberger 
288fa6999e3SHarald Freudenberger /*
289fa6999e3SHarald Freudenberger  * Simple check if the key blob is a valid EP11 ECC key blob with header.
290fa6999e3SHarald Freudenberger  */
ep11_check_ecc_key_with_hdr(debug_info_t * dbg,int dbflvl,const u8 * key,size_t keylen,int checkcpacfexp)291fa6999e3SHarald Freudenberger int ep11_check_ecc_key_with_hdr(debug_info_t *dbg, int dbflvl,
292fa6999e3SHarald Freudenberger 				const u8 *key, size_t keylen, int checkcpacfexp)
293fa6999e3SHarald Freudenberger {
294fa6999e3SHarald Freudenberger 	struct ep11kblob_header *hdr = (struct ep11kblob_header *)key;
295fa6999e3SHarald Freudenberger 	struct ep11keyblob *kb = (struct ep11keyblob *)(key + sizeof(*hdr));
296fa6999e3SHarald Freudenberger 
297fa6999e3SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__)
298fa6999e3SHarald Freudenberger 
299fa6999e3SHarald Freudenberger 	if (keylen < sizeof(*hdr) + sizeof(*kb)) {
300fa6999e3SHarald Freudenberger 		DBF("%s key check failed, keylen %zu < %zu\n",
301fa6999e3SHarald Freudenberger 		    __func__, keylen, sizeof(*hdr) + sizeof(*kb));
302fa6999e3SHarald Freudenberger 		return -EINVAL;
303fa6999e3SHarald Freudenberger 	}
304fa6999e3SHarald Freudenberger 
305fa6999e3SHarald Freudenberger 	if (hdr->type != TOKTYPE_NON_CCA) {
306fa6999e3SHarald Freudenberger 		if (dbg)
307fa6999e3SHarald Freudenberger 			DBF("%s key check failed, type 0x%02x != 0x%02x\n",
308fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->type, TOKTYPE_NON_CCA);
309fa6999e3SHarald Freudenberger 		return -EINVAL;
310fa6999e3SHarald Freudenberger 	}
311fa6999e3SHarald Freudenberger 	if (hdr->hver != 0x00) {
312fa6999e3SHarald Freudenberger 		if (dbg)
313fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header version 0x%02x != 0x00\n",
314fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->hver);
315fa6999e3SHarald Freudenberger 		return -EINVAL;
316fa6999e3SHarald Freudenberger 	}
317fa6999e3SHarald Freudenberger 	if (hdr->version != TOKVER_EP11_ECC_WITH_HEADER) {
318fa6999e3SHarald Freudenberger 		if (dbg)
319fa6999e3SHarald Freudenberger 			DBF("%s key check failed, version 0x%02x != 0x%02x\n",
320fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->version, TOKVER_EP11_ECC_WITH_HEADER);
321fa6999e3SHarald Freudenberger 		return -EINVAL;
322fa6999e3SHarald Freudenberger 	}
323fa6999e3SHarald Freudenberger 	if (hdr->len > keylen) {
324fa6999e3SHarald Freudenberger 		if (dbg)
325fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header len %d keylen %zu mismatch\n",
326fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->len, keylen);
327fa6999e3SHarald Freudenberger 		return -EINVAL;
328fa6999e3SHarald Freudenberger 	}
329fa6999e3SHarald Freudenberger 	if (hdr->len < sizeof(*hdr) + sizeof(*kb)) {
330fa6999e3SHarald Freudenberger 		if (dbg)
331fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header len %d < %zu\n",
332fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->len, sizeof(*hdr) + sizeof(*kb));
333fa6999e3SHarald Freudenberger 		return -EINVAL;
334fa6999e3SHarald Freudenberger 	}
335fa6999e3SHarald Freudenberger 
336fa6999e3SHarald Freudenberger 	if (kb->version != EP11_STRUCT_MAGIC) {
337fa6999e3SHarald Freudenberger 		if (dbg)
338fa6999e3SHarald Freudenberger 			DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n",
339fa6999e3SHarald Freudenberger 			    __func__, (int)kb->version, EP11_STRUCT_MAGIC);
340fa6999e3SHarald Freudenberger 		return -EINVAL;
341fa6999e3SHarald Freudenberger 	}
342fa6999e3SHarald Freudenberger 	if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) {
343fa6999e3SHarald Freudenberger 		if (dbg)
344fa6999e3SHarald Freudenberger 			DBF("%s key check failed, PKEY_EXTRACTABLE is off\n",
345fa6999e3SHarald Freudenberger 			    __func__);
346fa6999e3SHarald Freudenberger 		return -EINVAL;
347fa6999e3SHarald Freudenberger 	}
348fa6999e3SHarald Freudenberger 
349fa6999e3SHarald Freudenberger #undef DBF
350fa6999e3SHarald Freudenberger 
351fa6999e3SHarald Freudenberger 	return 0;
352fa6999e3SHarald Freudenberger }
353fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_ecc_key_with_hdr);
354fa6999e3SHarald Freudenberger 
355fa6999e3SHarald Freudenberger /*
356fa6999e3SHarald Freudenberger  * Simple check if the key blob is a valid EP11 AES key blob with
357fa6999e3SHarald Freudenberger  * the header in the session field (old style EP11 AES key).
358fa6999e3SHarald Freudenberger  */
ep11_check_aes_key(debug_info_t * dbg,int dbflvl,const u8 * key,size_t keylen,int checkcpacfexp)359fa6999e3SHarald Freudenberger int ep11_check_aes_key(debug_info_t *dbg, int dbflvl,
360fa6999e3SHarald Freudenberger 		       const u8 *key, size_t keylen, int checkcpacfexp)
36155d0a513SHarald Freudenberger {
36255d0a513SHarald Freudenberger 	struct ep11keyblob *kb = (struct ep11keyblob *)key;
36355d0a513SHarald Freudenberger 
36455d0a513SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__)
36555d0a513SHarald Freudenberger 
366fa6999e3SHarald Freudenberger 	if (keylen < sizeof(*kb)) {
367fa6999e3SHarald Freudenberger 		DBF("%s key check failed, keylen %zu < %zu\n",
368fa6999e3SHarald Freudenberger 		    __func__, keylen, sizeof(*kb));
369fa6999e3SHarald Freudenberger 		return -EINVAL;
370fa6999e3SHarald Freudenberger 	}
371fa6999e3SHarald Freudenberger 
37255d0a513SHarald Freudenberger 	if (kb->head.type != TOKTYPE_NON_CCA) {
37355d0a513SHarald Freudenberger 		if (dbg)
37455d0a513SHarald Freudenberger 			DBF("%s key check failed, type 0x%02x != 0x%02x\n",
37555d0a513SHarald Freudenberger 			    __func__, (int)kb->head.type, TOKTYPE_NON_CCA);
37655d0a513SHarald Freudenberger 		return -EINVAL;
37755d0a513SHarald Freudenberger 	}
37855d0a513SHarald Freudenberger 	if (kb->head.version != TOKVER_EP11_AES) {
37955d0a513SHarald Freudenberger 		if (dbg)
38055d0a513SHarald Freudenberger 			DBF("%s key check failed, version 0x%02x != 0x%02x\n",
38155d0a513SHarald Freudenberger 			    __func__, (int)kb->head.version, TOKVER_EP11_AES);
38255d0a513SHarald Freudenberger 		return -EINVAL;
38355d0a513SHarald Freudenberger 	}
384fa6999e3SHarald Freudenberger 	if (kb->head.len > keylen) {
385fa6999e3SHarald Freudenberger 		if (dbg)
386fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header len %d keylen %zu mismatch\n",
387fa6999e3SHarald Freudenberger 			    __func__, (int)kb->head.len, keylen);
388fa6999e3SHarald Freudenberger 		return -EINVAL;
389fa6999e3SHarald Freudenberger 	}
390fa6999e3SHarald Freudenberger 	if (kb->head.len < sizeof(*kb)) {
391fa6999e3SHarald Freudenberger 		if (dbg)
392fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header len %d < %zu\n",
393fa6999e3SHarald Freudenberger 			    __func__, (int)kb->head.len, sizeof(*kb));
394fa6999e3SHarald Freudenberger 		return -EINVAL;
395fa6999e3SHarald Freudenberger 	}
396fa6999e3SHarald Freudenberger 
39755d0a513SHarald Freudenberger 	if (kb->version != EP11_STRUCT_MAGIC) {
39855d0a513SHarald Freudenberger 		if (dbg)
399fa6999e3SHarald Freudenberger 			DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n",
40055d0a513SHarald Freudenberger 			    __func__, (int)kb->version, EP11_STRUCT_MAGIC);
40155d0a513SHarald Freudenberger 		return -EINVAL;
40255d0a513SHarald Freudenberger 	}
403fa6999e3SHarald Freudenberger 	if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) {
40455d0a513SHarald Freudenberger 		if (dbg)
405fa6999e3SHarald Freudenberger 			DBF("%s key check failed, PKEY_EXTRACTABLE is off\n",
40655d0a513SHarald Freudenberger 			    __func__);
40755d0a513SHarald Freudenberger 		return -EINVAL;
40855d0a513SHarald Freudenberger 	}
409fa6999e3SHarald Freudenberger 
41055d0a513SHarald Freudenberger #undef DBF
41155d0a513SHarald Freudenberger 
41255d0a513SHarald Freudenberger 	return 0;
41355d0a513SHarald Freudenberger }
414fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_aes_key);
41555d0a513SHarald Freudenberger 
41655d0a513SHarald Freudenberger /*
4177384eb72SHarald Freudenberger  * Allocate and prepare ep11 cprb plus additional payload.
4187384eb72SHarald Freudenberger  */
alloc_cprb(size_t payload_len)41955d0a513SHarald Freudenberger static inline struct ep11_cprb *alloc_cprb(size_t payload_len)
4207384eb72SHarald Freudenberger {
4217384eb72SHarald Freudenberger 	size_t len = sizeof(struct ep11_cprb) + payload_len;
4227384eb72SHarald Freudenberger 	struct ep11_cprb *cprb;
4237384eb72SHarald Freudenberger 
42479d6c502SZou Wei 	cprb = kzalloc(len, GFP_KERNEL);
4257384eb72SHarald Freudenberger 	if (!cprb)
4267384eb72SHarald Freudenberger 		return NULL;
4277384eb72SHarald Freudenberger 
4287384eb72SHarald Freudenberger 	cprb->cprb_len = sizeof(struct ep11_cprb);
4297384eb72SHarald Freudenberger 	cprb->cprb_ver_id = 0x04;
4307384eb72SHarald Freudenberger 	memcpy(cprb->func_id, "T4", 2);
4317384eb72SHarald Freudenberger 	cprb->ret_code = 0xFFFFFFFF;
4327384eb72SHarald Freudenberger 	cprb->payload_len = payload_len;
4337384eb72SHarald Freudenberger 
4347384eb72SHarald Freudenberger 	return cprb;
4357384eb72SHarald Freudenberger }
4367384eb72SHarald Freudenberger 
4377384eb72SHarald Freudenberger /*
43855d0a513SHarald Freudenberger  * Some helper functions related to ASN1 encoding.
43955d0a513SHarald Freudenberger  * Limited to length info <= 2 byte.
4407384eb72SHarald Freudenberger  */
44155d0a513SHarald Freudenberger 
44255d0a513SHarald Freudenberger #define ASN1TAGLEN(x) (2 + (x) + ((x) > 127 ? 1 : 0) + ((x) > 255 ? 1 : 0))
44355d0a513SHarald Freudenberger 
asn1tag_write(u8 * ptr,u8 tag,const u8 * pvalue,u16 valuelen)44455d0a513SHarald Freudenberger static int asn1tag_write(u8 *ptr, u8 tag, const u8 *pvalue, u16 valuelen)
4457384eb72SHarald Freudenberger {
44655d0a513SHarald Freudenberger 	ptr[0] = tag;
44755d0a513SHarald Freudenberger 	if (valuelen > 255) {
44855d0a513SHarald Freudenberger 		ptr[1] = 0x82;
44955d0a513SHarald Freudenberger 		*((u16 *)(ptr + 2)) = valuelen;
45055d0a513SHarald Freudenberger 		memcpy(ptr + 4, pvalue, valuelen);
45155d0a513SHarald Freudenberger 		return 4 + valuelen;
45255d0a513SHarald Freudenberger 	}
45355d0a513SHarald Freudenberger 	if (valuelen > 127) {
45455d0a513SHarald Freudenberger 		ptr[1] = 0x81;
45555d0a513SHarald Freudenberger 		ptr[2] = (u8)valuelen;
45655d0a513SHarald Freudenberger 		memcpy(ptr + 3, pvalue, valuelen);
45755d0a513SHarald Freudenberger 		return 3 + valuelen;
45855d0a513SHarald Freudenberger 	}
45955d0a513SHarald Freudenberger 	ptr[1] = (u8)valuelen;
46055d0a513SHarald Freudenberger 	memcpy(ptr + 2, pvalue, valuelen);
46155d0a513SHarald Freudenberger 	return 2 + valuelen;
46255d0a513SHarald Freudenberger }
46355d0a513SHarald Freudenberger 
46455d0a513SHarald Freudenberger /* EP11 payload > 127 bytes starts with this struct */
46555d0a513SHarald Freudenberger struct pl_head {
4667384eb72SHarald Freudenberger 	u8  tag;
4677384eb72SHarald Freudenberger 	u8  lenfmt;
4687384eb72SHarald Freudenberger 	u16 len;
4697384eb72SHarald Freudenberger 	u8  func_tag;
4707384eb72SHarald Freudenberger 	u8  func_len;
4717384eb72SHarald Freudenberger 	u32 func;
4727384eb72SHarald Freudenberger 	u8  dom_tag;
4737384eb72SHarald Freudenberger 	u8  dom_len;
4747384eb72SHarald Freudenberger 	u32 dom;
47555d0a513SHarald Freudenberger } __packed;
47655d0a513SHarald Freudenberger 
47755d0a513SHarald Freudenberger /* prep ep11 payload head helper function */
prep_head(struct pl_head * h,size_t pl_size,int api,int func)47855d0a513SHarald Freudenberger static inline void prep_head(struct pl_head *h,
47955d0a513SHarald Freudenberger 			     size_t pl_size, int api, int func)
48055d0a513SHarald Freudenberger {
48155d0a513SHarald Freudenberger 	h->tag = 0x30;
48255d0a513SHarald Freudenberger 	h->lenfmt = 0x82;
48355d0a513SHarald Freudenberger 	h->len = pl_size - 4;
48455d0a513SHarald Freudenberger 	h->func_tag = 0x04;
48555d0a513SHarald Freudenberger 	h->func_len = sizeof(u32);
48655d0a513SHarald Freudenberger 	h->func = (api << 16) + func;
48755d0a513SHarald Freudenberger 	h->dom_tag = 0x04;
48855d0a513SHarald Freudenberger 	h->dom_len = sizeof(u32);
48955d0a513SHarald Freudenberger }
49055d0a513SHarald Freudenberger 
49155d0a513SHarald Freudenberger /* prep urb helper function */
prep_urb(struct ep11_urb * u,struct ep11_target_dev * t,int nt,struct ep11_cprb * req,size_t req_len,struct ep11_cprb * rep,size_t rep_len)49255d0a513SHarald Freudenberger static inline void prep_urb(struct ep11_urb *u,
49355d0a513SHarald Freudenberger 			    struct ep11_target_dev *t, int nt,
49455d0a513SHarald Freudenberger 			    struct ep11_cprb *req, size_t req_len,
49555d0a513SHarald Freudenberger 			    struct ep11_cprb *rep, size_t rep_len)
49655d0a513SHarald Freudenberger {
49755d0a513SHarald Freudenberger 	u->targets = (u8 __user *)t;
49855d0a513SHarald Freudenberger 	u->targets_num = nt;
49955d0a513SHarald Freudenberger 	u->req = (u8 __user *)req;
50055d0a513SHarald Freudenberger 	u->req_len = req_len;
50155d0a513SHarald Freudenberger 	u->resp = (u8 __user *)rep;
50255d0a513SHarald Freudenberger 	u->resp_len = rep_len;
50355d0a513SHarald Freudenberger }
50455d0a513SHarald Freudenberger 
50555d0a513SHarald Freudenberger /* Check ep11 reply payload, return 0 or suggested errno value. */
check_reply_pl(const u8 * pl,const char * func)50655d0a513SHarald Freudenberger static int check_reply_pl(const u8 *pl, const char *func)
50755d0a513SHarald Freudenberger {
50855d0a513SHarald Freudenberger 	int len;
50955d0a513SHarald Freudenberger 	u32 ret;
51055d0a513SHarald Freudenberger 
51155d0a513SHarald Freudenberger 	/* start tag */
51255d0a513SHarald Freudenberger 	if (*pl++ != 0x30) {
51355d0a513SHarald Freudenberger 		DEBUG_ERR("%s reply start tag mismatch\n", func);
51455d0a513SHarald Freudenberger 		return -EIO;
51555d0a513SHarald Freudenberger 	}
51655d0a513SHarald Freudenberger 
51755d0a513SHarald Freudenberger 	/* payload length format */
51855d0a513SHarald Freudenberger 	if (*pl < 127) {
51955d0a513SHarald Freudenberger 		len = *pl;
52055d0a513SHarald Freudenberger 		pl++;
52155d0a513SHarald Freudenberger 	} else if (*pl == 0x81) {
52255d0a513SHarald Freudenberger 		pl++;
52355d0a513SHarald Freudenberger 		len = *pl;
52455d0a513SHarald Freudenberger 		pl++;
52555d0a513SHarald Freudenberger 	} else if (*pl == 0x82) {
52655d0a513SHarald Freudenberger 		pl++;
52755d0a513SHarald Freudenberger 		len = *((u16 *)pl);
52855d0a513SHarald Freudenberger 		pl += 2;
52955d0a513SHarald Freudenberger 	} else {
53055d0a513SHarald Freudenberger 		DEBUG_ERR("%s reply start tag lenfmt mismatch 0x%02hhx\n",
53155d0a513SHarald Freudenberger 			  func, *pl);
53255d0a513SHarald Freudenberger 		return -EIO;
53355d0a513SHarald Freudenberger 	}
53455d0a513SHarald Freudenberger 
53555d0a513SHarald Freudenberger 	/* len should cover at least 3 fields with 32 bit value each */
53655d0a513SHarald Freudenberger 	if (len < 3 * 6) {
53755d0a513SHarald Freudenberger 		DEBUG_ERR("%s reply length %d too small\n", func, len);
53855d0a513SHarald Freudenberger 		return -EIO;
53955d0a513SHarald Freudenberger 	}
54055d0a513SHarald Freudenberger 
54155d0a513SHarald Freudenberger 	/* function tag, length and value */
54255d0a513SHarald Freudenberger 	if (pl[0] != 0x04 || pl[1] != 0x04) {
54355d0a513SHarald Freudenberger 		DEBUG_ERR("%s function tag or length mismatch\n", func);
54455d0a513SHarald Freudenberger 		return -EIO;
54555d0a513SHarald Freudenberger 	}
54655d0a513SHarald Freudenberger 	pl += 6;
54755d0a513SHarald Freudenberger 
54855d0a513SHarald Freudenberger 	/* dom tag, length and value */
54955d0a513SHarald Freudenberger 	if (pl[0] != 0x04 || pl[1] != 0x04) {
55055d0a513SHarald Freudenberger 		DEBUG_ERR("%s dom tag or length mismatch\n", func);
55155d0a513SHarald Freudenberger 		return -EIO;
55255d0a513SHarald Freudenberger 	}
55355d0a513SHarald Freudenberger 	pl += 6;
55455d0a513SHarald Freudenberger 
55555d0a513SHarald Freudenberger 	/* return value tag, length and value */
55655d0a513SHarald Freudenberger 	if (pl[0] != 0x04 || pl[1] != 0x04) {
55755d0a513SHarald Freudenberger 		DEBUG_ERR("%s return value tag or length mismatch\n", func);
55855d0a513SHarald Freudenberger 		return -EIO;
55955d0a513SHarald Freudenberger 	}
56055d0a513SHarald Freudenberger 	pl += 2;
56155d0a513SHarald Freudenberger 	ret = *((u32 *)pl);
56255d0a513SHarald Freudenberger 	if (ret != 0) {
56355d0a513SHarald Freudenberger 		DEBUG_ERR("%s return value 0x%04x != 0\n", func, ret);
56455d0a513SHarald Freudenberger 		return -EIO;
56555d0a513SHarald Freudenberger 	}
56655d0a513SHarald Freudenberger 
56755d0a513SHarald Freudenberger 	return 0;
56855d0a513SHarald Freudenberger }
56955d0a513SHarald Freudenberger 
57055d0a513SHarald Freudenberger /*
57155d0a513SHarald Freudenberger  * Helper function which does an ep11 query with given query type.
57255d0a513SHarald Freudenberger  */
ep11_query_info(u16 cardnr,u16 domain,u32 query_type,size_t buflen,u8 * buf)57355d0a513SHarald Freudenberger static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
57455d0a513SHarald Freudenberger 			   size_t buflen, u8 *buf)
57555d0a513SHarald Freudenberger {
57655d0a513SHarald Freudenberger 	struct ep11_info_req_pl {
57755d0a513SHarald Freudenberger 		struct pl_head head;
57855d0a513SHarald Freudenberger 		u8  query_type_tag;
57955d0a513SHarald Freudenberger 		u8  query_type_len;
58055d0a513SHarald Freudenberger 		u32 query_type;
58155d0a513SHarald Freudenberger 		u8  query_subtype_tag;
58255d0a513SHarald Freudenberger 		u8  query_subtype_len;
58355d0a513SHarald Freudenberger 		u32 query_subtype;
58455d0a513SHarald Freudenberger 	} __packed * req_pl;
58555d0a513SHarald Freudenberger 	struct ep11_info_rep_pl {
58655d0a513SHarald Freudenberger 		struct pl_head head;
5877384eb72SHarald Freudenberger 		u8  rc_tag;
5887384eb72SHarald Freudenberger 		u8  rc_len;
5897384eb72SHarald Freudenberger 		u32 rc;
5907384eb72SHarald Freudenberger 		u8  data_tag;
5917384eb72SHarald Freudenberger 		u8  data_lenfmt;
5927384eb72SHarald Freudenberger 		u16 data_len;
5937384eb72SHarald Freudenberger 	} __packed * rep_pl;
5947384eb72SHarald Freudenberger 	struct ep11_cprb *req = NULL, *rep = NULL;
5957384eb72SHarald Freudenberger 	struct ep11_target_dev target;
5967384eb72SHarald Freudenberger 	struct ep11_urb *urb = NULL;
597*386cb81eSHolger Dengler 	int api = EP11_API_V1, rc = -ENOMEM;
5987384eb72SHarald Freudenberger 
5997384eb72SHarald Freudenberger 	/* request cprb and payload */
60055d0a513SHarald Freudenberger 	req = alloc_cprb(sizeof(struct ep11_info_req_pl));
6017384eb72SHarald Freudenberger 	if (!req)
6027384eb72SHarald Freudenberger 		goto out;
6037384eb72SHarald Freudenberger 	req_pl = (struct ep11_info_req_pl *)(((u8 *)req) + sizeof(*req));
60455d0a513SHarald Freudenberger 	prep_head(&req_pl->head, sizeof(*req_pl), api, 38); /* get xcp info */
6057384eb72SHarald Freudenberger 	req_pl->query_type_tag = 0x04;
6067384eb72SHarald Freudenberger 	req_pl->query_type_len = sizeof(u32);
6077384eb72SHarald Freudenberger 	req_pl->query_type = query_type;
6087384eb72SHarald Freudenberger 	req_pl->query_subtype_tag = 0x04;
6097384eb72SHarald Freudenberger 	req_pl->query_subtype_len = sizeof(u32);
6107384eb72SHarald Freudenberger 
6117384eb72SHarald Freudenberger 	/* reply cprb and payload */
61255d0a513SHarald Freudenberger 	rep = alloc_cprb(sizeof(struct ep11_info_rep_pl) + buflen);
6137384eb72SHarald Freudenberger 	if (!rep)
6147384eb72SHarald Freudenberger 		goto out;
6157384eb72SHarald Freudenberger 	rep_pl = (struct ep11_info_rep_pl *)(((u8 *)rep) + sizeof(*rep));
6167384eb72SHarald Freudenberger 
6177384eb72SHarald Freudenberger 	/* urb and target */
6182004b57cSHarald Freudenberger 	urb = kmalloc(sizeof(*urb), GFP_KERNEL);
6197384eb72SHarald Freudenberger 	if (!urb)
6207384eb72SHarald Freudenberger 		goto out;
6217384eb72SHarald Freudenberger 	target.ap_id = cardnr;
6227384eb72SHarald Freudenberger 	target.dom_id = domain;
62355d0a513SHarald Freudenberger 	prep_urb(urb, &target, 1,
62455d0a513SHarald Freudenberger 		 req, sizeof(*req) + sizeof(*req_pl),
62555d0a513SHarald Freudenberger 		 rep, sizeof(*rep) + sizeof(*rep_pl) + buflen);
6267384eb72SHarald Freudenberger 
62752f72febSHarald Freudenberger 	rc = zcrypt_send_ep11_cprb(urb);
6287384eb72SHarald Freudenberger 	if (rc) {
6297384eb72SHarald Freudenberger 		DEBUG_ERR(
6307384eb72SHarald Freudenberger 			"%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
6317384eb72SHarald Freudenberger 			__func__, (int)cardnr, (int)domain, rc);
6327384eb72SHarald Freudenberger 		goto out;
6337384eb72SHarald Freudenberger 	}
6347384eb72SHarald Freudenberger 
63555d0a513SHarald Freudenberger 	rc = check_reply_pl((u8 *)rep_pl, __func__);
63655d0a513SHarald Freudenberger 	if (rc)
6377384eb72SHarald Freudenberger 		goto out;
63855d0a513SHarald Freudenberger 	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
6397384eb72SHarald Freudenberger 		DEBUG_ERR("%s unknown reply data format\n", __func__);
64055d0a513SHarald Freudenberger 		rc = -EIO;
6417384eb72SHarald Freudenberger 		goto out;
6427384eb72SHarald Freudenberger 	}
6437384eb72SHarald Freudenberger 	if (rep_pl->data_len > buflen) {
6447384eb72SHarald Freudenberger 		DEBUG_ERR("%s mismatch between reply data len and buffer len\n",
6457384eb72SHarald Freudenberger 			  __func__);
64655d0a513SHarald Freudenberger 		rc = -ENOSPC;
6477384eb72SHarald Freudenberger 		goto out;
6487384eb72SHarald Freudenberger 	}
6497384eb72SHarald Freudenberger 
65055d0a513SHarald Freudenberger 	memcpy(buf, ((u8 *)rep_pl) + sizeof(*rep_pl), rep_pl->data_len);
6517384eb72SHarald Freudenberger 
6527384eb72SHarald Freudenberger out:
6537384eb72SHarald Freudenberger 	kfree(req);
6547384eb72SHarald Freudenberger 	kfree(rep);
6557384eb72SHarald Freudenberger 	kfree(urb);
6567384eb72SHarald Freudenberger 	return rc;
6577384eb72SHarald Freudenberger }
6587384eb72SHarald Freudenberger 
6597384eb72SHarald Freudenberger /*
6607384eb72SHarald Freudenberger  * Provide information about an EP11 card.
6617384eb72SHarald Freudenberger  */
ep11_get_card_info(u16 card,struct ep11_card_info * info,int verify)6627384eb72SHarald Freudenberger int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify)
6637384eb72SHarald Freudenberger {
6647384eb72SHarald Freudenberger 	int rc;
6657384eb72SHarald Freudenberger 	struct ep11_module_query_info {
6667384eb72SHarald Freudenberger 		u32 API_ord_nr;
6677384eb72SHarald Freudenberger 		u32 firmware_id;
6687384eb72SHarald Freudenberger 		u8  FW_major_vers;
6697384eb72SHarald Freudenberger 		u8  FW_minor_vers;
6707384eb72SHarald Freudenberger 		u8  CSP_major_vers;
6717384eb72SHarald Freudenberger 		u8  CSP_minor_vers;
6727384eb72SHarald Freudenberger 		u8  fwid[32];
6737384eb72SHarald Freudenberger 		u8  xcp_config_hash[32];
6747384eb72SHarald Freudenberger 		u8  CSP_config_hash[32];
6757384eb72SHarald Freudenberger 		u8  serial[16];
6767384eb72SHarald Freudenberger 		u8  module_date_time[16];
6777384eb72SHarald Freudenberger 		u64 op_mode;
6787384eb72SHarald Freudenberger 		u32 PKCS11_flags;
6797384eb72SHarald Freudenberger 		u32 ext_flags;
6807384eb72SHarald Freudenberger 		u32 domains;
6817384eb72SHarald Freudenberger 		u32 sym_state_bytes;
6827384eb72SHarald Freudenberger 		u32 digest_state_bytes;
6837384eb72SHarald Freudenberger 		u32 pin_blob_bytes;
6847384eb72SHarald Freudenberger 		u32 SPKI_bytes;
6857384eb72SHarald Freudenberger 		u32 priv_key_blob_bytes;
6867384eb72SHarald Freudenberger 		u32 sym_blob_bytes;
6877384eb72SHarald Freudenberger 		u32 max_payload_bytes;
6887384eb72SHarald Freudenberger 		u32 CP_profile_bytes;
6897384eb72SHarald Freudenberger 		u32 max_CP_index;
6907384eb72SHarald Freudenberger 	} __packed * pmqi = NULL;
6917384eb72SHarald Freudenberger 
6927384eb72SHarald Freudenberger 	rc = card_cache_fetch(card, info);
6937384eb72SHarald Freudenberger 	if (rc || verify) {
6947384eb72SHarald Freudenberger 		pmqi = kmalloc(sizeof(*pmqi), GFP_KERNEL);
6957384eb72SHarald Freudenberger 		if (!pmqi)
6967384eb72SHarald Freudenberger 			return -ENOMEM;
6977384eb72SHarald Freudenberger 		rc = ep11_query_info(card, AUTOSEL_DOM,
6987384eb72SHarald Freudenberger 				     0x01 /* module info query */,
6997384eb72SHarald Freudenberger 				     sizeof(*pmqi), (u8 *)pmqi);
7007384eb72SHarald Freudenberger 		if (rc) {
7017384eb72SHarald Freudenberger 			if (rc == -ENODEV)
7027384eb72SHarald Freudenberger 				card_cache_scrub(card);
7037384eb72SHarald Freudenberger 			goto out;
7047384eb72SHarald Freudenberger 		}
7057384eb72SHarald Freudenberger 		memset(info, 0, sizeof(*info));
7067384eb72SHarald Freudenberger 		info->API_ord_nr = pmqi->API_ord_nr;
7077384eb72SHarald Freudenberger 		info->FW_version =
7087384eb72SHarald Freudenberger 			(pmqi->FW_major_vers << 8) + pmqi->FW_minor_vers;
7097384eb72SHarald Freudenberger 		memcpy(info->serial, pmqi->serial, sizeof(info->serial));
7107384eb72SHarald Freudenberger 		info->op_mode = pmqi->op_mode;
7117384eb72SHarald Freudenberger 		card_cache_update(card, info);
7127384eb72SHarald Freudenberger 	}
7137384eb72SHarald Freudenberger 
7147384eb72SHarald Freudenberger out:
7157384eb72SHarald Freudenberger 	kfree(pmqi);
7167384eb72SHarald Freudenberger 	return rc;
7177384eb72SHarald Freudenberger }
7187384eb72SHarald Freudenberger EXPORT_SYMBOL(ep11_get_card_info);
7197384eb72SHarald Freudenberger 
7207384eb72SHarald Freudenberger /*
7217384eb72SHarald Freudenberger  * Provide information about a domain within an EP11 card.
7227384eb72SHarald Freudenberger  */
ep11_get_domain_info(u16 card,u16 domain,struct ep11_domain_info * info)7237384eb72SHarald Freudenberger int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info)
7247384eb72SHarald Freudenberger {
7257384eb72SHarald Freudenberger 	int rc;
7267384eb72SHarald Freudenberger 	struct ep11_domain_query_info {
7277384eb72SHarald Freudenberger 		u32 dom_index;
7287384eb72SHarald Freudenberger 		u8  cur_WK_VP[32];
7297384eb72SHarald Freudenberger 		u8  new_WK_VP[32];
7307384eb72SHarald Freudenberger 		u32 dom_flags;
7317384eb72SHarald Freudenberger 		u64 op_mode;
7327384eb72SHarald Freudenberger 	} __packed * p_dom_info;
7337384eb72SHarald Freudenberger 
7347384eb72SHarald Freudenberger 	p_dom_info = kmalloc(sizeof(*p_dom_info), GFP_KERNEL);
7357384eb72SHarald Freudenberger 	if (!p_dom_info)
7367384eb72SHarald Freudenberger 		return -ENOMEM;
7377384eb72SHarald Freudenberger 
7387384eb72SHarald Freudenberger 	rc = ep11_query_info(card, domain, 0x03 /* domain info query */,
7397384eb72SHarald Freudenberger 			     sizeof(*p_dom_info), (u8 *)p_dom_info);
7407384eb72SHarald Freudenberger 	if (rc)
7417384eb72SHarald Freudenberger 		goto out;
7427384eb72SHarald Freudenberger 
7437384eb72SHarald Freudenberger 	memset(info, 0, sizeof(*info));
7447384eb72SHarald Freudenberger 	info->cur_wk_state = '0';
7457384eb72SHarald Freudenberger 	info->new_wk_state = '0';
7467384eb72SHarald Freudenberger 	if (p_dom_info->dom_flags & 0x10 /* left imprint mode */) {
7477384eb72SHarald Freudenberger 		if (p_dom_info->dom_flags & 0x02 /* cur wk valid */) {
7487384eb72SHarald Freudenberger 			info->cur_wk_state = '1';
7497384eb72SHarald Freudenberger 			memcpy(info->cur_wkvp, p_dom_info->cur_WK_VP, 32);
7507384eb72SHarald Freudenberger 		}
7512004b57cSHarald Freudenberger 		if (p_dom_info->dom_flags & 0x04 || /* new wk present */
7522004b57cSHarald Freudenberger 		    p_dom_info->dom_flags & 0x08 /* new wk committed */) {
7537384eb72SHarald Freudenberger 			info->new_wk_state =
7547384eb72SHarald Freudenberger 				p_dom_info->dom_flags & 0x08 ? '2' : '1';
7557384eb72SHarald Freudenberger 			memcpy(info->new_wkvp, p_dom_info->new_WK_VP, 32);
7567384eb72SHarald Freudenberger 		}
7577384eb72SHarald Freudenberger 	}
7587384eb72SHarald Freudenberger 	info->op_mode = p_dom_info->op_mode;
7597384eb72SHarald Freudenberger 
7607384eb72SHarald Freudenberger out:
7617384eb72SHarald Freudenberger 	kfree(p_dom_info);
7627384eb72SHarald Freudenberger 	return rc;
7637384eb72SHarald Freudenberger }
7647384eb72SHarald Freudenberger EXPORT_SYMBOL(ep11_get_domain_info);
7657384eb72SHarald Freudenberger 
76655d0a513SHarald Freudenberger /*
76755d0a513SHarald Freudenberger  * Default EP11 AES key generate attributes, used when no keygenflags given:
76855d0a513SHarald Freudenberger  * XCP_BLOB_ENCRYPT | XCP_BLOB_DECRYPT | XCP_BLOB_PROTKEY_EXTRACTABLE
76955d0a513SHarald Freudenberger  */
77055d0a513SHarald Freudenberger #define KEY_ATTR_DEFAULTS 0x00200c00
77155d0a513SHarald Freudenberger 
_ep11_genaeskey(u16 card,u16 domain,u32 keybitsize,u32 keygenflags,u8 * keybuf,size_t * keybufsize)772fb249ce7SHolger Dengler static int _ep11_genaeskey(u16 card, u16 domain,
773fb249ce7SHolger Dengler 			   u32 keybitsize, u32 keygenflags,
77455d0a513SHarald Freudenberger 			   u8 *keybuf, size_t *keybufsize)
77555d0a513SHarald Freudenberger {
77655d0a513SHarald Freudenberger 	struct keygen_req_pl {
77755d0a513SHarald Freudenberger 		struct pl_head head;
77855d0a513SHarald Freudenberger 		u8  var_tag;
77955d0a513SHarald Freudenberger 		u8  var_len;
78055d0a513SHarald Freudenberger 		u32 var;
78155d0a513SHarald Freudenberger 		u8  keybytes_tag;
78255d0a513SHarald Freudenberger 		u8  keybytes_len;
78355d0a513SHarald Freudenberger 		u32 keybytes;
78455d0a513SHarald Freudenberger 		u8  mech_tag;
78555d0a513SHarald Freudenberger 		u8  mech_len;
78655d0a513SHarald Freudenberger 		u32 mech;
78755d0a513SHarald Freudenberger 		u8  attr_tag;
78855d0a513SHarald Freudenberger 		u8  attr_len;
78955d0a513SHarald Freudenberger 		u32 attr_header;
79055d0a513SHarald Freudenberger 		u32 attr_bool_mask;
79155d0a513SHarald Freudenberger 		u32 attr_bool_bits;
79255d0a513SHarald Freudenberger 		u32 attr_val_len_type;
79355d0a513SHarald Freudenberger 		u32 attr_val_len_value;
794*386cb81eSHolger Dengler 		/* followed by empty pin tag or empty pinblob tag */
79555d0a513SHarald Freudenberger 	} __packed * req_pl;
79655d0a513SHarald Freudenberger 	struct keygen_rep_pl {
79755d0a513SHarald Freudenberger 		struct pl_head head;
79855d0a513SHarald Freudenberger 		u8  rc_tag;
79955d0a513SHarald Freudenberger 		u8  rc_len;
80055d0a513SHarald Freudenberger 		u32 rc;
80155d0a513SHarald Freudenberger 		u8  data_tag;
80255d0a513SHarald Freudenberger 		u8  data_lenfmt;
80355d0a513SHarald Freudenberger 		u16 data_len;
80455d0a513SHarald Freudenberger 		u8  data[512];
80555d0a513SHarald Freudenberger 	} __packed * rep_pl;
80655d0a513SHarald Freudenberger 	struct ep11_cprb *req = NULL, *rep = NULL;
807*386cb81eSHolger Dengler 	size_t req_pl_size, pinblob_size = 0;
80855d0a513SHarald Freudenberger 	struct ep11_target_dev target;
80955d0a513SHarald Freudenberger 	struct ep11_urb *urb = NULL;
81055d0a513SHarald Freudenberger 	int api, rc = -ENOMEM;
811*386cb81eSHolger Dengler 	u8 *p;
81255d0a513SHarald Freudenberger 
81355d0a513SHarald Freudenberger 	switch (keybitsize) {
81455d0a513SHarald Freudenberger 	case 128:
81555d0a513SHarald Freudenberger 	case 192:
81655d0a513SHarald Freudenberger 	case 256:
81755d0a513SHarald Freudenberger 		break;
81855d0a513SHarald Freudenberger 	default:
81955d0a513SHarald Freudenberger 		DEBUG_ERR(
82055d0a513SHarald Freudenberger 			"%s unknown/unsupported keybitsize %d\n",
82155d0a513SHarald Freudenberger 			__func__, keybitsize);
82255d0a513SHarald Freudenberger 		rc = -EINVAL;
82355d0a513SHarald Freudenberger 		goto out;
82455d0a513SHarald Freudenberger 	}
82555d0a513SHarald Freudenberger 
82655d0a513SHarald Freudenberger 	/* request cprb and payload */
827*386cb81eSHolger Dengler 	api = (!keygenflags || keygenflags & 0x00200000) ?
828*386cb81eSHolger Dengler 		EP11_API_V4 : EP11_API_V1;
829*386cb81eSHolger Dengler 	if (ap_is_se_guest()) {
830*386cb81eSHolger Dengler 		/*
831*386cb81eSHolger Dengler 		 * genkey within SE environment requires API ordinal 6
832*386cb81eSHolger Dengler 		 * with empty pinblob
833*386cb81eSHolger Dengler 		 */
834*386cb81eSHolger Dengler 		api = EP11_API_V6;
835*386cb81eSHolger Dengler 		pinblob_size = EP11_PINBLOB_V1_BYTES;
836*386cb81eSHolger Dengler 	}
837*386cb81eSHolger Dengler 	req_pl_size = sizeof(struct keygen_req_pl) + ASN1TAGLEN(pinblob_size);
838*386cb81eSHolger Dengler 	req = alloc_cprb(req_pl_size);
83955d0a513SHarald Freudenberger 	if (!req)
84055d0a513SHarald Freudenberger 		goto out;
84155d0a513SHarald Freudenberger 	req_pl = (struct keygen_req_pl *)(((u8 *)req) + sizeof(*req));
842*386cb81eSHolger Dengler 	prep_head(&req_pl->head, req_pl_size, api, 21); /* GenerateKey */
84355d0a513SHarald Freudenberger 	req_pl->var_tag = 0x04;
84455d0a513SHarald Freudenberger 	req_pl->var_len = sizeof(u32);
84555d0a513SHarald Freudenberger 	req_pl->keybytes_tag = 0x04;
84655d0a513SHarald Freudenberger 	req_pl->keybytes_len = sizeof(u32);
84755d0a513SHarald Freudenberger 	req_pl->keybytes = keybitsize / 8;
84855d0a513SHarald Freudenberger 	req_pl->mech_tag = 0x04;
84955d0a513SHarald Freudenberger 	req_pl->mech_len = sizeof(u32);
85055d0a513SHarald Freudenberger 	req_pl->mech = 0x00001080; /* CKM_AES_KEY_GEN */
85155d0a513SHarald Freudenberger 	req_pl->attr_tag = 0x04;
85255d0a513SHarald Freudenberger 	req_pl->attr_len = 5 * sizeof(u32);
85355d0a513SHarald Freudenberger 	req_pl->attr_header = 0x10010000;
85455d0a513SHarald Freudenberger 	req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
85555d0a513SHarald Freudenberger 	req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
85655d0a513SHarald Freudenberger 	req_pl->attr_val_len_type = 0x00000161; /* CKA_VALUE_LEN */
85755d0a513SHarald Freudenberger 	req_pl->attr_val_len_value = keybitsize / 8;
858*386cb81eSHolger Dengler 	p = ((u8 *)req_pl) + sizeof(*req_pl);
859*386cb81eSHolger Dengler 	/* pin tag */
860*386cb81eSHolger Dengler 	*p++ = 0x04;
861*386cb81eSHolger Dengler 	*p++ = pinblob_size;
86255d0a513SHarald Freudenberger 
86355d0a513SHarald Freudenberger 	/* reply cprb and payload */
86455d0a513SHarald Freudenberger 	rep = alloc_cprb(sizeof(struct keygen_rep_pl));
86555d0a513SHarald Freudenberger 	if (!rep)
86655d0a513SHarald Freudenberger 		goto out;
86755d0a513SHarald Freudenberger 	rep_pl = (struct keygen_rep_pl *)(((u8 *)rep) + sizeof(*rep));
86855d0a513SHarald Freudenberger 
86955d0a513SHarald Freudenberger 	/* urb and target */
8702004b57cSHarald Freudenberger 	urb = kmalloc(sizeof(*urb), GFP_KERNEL);
87155d0a513SHarald Freudenberger 	if (!urb)
87255d0a513SHarald Freudenberger 		goto out;
87355d0a513SHarald Freudenberger 	target.ap_id = card;
87455d0a513SHarald Freudenberger 	target.dom_id = domain;
87555d0a513SHarald Freudenberger 	prep_urb(urb, &target, 1,
876*386cb81eSHolger Dengler 		 req, sizeof(*req) + req_pl_size,
87755d0a513SHarald Freudenberger 		 rep, sizeof(*rep) + sizeof(*rep_pl));
87855d0a513SHarald Freudenberger 
87952f72febSHarald Freudenberger 	rc = zcrypt_send_ep11_cprb(urb);
88055d0a513SHarald Freudenberger 	if (rc) {
88155d0a513SHarald Freudenberger 		DEBUG_ERR(
88255d0a513SHarald Freudenberger 			"%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
88355d0a513SHarald Freudenberger 			__func__, (int)card, (int)domain, rc);
88455d0a513SHarald Freudenberger 		goto out;
88555d0a513SHarald Freudenberger 	}
88655d0a513SHarald Freudenberger 
88755d0a513SHarald Freudenberger 	rc = check_reply_pl((u8 *)rep_pl, __func__);
88855d0a513SHarald Freudenberger 	if (rc)
88955d0a513SHarald Freudenberger 		goto out;
89055d0a513SHarald Freudenberger 	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
89155d0a513SHarald Freudenberger 		DEBUG_ERR("%s unknown reply data format\n", __func__);
89255d0a513SHarald Freudenberger 		rc = -EIO;
89355d0a513SHarald Freudenberger 		goto out;
89455d0a513SHarald Freudenberger 	}
89555d0a513SHarald Freudenberger 	if (rep_pl->data_len > *keybufsize) {
89655d0a513SHarald Freudenberger 		DEBUG_ERR("%s mismatch reply data len / key buffer len\n",
89755d0a513SHarald Freudenberger 			  __func__);
89855d0a513SHarald Freudenberger 		rc = -ENOSPC;
89955d0a513SHarald Freudenberger 		goto out;
90055d0a513SHarald Freudenberger 	}
90155d0a513SHarald Freudenberger 
902fb249ce7SHolger Dengler 	/* copy key blob */
90355d0a513SHarald Freudenberger 	memcpy(keybuf, rep_pl->data, rep_pl->data_len);
90455d0a513SHarald Freudenberger 	*keybufsize = rep_pl->data_len;
90555d0a513SHarald Freudenberger 
90655d0a513SHarald Freudenberger out:
90755d0a513SHarald Freudenberger 	kfree(req);
90855d0a513SHarald Freudenberger 	kfree(rep);
90955d0a513SHarald Freudenberger 	kfree(urb);
91055d0a513SHarald Freudenberger 	return rc;
91155d0a513SHarald Freudenberger }
912fb249ce7SHolger Dengler 
ep11_genaeskey(u16 card,u16 domain,u32 keybitsize,u32 keygenflags,u8 * keybuf,size_t * keybufsize,u32 keybufver)913fb249ce7SHolger Dengler int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
914fb249ce7SHolger Dengler 		   u8 *keybuf, size_t *keybufsize, u32 keybufver)
915fb249ce7SHolger Dengler {
916fb249ce7SHolger Dengler 	struct ep11kblob_header *hdr;
917fb249ce7SHolger Dengler 	size_t hdr_size, pl_size;
918fb249ce7SHolger Dengler 	u8 *pl;
919fb249ce7SHolger Dengler 	int rc;
920fb249ce7SHolger Dengler 
921fb249ce7SHolger Dengler 	switch (keybufver) {
922fb249ce7SHolger Dengler 	case TOKVER_EP11_AES:
923fb249ce7SHolger Dengler 	case TOKVER_EP11_AES_WITH_HEADER:
924fb249ce7SHolger Dengler 		break;
925fb249ce7SHolger Dengler 	default:
926fb249ce7SHolger Dengler 		return -EINVAL;
927fb249ce7SHolger Dengler 	}
928fb249ce7SHolger Dengler 
929fb249ce7SHolger Dengler 	rc = ep11_kb_split(keybuf, *keybufsize, keybufver,
930fb249ce7SHolger Dengler 			   &hdr, &hdr_size, &pl, &pl_size);
931fb249ce7SHolger Dengler 	if (rc)
932fb249ce7SHolger Dengler 		return rc;
933fb249ce7SHolger Dengler 
934fb249ce7SHolger Dengler 	rc = _ep11_genaeskey(card, domain, keybitsize, keygenflags,
935fb249ce7SHolger Dengler 			     pl, &pl_size);
936fb249ce7SHolger Dengler 	if (rc)
937fb249ce7SHolger Dengler 		return rc;
938fb249ce7SHolger Dengler 
939fb249ce7SHolger Dengler 	*keybufsize = hdr_size + pl_size;
940fb249ce7SHolger Dengler 
941fb249ce7SHolger Dengler 	/* update header information */
942fb249ce7SHolger Dengler 	hdr->type = TOKTYPE_NON_CCA;
943fb249ce7SHolger Dengler 	hdr->len = *keybufsize;
944fb249ce7SHolger Dengler 	hdr->version = keybufver;
945fb249ce7SHolger Dengler 	hdr->bitlen = keybitsize;
946fb249ce7SHolger Dengler 
947fb249ce7SHolger Dengler 	return 0;
948fb249ce7SHolger Dengler }
94955d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_genaeskey);
95055d0a513SHarald Freudenberger 
ep11_cryptsingle(u16 card,u16 domain,u16 mode,u32 mech,const u8 * iv,const u8 * key,size_t keysize,const u8 * inbuf,size_t inbufsize,u8 * outbuf,size_t * outbufsize)95155d0a513SHarald Freudenberger static int ep11_cryptsingle(u16 card, u16 domain,
95255d0a513SHarald Freudenberger 			    u16 mode, u32 mech, const u8 *iv,
95355d0a513SHarald Freudenberger 			    const u8 *key, size_t keysize,
95455d0a513SHarald Freudenberger 			    const u8 *inbuf, size_t inbufsize,
95555d0a513SHarald Freudenberger 			    u8 *outbuf, size_t *outbufsize)
95655d0a513SHarald Freudenberger {
95755d0a513SHarald Freudenberger 	struct crypt_req_pl {
95855d0a513SHarald Freudenberger 		struct pl_head head;
95955d0a513SHarald Freudenberger 		u8  var_tag;
96055d0a513SHarald Freudenberger 		u8  var_len;
96155d0a513SHarald Freudenberger 		u32 var;
96255d0a513SHarald Freudenberger 		u8  mech_tag;
96355d0a513SHarald Freudenberger 		u8  mech_len;
96455d0a513SHarald Freudenberger 		u32 mech;
96555d0a513SHarald Freudenberger 		/*
96655d0a513SHarald Freudenberger 		 * maybe followed by iv data
96755d0a513SHarald Freudenberger 		 * followed by key tag + key blob
96855d0a513SHarald Freudenberger 		 * followed by plaintext tag + plaintext
96955d0a513SHarald Freudenberger 		 */
97055d0a513SHarald Freudenberger 	} __packed * req_pl;
97155d0a513SHarald Freudenberger 	struct crypt_rep_pl {
97255d0a513SHarald Freudenberger 		struct pl_head head;
97355d0a513SHarald Freudenberger 		u8  rc_tag;
97455d0a513SHarald Freudenberger 		u8  rc_len;
97555d0a513SHarald Freudenberger 		u32 rc;
97655d0a513SHarald Freudenberger 		u8  data_tag;
97755d0a513SHarald Freudenberger 		u8  data_lenfmt;
97855d0a513SHarald Freudenberger 		/* data follows */
97955d0a513SHarald Freudenberger 	} __packed * rep_pl;
98055d0a513SHarald Freudenberger 	struct ep11_cprb *req = NULL, *rep = NULL;
98155d0a513SHarald Freudenberger 	struct ep11_target_dev target;
98255d0a513SHarald Freudenberger 	struct ep11_urb *urb = NULL;
98355d0a513SHarald Freudenberger 	size_t req_pl_size, rep_pl_size;
984*386cb81eSHolger Dengler 	int n, api = EP11_API_V1, rc = -ENOMEM;
98555d0a513SHarald Freudenberger 	u8 *p;
98655d0a513SHarald Freudenberger 
98755d0a513SHarald Freudenberger 	/* the simple asn1 coding used has length limits */
98855d0a513SHarald Freudenberger 	if (keysize > 0xFFFF || inbufsize > 0xFFFF)
98955d0a513SHarald Freudenberger 		return -EINVAL;
99055d0a513SHarald Freudenberger 
99155d0a513SHarald Freudenberger 	/* request cprb and payload */
99255d0a513SHarald Freudenberger 	req_pl_size = sizeof(struct crypt_req_pl) + (iv ? 16 : 0)
99355d0a513SHarald Freudenberger 		+ ASN1TAGLEN(keysize) + ASN1TAGLEN(inbufsize);
99455d0a513SHarald Freudenberger 	req = alloc_cprb(req_pl_size);
99555d0a513SHarald Freudenberger 	if (!req)
99655d0a513SHarald Freudenberger 		goto out;
99755d0a513SHarald Freudenberger 	req_pl = (struct crypt_req_pl *)(((u8 *)req) + sizeof(*req));
99855d0a513SHarald Freudenberger 	prep_head(&req_pl->head, req_pl_size, api, (mode ? 20 : 19));
99955d0a513SHarald Freudenberger 	req_pl->var_tag = 0x04;
100055d0a513SHarald Freudenberger 	req_pl->var_len = sizeof(u32);
100155d0a513SHarald Freudenberger 	/* mech is mech + mech params (iv here) */
100255d0a513SHarald Freudenberger 	req_pl->mech_tag = 0x04;
100355d0a513SHarald Freudenberger 	req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0);
100455d0a513SHarald Freudenberger 	req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */
100555d0a513SHarald Freudenberger 	p = ((u8 *)req_pl) + sizeof(*req_pl);
100655d0a513SHarald Freudenberger 	if (iv) {
100755d0a513SHarald Freudenberger 		memcpy(p, iv, 16);
100855d0a513SHarald Freudenberger 		p += 16;
100955d0a513SHarald Freudenberger 	}
101055d0a513SHarald Freudenberger 	/* key and input data */
101155d0a513SHarald Freudenberger 	p += asn1tag_write(p, 0x04, key, keysize);
101255d0a513SHarald Freudenberger 	p += asn1tag_write(p, 0x04, inbuf, inbufsize);
101355d0a513SHarald Freudenberger 
101455d0a513SHarald Freudenberger 	/* reply cprb and payload, assume out data size <= in data size + 32 */
101555d0a513SHarald Freudenberger 	rep_pl_size = sizeof(struct crypt_rep_pl) + ASN1TAGLEN(inbufsize + 32);
101655d0a513SHarald Freudenberger 	rep = alloc_cprb(rep_pl_size);
101755d0a513SHarald Freudenberger 	if (!rep)
101855d0a513SHarald Freudenberger 		goto out;
101955d0a513SHarald Freudenberger 	rep_pl = (struct crypt_rep_pl *)(((u8 *)rep) + sizeof(*rep));
102055d0a513SHarald Freudenberger 
102155d0a513SHarald Freudenberger 	/* urb and target */
10222004b57cSHarald Freudenberger 	urb = kmalloc(sizeof(*urb), GFP_KERNEL);
102355d0a513SHarald Freudenberger 	if (!urb)
102455d0a513SHarald Freudenberger 		goto out;
102555d0a513SHarald Freudenberger 	target.ap_id = card;
102655d0a513SHarald Freudenberger 	target.dom_id = domain;
102755d0a513SHarald Freudenberger 	prep_urb(urb, &target, 1,
102855d0a513SHarald Freudenberger 		 req, sizeof(*req) + req_pl_size,
102955d0a513SHarald Freudenberger 		 rep, sizeof(*rep) + rep_pl_size);
103055d0a513SHarald Freudenberger 
103152f72febSHarald Freudenberger 	rc = zcrypt_send_ep11_cprb(urb);
103255d0a513SHarald Freudenberger 	if (rc) {
103355d0a513SHarald Freudenberger 		DEBUG_ERR(
103455d0a513SHarald Freudenberger 			"%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
103555d0a513SHarald Freudenberger 			__func__, (int)card, (int)domain, rc);
103655d0a513SHarald Freudenberger 		goto out;
103755d0a513SHarald Freudenberger 	}
103855d0a513SHarald Freudenberger 
103955d0a513SHarald Freudenberger 	rc = check_reply_pl((u8 *)rep_pl, __func__);
104055d0a513SHarald Freudenberger 	if (rc)
104155d0a513SHarald Freudenberger 		goto out;
104255d0a513SHarald Freudenberger 	if (rep_pl->data_tag != 0x04) {
104355d0a513SHarald Freudenberger 		DEBUG_ERR("%s unknown reply data format\n", __func__);
104455d0a513SHarald Freudenberger 		rc = -EIO;
104555d0a513SHarald Freudenberger 		goto out;
104655d0a513SHarald Freudenberger 	}
104755d0a513SHarald Freudenberger 	p = ((u8 *)rep_pl) + sizeof(*rep_pl);
10482004b57cSHarald Freudenberger 	if (rep_pl->data_lenfmt <= 127) {
104955d0a513SHarald Freudenberger 		n = rep_pl->data_lenfmt;
10502004b57cSHarald Freudenberger 	} else if (rep_pl->data_lenfmt == 0x81) {
105155d0a513SHarald Freudenberger 		n = *p++;
10522004b57cSHarald Freudenberger 	} else if (rep_pl->data_lenfmt == 0x82) {
105355d0a513SHarald Freudenberger 		n = *((u16 *)p);
105455d0a513SHarald Freudenberger 		p += 2;
105555d0a513SHarald Freudenberger 	} else {
105655d0a513SHarald Freudenberger 		DEBUG_ERR("%s unknown reply data length format 0x%02hhx\n",
105755d0a513SHarald Freudenberger 			  __func__, rep_pl->data_lenfmt);
105855d0a513SHarald Freudenberger 		rc = -EIO;
105955d0a513SHarald Freudenberger 		goto out;
106055d0a513SHarald Freudenberger 	}
106155d0a513SHarald Freudenberger 	if (n > *outbufsize) {
106255d0a513SHarald Freudenberger 		DEBUG_ERR("%s mismatch reply data len %d / output buffer %zu\n",
106355d0a513SHarald Freudenberger 			  __func__, n, *outbufsize);
106455d0a513SHarald Freudenberger 		rc = -ENOSPC;
106555d0a513SHarald Freudenberger 		goto out;
106655d0a513SHarald Freudenberger 	}
106755d0a513SHarald Freudenberger 
106855d0a513SHarald Freudenberger 	memcpy(outbuf, p, n);
106955d0a513SHarald Freudenberger 	*outbufsize = n;
107055d0a513SHarald Freudenberger 
107155d0a513SHarald Freudenberger out:
107255d0a513SHarald Freudenberger 	kfree(req);
107355d0a513SHarald Freudenberger 	kfree(rep);
107455d0a513SHarald Freudenberger 	kfree(urb);
107555d0a513SHarald Freudenberger 	return rc;
107655d0a513SHarald Freudenberger }
107755d0a513SHarald Freudenberger 
_ep11_unwrapkey(u16 card,u16 domain,const u8 * kek,size_t keksize,const u8 * enckey,size_t enckeysize,u32 mech,const u8 * iv,u32 keybitsize,u32 keygenflags,u8 * keybuf,size_t * keybufsize)1078da2863f1SHolger Dengler static int _ep11_unwrapkey(u16 card, u16 domain,
107955d0a513SHarald Freudenberger 			   const u8 *kek, size_t keksize,
108055d0a513SHarald Freudenberger 			   const u8 *enckey, size_t enckeysize,
108155d0a513SHarald Freudenberger 			   u32 mech, const u8 *iv,
108255d0a513SHarald Freudenberger 			   u32 keybitsize, u32 keygenflags,
108355d0a513SHarald Freudenberger 			   u8 *keybuf, size_t *keybufsize)
108455d0a513SHarald Freudenberger {
108555d0a513SHarald Freudenberger 	struct uw_req_pl {
108655d0a513SHarald Freudenberger 		struct pl_head head;
108755d0a513SHarald Freudenberger 		u8  attr_tag;
108855d0a513SHarald Freudenberger 		u8  attr_len;
108955d0a513SHarald Freudenberger 		u32 attr_header;
109055d0a513SHarald Freudenberger 		u32 attr_bool_mask;
109155d0a513SHarald Freudenberger 		u32 attr_bool_bits;
109255d0a513SHarald Freudenberger 		u32 attr_key_type;
109355d0a513SHarald Freudenberger 		u32 attr_key_type_value;
109455d0a513SHarald Freudenberger 		u32 attr_val_len;
109555d0a513SHarald Freudenberger 		u32 attr_val_len_value;
109655d0a513SHarald Freudenberger 		u8  mech_tag;
109755d0a513SHarald Freudenberger 		u8  mech_len;
109855d0a513SHarald Freudenberger 		u32 mech;
109955d0a513SHarald Freudenberger 		/*
110055d0a513SHarald Freudenberger 		 * maybe followed by iv data
110155d0a513SHarald Freudenberger 		 * followed by kek tag + kek blob
110255d0a513SHarald Freudenberger 		 * followed by empty mac tag
1103*386cb81eSHolger Dengler 		 * followed by empty pin tag or empty pinblob tag
110455d0a513SHarald Freudenberger 		 * followed by encryted key tag + bytes
110555d0a513SHarald Freudenberger 		 */
110655d0a513SHarald Freudenberger 	} __packed * req_pl;
110755d0a513SHarald Freudenberger 	struct uw_rep_pl {
110855d0a513SHarald Freudenberger 		struct pl_head head;
110955d0a513SHarald Freudenberger 		u8  rc_tag;
111055d0a513SHarald Freudenberger 		u8  rc_len;
111155d0a513SHarald Freudenberger 		u32 rc;
111255d0a513SHarald Freudenberger 		u8  data_tag;
111355d0a513SHarald Freudenberger 		u8  data_lenfmt;
111455d0a513SHarald Freudenberger 		u16 data_len;
111555d0a513SHarald Freudenberger 		u8  data[512];
111655d0a513SHarald Freudenberger 	} __packed * rep_pl;
111755d0a513SHarald Freudenberger 	struct ep11_cprb *req = NULL, *rep = NULL;
1118*386cb81eSHolger Dengler 	size_t req_pl_size, pinblob_size = 0;
111955d0a513SHarald Freudenberger 	struct ep11_target_dev target;
112055d0a513SHarald Freudenberger 	struct ep11_urb *urb = NULL;
112155d0a513SHarald Freudenberger 	int api, rc = -ENOMEM;
112255d0a513SHarald Freudenberger 	u8 *p;
112355d0a513SHarald Freudenberger 
112455d0a513SHarald Freudenberger 	/* request cprb and payload */
1125*386cb81eSHolger Dengler 	api = (!keygenflags || keygenflags & 0x00200000) ?
1126*386cb81eSHolger Dengler 		EP11_API_V4 : EP11_API_V1;
1127*386cb81eSHolger Dengler 	if (ap_is_se_guest()) {
1128*386cb81eSHolger Dengler 		/*
1129*386cb81eSHolger Dengler 		 * unwrap within SE environment requires API ordinal 6
1130*386cb81eSHolger Dengler 		 * with empty pinblob
1131*386cb81eSHolger Dengler 		 */
1132*386cb81eSHolger Dengler 		api = EP11_API_V6;
1133*386cb81eSHolger Dengler 		pinblob_size = EP11_PINBLOB_V1_BYTES;
1134*386cb81eSHolger Dengler 	}
113555d0a513SHarald Freudenberger 	req_pl_size = sizeof(struct uw_req_pl) + (iv ? 16 : 0)
1136*386cb81eSHolger Dengler 		+ ASN1TAGLEN(keksize) + ASN1TAGLEN(0)
1137*386cb81eSHolger Dengler 		+ ASN1TAGLEN(pinblob_size) + ASN1TAGLEN(enckeysize);
113855d0a513SHarald Freudenberger 	req = alloc_cprb(req_pl_size);
113955d0a513SHarald Freudenberger 	if (!req)
114055d0a513SHarald Freudenberger 		goto out;
114155d0a513SHarald Freudenberger 	req_pl = (struct uw_req_pl *)(((u8 *)req) + sizeof(*req));
114255d0a513SHarald Freudenberger 	prep_head(&req_pl->head, req_pl_size, api, 34); /* UnwrapKey */
114355d0a513SHarald Freudenberger 	req_pl->attr_tag = 0x04;
114455d0a513SHarald Freudenberger 	req_pl->attr_len = 7 * sizeof(u32);
114555d0a513SHarald Freudenberger 	req_pl->attr_header = 0x10020000;
114655d0a513SHarald Freudenberger 	req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
114755d0a513SHarald Freudenberger 	req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
114855d0a513SHarald Freudenberger 	req_pl->attr_key_type = 0x00000100; /* CKA_KEY_TYPE */
114955d0a513SHarald Freudenberger 	req_pl->attr_key_type_value = 0x0000001f; /* CKK_AES */
115055d0a513SHarald Freudenberger 	req_pl->attr_val_len = 0x00000161; /* CKA_VALUE_LEN */
115155d0a513SHarald Freudenberger 	req_pl->attr_val_len_value = keybitsize / 8;
115255d0a513SHarald Freudenberger 	/* mech is mech + mech params (iv here) */
115355d0a513SHarald Freudenberger 	req_pl->mech_tag = 0x04;
115455d0a513SHarald Freudenberger 	req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0);
115555d0a513SHarald Freudenberger 	req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */
115655d0a513SHarald Freudenberger 	p = ((u8 *)req_pl) + sizeof(*req_pl);
115755d0a513SHarald Freudenberger 	if (iv) {
115855d0a513SHarald Freudenberger 		memcpy(p, iv, 16);
115955d0a513SHarald Freudenberger 		p += 16;
116055d0a513SHarald Freudenberger 	}
116155d0a513SHarald Freudenberger 	/* kek */
116255d0a513SHarald Freudenberger 	p += asn1tag_write(p, 0x04, kek, keksize);
116355d0a513SHarald Freudenberger 	/* empty mac key tag */
116455d0a513SHarald Freudenberger 	*p++ = 0x04;
116555d0a513SHarald Freudenberger 	*p++ = 0;
1166*386cb81eSHolger Dengler 	/* pin tag */
116755d0a513SHarald Freudenberger 	*p++ = 0x04;
1168*386cb81eSHolger Dengler 	*p++ = pinblob_size;
1169*386cb81eSHolger Dengler 	p += pinblob_size;
117005ccaca0SGeert Uytterhoeven 	/* encrypted key value tag and bytes */
117155d0a513SHarald Freudenberger 	p += asn1tag_write(p, 0x04, enckey, enckeysize);
117255d0a513SHarald Freudenberger 
117355d0a513SHarald Freudenberger 	/* reply cprb and payload */
117455d0a513SHarald Freudenberger 	rep = alloc_cprb(sizeof(struct uw_rep_pl));
117555d0a513SHarald Freudenberger 	if (!rep)
117655d0a513SHarald Freudenberger 		goto out;
117755d0a513SHarald Freudenberger 	rep_pl = (struct uw_rep_pl *)(((u8 *)rep) + sizeof(*rep));
117855d0a513SHarald Freudenberger 
117955d0a513SHarald Freudenberger 	/* urb and target */
11802004b57cSHarald Freudenberger 	urb = kmalloc(sizeof(*urb), GFP_KERNEL);
118155d0a513SHarald Freudenberger 	if (!urb)
118255d0a513SHarald Freudenberger 		goto out;
118355d0a513SHarald Freudenberger 	target.ap_id = card;
118455d0a513SHarald Freudenberger 	target.dom_id = domain;
118555d0a513SHarald Freudenberger 	prep_urb(urb, &target, 1,
118655d0a513SHarald Freudenberger 		 req, sizeof(*req) + req_pl_size,
118755d0a513SHarald Freudenberger 		 rep, sizeof(*rep) + sizeof(*rep_pl));
118855d0a513SHarald Freudenberger 
118952f72febSHarald Freudenberger 	rc = zcrypt_send_ep11_cprb(urb);
119055d0a513SHarald Freudenberger 	if (rc) {
119155d0a513SHarald Freudenberger 		DEBUG_ERR(
119255d0a513SHarald Freudenberger 			"%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
119355d0a513SHarald Freudenberger 			__func__, (int)card, (int)domain, rc);
119455d0a513SHarald Freudenberger 		goto out;
119555d0a513SHarald Freudenberger 	}
119655d0a513SHarald Freudenberger 
119755d0a513SHarald Freudenberger 	rc = check_reply_pl((u8 *)rep_pl, __func__);
119855d0a513SHarald Freudenberger 	if (rc)
119955d0a513SHarald Freudenberger 		goto out;
120055d0a513SHarald Freudenberger 	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
120155d0a513SHarald Freudenberger 		DEBUG_ERR("%s unknown reply data format\n", __func__);
120255d0a513SHarald Freudenberger 		rc = -EIO;
120355d0a513SHarald Freudenberger 		goto out;
120455d0a513SHarald Freudenberger 	}
120555d0a513SHarald Freudenberger 	if (rep_pl->data_len > *keybufsize) {
120655d0a513SHarald Freudenberger 		DEBUG_ERR("%s mismatch reply data len / key buffer len\n",
120755d0a513SHarald Freudenberger 			  __func__);
120855d0a513SHarald Freudenberger 		rc = -ENOSPC;
120955d0a513SHarald Freudenberger 		goto out;
121055d0a513SHarald Freudenberger 	}
121155d0a513SHarald Freudenberger 
1212da2863f1SHolger Dengler 	/* copy key blob */
121355d0a513SHarald Freudenberger 	memcpy(keybuf, rep_pl->data, rep_pl->data_len);
121455d0a513SHarald Freudenberger 	*keybufsize = rep_pl->data_len;
121555d0a513SHarald Freudenberger 
121655d0a513SHarald Freudenberger out:
121755d0a513SHarald Freudenberger 	kfree(req);
121855d0a513SHarald Freudenberger 	kfree(rep);
121955d0a513SHarald Freudenberger 	kfree(urb);
122055d0a513SHarald Freudenberger 	return rc;
122155d0a513SHarald Freudenberger }
122255d0a513SHarald Freudenberger 
ep11_unwrapkey(u16 card,u16 domain,const u8 * kek,size_t keksize,const u8 * enckey,size_t enckeysize,u32 mech,const u8 * iv,u32 keybitsize,u32 keygenflags,u8 * keybuf,size_t * keybufsize,u8 keybufver)1223da2863f1SHolger Dengler static int ep11_unwrapkey(u16 card, u16 domain,
1224da2863f1SHolger Dengler 			  const u8 *kek, size_t keksize,
1225da2863f1SHolger Dengler 			  const u8 *enckey, size_t enckeysize,
1226da2863f1SHolger Dengler 			  u32 mech, const u8 *iv,
1227da2863f1SHolger Dengler 			  u32 keybitsize, u32 keygenflags,
1228da2863f1SHolger Dengler 			  u8 *keybuf, size_t *keybufsize,
1229da2863f1SHolger Dengler 			  u8 keybufver)
1230da2863f1SHolger Dengler {
1231da2863f1SHolger Dengler 	struct ep11kblob_header *hdr;
1232da2863f1SHolger Dengler 	size_t hdr_size, pl_size;
1233da2863f1SHolger Dengler 	u8 *pl;
1234da2863f1SHolger Dengler 	int rc;
1235da2863f1SHolger Dengler 
1236da2863f1SHolger Dengler 	rc = ep11_kb_split(keybuf, *keybufsize, keybufver,
1237da2863f1SHolger Dengler 			   &hdr, &hdr_size, &pl, &pl_size);
1238da2863f1SHolger Dengler 	if (rc)
1239da2863f1SHolger Dengler 		return rc;
1240da2863f1SHolger Dengler 
1241da2863f1SHolger Dengler 	rc = _ep11_unwrapkey(card, domain, kek, keksize, enckey, enckeysize,
1242da2863f1SHolger Dengler 			     mech, iv, keybitsize, keygenflags,
1243da2863f1SHolger Dengler 			     pl, &pl_size);
1244da2863f1SHolger Dengler 	if (rc)
1245da2863f1SHolger Dengler 		return rc;
1246da2863f1SHolger Dengler 
1247da2863f1SHolger Dengler 	*keybufsize = hdr_size + pl_size;
1248da2863f1SHolger Dengler 
1249da2863f1SHolger Dengler 	/* update header information */
1250da2863f1SHolger Dengler 	hdr = (struct ep11kblob_header *)keybuf;
1251da2863f1SHolger Dengler 	hdr->type = TOKTYPE_NON_CCA;
1252da2863f1SHolger Dengler 	hdr->len = *keybufsize;
1253da2863f1SHolger Dengler 	hdr->version = keybufver;
1254da2863f1SHolger Dengler 	hdr->bitlen = keybitsize;
1255da2863f1SHolger Dengler 
1256da2863f1SHolger Dengler 	return 0;
1257da2863f1SHolger Dengler }
1258da2863f1SHolger Dengler 
_ep11_wrapkey(u16 card,u16 domain,const u8 * key,size_t keysize,u32 mech,const u8 * iv,u8 * databuf,size_t * datasize)1259d1fdfb0bSHolger Dengler static int _ep11_wrapkey(u16 card, u16 domain,
126055d0a513SHarald Freudenberger 			 const u8 *key, size_t keysize,
126155d0a513SHarald Freudenberger 			 u32 mech, const u8 *iv,
126255d0a513SHarald Freudenberger 			 u8 *databuf, size_t *datasize)
126355d0a513SHarald Freudenberger {
126455d0a513SHarald Freudenberger 	struct wk_req_pl {
126555d0a513SHarald Freudenberger 		struct pl_head head;
126655d0a513SHarald Freudenberger 		u8  var_tag;
126755d0a513SHarald Freudenberger 		u8  var_len;
126855d0a513SHarald Freudenberger 		u32 var;
126955d0a513SHarald Freudenberger 		u8  mech_tag;
127055d0a513SHarald Freudenberger 		u8  mech_len;
127155d0a513SHarald Freudenberger 		u32 mech;
127255d0a513SHarald Freudenberger 		/*
127355d0a513SHarald Freudenberger 		 * followed by iv data
127455d0a513SHarald Freudenberger 		 * followed by key tag + key blob
127555d0a513SHarald Freudenberger 		 * followed by dummy kek param
127655d0a513SHarald Freudenberger 		 * followed by dummy mac param
127755d0a513SHarald Freudenberger 		 */
127855d0a513SHarald Freudenberger 	} __packed * req_pl;
127955d0a513SHarald Freudenberger 	struct wk_rep_pl {
128055d0a513SHarald Freudenberger 		struct pl_head head;
128155d0a513SHarald Freudenberger 		u8  rc_tag;
128255d0a513SHarald Freudenberger 		u8  rc_len;
128355d0a513SHarald Freudenberger 		u32 rc;
128455d0a513SHarald Freudenberger 		u8  data_tag;
128555d0a513SHarald Freudenberger 		u8  data_lenfmt;
128655d0a513SHarald Freudenberger 		u16 data_len;
1287fa6999e3SHarald Freudenberger 		u8  data[1024];
128855d0a513SHarald Freudenberger 	} __packed * rep_pl;
128955d0a513SHarald Freudenberger 	struct ep11_cprb *req = NULL, *rep = NULL;
129055d0a513SHarald Freudenberger 	struct ep11_target_dev target;
129155d0a513SHarald Freudenberger 	struct ep11_urb *urb = NULL;
129255d0a513SHarald Freudenberger 	size_t req_pl_size;
129355d0a513SHarald Freudenberger 	int api, rc = -ENOMEM;
129455d0a513SHarald Freudenberger 	u8 *p;
129555d0a513SHarald Freudenberger 
129655d0a513SHarald Freudenberger 	/* request cprb and payload */
129755d0a513SHarald Freudenberger 	req_pl_size = sizeof(struct wk_req_pl) + (iv ? 16 : 0)
129855d0a513SHarald Freudenberger 		+ ASN1TAGLEN(keysize) + 4;
129955d0a513SHarald Freudenberger 	req = alloc_cprb(req_pl_size);
130055d0a513SHarald Freudenberger 	if (!req)
130155d0a513SHarald Freudenberger 		goto out;
130255d0a513SHarald Freudenberger 	if (!mech || mech == 0x80060001)
130355d0a513SHarald Freudenberger 		req->flags |= 0x20; /* CPACF_WRAP needs special bit */
130455d0a513SHarald Freudenberger 	req_pl = (struct wk_req_pl *)(((u8 *)req) + sizeof(*req));
1305*386cb81eSHolger Dengler 	api = (!mech || mech == 0x80060001) ? /* CKM_IBM_CPACF_WRAP */
1306*386cb81eSHolger Dengler 		EP11_API_V4 : EP11_API_V1;
130755d0a513SHarald Freudenberger 	prep_head(&req_pl->head, req_pl_size, api, 33); /* WrapKey */
130855d0a513SHarald Freudenberger 	req_pl->var_tag = 0x04;
130955d0a513SHarald Freudenberger 	req_pl->var_len = sizeof(u32);
131055d0a513SHarald Freudenberger 	/* mech is mech + mech params (iv here) */
131155d0a513SHarald Freudenberger 	req_pl->mech_tag = 0x04;
131255d0a513SHarald Freudenberger 	req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0);
131355d0a513SHarald Freudenberger 	req_pl->mech = (mech ? mech : 0x80060001); /* CKM_IBM_CPACF_WRAP */
131455d0a513SHarald Freudenberger 	p = ((u8 *)req_pl) + sizeof(*req_pl);
131555d0a513SHarald Freudenberger 	if (iv) {
131655d0a513SHarald Freudenberger 		memcpy(p, iv, 16);
131755d0a513SHarald Freudenberger 		p += 16;
131855d0a513SHarald Freudenberger 	}
131955d0a513SHarald Freudenberger 	/* key blob */
132055d0a513SHarald Freudenberger 	p += asn1tag_write(p, 0x04, key, keysize);
132155d0a513SHarald Freudenberger 	/* empty kek tag */
132255d0a513SHarald Freudenberger 	*p++ = 0x04;
132355d0a513SHarald Freudenberger 	*p++ = 0;
132455d0a513SHarald Freudenberger 	/* empty mac tag */
132555d0a513SHarald Freudenberger 	*p++ = 0x04;
132655d0a513SHarald Freudenberger 	*p++ = 0;
132755d0a513SHarald Freudenberger 
132855d0a513SHarald Freudenberger 	/* reply cprb and payload */
132955d0a513SHarald Freudenberger 	rep = alloc_cprb(sizeof(struct wk_rep_pl));
133055d0a513SHarald Freudenberger 	if (!rep)
133155d0a513SHarald Freudenberger 		goto out;
133255d0a513SHarald Freudenberger 	rep_pl = (struct wk_rep_pl *)(((u8 *)rep) + sizeof(*rep));
133355d0a513SHarald Freudenberger 
133455d0a513SHarald Freudenberger 	/* urb and target */
13352004b57cSHarald Freudenberger 	urb = kmalloc(sizeof(*urb), GFP_KERNEL);
133655d0a513SHarald Freudenberger 	if (!urb)
133755d0a513SHarald Freudenberger 		goto out;
133855d0a513SHarald Freudenberger 	target.ap_id = card;
133955d0a513SHarald Freudenberger 	target.dom_id = domain;
134055d0a513SHarald Freudenberger 	prep_urb(urb, &target, 1,
134155d0a513SHarald Freudenberger 		 req, sizeof(*req) + req_pl_size,
134255d0a513SHarald Freudenberger 		 rep, sizeof(*rep) + sizeof(*rep_pl));
134355d0a513SHarald Freudenberger 
134452f72febSHarald Freudenberger 	rc = zcrypt_send_ep11_cprb(urb);
134555d0a513SHarald Freudenberger 	if (rc) {
134655d0a513SHarald Freudenberger 		DEBUG_ERR(
134755d0a513SHarald Freudenberger 			"%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
134855d0a513SHarald Freudenberger 			__func__, (int)card, (int)domain, rc);
134955d0a513SHarald Freudenberger 		goto out;
135055d0a513SHarald Freudenberger 	}
135155d0a513SHarald Freudenberger 
135255d0a513SHarald Freudenberger 	rc = check_reply_pl((u8 *)rep_pl, __func__);
135355d0a513SHarald Freudenberger 	if (rc)
135455d0a513SHarald Freudenberger 		goto out;
135555d0a513SHarald Freudenberger 	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
135655d0a513SHarald Freudenberger 		DEBUG_ERR("%s unknown reply data format\n", __func__);
135755d0a513SHarald Freudenberger 		rc = -EIO;
135855d0a513SHarald Freudenberger 		goto out;
135955d0a513SHarald Freudenberger 	}
136055d0a513SHarald Freudenberger 	if (rep_pl->data_len > *datasize) {
136155d0a513SHarald Freudenberger 		DEBUG_ERR("%s mismatch reply data len / data buffer len\n",
136255d0a513SHarald Freudenberger 			  __func__);
136355d0a513SHarald Freudenberger 		rc = -ENOSPC;
136455d0a513SHarald Freudenberger 		goto out;
136555d0a513SHarald Freudenberger 	}
136655d0a513SHarald Freudenberger 
136755d0a513SHarald Freudenberger 	/* copy the data from the cprb to the data buffer */
136855d0a513SHarald Freudenberger 	memcpy(databuf, rep_pl->data, rep_pl->data_len);
136955d0a513SHarald Freudenberger 	*datasize = rep_pl->data_len;
137055d0a513SHarald Freudenberger 
137155d0a513SHarald Freudenberger out:
137255d0a513SHarald Freudenberger 	kfree(req);
137355d0a513SHarald Freudenberger 	kfree(rep);
137455d0a513SHarald Freudenberger 	kfree(urb);
137555d0a513SHarald Freudenberger 	return rc;
137655d0a513SHarald Freudenberger }
137755d0a513SHarald Freudenberger 
ep11_clr2keyblob(u16 card,u16 domain,u32 keybitsize,u32 keygenflags,const u8 * clrkey,u8 * keybuf,size_t * keybufsize,u32 keytype)137855d0a513SHarald Freudenberger int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
1379da2863f1SHolger Dengler 		     const u8 *clrkey, u8 *keybuf, size_t *keybufsize,
1380da2863f1SHolger Dengler 		     u32 keytype)
138155d0a513SHarald Freudenberger {
138255d0a513SHarald Freudenberger 	int rc;
138355d0a513SHarald Freudenberger 	u8 encbuf[64], *kek = NULL;
138455d0a513SHarald Freudenberger 	size_t clrkeylen, keklen, encbuflen = sizeof(encbuf);
138555d0a513SHarald Freudenberger 
13862004b57cSHarald Freudenberger 	if (keybitsize == 128 || keybitsize == 192 || keybitsize == 256) {
138755d0a513SHarald Freudenberger 		clrkeylen = keybitsize / 8;
13882004b57cSHarald Freudenberger 	} else {
138955d0a513SHarald Freudenberger 		DEBUG_ERR(
139055d0a513SHarald Freudenberger 			"%s unknown/unsupported keybitsize %d\n",
139155d0a513SHarald Freudenberger 			__func__, keybitsize);
139255d0a513SHarald Freudenberger 		return -EINVAL;
139355d0a513SHarald Freudenberger 	}
139455d0a513SHarald Freudenberger 
139555d0a513SHarald Freudenberger 	/* allocate memory for the temp kek */
139655d0a513SHarald Freudenberger 	keklen = MAXEP11AESKEYBLOBSIZE;
139755d0a513SHarald Freudenberger 	kek = kmalloc(keklen, GFP_ATOMIC);
139855d0a513SHarald Freudenberger 	if (!kek) {
139955d0a513SHarald Freudenberger 		rc = -ENOMEM;
140055d0a513SHarald Freudenberger 		goto out;
140155d0a513SHarald Freudenberger 	}
140255d0a513SHarald Freudenberger 
140355d0a513SHarald Freudenberger 	/* Step 1: generate AES 256 bit random kek key */
1404fb249ce7SHolger Dengler 	rc = _ep11_genaeskey(card, domain, 256,
140505ccaca0SGeert Uytterhoeven 			     0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */
140655d0a513SHarald Freudenberger 			     kek, &keklen);
140755d0a513SHarald Freudenberger 	if (rc) {
140855d0a513SHarald Freudenberger 		DEBUG_ERR(
140955d0a513SHarald Freudenberger 			"%s generate kek key failed, rc=%d\n",
141055d0a513SHarald Freudenberger 			__func__, rc);
141155d0a513SHarald Freudenberger 		goto out;
141255d0a513SHarald Freudenberger 	}
141355d0a513SHarald Freudenberger 
141455d0a513SHarald Freudenberger 	/* Step 2: encrypt clear key value with the kek key */
141555d0a513SHarald Freudenberger 	rc = ep11_cryptsingle(card, domain, 0, 0, def_iv, kek, keklen,
141655d0a513SHarald Freudenberger 			      clrkey, clrkeylen, encbuf, &encbuflen);
141755d0a513SHarald Freudenberger 	if (rc) {
141855d0a513SHarald Freudenberger 		DEBUG_ERR(
141955d0a513SHarald Freudenberger 			"%s encrypting key value with kek key failed, rc=%d\n",
142055d0a513SHarald Freudenberger 			__func__, rc);
142155d0a513SHarald Freudenberger 		goto out;
142255d0a513SHarald Freudenberger 	}
142355d0a513SHarald Freudenberger 
142455d0a513SHarald Freudenberger 	/* Step 3: import the encrypted key value as a new key */
142555d0a513SHarald Freudenberger 	rc = ep11_unwrapkey(card, domain, kek, keklen,
142655d0a513SHarald Freudenberger 			    encbuf, encbuflen, 0, def_iv,
1427da2863f1SHolger Dengler 			    keybitsize, 0, keybuf, keybufsize, keytype);
142855d0a513SHarald Freudenberger 	if (rc) {
142955d0a513SHarald Freudenberger 		DEBUG_ERR(
143055d0a513SHarald Freudenberger 			"%s importing key value as new key failed,, rc=%d\n",
143155d0a513SHarald Freudenberger 			__func__, rc);
143255d0a513SHarald Freudenberger 		goto out;
143355d0a513SHarald Freudenberger 	}
143455d0a513SHarald Freudenberger 
143555d0a513SHarald Freudenberger out:
143655d0a513SHarald Freudenberger 	kfree(kek);
143755d0a513SHarald Freudenberger 	return rc;
143855d0a513SHarald Freudenberger }
143955d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_clr2keyblob);
144055d0a513SHarald Freudenberger 
ep11_kblob2protkey(u16 card,u16 dom,const u8 * keyblob,size_t keybloblen,u8 * protkey,u32 * protkeylen,u32 * protkeytype)1441d1fdfb0bSHolger Dengler int ep11_kblob2protkey(u16 card, u16 dom,
1442d1fdfb0bSHolger Dengler 		       const u8 *keyblob, size_t keybloblen,
144355d0a513SHarald Freudenberger 		       u8 *protkey, u32 *protkeylen, u32 *protkeytype)
144455d0a513SHarald Freudenberger {
1445d1fdfb0bSHolger Dengler 	struct ep11kblob_header *hdr;
1446d1fdfb0bSHolger Dengler 	struct ep11keyblob *key;
1447fa6999e3SHarald Freudenberger 	size_t wkbuflen, keylen;
144855d0a513SHarald Freudenberger 	struct wk_info {
144955d0a513SHarald Freudenberger 		u16 version;
145055d0a513SHarald Freudenberger 		u8  res1[16];
145155d0a513SHarald Freudenberger 		u32 pkeytype;
145255d0a513SHarald Freudenberger 		u32 pkeybitsize;
145355d0a513SHarald Freudenberger 		u64 pkeysize;
145455d0a513SHarald Freudenberger 		u8  res2[8];
14553b42877cSHarald Freudenberger 		u8  pkey[];
145655d0a513SHarald Freudenberger 	} __packed * wki;
1457d1fdfb0bSHolger Dengler 	u8 *wkbuf = NULL;
1458d1fdfb0bSHolger Dengler 	int rc = -EIO;
1459fa6999e3SHarald Freudenberger 
1460d1fdfb0bSHolger Dengler 	if (ep11_kb_decode((u8 *)keyblob, keybloblen, &hdr, NULL, &key, &keylen))
1461fa6999e3SHarald Freudenberger 		return -EINVAL;
1462d1fdfb0bSHolger Dengler 
1463d1fdfb0bSHolger Dengler 	if (hdr->version == TOKVER_EP11_AES) {
1464d1fdfb0bSHolger Dengler 		/* wipe overlayed header */
1465d1fdfb0bSHolger Dengler 		memset(hdr, 0, sizeof(*hdr));
14662004b57cSHarald Freudenberger 	}
1467d1fdfb0bSHolger Dengler 	/* !!! hdr is no longer a valid header !!! */
146855d0a513SHarald Freudenberger 
146955d0a513SHarald Freudenberger 	/* alloc temp working buffer */
1470fa6999e3SHarald Freudenberger 	wkbuflen = (keylen + AES_BLOCK_SIZE) & (~(AES_BLOCK_SIZE - 1));
147155d0a513SHarald Freudenberger 	wkbuf = kmalloc(wkbuflen, GFP_ATOMIC);
147255d0a513SHarald Freudenberger 	if (!wkbuf)
147355d0a513SHarald Freudenberger 		return -ENOMEM;
147455d0a513SHarald Freudenberger 
147555d0a513SHarald Freudenberger 	/* ep11 secure key -> protected key + info */
1476d1fdfb0bSHolger Dengler 	rc = _ep11_wrapkey(card, dom, (u8 *)key, keylen,
147755d0a513SHarald Freudenberger 			   0, def_iv, wkbuf, &wkbuflen);
147855d0a513SHarald Freudenberger 	if (rc) {
147955d0a513SHarald Freudenberger 		DEBUG_ERR(
148055d0a513SHarald Freudenberger 			"%s rewrapping ep11 key to pkey failed, rc=%d\n",
148155d0a513SHarald Freudenberger 			__func__, rc);
148255d0a513SHarald Freudenberger 		goto out;
148355d0a513SHarald Freudenberger 	}
148455d0a513SHarald Freudenberger 	wki = (struct wk_info *)wkbuf;
148555d0a513SHarald Freudenberger 
148655d0a513SHarald Freudenberger 	/* check struct version and pkey type */
1487fa6999e3SHarald Freudenberger 	if (wki->version != 1 || wki->pkeytype < 1 || wki->pkeytype > 5) {
148855d0a513SHarald Freudenberger 		DEBUG_ERR("%s wk info version %d or pkeytype %d mismatch.\n",
148955d0a513SHarald Freudenberger 			  __func__, (int)wki->version, (int)wki->pkeytype);
149055d0a513SHarald Freudenberger 		rc = -EIO;
149155d0a513SHarald Freudenberger 		goto out;
149255d0a513SHarald Freudenberger 	}
149355d0a513SHarald Freudenberger 
1494fa6999e3SHarald Freudenberger 	/* check protected key type field */
1495fa6999e3SHarald Freudenberger 	switch (wki->pkeytype) {
1496fa6999e3SHarald Freudenberger 	case 1: /* AES */
149755d0a513SHarald Freudenberger 		switch (wki->pkeysize) {
149855d0a513SHarald Freudenberger 		case 16 + 32:
149955d0a513SHarald Freudenberger 			/* AES 128 protected key */
150055d0a513SHarald Freudenberger 			if (protkeytype)
150155d0a513SHarald Freudenberger 				*protkeytype = PKEY_KEYTYPE_AES_128;
150255d0a513SHarald Freudenberger 			break;
150355d0a513SHarald Freudenberger 		case 24 + 32:
150455d0a513SHarald Freudenberger 			/* AES 192 protected key */
150555d0a513SHarald Freudenberger 			if (protkeytype)
150655d0a513SHarald Freudenberger 				*protkeytype = PKEY_KEYTYPE_AES_192;
150755d0a513SHarald Freudenberger 			break;
150855d0a513SHarald Freudenberger 		case 32 + 32:
150955d0a513SHarald Freudenberger 			/* AES 256 protected key */
151055d0a513SHarald Freudenberger 			if (protkeytype)
151155d0a513SHarald Freudenberger 				*protkeytype = PKEY_KEYTYPE_AES_256;
151255d0a513SHarald Freudenberger 			break;
151355d0a513SHarald Freudenberger 		default:
1514fa6999e3SHarald Freudenberger 			DEBUG_ERR("%s unknown/unsupported AES pkeysize %d\n",
151555d0a513SHarald Freudenberger 				  __func__, (int)wki->pkeysize);
151655d0a513SHarald Freudenberger 			rc = -EIO;
151755d0a513SHarald Freudenberger 			goto out;
151855d0a513SHarald Freudenberger 		}
1519fa6999e3SHarald Freudenberger 		break;
1520fa6999e3SHarald Freudenberger 	case 3: /* EC-P */
1521fa6999e3SHarald Freudenberger 	case 4: /* EC-ED */
1522fa6999e3SHarald Freudenberger 	case 5: /* EC-BP */
1523fa6999e3SHarald Freudenberger 		if (protkeytype)
1524fa6999e3SHarald Freudenberger 			*protkeytype = PKEY_KEYTYPE_ECC;
1525fa6999e3SHarald Freudenberger 		break;
1526fa6999e3SHarald Freudenberger 	case 2: /* TDES */
1527fa6999e3SHarald Freudenberger 	default:
1528fa6999e3SHarald Freudenberger 		DEBUG_ERR("%s unknown/unsupported key type %d\n",
1529fa6999e3SHarald Freudenberger 			  __func__, (int)wki->pkeytype);
1530fa6999e3SHarald Freudenberger 		rc = -EIO;
1531fa6999e3SHarald Freudenberger 		goto out;
1532fa6999e3SHarald Freudenberger 	}
1533fa6999e3SHarald Freudenberger 
1534cada938aSHeiko Carstens 	/* copy the translated protected key */
1535fa6999e3SHarald Freudenberger 	if (wki->pkeysize > *protkeylen) {
1536fa6999e3SHarald Freudenberger 		DEBUG_ERR("%s wk info pkeysize %llu > protkeysize %u\n",
1537fa6999e3SHarald Freudenberger 			  __func__, wki->pkeysize, *protkeylen);
1538fa6999e3SHarald Freudenberger 		rc = -EINVAL;
1539fa6999e3SHarald Freudenberger 		goto out;
1540fa6999e3SHarald Freudenberger 	}
154155d0a513SHarald Freudenberger 	memcpy(protkey, wki->pkey, wki->pkeysize);
1542fa6999e3SHarald Freudenberger 	*protkeylen = wki->pkeysize;
154355d0a513SHarald Freudenberger 
154455d0a513SHarald Freudenberger out:
154555d0a513SHarald Freudenberger 	kfree(wkbuf);
154655d0a513SHarald Freudenberger 	return rc;
154755d0a513SHarald Freudenberger }
1548fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_kblob2protkey);
154955d0a513SHarald Freudenberger 
ep11_findcard2(u32 ** apqns,u32 * nr_apqns,u16 cardnr,u16 domain,int minhwtype,int minapi,const u8 * wkvp)155055d0a513SHarald Freudenberger int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
155155d0a513SHarald Freudenberger 		   int minhwtype, int minapi, const u8 *wkvp)
155255d0a513SHarald Freudenberger {
155355d0a513SHarald Freudenberger 	struct zcrypt_device_status_ext *device_status;
155455d0a513SHarald Freudenberger 	u32 *_apqns = NULL, _nr_apqns = 0;
155555d0a513SHarald Freudenberger 	int i, card, dom, rc = -ENOMEM;
155655d0a513SHarald Freudenberger 	struct ep11_domain_info edi;
155755d0a513SHarald Freudenberger 	struct ep11_card_info eci;
155855d0a513SHarald Freudenberger 
155955d0a513SHarald Freudenberger 	/* fetch status of all crypto cards */
156034515df2SHarald Freudenberger 	device_status = kvmalloc_array(MAX_ZDEV_ENTRIES_EXT,
156155d0a513SHarald Freudenberger 				       sizeof(struct zcrypt_device_status_ext),
156255d0a513SHarald Freudenberger 				       GFP_KERNEL);
156355d0a513SHarald Freudenberger 	if (!device_status)
156455d0a513SHarald Freudenberger 		return -ENOMEM;
156555d0a513SHarald Freudenberger 	zcrypt_device_status_mask_ext(device_status);
156655d0a513SHarald Freudenberger 
156755d0a513SHarald Freudenberger 	/* allocate 1k space for up to 256 apqns */
156855d0a513SHarald Freudenberger 	_apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL);
156955d0a513SHarald Freudenberger 	if (!_apqns) {
157034515df2SHarald Freudenberger 		kvfree(device_status);
157155d0a513SHarald Freudenberger 		return -ENOMEM;
157255d0a513SHarald Freudenberger 	}
157355d0a513SHarald Freudenberger 
157455d0a513SHarald Freudenberger 	/* walk through all the crypto apqnss */
157555d0a513SHarald Freudenberger 	for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
157655d0a513SHarald Freudenberger 		card = AP_QID_CARD(device_status[i].qid);
157755d0a513SHarald Freudenberger 		dom = AP_QID_QUEUE(device_status[i].qid);
157855d0a513SHarald Freudenberger 		/* check online state */
157955d0a513SHarald Freudenberger 		if (!device_status[i].online)
158055d0a513SHarald Freudenberger 			continue;
158155d0a513SHarald Freudenberger 		/* check for ep11 functions */
158255d0a513SHarald Freudenberger 		if (!(device_status[i].functions & 0x01))
158355d0a513SHarald Freudenberger 			continue;
158455d0a513SHarald Freudenberger 		/* check cardnr */
158555d0a513SHarald Freudenberger 		if (cardnr != 0xFFFF && card != cardnr)
158655d0a513SHarald Freudenberger 			continue;
158755d0a513SHarald Freudenberger 		/* check domain */
158855d0a513SHarald Freudenberger 		if (domain != 0xFFFF && dom != domain)
158955d0a513SHarald Freudenberger 			continue;
159055d0a513SHarald Freudenberger 		/* check min hardware type */
159155d0a513SHarald Freudenberger 		if (minhwtype && device_status[i].hwtype < minhwtype)
159255d0a513SHarald Freudenberger 			continue;
159355d0a513SHarald Freudenberger 		/* check min api version if given */
159455d0a513SHarald Freudenberger 		if (minapi > 0) {
159555d0a513SHarald Freudenberger 			if (ep11_get_card_info(card, &eci, 0))
159655d0a513SHarald Freudenberger 				continue;
159755d0a513SHarald Freudenberger 			if (minapi > eci.API_ord_nr)
159855d0a513SHarald Freudenberger 				continue;
159955d0a513SHarald Freudenberger 		}
160055d0a513SHarald Freudenberger 		/* check wkvp if given */
160155d0a513SHarald Freudenberger 		if (wkvp) {
160255d0a513SHarald Freudenberger 			if (ep11_get_domain_info(card, dom, &edi))
160355d0a513SHarald Freudenberger 				continue;
160455d0a513SHarald Freudenberger 			if (edi.cur_wk_state != '1')
160555d0a513SHarald Freudenberger 				continue;
160655d0a513SHarald Freudenberger 			if (memcmp(wkvp, edi.cur_wkvp, 16))
160755d0a513SHarald Freudenberger 				continue;
160855d0a513SHarald Freudenberger 		}
160955d0a513SHarald Freudenberger 		/* apqn passed all filtering criterons, add to the array */
161055d0a513SHarald Freudenberger 		if (_nr_apqns < 256)
161155d0a513SHarald Freudenberger 			_apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom);
161255d0a513SHarald Freudenberger 	}
161355d0a513SHarald Freudenberger 
161455d0a513SHarald Freudenberger 	/* nothing found ? */
161555d0a513SHarald Freudenberger 	if (!_nr_apqns) {
161655d0a513SHarald Freudenberger 		kfree(_apqns);
161755d0a513SHarald Freudenberger 		rc = -ENODEV;
161855d0a513SHarald Freudenberger 	} else {
161955d0a513SHarald Freudenberger 		/* no re-allocation, simple return the _apqns array */
162055d0a513SHarald Freudenberger 		*apqns = _apqns;
162155d0a513SHarald Freudenberger 		*nr_apqns = _nr_apqns;
162255d0a513SHarald Freudenberger 		rc = 0;
162355d0a513SHarald Freudenberger 	}
162455d0a513SHarald Freudenberger 
162534515df2SHarald Freudenberger 	kvfree(device_status);
162655d0a513SHarald Freudenberger 	return rc;
162755d0a513SHarald Freudenberger }
162855d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_findcard2);
162955d0a513SHarald Freudenberger 
zcrypt_ep11misc_exit(void)16307384eb72SHarald Freudenberger void __exit zcrypt_ep11misc_exit(void)
16317384eb72SHarald Freudenberger {
16327384eb72SHarald Freudenberger 	card_cache_free();
16337384eb72SHarald Freudenberger }
1634