xref: /linux/drivers/s390/crypto/zcrypt_ep11misc.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
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 
27386cb81eSHolger Dengler #define EP11_PINBLOB_V1_BYTES 56
28386cb81eSHolger Dengler 
2955d0a513SHarald Freudenberger /* default iv used here */
3055d0a513SHarald Freudenberger static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
3155d0a513SHarald Freudenberger 			       0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
3255d0a513SHarald Freudenberger 
337384eb72SHarald Freudenberger /* ep11 card info cache */
347384eb72SHarald Freudenberger struct card_list_entry {
357384eb72SHarald Freudenberger 	struct list_head list;
367384eb72SHarald Freudenberger 	u16 cardnr;
377384eb72SHarald Freudenberger 	struct ep11_card_info info;
387384eb72SHarald Freudenberger };
397384eb72SHarald Freudenberger static LIST_HEAD(card_list);
407384eb72SHarald Freudenberger static DEFINE_SPINLOCK(card_list_lock);
417384eb72SHarald Freudenberger 
card_cache_fetch(u16 cardnr,struct ep11_card_info * ci)427384eb72SHarald Freudenberger static int card_cache_fetch(u16 cardnr, struct ep11_card_info *ci)
437384eb72SHarald Freudenberger {
447384eb72SHarald Freudenberger 	int rc = -ENOENT;
457384eb72SHarald Freudenberger 	struct card_list_entry *ptr;
467384eb72SHarald Freudenberger 
477384eb72SHarald Freudenberger 	spin_lock_bh(&card_list_lock);
487384eb72SHarald Freudenberger 	list_for_each_entry(ptr, &card_list, list) {
497384eb72SHarald Freudenberger 		if (ptr->cardnr == cardnr) {
507384eb72SHarald Freudenberger 			memcpy(ci, &ptr->info, sizeof(*ci));
517384eb72SHarald Freudenberger 			rc = 0;
527384eb72SHarald Freudenberger 			break;
537384eb72SHarald Freudenberger 		}
547384eb72SHarald Freudenberger 	}
557384eb72SHarald Freudenberger 	spin_unlock_bh(&card_list_lock);
567384eb72SHarald Freudenberger 
577384eb72SHarald Freudenberger 	return rc;
587384eb72SHarald Freudenberger }
597384eb72SHarald Freudenberger 
card_cache_update(u16 cardnr,const struct ep11_card_info * ci)607384eb72SHarald Freudenberger static void card_cache_update(u16 cardnr, const struct ep11_card_info *ci)
617384eb72SHarald Freudenberger {
627384eb72SHarald Freudenberger 	int found = 0;
637384eb72SHarald Freudenberger 	struct card_list_entry *ptr;
647384eb72SHarald Freudenberger 
657384eb72SHarald Freudenberger 	spin_lock_bh(&card_list_lock);
667384eb72SHarald Freudenberger 	list_for_each_entry(ptr, &card_list, list) {
677384eb72SHarald Freudenberger 		if (ptr->cardnr == cardnr) {
687384eb72SHarald Freudenberger 			memcpy(&ptr->info, ci, sizeof(*ci));
697384eb72SHarald Freudenberger 			found = 1;
707384eb72SHarald Freudenberger 			break;
717384eb72SHarald Freudenberger 		}
727384eb72SHarald Freudenberger 	}
737384eb72SHarald Freudenberger 	if (!found) {
747384eb72SHarald Freudenberger 		ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC);
757384eb72SHarald Freudenberger 		if (!ptr) {
767384eb72SHarald Freudenberger 			spin_unlock_bh(&card_list_lock);
777384eb72SHarald Freudenberger 			return;
787384eb72SHarald Freudenberger 		}
797384eb72SHarald Freudenberger 		ptr->cardnr = cardnr;
807384eb72SHarald Freudenberger 		memcpy(&ptr->info, ci, sizeof(*ci));
817384eb72SHarald Freudenberger 		list_add(&ptr->list, &card_list);
827384eb72SHarald Freudenberger 	}
837384eb72SHarald Freudenberger 	spin_unlock_bh(&card_list_lock);
847384eb72SHarald Freudenberger }
857384eb72SHarald Freudenberger 
card_cache_scrub(u16 cardnr)867384eb72SHarald Freudenberger static void card_cache_scrub(u16 cardnr)
877384eb72SHarald Freudenberger {
887384eb72SHarald Freudenberger 	struct card_list_entry *ptr;
897384eb72SHarald Freudenberger 
907384eb72SHarald Freudenberger 	spin_lock_bh(&card_list_lock);
917384eb72SHarald Freudenberger 	list_for_each_entry(ptr, &card_list, list) {
927384eb72SHarald Freudenberger 		if (ptr->cardnr == cardnr) {
937384eb72SHarald Freudenberger 			list_del(&ptr->list);
947384eb72SHarald Freudenberger 			kfree(ptr);
957384eb72SHarald Freudenberger 			break;
967384eb72SHarald Freudenberger 		}
977384eb72SHarald Freudenberger 	}
987384eb72SHarald Freudenberger 	spin_unlock_bh(&card_list_lock);
997384eb72SHarald Freudenberger }
1007384eb72SHarald Freudenberger 
card_cache_free(void)1017384eb72SHarald Freudenberger static void __exit card_cache_free(void)
1027384eb72SHarald Freudenberger {
1037384eb72SHarald Freudenberger 	struct card_list_entry *ptr, *pnext;
1047384eb72SHarald Freudenberger 
1057384eb72SHarald Freudenberger 	spin_lock_bh(&card_list_lock);
1067384eb72SHarald Freudenberger 	list_for_each_entry_safe(ptr, pnext, &card_list, list) {
1077384eb72SHarald Freudenberger 		list_del(&ptr->list);
1087384eb72SHarald Freudenberger 		kfree(ptr);
1097384eb72SHarald Freudenberger 	}
1107384eb72SHarald Freudenberger 	spin_unlock_bh(&card_list_lock);
1117384eb72SHarald Freudenberger }
1127384eb72SHarald Freudenberger 
ep11_kb_split(const u8 * kb,size_t kblen,u32 kbver,struct ep11kblob_header ** kbhdr,size_t * kbhdrsize,u8 ** kbpl,size_t * kbplsize)113fb249ce7SHolger Dengler static int ep11_kb_split(const u8 *kb, size_t kblen, u32 kbver,
114fb249ce7SHolger Dengler 			 struct ep11kblob_header **kbhdr, size_t *kbhdrsize,
115fb249ce7SHolger Dengler 			 u8 **kbpl, size_t *kbplsize)
116fb249ce7SHolger Dengler {
117fb249ce7SHolger Dengler 	struct ep11kblob_header *hdr = NULL;
118fb249ce7SHolger Dengler 	size_t hdrsize, plsize = 0;
119fb249ce7SHolger Dengler 	int rc = -EINVAL;
120fb249ce7SHolger Dengler 	u8 *pl = NULL;
121fb249ce7SHolger Dengler 
122fb249ce7SHolger Dengler 	if (kblen < sizeof(struct ep11kblob_header))
123fb249ce7SHolger Dengler 		goto out;
124fb249ce7SHolger Dengler 	hdr = (struct ep11kblob_header *)kb;
125fb249ce7SHolger Dengler 
126fb249ce7SHolger Dengler 	switch (kbver) {
127fb249ce7SHolger Dengler 	case TOKVER_EP11_AES:
128fb249ce7SHolger Dengler 		/* header overlays the payload */
129fb249ce7SHolger Dengler 		hdrsize = 0;
130fb249ce7SHolger Dengler 		break;
131fb249ce7SHolger Dengler 	case TOKVER_EP11_ECC_WITH_HEADER:
132fb249ce7SHolger Dengler 	case TOKVER_EP11_AES_WITH_HEADER:
133fb249ce7SHolger Dengler 		/* payload starts after the header */
134fb249ce7SHolger Dengler 		hdrsize = sizeof(struct ep11kblob_header);
135fb249ce7SHolger Dengler 		break;
136fb249ce7SHolger Dengler 	default:
137fb249ce7SHolger Dengler 		goto out;
138fb249ce7SHolger Dengler 	}
139fb249ce7SHolger Dengler 
140fb249ce7SHolger Dengler 	plsize = kblen - hdrsize;
141fb249ce7SHolger Dengler 	pl = (u8 *)kb + hdrsize;
142fb249ce7SHolger Dengler 
143fb249ce7SHolger Dengler 	if (kbhdr)
144fb249ce7SHolger Dengler 		*kbhdr = hdr;
145fb249ce7SHolger Dengler 	if (kbhdrsize)
146fb249ce7SHolger Dengler 		*kbhdrsize = hdrsize;
147fb249ce7SHolger Dengler 	if (kbpl)
148fb249ce7SHolger Dengler 		*kbpl = pl;
149fb249ce7SHolger Dengler 	if (kbplsize)
150fb249ce7SHolger Dengler 		*kbplsize = plsize;
151fb249ce7SHolger Dengler 
152fb249ce7SHolger Dengler 	rc = 0;
153fb249ce7SHolger Dengler out:
154fb249ce7SHolger Dengler 	return rc;
155fb249ce7SHolger Dengler }
156fb249ce7SHolger Dengler 
ep11_kb_decode(const u8 * kb,size_t kblen,struct ep11kblob_header ** kbhdr,size_t * kbhdrsize,struct ep11keyblob ** kbpl,size_t * kbplsize)157d1fdfb0bSHolger Dengler static int ep11_kb_decode(const u8 *kb, size_t kblen,
158d1fdfb0bSHolger Dengler 			  struct ep11kblob_header **kbhdr, size_t *kbhdrsize,
159d1fdfb0bSHolger Dengler 			  struct ep11keyblob **kbpl, size_t *kbplsize)
160d1fdfb0bSHolger Dengler {
161d1fdfb0bSHolger Dengler 	struct ep11kblob_header *tmph, *hdr = NULL;
162d1fdfb0bSHolger Dengler 	size_t hdrsize = 0, plsize = 0;
163d1fdfb0bSHolger Dengler 	struct ep11keyblob *pl = NULL;
164d1fdfb0bSHolger Dengler 	int rc = -EINVAL;
165d1fdfb0bSHolger Dengler 	u8 *tmpp;
166d1fdfb0bSHolger Dengler 
167d1fdfb0bSHolger Dengler 	if (kblen < sizeof(struct ep11kblob_header))
168d1fdfb0bSHolger Dengler 		goto out;
169d1fdfb0bSHolger Dengler 	tmph = (struct ep11kblob_header *)kb;
170d1fdfb0bSHolger Dengler 
171d1fdfb0bSHolger Dengler 	if (tmph->type != TOKTYPE_NON_CCA &&
172d1fdfb0bSHolger Dengler 	    tmph->len > kblen)
173d1fdfb0bSHolger Dengler 		goto out;
174d1fdfb0bSHolger Dengler 
175d1fdfb0bSHolger Dengler 	if (ep11_kb_split(kb, kblen, tmph->version,
176d1fdfb0bSHolger Dengler 			  &hdr, &hdrsize, &tmpp, &plsize))
177d1fdfb0bSHolger Dengler 		goto out;
178d1fdfb0bSHolger Dengler 
179d1fdfb0bSHolger Dengler 	if (plsize < sizeof(struct ep11keyblob))
180d1fdfb0bSHolger Dengler 		goto out;
181d1fdfb0bSHolger Dengler 
182d1fdfb0bSHolger Dengler 	if (!is_ep11_keyblob(tmpp))
183d1fdfb0bSHolger Dengler 		goto out;
184d1fdfb0bSHolger Dengler 
185d1fdfb0bSHolger Dengler 	pl = (struct ep11keyblob *)tmpp;
186d1fdfb0bSHolger Dengler 	plsize = hdr->len - hdrsize;
187d1fdfb0bSHolger Dengler 
188d1fdfb0bSHolger Dengler 	if (kbhdr)
189d1fdfb0bSHolger Dengler 		*kbhdr = hdr;
190d1fdfb0bSHolger Dengler 	if (kbhdrsize)
191d1fdfb0bSHolger Dengler 		*kbhdrsize = hdrsize;
192d1fdfb0bSHolger Dengler 	if (kbpl)
193d1fdfb0bSHolger Dengler 		*kbpl = pl;
194d1fdfb0bSHolger Dengler 	if (kbplsize)
195d1fdfb0bSHolger Dengler 		*kbplsize = plsize;
196d1fdfb0bSHolger Dengler 
197d1fdfb0bSHolger Dengler 	rc = 0;
198d1fdfb0bSHolger Dengler out:
199d1fdfb0bSHolger Dengler 	return rc;
200d1fdfb0bSHolger Dengler }
201d1fdfb0bSHolger Dengler 
202d1fdfb0bSHolger Dengler /*
203d1fdfb0bSHolger Dengler  * For valid ep11 keyblobs, returns a reference to the wrappingkey verification
204d1fdfb0bSHolger Dengler  * pattern. Otherwise NULL.
205d1fdfb0bSHolger Dengler  */
ep11_kb_wkvp(const u8 * keyblob,u32 keybloblen)206*86fbf5e2SHarald Freudenberger const u8 *ep11_kb_wkvp(const u8 *keyblob, u32 keybloblen)
207d1fdfb0bSHolger Dengler {
208d1fdfb0bSHolger Dengler 	struct ep11keyblob *kb;
209d1fdfb0bSHolger Dengler 
210d1fdfb0bSHolger Dengler 	if (ep11_kb_decode(keyblob, keybloblen, NULL, NULL, &kb, NULL))
211d1fdfb0bSHolger Dengler 		return NULL;
212d1fdfb0bSHolger Dengler 	return kb->wkvp;
213d1fdfb0bSHolger Dengler }
214d1fdfb0bSHolger Dengler EXPORT_SYMBOL(ep11_kb_wkvp);
215d1fdfb0bSHolger Dengler 
2167384eb72SHarald Freudenberger /*
217fa6999e3SHarald Freudenberger  * Simple check if the key blob is a valid EP11 AES key blob with header.
21855d0a513SHarald Freudenberger  */
ep11_check_aes_key_with_hdr(debug_info_t * dbg,int dbflvl,const u8 * key,u32 keylen,int checkcpacfexp)219fa6999e3SHarald Freudenberger int ep11_check_aes_key_with_hdr(debug_info_t *dbg, int dbflvl,
220*86fbf5e2SHarald Freudenberger 				const u8 *key, u32 keylen, int checkcpacfexp)
221fa6999e3SHarald Freudenberger {
222fa6999e3SHarald Freudenberger 	struct ep11kblob_header *hdr = (struct ep11kblob_header *)key;
223fa6999e3SHarald Freudenberger 	struct ep11keyblob *kb = (struct ep11keyblob *)(key + sizeof(*hdr));
224fa6999e3SHarald Freudenberger 
225fa6999e3SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__)
226fa6999e3SHarald Freudenberger 
227fa6999e3SHarald Freudenberger 	if (keylen < sizeof(*hdr) + sizeof(*kb)) {
228*86fbf5e2SHarald Freudenberger 		DBF("%s key check failed, keylen %u < %zu\n",
229fa6999e3SHarald Freudenberger 		    __func__, keylen, sizeof(*hdr) + sizeof(*kb));
230fa6999e3SHarald Freudenberger 		return -EINVAL;
231fa6999e3SHarald Freudenberger 	}
232fa6999e3SHarald Freudenberger 
233fa6999e3SHarald Freudenberger 	if (hdr->type != TOKTYPE_NON_CCA) {
234fa6999e3SHarald Freudenberger 		if (dbg)
235fa6999e3SHarald Freudenberger 			DBF("%s key check failed, type 0x%02x != 0x%02x\n",
236fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->type, TOKTYPE_NON_CCA);
237fa6999e3SHarald Freudenberger 		return -EINVAL;
238fa6999e3SHarald Freudenberger 	}
239fa6999e3SHarald Freudenberger 	if (hdr->hver != 0x00) {
240fa6999e3SHarald Freudenberger 		if (dbg)
241fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header version 0x%02x != 0x00\n",
242fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->hver);
243fa6999e3SHarald Freudenberger 		return -EINVAL;
244fa6999e3SHarald Freudenberger 	}
245fa6999e3SHarald Freudenberger 	if (hdr->version != TOKVER_EP11_AES_WITH_HEADER) {
246fa6999e3SHarald Freudenberger 		if (dbg)
247fa6999e3SHarald Freudenberger 			DBF("%s key check failed, version 0x%02x != 0x%02x\n",
248fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->version, TOKVER_EP11_AES_WITH_HEADER);
249fa6999e3SHarald Freudenberger 		return -EINVAL;
250fa6999e3SHarald Freudenberger 	}
251fa6999e3SHarald Freudenberger 	if (hdr->len > keylen) {
252fa6999e3SHarald Freudenberger 		if (dbg)
253*86fbf5e2SHarald Freudenberger 			DBF("%s key check failed, header len %d keylen %u mismatch\n",
254fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->len, keylen);
255fa6999e3SHarald Freudenberger 		return -EINVAL;
256fa6999e3SHarald Freudenberger 	}
257fa6999e3SHarald Freudenberger 	if (hdr->len < sizeof(*hdr) + sizeof(*kb)) {
258fa6999e3SHarald Freudenberger 		if (dbg)
259fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header len %d < %zu\n",
260fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->len, sizeof(*hdr) + sizeof(*kb));
261fa6999e3SHarald Freudenberger 		return -EINVAL;
262fa6999e3SHarald Freudenberger 	}
263fa6999e3SHarald Freudenberger 
264fa6999e3SHarald Freudenberger 	if (kb->version != EP11_STRUCT_MAGIC) {
265fa6999e3SHarald Freudenberger 		if (dbg)
266fa6999e3SHarald Freudenberger 			DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n",
267fa6999e3SHarald Freudenberger 			    __func__, (int)kb->version, EP11_STRUCT_MAGIC);
268fa6999e3SHarald Freudenberger 		return -EINVAL;
269fa6999e3SHarald Freudenberger 	}
270fa6999e3SHarald Freudenberger 	if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) {
271fa6999e3SHarald Freudenberger 		if (dbg)
272fa6999e3SHarald Freudenberger 			DBF("%s key check failed, PKEY_EXTRACTABLE is off\n",
273fa6999e3SHarald Freudenberger 			    __func__);
274fa6999e3SHarald Freudenberger 		return -EINVAL;
275fa6999e3SHarald Freudenberger 	}
276fa6999e3SHarald Freudenberger 
277fa6999e3SHarald Freudenberger #undef DBF
278fa6999e3SHarald Freudenberger 
279fa6999e3SHarald Freudenberger 	return 0;
280fa6999e3SHarald Freudenberger }
281fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_aes_key_with_hdr);
282fa6999e3SHarald Freudenberger 
283fa6999e3SHarald Freudenberger /*
284fa6999e3SHarald Freudenberger  * Simple check if the key blob is a valid EP11 ECC key blob with header.
285fa6999e3SHarald Freudenberger  */
ep11_check_ecc_key_with_hdr(debug_info_t * dbg,int dbflvl,const u8 * key,u32 keylen,int checkcpacfexp)286fa6999e3SHarald Freudenberger int ep11_check_ecc_key_with_hdr(debug_info_t *dbg, int dbflvl,
287*86fbf5e2SHarald Freudenberger 				const u8 *key, u32 keylen, int checkcpacfexp)
288fa6999e3SHarald Freudenberger {
289fa6999e3SHarald Freudenberger 	struct ep11kblob_header *hdr = (struct ep11kblob_header *)key;
290fa6999e3SHarald Freudenberger 	struct ep11keyblob *kb = (struct ep11keyblob *)(key + sizeof(*hdr));
291fa6999e3SHarald Freudenberger 
292fa6999e3SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__)
293fa6999e3SHarald Freudenberger 
294fa6999e3SHarald Freudenberger 	if (keylen < sizeof(*hdr) + sizeof(*kb)) {
295*86fbf5e2SHarald Freudenberger 		DBF("%s key check failed, keylen %u < %zu\n",
296fa6999e3SHarald Freudenberger 		    __func__, keylen, sizeof(*hdr) + sizeof(*kb));
297fa6999e3SHarald Freudenberger 		return -EINVAL;
298fa6999e3SHarald Freudenberger 	}
299fa6999e3SHarald Freudenberger 
300fa6999e3SHarald Freudenberger 	if (hdr->type != TOKTYPE_NON_CCA) {
301fa6999e3SHarald Freudenberger 		if (dbg)
302fa6999e3SHarald Freudenberger 			DBF("%s key check failed, type 0x%02x != 0x%02x\n",
303fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->type, TOKTYPE_NON_CCA);
304fa6999e3SHarald Freudenberger 		return -EINVAL;
305fa6999e3SHarald Freudenberger 	}
306fa6999e3SHarald Freudenberger 	if (hdr->hver != 0x00) {
307fa6999e3SHarald Freudenberger 		if (dbg)
308fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header version 0x%02x != 0x00\n",
309fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->hver);
310fa6999e3SHarald Freudenberger 		return -EINVAL;
311fa6999e3SHarald Freudenberger 	}
312fa6999e3SHarald Freudenberger 	if (hdr->version != TOKVER_EP11_ECC_WITH_HEADER) {
313fa6999e3SHarald Freudenberger 		if (dbg)
314fa6999e3SHarald Freudenberger 			DBF("%s key check failed, version 0x%02x != 0x%02x\n",
315fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->version, TOKVER_EP11_ECC_WITH_HEADER);
316fa6999e3SHarald Freudenberger 		return -EINVAL;
317fa6999e3SHarald Freudenberger 	}
318fa6999e3SHarald Freudenberger 	if (hdr->len > keylen) {
319fa6999e3SHarald Freudenberger 		if (dbg)
320*86fbf5e2SHarald Freudenberger 			DBF("%s key check failed, header len %d keylen %u mismatch\n",
321fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->len, keylen);
322fa6999e3SHarald Freudenberger 		return -EINVAL;
323fa6999e3SHarald Freudenberger 	}
324fa6999e3SHarald Freudenberger 	if (hdr->len < sizeof(*hdr) + sizeof(*kb)) {
325fa6999e3SHarald Freudenberger 		if (dbg)
326fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header len %d < %zu\n",
327fa6999e3SHarald Freudenberger 			    __func__, (int)hdr->len, sizeof(*hdr) + sizeof(*kb));
328fa6999e3SHarald Freudenberger 		return -EINVAL;
329fa6999e3SHarald Freudenberger 	}
330fa6999e3SHarald Freudenberger 
331fa6999e3SHarald Freudenberger 	if (kb->version != EP11_STRUCT_MAGIC) {
332fa6999e3SHarald Freudenberger 		if (dbg)
333fa6999e3SHarald Freudenberger 			DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n",
334fa6999e3SHarald Freudenberger 			    __func__, (int)kb->version, EP11_STRUCT_MAGIC);
335fa6999e3SHarald Freudenberger 		return -EINVAL;
336fa6999e3SHarald Freudenberger 	}
337fa6999e3SHarald Freudenberger 	if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) {
338fa6999e3SHarald Freudenberger 		if (dbg)
339fa6999e3SHarald Freudenberger 			DBF("%s key check failed, PKEY_EXTRACTABLE is off\n",
340fa6999e3SHarald Freudenberger 			    __func__);
341fa6999e3SHarald Freudenberger 		return -EINVAL;
342fa6999e3SHarald Freudenberger 	}
343fa6999e3SHarald Freudenberger 
344fa6999e3SHarald Freudenberger #undef DBF
345fa6999e3SHarald Freudenberger 
346fa6999e3SHarald Freudenberger 	return 0;
347fa6999e3SHarald Freudenberger }
348fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_ecc_key_with_hdr);
349fa6999e3SHarald Freudenberger 
350fa6999e3SHarald Freudenberger /*
351fa6999e3SHarald Freudenberger  * Simple check if the key blob is a valid EP11 AES key blob with
352fa6999e3SHarald Freudenberger  * the header in the session field (old style EP11 AES key).
353fa6999e3SHarald Freudenberger  */
ep11_check_aes_key(debug_info_t * dbg,int dbflvl,const u8 * key,u32 keylen,int checkcpacfexp)354fa6999e3SHarald Freudenberger int ep11_check_aes_key(debug_info_t *dbg, int dbflvl,
355*86fbf5e2SHarald Freudenberger 		       const u8 *key, u32 keylen, int checkcpacfexp)
35655d0a513SHarald Freudenberger {
35755d0a513SHarald Freudenberger 	struct ep11keyblob *kb = (struct ep11keyblob *)key;
35855d0a513SHarald Freudenberger 
35955d0a513SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__)
36055d0a513SHarald Freudenberger 
361fa6999e3SHarald Freudenberger 	if (keylen < sizeof(*kb)) {
362*86fbf5e2SHarald Freudenberger 		DBF("%s key check failed, keylen %u < %zu\n",
363fa6999e3SHarald Freudenberger 		    __func__, keylen, sizeof(*kb));
364fa6999e3SHarald Freudenberger 		return -EINVAL;
365fa6999e3SHarald Freudenberger 	}
366fa6999e3SHarald Freudenberger 
36755d0a513SHarald Freudenberger 	if (kb->head.type != TOKTYPE_NON_CCA) {
36855d0a513SHarald Freudenberger 		if (dbg)
36955d0a513SHarald Freudenberger 			DBF("%s key check failed, type 0x%02x != 0x%02x\n",
37055d0a513SHarald Freudenberger 			    __func__, (int)kb->head.type, TOKTYPE_NON_CCA);
37155d0a513SHarald Freudenberger 		return -EINVAL;
37255d0a513SHarald Freudenberger 	}
37355d0a513SHarald Freudenberger 	if (kb->head.version != TOKVER_EP11_AES) {
37455d0a513SHarald Freudenberger 		if (dbg)
37555d0a513SHarald Freudenberger 			DBF("%s key check failed, version 0x%02x != 0x%02x\n",
37655d0a513SHarald Freudenberger 			    __func__, (int)kb->head.version, TOKVER_EP11_AES);
37755d0a513SHarald Freudenberger 		return -EINVAL;
37855d0a513SHarald Freudenberger 	}
379fa6999e3SHarald Freudenberger 	if (kb->head.len > keylen) {
380fa6999e3SHarald Freudenberger 		if (dbg)
381*86fbf5e2SHarald Freudenberger 			DBF("%s key check failed, header len %d keylen %u mismatch\n",
382fa6999e3SHarald Freudenberger 			    __func__, (int)kb->head.len, keylen);
383fa6999e3SHarald Freudenberger 		return -EINVAL;
384fa6999e3SHarald Freudenberger 	}
385fa6999e3SHarald Freudenberger 	if (kb->head.len < sizeof(*kb)) {
386fa6999e3SHarald Freudenberger 		if (dbg)
387fa6999e3SHarald Freudenberger 			DBF("%s key check failed, header len %d < %zu\n",
388fa6999e3SHarald Freudenberger 			    __func__, (int)kb->head.len, sizeof(*kb));
389fa6999e3SHarald Freudenberger 		return -EINVAL;
390fa6999e3SHarald Freudenberger 	}
391fa6999e3SHarald Freudenberger 
39255d0a513SHarald Freudenberger 	if (kb->version != EP11_STRUCT_MAGIC) {
39355d0a513SHarald Freudenberger 		if (dbg)
394fa6999e3SHarald Freudenberger 			DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n",
39555d0a513SHarald Freudenberger 			    __func__, (int)kb->version, EP11_STRUCT_MAGIC);
39655d0a513SHarald Freudenberger 		return -EINVAL;
39755d0a513SHarald Freudenberger 	}
398fa6999e3SHarald Freudenberger 	if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) {
39955d0a513SHarald Freudenberger 		if (dbg)
400fa6999e3SHarald Freudenberger 			DBF("%s key check failed, PKEY_EXTRACTABLE is off\n",
40155d0a513SHarald Freudenberger 			    __func__);
40255d0a513SHarald Freudenberger 		return -EINVAL;
40355d0a513SHarald Freudenberger 	}
404fa6999e3SHarald Freudenberger 
40555d0a513SHarald Freudenberger #undef DBF
40655d0a513SHarald Freudenberger 
40755d0a513SHarald Freudenberger 	return 0;
40855d0a513SHarald Freudenberger }
409fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_aes_key);
41055d0a513SHarald Freudenberger 
41155d0a513SHarald Freudenberger /*
4127384eb72SHarald Freudenberger  * Allocate and prepare ep11 cprb plus additional payload.
4137384eb72SHarald Freudenberger  */
alloc_cprb(size_t payload_len)41455d0a513SHarald Freudenberger static inline struct ep11_cprb *alloc_cprb(size_t payload_len)
4157384eb72SHarald Freudenberger {
4167384eb72SHarald Freudenberger 	size_t len = sizeof(struct ep11_cprb) + payload_len;
4177384eb72SHarald Freudenberger 	struct ep11_cprb *cprb;
4187384eb72SHarald Freudenberger 
41979d6c502SZou Wei 	cprb = kzalloc(len, GFP_KERNEL);
4207384eb72SHarald Freudenberger 	if (!cprb)
4217384eb72SHarald Freudenberger 		return NULL;
4227384eb72SHarald Freudenberger 
4237384eb72SHarald Freudenberger 	cprb->cprb_len = sizeof(struct ep11_cprb);
4247384eb72SHarald Freudenberger 	cprb->cprb_ver_id = 0x04;
4257384eb72SHarald Freudenberger 	memcpy(cprb->func_id, "T4", 2);
4267384eb72SHarald Freudenberger 	cprb->ret_code = 0xFFFFFFFF;
4277384eb72SHarald Freudenberger 	cprb->payload_len = payload_len;
4287384eb72SHarald Freudenberger 
4297384eb72SHarald Freudenberger 	return cprb;
4307384eb72SHarald Freudenberger }
4317384eb72SHarald Freudenberger 
4327384eb72SHarald Freudenberger /*
43355d0a513SHarald Freudenberger  * Some helper functions related to ASN1 encoding.
43455d0a513SHarald Freudenberger  * Limited to length info <= 2 byte.
4357384eb72SHarald Freudenberger  */
43655d0a513SHarald Freudenberger 
43755d0a513SHarald Freudenberger #define ASN1TAGLEN(x) (2 + (x) + ((x) > 127 ? 1 : 0) + ((x) > 255 ? 1 : 0))
43855d0a513SHarald Freudenberger 
asn1tag_write(u8 * ptr,u8 tag,const u8 * pvalue,u16 valuelen)43955d0a513SHarald Freudenberger static int asn1tag_write(u8 *ptr, u8 tag, const u8 *pvalue, u16 valuelen)
4407384eb72SHarald Freudenberger {
44155d0a513SHarald Freudenberger 	ptr[0] = tag;
44255d0a513SHarald Freudenberger 	if (valuelen > 255) {
44355d0a513SHarald Freudenberger 		ptr[1] = 0x82;
44455d0a513SHarald Freudenberger 		*((u16 *)(ptr + 2)) = valuelen;
44555d0a513SHarald Freudenberger 		memcpy(ptr + 4, pvalue, valuelen);
44655d0a513SHarald Freudenberger 		return 4 + valuelen;
44755d0a513SHarald Freudenberger 	}
44855d0a513SHarald Freudenberger 	if (valuelen > 127) {
44955d0a513SHarald Freudenberger 		ptr[1] = 0x81;
45055d0a513SHarald Freudenberger 		ptr[2] = (u8)valuelen;
45155d0a513SHarald Freudenberger 		memcpy(ptr + 3, pvalue, valuelen);
45255d0a513SHarald Freudenberger 		return 3 + valuelen;
45355d0a513SHarald Freudenberger 	}
45455d0a513SHarald Freudenberger 	ptr[1] = (u8)valuelen;
45555d0a513SHarald Freudenberger 	memcpy(ptr + 2, pvalue, valuelen);
45655d0a513SHarald Freudenberger 	return 2 + valuelen;
45755d0a513SHarald Freudenberger }
45855d0a513SHarald Freudenberger 
45955d0a513SHarald Freudenberger /* EP11 payload > 127 bytes starts with this struct */
46055d0a513SHarald Freudenberger struct pl_head {
4617384eb72SHarald Freudenberger 	u8  tag;
4627384eb72SHarald Freudenberger 	u8  lenfmt;
4637384eb72SHarald Freudenberger 	u16 len;
4647384eb72SHarald Freudenberger 	u8  func_tag;
4657384eb72SHarald Freudenberger 	u8  func_len;
4667384eb72SHarald Freudenberger 	u32 func;
4677384eb72SHarald Freudenberger 	u8  dom_tag;
4687384eb72SHarald Freudenberger 	u8  dom_len;
4697384eb72SHarald Freudenberger 	u32 dom;
47055d0a513SHarald Freudenberger } __packed;
47155d0a513SHarald Freudenberger 
47255d0a513SHarald Freudenberger /* prep ep11 payload head helper function */
prep_head(struct pl_head * h,size_t pl_size,int api,int func)47355d0a513SHarald Freudenberger static inline void prep_head(struct pl_head *h,
47455d0a513SHarald Freudenberger 			     size_t pl_size, int api, int func)
47555d0a513SHarald Freudenberger {
47655d0a513SHarald Freudenberger 	h->tag = 0x30;
47755d0a513SHarald Freudenberger 	h->lenfmt = 0x82;
47855d0a513SHarald Freudenberger 	h->len = pl_size - 4;
47955d0a513SHarald Freudenberger 	h->func_tag = 0x04;
48055d0a513SHarald Freudenberger 	h->func_len = sizeof(u32);
48155d0a513SHarald Freudenberger 	h->func = (api << 16) + func;
48255d0a513SHarald Freudenberger 	h->dom_tag = 0x04;
48355d0a513SHarald Freudenberger 	h->dom_len = sizeof(u32);
48455d0a513SHarald Freudenberger }
48555d0a513SHarald Freudenberger 
48655d0a513SHarald 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)48755d0a513SHarald Freudenberger static inline void prep_urb(struct ep11_urb *u,
48855d0a513SHarald Freudenberger 			    struct ep11_target_dev *t, int nt,
48955d0a513SHarald Freudenberger 			    struct ep11_cprb *req, size_t req_len,
49055d0a513SHarald Freudenberger 			    struct ep11_cprb *rep, size_t rep_len)
49155d0a513SHarald Freudenberger {
49255d0a513SHarald Freudenberger 	u->targets = (u8 __user *)t;
49355d0a513SHarald Freudenberger 	u->targets_num = nt;
49455d0a513SHarald Freudenberger 	u->req = (u8 __user *)req;
49555d0a513SHarald Freudenberger 	u->req_len = req_len;
49655d0a513SHarald Freudenberger 	u->resp = (u8 __user *)rep;
49755d0a513SHarald Freudenberger 	u->resp_len = rep_len;
49855d0a513SHarald Freudenberger }
49955d0a513SHarald Freudenberger 
50055d0a513SHarald Freudenberger /* Check ep11 reply payload, return 0 or suggested errno value. */
check_reply_pl(const u8 * pl,const char * func)50155d0a513SHarald Freudenberger static int check_reply_pl(const u8 *pl, const char *func)
50255d0a513SHarald Freudenberger {
50355d0a513SHarald Freudenberger 	int len;
50455d0a513SHarald Freudenberger 	u32 ret;
50555d0a513SHarald Freudenberger 
50655d0a513SHarald Freudenberger 	/* start tag */
50755d0a513SHarald Freudenberger 	if (*pl++ != 0x30) {
50888e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s reply start tag mismatch\n", func);
50955d0a513SHarald Freudenberger 		return -EIO;
51055d0a513SHarald Freudenberger 	}
51155d0a513SHarald Freudenberger 
51255d0a513SHarald Freudenberger 	/* payload length format */
51355d0a513SHarald Freudenberger 	if (*pl < 127) {
51455d0a513SHarald Freudenberger 		len = *pl;
51555d0a513SHarald Freudenberger 		pl++;
51655d0a513SHarald Freudenberger 	} else if (*pl == 0x81) {
51755d0a513SHarald Freudenberger 		pl++;
51855d0a513SHarald Freudenberger 		len = *pl;
51955d0a513SHarald Freudenberger 		pl++;
52055d0a513SHarald Freudenberger 	} else if (*pl == 0x82) {
52155d0a513SHarald Freudenberger 		pl++;
52255d0a513SHarald Freudenberger 		len = *((u16 *)pl);
52355d0a513SHarald Freudenberger 		pl += 2;
52455d0a513SHarald Freudenberger 	} else {
52588e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s reply start tag lenfmt mismatch 0x%02hhx\n",
52655d0a513SHarald Freudenberger 			       func, *pl);
52755d0a513SHarald Freudenberger 		return -EIO;
52855d0a513SHarald Freudenberger 	}
52955d0a513SHarald Freudenberger 
53055d0a513SHarald Freudenberger 	/* len should cover at least 3 fields with 32 bit value each */
53155d0a513SHarald Freudenberger 	if (len < 3 * 6) {
53288e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s reply length %d too small\n", func, len);
53355d0a513SHarald Freudenberger 		return -EIO;
53455d0a513SHarald Freudenberger 	}
53555d0a513SHarald Freudenberger 
53655d0a513SHarald Freudenberger 	/* function tag, length and value */
53755d0a513SHarald Freudenberger 	if (pl[0] != 0x04 || pl[1] != 0x04) {
53888e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s function tag or length mismatch\n", func);
53955d0a513SHarald Freudenberger 		return -EIO;
54055d0a513SHarald Freudenberger 	}
54155d0a513SHarald Freudenberger 	pl += 6;
54255d0a513SHarald Freudenberger 
54355d0a513SHarald Freudenberger 	/* dom tag, length and value */
54455d0a513SHarald Freudenberger 	if (pl[0] != 0x04 || pl[1] != 0x04) {
54588e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s dom tag or length mismatch\n", func);
54655d0a513SHarald Freudenberger 		return -EIO;
54755d0a513SHarald Freudenberger 	}
54855d0a513SHarald Freudenberger 	pl += 6;
54955d0a513SHarald Freudenberger 
55055d0a513SHarald Freudenberger 	/* return value tag, length and value */
55155d0a513SHarald Freudenberger 	if (pl[0] != 0x04 || pl[1] != 0x04) {
55288e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s return value tag or length mismatch\n",
55388e4c0daSHarald Freudenberger 			       func);
55455d0a513SHarald Freudenberger 		return -EIO;
55555d0a513SHarald Freudenberger 	}
55655d0a513SHarald Freudenberger 	pl += 2;
55755d0a513SHarald Freudenberger 	ret = *((u32 *)pl);
55855d0a513SHarald Freudenberger 	if (ret != 0) {
559a4499998SHarald Freudenberger 		ZCRYPT_DBF_ERR("%s return value 0x%08x != 0\n", func, ret);
56055d0a513SHarald Freudenberger 		return -EIO;
56155d0a513SHarald Freudenberger 	}
56255d0a513SHarald Freudenberger 
56355d0a513SHarald Freudenberger 	return 0;
56455d0a513SHarald Freudenberger }
56555d0a513SHarald Freudenberger 
566c0e983b6SHarald Freudenberger /* Check ep11 reply cprb, return 0 or suggested errno value. */
check_reply_cprb(const struct ep11_cprb * rep,const char * func)567c0e983b6SHarald Freudenberger static int check_reply_cprb(const struct ep11_cprb *rep, const char *func)
568c0e983b6SHarald Freudenberger {
569c0e983b6SHarald Freudenberger 	/* check ep11 reply return code field */
570c0e983b6SHarald Freudenberger 	if (rep->ret_code) {
571c0e983b6SHarald Freudenberger 		ZCRYPT_DBF_ERR("%s ep11 reply ret_code=0x%08x\n", __func__,
572c0e983b6SHarald Freudenberger 			       rep->ret_code);
573c0e983b6SHarald Freudenberger 		if (rep->ret_code == 0x000c0003)
574c0e983b6SHarald Freudenberger 			return -EBUSY;
575c0e983b6SHarald Freudenberger 		else
576c0e983b6SHarald Freudenberger 			return -EIO;
577c0e983b6SHarald Freudenberger 	}
578c0e983b6SHarald Freudenberger 
579c0e983b6SHarald Freudenberger 	return 0;
580c0e983b6SHarald Freudenberger }
581c0e983b6SHarald Freudenberger 
58255d0a513SHarald Freudenberger /*
58355d0a513SHarald Freudenberger  * Helper function which does an ep11 query with given query type.
58455d0a513SHarald Freudenberger  */
ep11_query_info(u16 cardnr,u16 domain,u32 query_type,size_t buflen,u8 * buf)58555d0a513SHarald Freudenberger static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
58655d0a513SHarald Freudenberger 			   size_t buflen, u8 *buf)
58755d0a513SHarald Freudenberger {
58855d0a513SHarald Freudenberger 	struct ep11_info_req_pl {
58955d0a513SHarald Freudenberger 		struct pl_head head;
59055d0a513SHarald Freudenberger 		u8  query_type_tag;
59155d0a513SHarald Freudenberger 		u8  query_type_len;
59255d0a513SHarald Freudenberger 		u32 query_type;
59355d0a513SHarald Freudenberger 		u8  query_subtype_tag;
59455d0a513SHarald Freudenberger 		u8  query_subtype_len;
59555d0a513SHarald Freudenberger 		u32 query_subtype;
59655d0a513SHarald Freudenberger 	} __packed * req_pl;
59755d0a513SHarald Freudenberger 	struct ep11_info_rep_pl {
59855d0a513SHarald Freudenberger 		struct pl_head head;
5997384eb72SHarald Freudenberger 		u8  rc_tag;
6007384eb72SHarald Freudenberger 		u8  rc_len;
6017384eb72SHarald Freudenberger 		u32 rc;
6027384eb72SHarald Freudenberger 		u8  data_tag;
6037384eb72SHarald Freudenberger 		u8  data_lenfmt;
6047384eb72SHarald Freudenberger 		u16 data_len;
6057384eb72SHarald Freudenberger 	} __packed * rep_pl;
6067384eb72SHarald Freudenberger 	struct ep11_cprb *req = NULL, *rep = NULL;
6077384eb72SHarald Freudenberger 	struct ep11_target_dev target;
6087384eb72SHarald Freudenberger 	struct ep11_urb *urb = NULL;
609386cb81eSHolger Dengler 	int api = EP11_API_V1, rc = -ENOMEM;
6107384eb72SHarald Freudenberger 
6117384eb72SHarald Freudenberger 	/* request cprb and payload */
61255d0a513SHarald Freudenberger 	req = alloc_cprb(sizeof(struct ep11_info_req_pl));
6137384eb72SHarald Freudenberger 	if (!req)
6147384eb72SHarald Freudenberger 		goto out;
6157384eb72SHarald Freudenberger 	req_pl = (struct ep11_info_req_pl *)(((u8 *)req) + sizeof(*req));
61655d0a513SHarald Freudenberger 	prep_head(&req_pl->head, sizeof(*req_pl), api, 38); /* get xcp info */
6177384eb72SHarald Freudenberger 	req_pl->query_type_tag = 0x04;
6187384eb72SHarald Freudenberger 	req_pl->query_type_len = sizeof(u32);
6197384eb72SHarald Freudenberger 	req_pl->query_type = query_type;
6207384eb72SHarald Freudenberger 	req_pl->query_subtype_tag = 0x04;
6217384eb72SHarald Freudenberger 	req_pl->query_subtype_len = sizeof(u32);
6227384eb72SHarald Freudenberger 
6237384eb72SHarald Freudenberger 	/* reply cprb and payload */
62455d0a513SHarald Freudenberger 	rep = alloc_cprb(sizeof(struct ep11_info_rep_pl) + buflen);
6257384eb72SHarald Freudenberger 	if (!rep)
6267384eb72SHarald Freudenberger 		goto out;
6277384eb72SHarald Freudenberger 	rep_pl = (struct ep11_info_rep_pl *)(((u8 *)rep) + sizeof(*rep));
6287384eb72SHarald Freudenberger 
6297384eb72SHarald Freudenberger 	/* urb and target */
6302004b57cSHarald Freudenberger 	urb = kmalloc(sizeof(*urb), GFP_KERNEL);
6317384eb72SHarald Freudenberger 	if (!urb)
6327384eb72SHarald Freudenberger 		goto out;
6337384eb72SHarald Freudenberger 	target.ap_id = cardnr;
6347384eb72SHarald Freudenberger 	target.dom_id = domain;
63555d0a513SHarald Freudenberger 	prep_urb(urb, &target, 1,
63655d0a513SHarald Freudenberger 		 req, sizeof(*req) + sizeof(*req_pl),
63755d0a513SHarald Freudenberger 		 rep, sizeof(*rep) + sizeof(*rep_pl) + buflen);
6387384eb72SHarald Freudenberger 
63952f72febSHarald Freudenberger 	rc = zcrypt_send_ep11_cprb(urb);
6407384eb72SHarald Freudenberger 	if (rc) {
64188e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
6427384eb72SHarald Freudenberger 			       __func__, (int)cardnr, (int)domain, rc);
6437384eb72SHarald Freudenberger 		goto out;
6447384eb72SHarald Freudenberger 	}
6457384eb72SHarald Freudenberger 
646c0e983b6SHarald Freudenberger 	/* check ep11 reply cprb */
647c0e983b6SHarald Freudenberger 	rc = check_reply_cprb(rep, __func__);
648c0e983b6SHarald Freudenberger 	if (rc)
649c0e983b6SHarald Freudenberger 		goto out;
650c0e983b6SHarald Freudenberger 
651c0e983b6SHarald Freudenberger 	/* check payload */
65255d0a513SHarald Freudenberger 	rc = check_reply_pl((u8 *)rep_pl, __func__);
65355d0a513SHarald Freudenberger 	if (rc)
6547384eb72SHarald Freudenberger 		goto out;
65555d0a513SHarald Freudenberger 	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
65688e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s unknown reply data format\n", __func__);
65755d0a513SHarald Freudenberger 		rc = -EIO;
6587384eb72SHarald Freudenberger 		goto out;
6597384eb72SHarald Freudenberger 	}
6607384eb72SHarald Freudenberger 	if (rep_pl->data_len > buflen) {
66188e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s mismatch between reply data len and buffer len\n",
6627384eb72SHarald Freudenberger 			       __func__);
66355d0a513SHarald Freudenberger 		rc = -ENOSPC;
6647384eb72SHarald Freudenberger 		goto out;
6657384eb72SHarald Freudenberger 	}
6667384eb72SHarald Freudenberger 
66755d0a513SHarald Freudenberger 	memcpy(buf, ((u8 *)rep_pl) + sizeof(*rep_pl), rep_pl->data_len);
6687384eb72SHarald Freudenberger 
6697384eb72SHarald Freudenberger out:
6707384eb72SHarald Freudenberger 	kfree(req);
6717384eb72SHarald Freudenberger 	kfree(rep);
6727384eb72SHarald Freudenberger 	kfree(urb);
6737384eb72SHarald Freudenberger 	return rc;
6747384eb72SHarald Freudenberger }
6757384eb72SHarald Freudenberger 
6767384eb72SHarald Freudenberger /*
6777384eb72SHarald Freudenberger  * Provide information about an EP11 card.
6787384eb72SHarald Freudenberger  */
ep11_get_card_info(u16 card,struct ep11_card_info * info,int verify)6797384eb72SHarald Freudenberger int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify)
6807384eb72SHarald Freudenberger {
6817384eb72SHarald Freudenberger 	int rc;
6827384eb72SHarald Freudenberger 	struct ep11_module_query_info {
6837384eb72SHarald Freudenberger 		u32 API_ord_nr;
6847384eb72SHarald Freudenberger 		u32 firmware_id;
6857384eb72SHarald Freudenberger 		u8  FW_major_vers;
6867384eb72SHarald Freudenberger 		u8  FW_minor_vers;
6877384eb72SHarald Freudenberger 		u8  CSP_major_vers;
6887384eb72SHarald Freudenberger 		u8  CSP_minor_vers;
6897384eb72SHarald Freudenberger 		u8  fwid[32];
6907384eb72SHarald Freudenberger 		u8  xcp_config_hash[32];
6917384eb72SHarald Freudenberger 		u8  CSP_config_hash[32];
6927384eb72SHarald Freudenberger 		u8  serial[16];
6937384eb72SHarald Freudenberger 		u8  module_date_time[16];
6947384eb72SHarald Freudenberger 		u64 op_mode;
6957384eb72SHarald Freudenberger 		u32 PKCS11_flags;
6967384eb72SHarald Freudenberger 		u32 ext_flags;
6977384eb72SHarald Freudenberger 		u32 domains;
6987384eb72SHarald Freudenberger 		u32 sym_state_bytes;
6997384eb72SHarald Freudenberger 		u32 digest_state_bytes;
7007384eb72SHarald Freudenberger 		u32 pin_blob_bytes;
7017384eb72SHarald Freudenberger 		u32 SPKI_bytes;
7027384eb72SHarald Freudenberger 		u32 priv_key_blob_bytes;
7037384eb72SHarald Freudenberger 		u32 sym_blob_bytes;
7047384eb72SHarald Freudenberger 		u32 max_payload_bytes;
7057384eb72SHarald Freudenberger 		u32 CP_profile_bytes;
7067384eb72SHarald Freudenberger 		u32 max_CP_index;
7077384eb72SHarald Freudenberger 	} __packed * pmqi = NULL;
7087384eb72SHarald Freudenberger 
7097384eb72SHarald Freudenberger 	rc = card_cache_fetch(card, info);
7107384eb72SHarald Freudenberger 	if (rc || verify) {
7117384eb72SHarald Freudenberger 		pmqi = kmalloc(sizeof(*pmqi), GFP_KERNEL);
7127384eb72SHarald Freudenberger 		if (!pmqi)
7137384eb72SHarald Freudenberger 			return -ENOMEM;
7147384eb72SHarald Freudenberger 		rc = ep11_query_info(card, AUTOSEL_DOM,
7157384eb72SHarald Freudenberger 				     0x01 /* module info query */,
7167384eb72SHarald Freudenberger 				     sizeof(*pmqi), (u8 *)pmqi);
7177384eb72SHarald Freudenberger 		if (rc) {
7187384eb72SHarald Freudenberger 			if (rc == -ENODEV)
7197384eb72SHarald Freudenberger 				card_cache_scrub(card);
7207384eb72SHarald Freudenberger 			goto out;
7217384eb72SHarald Freudenberger 		}
7227384eb72SHarald Freudenberger 		memset(info, 0, sizeof(*info));
7237384eb72SHarald Freudenberger 		info->API_ord_nr = pmqi->API_ord_nr;
7247384eb72SHarald Freudenberger 		info->FW_version =
7257384eb72SHarald Freudenberger 			(pmqi->FW_major_vers << 8) + pmqi->FW_minor_vers;
7267384eb72SHarald Freudenberger 		memcpy(info->serial, pmqi->serial, sizeof(info->serial));
7277384eb72SHarald Freudenberger 		info->op_mode = pmqi->op_mode;
7287384eb72SHarald Freudenberger 		card_cache_update(card, info);
7297384eb72SHarald Freudenberger 	}
7307384eb72SHarald Freudenberger 
7317384eb72SHarald Freudenberger out:
7327384eb72SHarald Freudenberger 	kfree(pmqi);
7337384eb72SHarald Freudenberger 	return rc;
7347384eb72SHarald Freudenberger }
7357384eb72SHarald Freudenberger EXPORT_SYMBOL(ep11_get_card_info);
7367384eb72SHarald Freudenberger 
7377384eb72SHarald Freudenberger /*
7387384eb72SHarald Freudenberger  * Provide information about a domain within an EP11 card.
7397384eb72SHarald Freudenberger  */
ep11_get_domain_info(u16 card,u16 domain,struct ep11_domain_info * info)7407384eb72SHarald Freudenberger int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info)
7417384eb72SHarald Freudenberger {
7427384eb72SHarald Freudenberger 	int rc;
7437384eb72SHarald Freudenberger 	struct ep11_domain_query_info {
7447384eb72SHarald Freudenberger 		u32 dom_index;
7457384eb72SHarald Freudenberger 		u8  cur_WK_VP[32];
7467384eb72SHarald Freudenberger 		u8  new_WK_VP[32];
7477384eb72SHarald Freudenberger 		u32 dom_flags;
7487384eb72SHarald Freudenberger 		u64 op_mode;
7497384eb72SHarald Freudenberger 	} __packed * p_dom_info;
7507384eb72SHarald Freudenberger 
7517384eb72SHarald Freudenberger 	p_dom_info = kmalloc(sizeof(*p_dom_info), GFP_KERNEL);
7527384eb72SHarald Freudenberger 	if (!p_dom_info)
7537384eb72SHarald Freudenberger 		return -ENOMEM;
7547384eb72SHarald Freudenberger 
7557384eb72SHarald Freudenberger 	rc = ep11_query_info(card, domain, 0x03 /* domain info query */,
7567384eb72SHarald Freudenberger 			     sizeof(*p_dom_info), (u8 *)p_dom_info);
7577384eb72SHarald Freudenberger 	if (rc)
7587384eb72SHarald Freudenberger 		goto out;
7597384eb72SHarald Freudenberger 
7607384eb72SHarald Freudenberger 	memset(info, 0, sizeof(*info));
7617384eb72SHarald Freudenberger 	info->cur_wk_state = '0';
7627384eb72SHarald Freudenberger 	info->new_wk_state = '0';
7637384eb72SHarald Freudenberger 	if (p_dom_info->dom_flags & 0x10 /* left imprint mode */) {
7647384eb72SHarald Freudenberger 		if (p_dom_info->dom_flags & 0x02 /* cur wk valid */) {
7657384eb72SHarald Freudenberger 			info->cur_wk_state = '1';
7667384eb72SHarald Freudenberger 			memcpy(info->cur_wkvp, p_dom_info->cur_WK_VP, 32);
7677384eb72SHarald Freudenberger 		}
7682004b57cSHarald Freudenberger 		if (p_dom_info->dom_flags & 0x04 || /* new wk present */
7692004b57cSHarald Freudenberger 		    p_dom_info->dom_flags & 0x08 /* new wk committed */) {
7707384eb72SHarald Freudenberger 			info->new_wk_state =
7717384eb72SHarald Freudenberger 				p_dom_info->dom_flags & 0x08 ? '2' : '1';
7727384eb72SHarald Freudenberger 			memcpy(info->new_wkvp, p_dom_info->new_WK_VP, 32);
7737384eb72SHarald Freudenberger 		}
7747384eb72SHarald Freudenberger 	}
7757384eb72SHarald Freudenberger 	info->op_mode = p_dom_info->op_mode;
7767384eb72SHarald Freudenberger 
7777384eb72SHarald Freudenberger out:
7787384eb72SHarald Freudenberger 	kfree(p_dom_info);
7797384eb72SHarald Freudenberger 	return rc;
7807384eb72SHarald Freudenberger }
7817384eb72SHarald Freudenberger EXPORT_SYMBOL(ep11_get_domain_info);
7827384eb72SHarald Freudenberger 
78355d0a513SHarald Freudenberger /*
78455d0a513SHarald Freudenberger  * Default EP11 AES key generate attributes, used when no keygenflags given:
78555d0a513SHarald Freudenberger  * XCP_BLOB_ENCRYPT | XCP_BLOB_DECRYPT | XCP_BLOB_PROTKEY_EXTRACTABLE
78655d0a513SHarald Freudenberger  */
78755d0a513SHarald Freudenberger #define KEY_ATTR_DEFAULTS 0x00200c00
78855d0a513SHarald Freudenberger 
_ep11_genaeskey(u16 card,u16 domain,u32 keybitsize,u32 keygenflags,u8 * keybuf,size_t * keybufsize)789fb249ce7SHolger Dengler static int _ep11_genaeskey(u16 card, u16 domain,
790fb249ce7SHolger Dengler 			   u32 keybitsize, u32 keygenflags,
79155d0a513SHarald Freudenberger 			   u8 *keybuf, size_t *keybufsize)
79255d0a513SHarald Freudenberger {
79355d0a513SHarald Freudenberger 	struct keygen_req_pl {
79455d0a513SHarald Freudenberger 		struct pl_head head;
79555d0a513SHarald Freudenberger 		u8  var_tag;
79655d0a513SHarald Freudenberger 		u8  var_len;
79755d0a513SHarald Freudenberger 		u32 var;
79855d0a513SHarald Freudenberger 		u8  keybytes_tag;
79955d0a513SHarald Freudenberger 		u8  keybytes_len;
80055d0a513SHarald Freudenberger 		u32 keybytes;
80155d0a513SHarald Freudenberger 		u8  mech_tag;
80255d0a513SHarald Freudenberger 		u8  mech_len;
80355d0a513SHarald Freudenberger 		u32 mech;
80455d0a513SHarald Freudenberger 		u8  attr_tag;
80555d0a513SHarald Freudenberger 		u8  attr_len;
80655d0a513SHarald Freudenberger 		u32 attr_header;
80755d0a513SHarald Freudenberger 		u32 attr_bool_mask;
80855d0a513SHarald Freudenberger 		u32 attr_bool_bits;
80955d0a513SHarald Freudenberger 		u32 attr_val_len_type;
81055d0a513SHarald Freudenberger 		u32 attr_val_len_value;
811386cb81eSHolger Dengler 		/* followed by empty pin tag or empty pinblob tag */
81255d0a513SHarald Freudenberger 	} __packed * req_pl;
81355d0a513SHarald Freudenberger 	struct keygen_rep_pl {
81455d0a513SHarald Freudenberger 		struct pl_head head;
81555d0a513SHarald Freudenberger 		u8  rc_tag;
81655d0a513SHarald Freudenberger 		u8  rc_len;
81755d0a513SHarald Freudenberger 		u32 rc;
81855d0a513SHarald Freudenberger 		u8  data_tag;
81955d0a513SHarald Freudenberger 		u8  data_lenfmt;
82055d0a513SHarald Freudenberger 		u16 data_len;
82155d0a513SHarald Freudenberger 		u8  data[512];
82255d0a513SHarald Freudenberger 	} __packed * rep_pl;
82355d0a513SHarald Freudenberger 	struct ep11_cprb *req = NULL, *rep = NULL;
824386cb81eSHolger Dengler 	size_t req_pl_size, pinblob_size = 0;
82555d0a513SHarald Freudenberger 	struct ep11_target_dev target;
82655d0a513SHarald Freudenberger 	struct ep11_urb *urb = NULL;
82755d0a513SHarald Freudenberger 	int api, rc = -ENOMEM;
828386cb81eSHolger Dengler 	u8 *p;
82955d0a513SHarald Freudenberger 
83055d0a513SHarald Freudenberger 	switch (keybitsize) {
83155d0a513SHarald Freudenberger 	case 128:
83255d0a513SHarald Freudenberger 	case 192:
83355d0a513SHarald Freudenberger 	case 256:
83455d0a513SHarald Freudenberger 		break;
83555d0a513SHarald Freudenberger 	default:
83688e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
83755d0a513SHarald Freudenberger 			       __func__, keybitsize);
83855d0a513SHarald Freudenberger 		rc = -EINVAL;
83955d0a513SHarald Freudenberger 		goto out;
84055d0a513SHarald Freudenberger 	}
84155d0a513SHarald Freudenberger 
84255d0a513SHarald Freudenberger 	/* request cprb and payload */
843386cb81eSHolger Dengler 	api = (!keygenflags || keygenflags & 0x00200000) ?
844386cb81eSHolger Dengler 		EP11_API_V4 : EP11_API_V1;
845386cb81eSHolger Dengler 	if (ap_is_se_guest()) {
846386cb81eSHolger Dengler 		/*
847386cb81eSHolger Dengler 		 * genkey within SE environment requires API ordinal 6
848386cb81eSHolger Dengler 		 * with empty pinblob
849386cb81eSHolger Dengler 		 */
850386cb81eSHolger Dengler 		api = EP11_API_V6;
851386cb81eSHolger Dengler 		pinblob_size = EP11_PINBLOB_V1_BYTES;
852386cb81eSHolger Dengler 	}
853386cb81eSHolger Dengler 	req_pl_size = sizeof(struct keygen_req_pl) + ASN1TAGLEN(pinblob_size);
854386cb81eSHolger Dengler 	req = alloc_cprb(req_pl_size);
85555d0a513SHarald Freudenberger 	if (!req)
85655d0a513SHarald Freudenberger 		goto out;
85755d0a513SHarald Freudenberger 	req_pl = (struct keygen_req_pl *)(((u8 *)req) + sizeof(*req));
858386cb81eSHolger Dengler 	prep_head(&req_pl->head, req_pl_size, api, 21); /* GenerateKey */
85955d0a513SHarald Freudenberger 	req_pl->var_tag = 0x04;
86055d0a513SHarald Freudenberger 	req_pl->var_len = sizeof(u32);
86155d0a513SHarald Freudenberger 	req_pl->keybytes_tag = 0x04;
86255d0a513SHarald Freudenberger 	req_pl->keybytes_len = sizeof(u32);
86355d0a513SHarald Freudenberger 	req_pl->keybytes = keybitsize / 8;
86455d0a513SHarald Freudenberger 	req_pl->mech_tag = 0x04;
86555d0a513SHarald Freudenberger 	req_pl->mech_len = sizeof(u32);
86655d0a513SHarald Freudenberger 	req_pl->mech = 0x00001080; /* CKM_AES_KEY_GEN */
86755d0a513SHarald Freudenberger 	req_pl->attr_tag = 0x04;
86855d0a513SHarald Freudenberger 	req_pl->attr_len = 5 * sizeof(u32);
86955d0a513SHarald Freudenberger 	req_pl->attr_header = 0x10010000;
87055d0a513SHarald Freudenberger 	req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
87155d0a513SHarald Freudenberger 	req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
87255d0a513SHarald Freudenberger 	req_pl->attr_val_len_type = 0x00000161; /* CKA_VALUE_LEN */
87355d0a513SHarald Freudenberger 	req_pl->attr_val_len_value = keybitsize / 8;
874386cb81eSHolger Dengler 	p = ((u8 *)req_pl) + sizeof(*req_pl);
875386cb81eSHolger Dengler 	/* pin tag */
876386cb81eSHolger Dengler 	*p++ = 0x04;
877386cb81eSHolger Dengler 	*p++ = pinblob_size;
87855d0a513SHarald Freudenberger 
87955d0a513SHarald Freudenberger 	/* reply cprb and payload */
88055d0a513SHarald Freudenberger 	rep = alloc_cprb(sizeof(struct keygen_rep_pl));
88155d0a513SHarald Freudenberger 	if (!rep)
88255d0a513SHarald Freudenberger 		goto out;
88355d0a513SHarald Freudenberger 	rep_pl = (struct keygen_rep_pl *)(((u8 *)rep) + sizeof(*rep));
88455d0a513SHarald Freudenberger 
88555d0a513SHarald Freudenberger 	/* urb and target */
8862004b57cSHarald Freudenberger 	urb = kmalloc(sizeof(*urb), GFP_KERNEL);
88755d0a513SHarald Freudenberger 	if (!urb)
88855d0a513SHarald Freudenberger 		goto out;
88955d0a513SHarald Freudenberger 	target.ap_id = card;
89055d0a513SHarald Freudenberger 	target.dom_id = domain;
89155d0a513SHarald Freudenberger 	prep_urb(urb, &target, 1,
892386cb81eSHolger Dengler 		 req, sizeof(*req) + req_pl_size,
89355d0a513SHarald Freudenberger 		 rep, sizeof(*rep) + sizeof(*rep_pl));
89455d0a513SHarald Freudenberger 
89552f72febSHarald Freudenberger 	rc = zcrypt_send_ep11_cprb(urb);
89655d0a513SHarald Freudenberger 	if (rc) {
89788e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
89855d0a513SHarald Freudenberger 			       __func__, (int)card, (int)domain, rc);
89955d0a513SHarald Freudenberger 		goto out;
90055d0a513SHarald Freudenberger 	}
90155d0a513SHarald Freudenberger 
902c0e983b6SHarald Freudenberger 	/* check ep11 reply cprb */
903c0e983b6SHarald Freudenberger 	rc = check_reply_cprb(rep, __func__);
904c0e983b6SHarald Freudenberger 	if (rc)
905c0e983b6SHarald Freudenberger 		goto out;
906c0e983b6SHarald Freudenberger 
907c0e983b6SHarald Freudenberger 	/* check payload */
90855d0a513SHarald Freudenberger 	rc = check_reply_pl((u8 *)rep_pl, __func__);
90955d0a513SHarald Freudenberger 	if (rc)
91055d0a513SHarald Freudenberger 		goto out;
91155d0a513SHarald Freudenberger 	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
91288e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s unknown reply data format\n", __func__);
91355d0a513SHarald Freudenberger 		rc = -EIO;
91455d0a513SHarald Freudenberger 		goto out;
91555d0a513SHarald Freudenberger 	}
91655d0a513SHarald Freudenberger 	if (rep_pl->data_len > *keybufsize) {
91788e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s mismatch reply data len / key buffer len\n",
91855d0a513SHarald Freudenberger 			       __func__);
91955d0a513SHarald Freudenberger 		rc = -ENOSPC;
92055d0a513SHarald Freudenberger 		goto out;
92155d0a513SHarald Freudenberger 	}
92255d0a513SHarald Freudenberger 
923fb249ce7SHolger Dengler 	/* copy key blob */
92455d0a513SHarald Freudenberger 	memcpy(keybuf, rep_pl->data, rep_pl->data_len);
92555d0a513SHarald Freudenberger 	*keybufsize = rep_pl->data_len;
92655d0a513SHarald Freudenberger 
92755d0a513SHarald Freudenberger out:
92855d0a513SHarald Freudenberger 	kfree(req);
92955d0a513SHarald Freudenberger 	kfree(rep);
93055d0a513SHarald Freudenberger 	kfree(urb);
93155d0a513SHarald Freudenberger 	return rc;
93255d0a513SHarald Freudenberger }
933fb249ce7SHolger Dengler 
ep11_genaeskey(u16 card,u16 domain,u32 keybitsize,u32 keygenflags,u8 * keybuf,u32 * keybufsize,u32 keybufver)934fb249ce7SHolger Dengler int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
935*86fbf5e2SHarald Freudenberger 		   u8 *keybuf, u32 *keybufsize, u32 keybufver)
936fb249ce7SHolger Dengler {
937fb249ce7SHolger Dengler 	struct ep11kblob_header *hdr;
938fb249ce7SHolger Dengler 	size_t hdr_size, pl_size;
939fb249ce7SHolger Dengler 	u8 *pl;
940fb249ce7SHolger Dengler 	int rc;
941fb249ce7SHolger Dengler 
942fb249ce7SHolger Dengler 	switch (keybufver) {
943fb249ce7SHolger Dengler 	case TOKVER_EP11_AES:
944fb249ce7SHolger Dengler 	case TOKVER_EP11_AES_WITH_HEADER:
945fb249ce7SHolger Dengler 		break;
946fb249ce7SHolger Dengler 	default:
947fb249ce7SHolger Dengler 		return -EINVAL;
948fb249ce7SHolger Dengler 	}
949fb249ce7SHolger Dengler 
950fb249ce7SHolger Dengler 	rc = ep11_kb_split(keybuf, *keybufsize, keybufver,
951fb249ce7SHolger Dengler 			   &hdr, &hdr_size, &pl, &pl_size);
952fb249ce7SHolger Dengler 	if (rc)
953fb249ce7SHolger Dengler 		return rc;
954fb249ce7SHolger Dengler 
955fb249ce7SHolger Dengler 	rc = _ep11_genaeskey(card, domain, keybitsize, keygenflags,
956fb249ce7SHolger Dengler 			     pl, &pl_size);
957fb249ce7SHolger Dengler 	if (rc)
958fb249ce7SHolger Dengler 		return rc;
959fb249ce7SHolger Dengler 
960fb249ce7SHolger Dengler 	*keybufsize = hdr_size + pl_size;
961fb249ce7SHolger Dengler 
962fb249ce7SHolger Dengler 	/* update header information */
963fb249ce7SHolger Dengler 	hdr->type = TOKTYPE_NON_CCA;
964fb249ce7SHolger Dengler 	hdr->len = *keybufsize;
965fb249ce7SHolger Dengler 	hdr->version = keybufver;
966fb249ce7SHolger Dengler 	hdr->bitlen = keybitsize;
967fb249ce7SHolger Dengler 
968fb249ce7SHolger Dengler 	return 0;
969fb249ce7SHolger Dengler }
97055d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_genaeskey);
97155d0a513SHarald 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)97255d0a513SHarald Freudenberger static int ep11_cryptsingle(u16 card, u16 domain,
97355d0a513SHarald Freudenberger 			    u16 mode, u32 mech, const u8 *iv,
97455d0a513SHarald Freudenberger 			    const u8 *key, size_t keysize,
97555d0a513SHarald Freudenberger 			    const u8 *inbuf, size_t inbufsize,
97655d0a513SHarald Freudenberger 			    u8 *outbuf, size_t *outbufsize)
97755d0a513SHarald Freudenberger {
97855d0a513SHarald Freudenberger 	struct crypt_req_pl {
97955d0a513SHarald Freudenberger 		struct pl_head head;
98055d0a513SHarald Freudenberger 		u8  var_tag;
98155d0a513SHarald Freudenberger 		u8  var_len;
98255d0a513SHarald Freudenberger 		u32 var;
98355d0a513SHarald Freudenberger 		u8  mech_tag;
98455d0a513SHarald Freudenberger 		u8  mech_len;
98555d0a513SHarald Freudenberger 		u32 mech;
98655d0a513SHarald Freudenberger 		/*
98755d0a513SHarald Freudenberger 		 * maybe followed by iv data
98855d0a513SHarald Freudenberger 		 * followed by key tag + key blob
98955d0a513SHarald Freudenberger 		 * followed by plaintext tag + plaintext
99055d0a513SHarald Freudenberger 		 */
99155d0a513SHarald Freudenberger 	} __packed * req_pl;
99255d0a513SHarald Freudenberger 	struct crypt_rep_pl {
99355d0a513SHarald Freudenberger 		struct pl_head head;
99455d0a513SHarald Freudenberger 		u8  rc_tag;
99555d0a513SHarald Freudenberger 		u8  rc_len;
99655d0a513SHarald Freudenberger 		u32 rc;
99755d0a513SHarald Freudenberger 		u8  data_tag;
99855d0a513SHarald Freudenberger 		u8  data_lenfmt;
99955d0a513SHarald Freudenberger 		/* data follows */
100055d0a513SHarald Freudenberger 	} __packed * rep_pl;
100155d0a513SHarald Freudenberger 	struct ep11_cprb *req = NULL, *rep = NULL;
100255d0a513SHarald Freudenberger 	struct ep11_target_dev target;
100355d0a513SHarald Freudenberger 	struct ep11_urb *urb = NULL;
100455d0a513SHarald Freudenberger 	size_t req_pl_size, rep_pl_size;
1005386cb81eSHolger Dengler 	int n, api = EP11_API_V1, rc = -ENOMEM;
100655d0a513SHarald Freudenberger 	u8 *p;
100755d0a513SHarald Freudenberger 
100855d0a513SHarald Freudenberger 	/* the simple asn1 coding used has length limits */
100955d0a513SHarald Freudenberger 	if (keysize > 0xFFFF || inbufsize > 0xFFFF)
101055d0a513SHarald Freudenberger 		return -EINVAL;
101155d0a513SHarald Freudenberger 
101255d0a513SHarald Freudenberger 	/* request cprb and payload */
101355d0a513SHarald Freudenberger 	req_pl_size = sizeof(struct crypt_req_pl) + (iv ? 16 : 0)
101455d0a513SHarald Freudenberger 		+ ASN1TAGLEN(keysize) + ASN1TAGLEN(inbufsize);
101555d0a513SHarald Freudenberger 	req = alloc_cprb(req_pl_size);
101655d0a513SHarald Freudenberger 	if (!req)
101755d0a513SHarald Freudenberger 		goto out;
101855d0a513SHarald Freudenberger 	req_pl = (struct crypt_req_pl *)(((u8 *)req) + sizeof(*req));
101955d0a513SHarald Freudenberger 	prep_head(&req_pl->head, req_pl_size, api, (mode ? 20 : 19));
102055d0a513SHarald Freudenberger 	req_pl->var_tag = 0x04;
102155d0a513SHarald Freudenberger 	req_pl->var_len = sizeof(u32);
102255d0a513SHarald Freudenberger 	/* mech is mech + mech params (iv here) */
102355d0a513SHarald Freudenberger 	req_pl->mech_tag = 0x04;
102455d0a513SHarald Freudenberger 	req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0);
102555d0a513SHarald Freudenberger 	req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */
102655d0a513SHarald Freudenberger 	p = ((u8 *)req_pl) + sizeof(*req_pl);
102755d0a513SHarald Freudenberger 	if (iv) {
102855d0a513SHarald Freudenberger 		memcpy(p, iv, 16);
102955d0a513SHarald Freudenberger 		p += 16;
103055d0a513SHarald Freudenberger 	}
103155d0a513SHarald Freudenberger 	/* key and input data */
103255d0a513SHarald Freudenberger 	p += asn1tag_write(p, 0x04, key, keysize);
103355d0a513SHarald Freudenberger 	p += asn1tag_write(p, 0x04, inbuf, inbufsize);
103455d0a513SHarald Freudenberger 
103555d0a513SHarald Freudenberger 	/* reply cprb and payload, assume out data size <= in data size + 32 */
103655d0a513SHarald Freudenberger 	rep_pl_size = sizeof(struct crypt_rep_pl) + ASN1TAGLEN(inbufsize + 32);
103755d0a513SHarald Freudenberger 	rep = alloc_cprb(rep_pl_size);
103855d0a513SHarald Freudenberger 	if (!rep)
103955d0a513SHarald Freudenberger 		goto out;
104055d0a513SHarald Freudenberger 	rep_pl = (struct crypt_rep_pl *)(((u8 *)rep) + sizeof(*rep));
104155d0a513SHarald Freudenberger 
104255d0a513SHarald Freudenberger 	/* urb and target */
10432004b57cSHarald Freudenberger 	urb = kmalloc(sizeof(*urb), GFP_KERNEL);
104455d0a513SHarald Freudenberger 	if (!urb)
104555d0a513SHarald Freudenberger 		goto out;
104655d0a513SHarald Freudenberger 	target.ap_id = card;
104755d0a513SHarald Freudenberger 	target.dom_id = domain;
104855d0a513SHarald Freudenberger 	prep_urb(urb, &target, 1,
104955d0a513SHarald Freudenberger 		 req, sizeof(*req) + req_pl_size,
105055d0a513SHarald Freudenberger 		 rep, sizeof(*rep) + rep_pl_size);
105155d0a513SHarald Freudenberger 
105252f72febSHarald Freudenberger 	rc = zcrypt_send_ep11_cprb(urb);
105355d0a513SHarald Freudenberger 	if (rc) {
105488e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
105555d0a513SHarald Freudenberger 			       __func__, (int)card, (int)domain, rc);
105655d0a513SHarald Freudenberger 		goto out;
105755d0a513SHarald Freudenberger 	}
105855d0a513SHarald Freudenberger 
1059c0e983b6SHarald Freudenberger 	/* check ep11 reply cprb */
1060c0e983b6SHarald Freudenberger 	rc = check_reply_cprb(rep, __func__);
1061c0e983b6SHarald Freudenberger 	if (rc)
1062c0e983b6SHarald Freudenberger 		goto out;
1063c0e983b6SHarald Freudenberger 
1064c0e983b6SHarald Freudenberger 	/* check payload */
106555d0a513SHarald Freudenberger 	rc = check_reply_pl((u8 *)rep_pl, __func__);
106655d0a513SHarald Freudenberger 	if (rc)
106755d0a513SHarald Freudenberger 		goto out;
106855d0a513SHarald Freudenberger 	if (rep_pl->data_tag != 0x04) {
106988e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s unknown reply data format\n", __func__);
107055d0a513SHarald Freudenberger 		rc = -EIO;
107155d0a513SHarald Freudenberger 		goto out;
107255d0a513SHarald Freudenberger 	}
107355d0a513SHarald Freudenberger 	p = ((u8 *)rep_pl) + sizeof(*rep_pl);
10742004b57cSHarald Freudenberger 	if (rep_pl->data_lenfmt <= 127) {
107555d0a513SHarald Freudenberger 		n = rep_pl->data_lenfmt;
10762004b57cSHarald Freudenberger 	} else if (rep_pl->data_lenfmt == 0x81) {
107755d0a513SHarald Freudenberger 		n = *p++;
10782004b57cSHarald Freudenberger 	} else if (rep_pl->data_lenfmt == 0x82) {
107955d0a513SHarald Freudenberger 		n = *((u16 *)p);
108055d0a513SHarald Freudenberger 		p += 2;
108155d0a513SHarald Freudenberger 	} else {
108288e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s unknown reply data length format 0x%02hhx\n",
108355d0a513SHarald Freudenberger 			       __func__, rep_pl->data_lenfmt);
108455d0a513SHarald Freudenberger 		rc = -EIO;
108555d0a513SHarald Freudenberger 		goto out;
108655d0a513SHarald Freudenberger 	}
108755d0a513SHarald Freudenberger 	if (n > *outbufsize) {
108888e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s mismatch reply data len %d / output buffer %zu\n",
108955d0a513SHarald Freudenberger 			       __func__, n, *outbufsize);
109055d0a513SHarald Freudenberger 		rc = -ENOSPC;
109155d0a513SHarald Freudenberger 		goto out;
109255d0a513SHarald Freudenberger 	}
109355d0a513SHarald Freudenberger 
109455d0a513SHarald Freudenberger 	memcpy(outbuf, p, n);
109555d0a513SHarald Freudenberger 	*outbufsize = n;
109655d0a513SHarald Freudenberger 
109755d0a513SHarald Freudenberger out:
109855d0a513SHarald Freudenberger 	kfree(req);
109955d0a513SHarald Freudenberger 	kfree(rep);
110055d0a513SHarald Freudenberger 	kfree(urb);
110155d0a513SHarald Freudenberger 	return rc;
110255d0a513SHarald Freudenberger }
110355d0a513SHarald 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)1104da2863f1SHolger Dengler static int _ep11_unwrapkey(u16 card, u16 domain,
110555d0a513SHarald Freudenberger 			   const u8 *kek, size_t keksize,
110655d0a513SHarald Freudenberger 			   const u8 *enckey, size_t enckeysize,
110755d0a513SHarald Freudenberger 			   u32 mech, const u8 *iv,
110855d0a513SHarald Freudenberger 			   u32 keybitsize, u32 keygenflags,
110955d0a513SHarald Freudenberger 			   u8 *keybuf, size_t *keybufsize)
111055d0a513SHarald Freudenberger {
111155d0a513SHarald Freudenberger 	struct uw_req_pl {
111255d0a513SHarald Freudenberger 		struct pl_head head;
111355d0a513SHarald Freudenberger 		u8  attr_tag;
111455d0a513SHarald Freudenberger 		u8  attr_len;
111555d0a513SHarald Freudenberger 		u32 attr_header;
111655d0a513SHarald Freudenberger 		u32 attr_bool_mask;
111755d0a513SHarald Freudenberger 		u32 attr_bool_bits;
111855d0a513SHarald Freudenberger 		u32 attr_key_type;
111955d0a513SHarald Freudenberger 		u32 attr_key_type_value;
112055d0a513SHarald Freudenberger 		u32 attr_val_len;
112155d0a513SHarald Freudenberger 		u32 attr_val_len_value;
112255d0a513SHarald Freudenberger 		u8  mech_tag;
112355d0a513SHarald Freudenberger 		u8  mech_len;
112455d0a513SHarald Freudenberger 		u32 mech;
112555d0a513SHarald Freudenberger 		/*
112655d0a513SHarald Freudenberger 		 * maybe followed by iv data
112755d0a513SHarald Freudenberger 		 * followed by kek tag + kek blob
112855d0a513SHarald Freudenberger 		 * followed by empty mac tag
1129386cb81eSHolger Dengler 		 * followed by empty pin tag or empty pinblob tag
113055d0a513SHarald Freudenberger 		 * followed by encryted key tag + bytes
113155d0a513SHarald Freudenberger 		 */
113255d0a513SHarald Freudenberger 	} __packed * req_pl;
113355d0a513SHarald Freudenberger 	struct uw_rep_pl {
113455d0a513SHarald Freudenberger 		struct pl_head head;
113555d0a513SHarald Freudenberger 		u8  rc_tag;
113655d0a513SHarald Freudenberger 		u8  rc_len;
113755d0a513SHarald Freudenberger 		u32 rc;
113855d0a513SHarald Freudenberger 		u8  data_tag;
113955d0a513SHarald Freudenberger 		u8  data_lenfmt;
114055d0a513SHarald Freudenberger 		u16 data_len;
114155d0a513SHarald Freudenberger 		u8  data[512];
114255d0a513SHarald Freudenberger 	} __packed * rep_pl;
114355d0a513SHarald Freudenberger 	struct ep11_cprb *req = NULL, *rep = NULL;
1144386cb81eSHolger Dengler 	size_t req_pl_size, pinblob_size = 0;
114555d0a513SHarald Freudenberger 	struct ep11_target_dev target;
114655d0a513SHarald Freudenberger 	struct ep11_urb *urb = NULL;
114755d0a513SHarald Freudenberger 	int api, rc = -ENOMEM;
114855d0a513SHarald Freudenberger 	u8 *p;
114955d0a513SHarald Freudenberger 
115055d0a513SHarald Freudenberger 	/* request cprb and payload */
1151386cb81eSHolger Dengler 	api = (!keygenflags || keygenflags & 0x00200000) ?
1152386cb81eSHolger Dengler 		EP11_API_V4 : EP11_API_V1;
1153386cb81eSHolger Dengler 	if (ap_is_se_guest()) {
1154386cb81eSHolger Dengler 		/*
1155386cb81eSHolger Dengler 		 * unwrap within SE environment requires API ordinal 6
1156386cb81eSHolger Dengler 		 * with empty pinblob
1157386cb81eSHolger Dengler 		 */
1158386cb81eSHolger Dengler 		api = EP11_API_V6;
1159386cb81eSHolger Dengler 		pinblob_size = EP11_PINBLOB_V1_BYTES;
1160386cb81eSHolger Dengler 	}
116155d0a513SHarald Freudenberger 	req_pl_size = sizeof(struct uw_req_pl) + (iv ? 16 : 0)
1162386cb81eSHolger Dengler 		+ ASN1TAGLEN(keksize) + ASN1TAGLEN(0)
1163386cb81eSHolger Dengler 		+ ASN1TAGLEN(pinblob_size) + ASN1TAGLEN(enckeysize);
116455d0a513SHarald Freudenberger 	req = alloc_cprb(req_pl_size);
116555d0a513SHarald Freudenberger 	if (!req)
116655d0a513SHarald Freudenberger 		goto out;
116755d0a513SHarald Freudenberger 	req_pl = (struct uw_req_pl *)(((u8 *)req) + sizeof(*req));
116855d0a513SHarald Freudenberger 	prep_head(&req_pl->head, req_pl_size, api, 34); /* UnwrapKey */
116955d0a513SHarald Freudenberger 	req_pl->attr_tag = 0x04;
117055d0a513SHarald Freudenberger 	req_pl->attr_len = 7 * sizeof(u32);
117155d0a513SHarald Freudenberger 	req_pl->attr_header = 0x10020000;
117255d0a513SHarald Freudenberger 	req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
117355d0a513SHarald Freudenberger 	req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
117455d0a513SHarald Freudenberger 	req_pl->attr_key_type = 0x00000100; /* CKA_KEY_TYPE */
117555d0a513SHarald Freudenberger 	req_pl->attr_key_type_value = 0x0000001f; /* CKK_AES */
117655d0a513SHarald Freudenberger 	req_pl->attr_val_len = 0x00000161; /* CKA_VALUE_LEN */
117755d0a513SHarald Freudenberger 	req_pl->attr_val_len_value = keybitsize / 8;
117855d0a513SHarald Freudenberger 	/* mech is mech + mech params (iv here) */
117955d0a513SHarald Freudenberger 	req_pl->mech_tag = 0x04;
118055d0a513SHarald Freudenberger 	req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0);
118155d0a513SHarald Freudenberger 	req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */
118255d0a513SHarald Freudenberger 	p = ((u8 *)req_pl) + sizeof(*req_pl);
118355d0a513SHarald Freudenberger 	if (iv) {
118455d0a513SHarald Freudenberger 		memcpy(p, iv, 16);
118555d0a513SHarald Freudenberger 		p += 16;
118655d0a513SHarald Freudenberger 	}
118755d0a513SHarald Freudenberger 	/* kek */
118855d0a513SHarald Freudenberger 	p += asn1tag_write(p, 0x04, kek, keksize);
118955d0a513SHarald Freudenberger 	/* empty mac key tag */
119055d0a513SHarald Freudenberger 	*p++ = 0x04;
119155d0a513SHarald Freudenberger 	*p++ = 0;
1192386cb81eSHolger Dengler 	/* pin tag */
119355d0a513SHarald Freudenberger 	*p++ = 0x04;
1194386cb81eSHolger Dengler 	*p++ = pinblob_size;
1195386cb81eSHolger Dengler 	p += pinblob_size;
119605ccaca0SGeert Uytterhoeven 	/* encrypted key value tag and bytes */
119755d0a513SHarald Freudenberger 	p += asn1tag_write(p, 0x04, enckey, enckeysize);
119855d0a513SHarald Freudenberger 
119955d0a513SHarald Freudenberger 	/* reply cprb and payload */
120055d0a513SHarald Freudenberger 	rep = alloc_cprb(sizeof(struct uw_rep_pl));
120155d0a513SHarald Freudenberger 	if (!rep)
120255d0a513SHarald Freudenberger 		goto out;
120355d0a513SHarald Freudenberger 	rep_pl = (struct uw_rep_pl *)(((u8 *)rep) + sizeof(*rep));
120455d0a513SHarald Freudenberger 
120555d0a513SHarald Freudenberger 	/* urb and target */
12062004b57cSHarald Freudenberger 	urb = kmalloc(sizeof(*urb), GFP_KERNEL);
120755d0a513SHarald Freudenberger 	if (!urb)
120855d0a513SHarald Freudenberger 		goto out;
120955d0a513SHarald Freudenberger 	target.ap_id = card;
121055d0a513SHarald Freudenberger 	target.dom_id = domain;
121155d0a513SHarald Freudenberger 	prep_urb(urb, &target, 1,
121255d0a513SHarald Freudenberger 		 req, sizeof(*req) + req_pl_size,
121355d0a513SHarald Freudenberger 		 rep, sizeof(*rep) + sizeof(*rep_pl));
121455d0a513SHarald Freudenberger 
121552f72febSHarald Freudenberger 	rc = zcrypt_send_ep11_cprb(urb);
121655d0a513SHarald Freudenberger 	if (rc) {
121788e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
121855d0a513SHarald Freudenberger 			       __func__, (int)card, (int)domain, rc);
121955d0a513SHarald Freudenberger 		goto out;
122055d0a513SHarald Freudenberger 	}
122155d0a513SHarald Freudenberger 
1222c0e983b6SHarald Freudenberger 	/* check ep11 reply cprb */
1223c0e983b6SHarald Freudenberger 	rc = check_reply_cprb(rep, __func__);
1224c0e983b6SHarald Freudenberger 	if (rc)
1225c0e983b6SHarald Freudenberger 		goto out;
1226c0e983b6SHarald Freudenberger 
1227c0e983b6SHarald Freudenberger 	/* check payload */
122855d0a513SHarald Freudenberger 	rc = check_reply_pl((u8 *)rep_pl, __func__);
122955d0a513SHarald Freudenberger 	if (rc)
123055d0a513SHarald Freudenberger 		goto out;
123155d0a513SHarald Freudenberger 	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
123288e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s unknown reply data format\n", __func__);
123355d0a513SHarald Freudenberger 		rc = -EIO;
123455d0a513SHarald Freudenberger 		goto out;
123555d0a513SHarald Freudenberger 	}
123655d0a513SHarald Freudenberger 	if (rep_pl->data_len > *keybufsize) {
123788e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s mismatch reply data len / key buffer len\n",
123855d0a513SHarald Freudenberger 			       __func__);
123955d0a513SHarald Freudenberger 		rc = -ENOSPC;
124055d0a513SHarald Freudenberger 		goto out;
124155d0a513SHarald Freudenberger 	}
124255d0a513SHarald Freudenberger 
1243da2863f1SHolger Dengler 	/* copy key blob */
124455d0a513SHarald Freudenberger 	memcpy(keybuf, rep_pl->data, rep_pl->data_len);
124555d0a513SHarald Freudenberger 	*keybufsize = rep_pl->data_len;
124655d0a513SHarald Freudenberger 
124755d0a513SHarald Freudenberger out:
124855d0a513SHarald Freudenberger 	kfree(req);
124955d0a513SHarald Freudenberger 	kfree(rep);
125055d0a513SHarald Freudenberger 	kfree(urb);
125155d0a513SHarald Freudenberger 	return rc;
125255d0a513SHarald Freudenberger }
125355d0a513SHarald 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,u32 * keybufsize,u8 keybufver)1254da2863f1SHolger Dengler static int ep11_unwrapkey(u16 card, u16 domain,
1255da2863f1SHolger Dengler 			  const u8 *kek, size_t keksize,
1256da2863f1SHolger Dengler 			  const u8 *enckey, size_t enckeysize,
1257da2863f1SHolger Dengler 			  u32 mech, const u8 *iv,
1258da2863f1SHolger Dengler 			  u32 keybitsize, u32 keygenflags,
1259*86fbf5e2SHarald Freudenberger 			  u8 *keybuf, u32 *keybufsize,
1260da2863f1SHolger Dengler 			  u8 keybufver)
1261da2863f1SHolger Dengler {
1262da2863f1SHolger Dengler 	struct ep11kblob_header *hdr;
1263da2863f1SHolger Dengler 	size_t hdr_size, pl_size;
1264da2863f1SHolger Dengler 	u8 *pl;
1265da2863f1SHolger Dengler 	int rc;
1266da2863f1SHolger Dengler 
1267da2863f1SHolger Dengler 	rc = ep11_kb_split(keybuf, *keybufsize, keybufver,
1268da2863f1SHolger Dengler 			   &hdr, &hdr_size, &pl, &pl_size);
1269da2863f1SHolger Dengler 	if (rc)
1270da2863f1SHolger Dengler 		return rc;
1271da2863f1SHolger Dengler 
1272da2863f1SHolger Dengler 	rc = _ep11_unwrapkey(card, domain, kek, keksize, enckey, enckeysize,
1273da2863f1SHolger Dengler 			     mech, iv, keybitsize, keygenflags,
1274da2863f1SHolger Dengler 			     pl, &pl_size);
1275da2863f1SHolger Dengler 	if (rc)
1276da2863f1SHolger Dengler 		return rc;
1277da2863f1SHolger Dengler 
1278da2863f1SHolger Dengler 	*keybufsize = hdr_size + pl_size;
1279da2863f1SHolger Dengler 
1280da2863f1SHolger Dengler 	/* update header information */
1281da2863f1SHolger Dengler 	hdr = (struct ep11kblob_header *)keybuf;
1282da2863f1SHolger Dengler 	hdr->type = TOKTYPE_NON_CCA;
1283da2863f1SHolger Dengler 	hdr->len = *keybufsize;
1284da2863f1SHolger Dengler 	hdr->version = keybufver;
1285da2863f1SHolger Dengler 	hdr->bitlen = keybitsize;
1286da2863f1SHolger Dengler 
1287da2863f1SHolger Dengler 	return 0;
1288da2863f1SHolger Dengler }
1289da2863f1SHolger Dengler 
_ep11_wrapkey(u16 card,u16 domain,const u8 * key,size_t keysize,u32 mech,const u8 * iv,u8 * databuf,size_t * datasize)1290d1fdfb0bSHolger Dengler static int _ep11_wrapkey(u16 card, u16 domain,
129155d0a513SHarald Freudenberger 			 const u8 *key, size_t keysize,
129255d0a513SHarald Freudenberger 			 u32 mech, const u8 *iv,
129355d0a513SHarald Freudenberger 			 u8 *databuf, size_t *datasize)
129455d0a513SHarald Freudenberger {
129555d0a513SHarald Freudenberger 	struct wk_req_pl {
129655d0a513SHarald Freudenberger 		struct pl_head head;
129755d0a513SHarald Freudenberger 		u8  var_tag;
129855d0a513SHarald Freudenberger 		u8  var_len;
129955d0a513SHarald Freudenberger 		u32 var;
130055d0a513SHarald Freudenberger 		u8  mech_tag;
130155d0a513SHarald Freudenberger 		u8  mech_len;
130255d0a513SHarald Freudenberger 		u32 mech;
130355d0a513SHarald Freudenberger 		/*
130455d0a513SHarald Freudenberger 		 * followed by iv data
130555d0a513SHarald Freudenberger 		 * followed by key tag + key blob
130655d0a513SHarald Freudenberger 		 * followed by dummy kek param
130755d0a513SHarald Freudenberger 		 * followed by dummy mac param
130855d0a513SHarald Freudenberger 		 */
130955d0a513SHarald Freudenberger 	} __packed * req_pl;
131055d0a513SHarald Freudenberger 	struct wk_rep_pl {
131155d0a513SHarald Freudenberger 		struct pl_head head;
131255d0a513SHarald Freudenberger 		u8  rc_tag;
131355d0a513SHarald Freudenberger 		u8  rc_len;
131455d0a513SHarald Freudenberger 		u32 rc;
131555d0a513SHarald Freudenberger 		u8  data_tag;
131655d0a513SHarald Freudenberger 		u8  data_lenfmt;
131755d0a513SHarald Freudenberger 		u16 data_len;
1318fa6999e3SHarald Freudenberger 		u8  data[1024];
131955d0a513SHarald Freudenberger 	} __packed * rep_pl;
132055d0a513SHarald Freudenberger 	struct ep11_cprb *req = NULL, *rep = NULL;
132155d0a513SHarald Freudenberger 	struct ep11_target_dev target;
132255d0a513SHarald Freudenberger 	struct ep11_urb *urb = NULL;
132355d0a513SHarald Freudenberger 	size_t req_pl_size;
132455d0a513SHarald Freudenberger 	int api, rc = -ENOMEM;
132555d0a513SHarald Freudenberger 	u8 *p;
132655d0a513SHarald Freudenberger 
132755d0a513SHarald Freudenberger 	/* request cprb and payload */
132855d0a513SHarald Freudenberger 	req_pl_size = sizeof(struct wk_req_pl) + (iv ? 16 : 0)
132955d0a513SHarald Freudenberger 		+ ASN1TAGLEN(keysize) + 4;
133055d0a513SHarald Freudenberger 	req = alloc_cprb(req_pl_size);
133155d0a513SHarald Freudenberger 	if (!req)
133255d0a513SHarald Freudenberger 		goto out;
133355d0a513SHarald Freudenberger 	if (!mech || mech == 0x80060001)
133455d0a513SHarald Freudenberger 		req->flags |= 0x20; /* CPACF_WRAP needs special bit */
133555d0a513SHarald Freudenberger 	req_pl = (struct wk_req_pl *)(((u8 *)req) + sizeof(*req));
1336386cb81eSHolger Dengler 	api = (!mech || mech == 0x80060001) ? /* CKM_IBM_CPACF_WRAP */
1337386cb81eSHolger Dengler 		EP11_API_V4 : EP11_API_V1;
133855d0a513SHarald Freudenberger 	prep_head(&req_pl->head, req_pl_size, api, 33); /* WrapKey */
133955d0a513SHarald Freudenberger 	req_pl->var_tag = 0x04;
134055d0a513SHarald Freudenberger 	req_pl->var_len = sizeof(u32);
134155d0a513SHarald Freudenberger 	/* mech is mech + mech params (iv here) */
134255d0a513SHarald Freudenberger 	req_pl->mech_tag = 0x04;
134355d0a513SHarald Freudenberger 	req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0);
134455d0a513SHarald Freudenberger 	req_pl->mech = (mech ? mech : 0x80060001); /* CKM_IBM_CPACF_WRAP */
134555d0a513SHarald Freudenberger 	p = ((u8 *)req_pl) + sizeof(*req_pl);
134655d0a513SHarald Freudenberger 	if (iv) {
134755d0a513SHarald Freudenberger 		memcpy(p, iv, 16);
134855d0a513SHarald Freudenberger 		p += 16;
134955d0a513SHarald Freudenberger 	}
135055d0a513SHarald Freudenberger 	/* key blob */
135155d0a513SHarald Freudenberger 	p += asn1tag_write(p, 0x04, key, keysize);
135255d0a513SHarald Freudenberger 	/* empty kek tag */
135355d0a513SHarald Freudenberger 	*p++ = 0x04;
135455d0a513SHarald Freudenberger 	*p++ = 0;
135555d0a513SHarald Freudenberger 	/* empty mac tag */
135655d0a513SHarald Freudenberger 	*p++ = 0x04;
135755d0a513SHarald Freudenberger 	*p++ = 0;
135855d0a513SHarald Freudenberger 
135955d0a513SHarald Freudenberger 	/* reply cprb and payload */
136055d0a513SHarald Freudenberger 	rep = alloc_cprb(sizeof(struct wk_rep_pl));
136155d0a513SHarald Freudenberger 	if (!rep)
136255d0a513SHarald Freudenberger 		goto out;
136355d0a513SHarald Freudenberger 	rep_pl = (struct wk_rep_pl *)(((u8 *)rep) + sizeof(*rep));
136455d0a513SHarald Freudenberger 
136555d0a513SHarald Freudenberger 	/* urb and target */
13662004b57cSHarald Freudenberger 	urb = kmalloc(sizeof(*urb), GFP_KERNEL);
136755d0a513SHarald Freudenberger 	if (!urb)
136855d0a513SHarald Freudenberger 		goto out;
136955d0a513SHarald Freudenberger 	target.ap_id = card;
137055d0a513SHarald Freudenberger 	target.dom_id = domain;
137155d0a513SHarald Freudenberger 	prep_urb(urb, &target, 1,
137255d0a513SHarald Freudenberger 		 req, sizeof(*req) + req_pl_size,
137355d0a513SHarald Freudenberger 		 rep, sizeof(*rep) + sizeof(*rep_pl));
137455d0a513SHarald Freudenberger 
137552f72febSHarald Freudenberger 	rc = zcrypt_send_ep11_cprb(urb);
137655d0a513SHarald Freudenberger 	if (rc) {
137788e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
137855d0a513SHarald Freudenberger 			       __func__, (int)card, (int)domain, rc);
137955d0a513SHarald Freudenberger 		goto out;
138055d0a513SHarald Freudenberger 	}
138155d0a513SHarald Freudenberger 
1382c0e983b6SHarald Freudenberger 	/* check ep11 reply cprb */
1383c0e983b6SHarald Freudenberger 	rc = check_reply_cprb(rep, __func__);
1384c0e983b6SHarald Freudenberger 	if (rc)
1385c0e983b6SHarald Freudenberger 		goto out;
1386c0e983b6SHarald Freudenberger 
1387c0e983b6SHarald Freudenberger 	/* check payload */
138855d0a513SHarald Freudenberger 	rc = check_reply_pl((u8 *)rep_pl, __func__);
138955d0a513SHarald Freudenberger 	if (rc)
139055d0a513SHarald Freudenberger 		goto out;
139155d0a513SHarald Freudenberger 	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
139288e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s unknown reply data format\n", __func__);
139355d0a513SHarald Freudenberger 		rc = -EIO;
139455d0a513SHarald Freudenberger 		goto out;
139555d0a513SHarald Freudenberger 	}
139655d0a513SHarald Freudenberger 	if (rep_pl->data_len > *datasize) {
139788e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s mismatch reply data len / data buffer len\n",
139855d0a513SHarald Freudenberger 			       __func__);
139955d0a513SHarald Freudenberger 		rc = -ENOSPC;
140055d0a513SHarald Freudenberger 		goto out;
140155d0a513SHarald Freudenberger 	}
140255d0a513SHarald Freudenberger 
140355d0a513SHarald Freudenberger 	/* copy the data from the cprb to the data buffer */
140455d0a513SHarald Freudenberger 	memcpy(databuf, rep_pl->data, rep_pl->data_len);
140555d0a513SHarald Freudenberger 	*datasize = rep_pl->data_len;
140655d0a513SHarald Freudenberger 
140755d0a513SHarald Freudenberger out:
140855d0a513SHarald Freudenberger 	kfree(req);
140955d0a513SHarald Freudenberger 	kfree(rep);
141055d0a513SHarald Freudenberger 	kfree(urb);
141155d0a513SHarald Freudenberger 	return rc;
141255d0a513SHarald Freudenberger }
141355d0a513SHarald Freudenberger 
ep11_clr2keyblob(u16 card,u16 domain,u32 keybitsize,u32 keygenflags,const u8 * clrkey,u8 * keybuf,u32 * keybufsize,u32 keytype)141455d0a513SHarald Freudenberger int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
1415*86fbf5e2SHarald Freudenberger 		     const u8 *clrkey, u8 *keybuf, u32 *keybufsize,
1416da2863f1SHolger Dengler 		     u32 keytype)
141755d0a513SHarald Freudenberger {
141855d0a513SHarald Freudenberger 	int rc;
141955d0a513SHarald Freudenberger 	u8 encbuf[64], *kek = NULL;
142055d0a513SHarald Freudenberger 	size_t clrkeylen, keklen, encbuflen = sizeof(encbuf);
142155d0a513SHarald Freudenberger 
14222004b57cSHarald Freudenberger 	if (keybitsize == 128 || keybitsize == 192 || keybitsize == 256) {
142355d0a513SHarald Freudenberger 		clrkeylen = keybitsize / 8;
14242004b57cSHarald Freudenberger 	} else {
142588e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
142655d0a513SHarald Freudenberger 			       __func__, keybitsize);
142755d0a513SHarald Freudenberger 		return -EINVAL;
142855d0a513SHarald Freudenberger 	}
142955d0a513SHarald Freudenberger 
143055d0a513SHarald Freudenberger 	/* allocate memory for the temp kek */
143155d0a513SHarald Freudenberger 	keklen = MAXEP11AESKEYBLOBSIZE;
143255d0a513SHarald Freudenberger 	kek = kmalloc(keklen, GFP_ATOMIC);
143355d0a513SHarald Freudenberger 	if (!kek) {
143455d0a513SHarald Freudenberger 		rc = -ENOMEM;
143555d0a513SHarald Freudenberger 		goto out;
143655d0a513SHarald Freudenberger 	}
143755d0a513SHarald Freudenberger 
143855d0a513SHarald Freudenberger 	/* Step 1: generate AES 256 bit random kek key */
1439fb249ce7SHolger Dengler 	rc = _ep11_genaeskey(card, domain, 256,
144005ccaca0SGeert Uytterhoeven 			     0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */
144155d0a513SHarald Freudenberger 			     kek, &keklen);
144255d0a513SHarald Freudenberger 	if (rc) {
144388e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s generate kek key failed, rc=%d\n",
144455d0a513SHarald Freudenberger 			       __func__, rc);
144555d0a513SHarald Freudenberger 		goto out;
144655d0a513SHarald Freudenberger 	}
144755d0a513SHarald Freudenberger 
144855d0a513SHarald Freudenberger 	/* Step 2: encrypt clear key value with the kek key */
144955d0a513SHarald Freudenberger 	rc = ep11_cryptsingle(card, domain, 0, 0, def_iv, kek, keklen,
145055d0a513SHarald Freudenberger 			      clrkey, clrkeylen, encbuf, &encbuflen);
145155d0a513SHarald Freudenberger 	if (rc) {
145288e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s encrypting key value with kek key failed, rc=%d\n",
145355d0a513SHarald Freudenberger 			       __func__, rc);
145455d0a513SHarald Freudenberger 		goto out;
145555d0a513SHarald Freudenberger 	}
145655d0a513SHarald Freudenberger 
145755d0a513SHarald Freudenberger 	/* Step 3: import the encrypted key value as a new key */
145855d0a513SHarald Freudenberger 	rc = ep11_unwrapkey(card, domain, kek, keklen,
145955d0a513SHarald Freudenberger 			    encbuf, encbuflen, 0, def_iv,
1460da2863f1SHolger Dengler 			    keybitsize, 0, keybuf, keybufsize, keytype);
146155d0a513SHarald Freudenberger 	if (rc) {
146288e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s importing key value as new key failed,, rc=%d\n",
146355d0a513SHarald Freudenberger 			       __func__, rc);
146455d0a513SHarald Freudenberger 		goto out;
146555d0a513SHarald Freudenberger 	}
146655d0a513SHarald Freudenberger 
146755d0a513SHarald Freudenberger out:
146855d0a513SHarald Freudenberger 	kfree(kek);
146955d0a513SHarald Freudenberger 	return rc;
147055d0a513SHarald Freudenberger }
147155d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_clr2keyblob);
147255d0a513SHarald Freudenberger 
ep11_kblob2protkey(u16 card,u16 dom,const u8 * keyblob,u32 keybloblen,u8 * protkey,u32 * protkeylen,u32 * protkeytype)1473d1fdfb0bSHolger Dengler int ep11_kblob2protkey(u16 card, u16 dom,
1474*86fbf5e2SHarald Freudenberger 		       const u8 *keyblob, u32 keybloblen,
147555d0a513SHarald Freudenberger 		       u8 *protkey, u32 *protkeylen, u32 *protkeytype)
147655d0a513SHarald Freudenberger {
1477d1fdfb0bSHolger Dengler 	struct ep11kblob_header *hdr;
1478d1fdfb0bSHolger Dengler 	struct ep11keyblob *key;
1479fa6999e3SHarald Freudenberger 	size_t wkbuflen, keylen;
148055d0a513SHarald Freudenberger 	struct wk_info {
148155d0a513SHarald Freudenberger 		u16 version;
148255d0a513SHarald Freudenberger 		u8  res1[16];
148355d0a513SHarald Freudenberger 		u32 pkeytype;
148455d0a513SHarald Freudenberger 		u32 pkeybitsize;
148555d0a513SHarald Freudenberger 		u64 pkeysize;
148655d0a513SHarald Freudenberger 		u8  res2[8];
14873b42877cSHarald Freudenberger 		u8  pkey[];
148855d0a513SHarald Freudenberger 	} __packed * wki;
1489d1fdfb0bSHolger Dengler 	u8 *wkbuf = NULL;
1490d1fdfb0bSHolger Dengler 	int rc = -EIO;
1491fa6999e3SHarald Freudenberger 
1492d1fdfb0bSHolger Dengler 	if (ep11_kb_decode((u8 *)keyblob, keybloblen, &hdr, NULL, &key, &keylen))
1493fa6999e3SHarald Freudenberger 		return -EINVAL;
1494d1fdfb0bSHolger Dengler 
1495d1fdfb0bSHolger Dengler 	if (hdr->version == TOKVER_EP11_AES) {
1496d1fdfb0bSHolger Dengler 		/* wipe overlayed header */
1497d1fdfb0bSHolger Dengler 		memset(hdr, 0, sizeof(*hdr));
14982004b57cSHarald Freudenberger 	}
1499d1fdfb0bSHolger Dengler 	/* !!! hdr is no longer a valid header !!! */
150055d0a513SHarald Freudenberger 
150155d0a513SHarald Freudenberger 	/* alloc temp working buffer */
1502fa6999e3SHarald Freudenberger 	wkbuflen = (keylen + AES_BLOCK_SIZE) & (~(AES_BLOCK_SIZE - 1));
150355d0a513SHarald Freudenberger 	wkbuf = kmalloc(wkbuflen, GFP_ATOMIC);
150455d0a513SHarald Freudenberger 	if (!wkbuf)
150555d0a513SHarald Freudenberger 		return -ENOMEM;
150655d0a513SHarald Freudenberger 
150755d0a513SHarald Freudenberger 	/* ep11 secure key -> protected key + info */
1508d1fdfb0bSHolger Dengler 	rc = _ep11_wrapkey(card, dom, (u8 *)key, keylen,
150955d0a513SHarald Freudenberger 			   0, def_iv, wkbuf, &wkbuflen);
151055d0a513SHarald Freudenberger 	if (rc) {
151188e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s rewrapping ep11 key to pkey failed, rc=%d\n",
151255d0a513SHarald Freudenberger 			       __func__, rc);
151355d0a513SHarald Freudenberger 		goto out;
151455d0a513SHarald Freudenberger 	}
151555d0a513SHarald Freudenberger 	wki = (struct wk_info *)wkbuf;
151655d0a513SHarald Freudenberger 
151755d0a513SHarald Freudenberger 	/* check struct version and pkey type */
1518fa6999e3SHarald Freudenberger 	if (wki->version != 1 || wki->pkeytype < 1 || wki->pkeytype > 5) {
151988e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s wk info version %d or pkeytype %d mismatch.\n",
152055d0a513SHarald Freudenberger 			       __func__, (int)wki->version, (int)wki->pkeytype);
152155d0a513SHarald Freudenberger 		rc = -EIO;
152255d0a513SHarald Freudenberger 		goto out;
152355d0a513SHarald Freudenberger 	}
152455d0a513SHarald Freudenberger 
1525fa6999e3SHarald Freudenberger 	/* check protected key type field */
1526fa6999e3SHarald Freudenberger 	switch (wki->pkeytype) {
1527fa6999e3SHarald Freudenberger 	case 1: /* AES */
152855d0a513SHarald Freudenberger 		switch (wki->pkeysize) {
152955d0a513SHarald Freudenberger 		case 16 + 32:
153055d0a513SHarald Freudenberger 			/* AES 128 protected key */
153155d0a513SHarald Freudenberger 			if (protkeytype)
153255d0a513SHarald Freudenberger 				*protkeytype = PKEY_KEYTYPE_AES_128;
153355d0a513SHarald Freudenberger 			break;
153455d0a513SHarald Freudenberger 		case 24 + 32:
153555d0a513SHarald Freudenberger 			/* AES 192 protected key */
153655d0a513SHarald Freudenberger 			if (protkeytype)
153755d0a513SHarald Freudenberger 				*protkeytype = PKEY_KEYTYPE_AES_192;
153855d0a513SHarald Freudenberger 			break;
153955d0a513SHarald Freudenberger 		case 32 + 32:
154055d0a513SHarald Freudenberger 			/* AES 256 protected key */
154155d0a513SHarald Freudenberger 			if (protkeytype)
154255d0a513SHarald Freudenberger 				*protkeytype = PKEY_KEYTYPE_AES_256;
154355d0a513SHarald Freudenberger 			break;
154455d0a513SHarald Freudenberger 		default:
154588e4c0daSHarald Freudenberger 			ZCRYPT_DBF_ERR("%s unknown/unsupported AES pkeysize %d\n",
154655d0a513SHarald Freudenberger 				       __func__, (int)wki->pkeysize);
154755d0a513SHarald Freudenberger 			rc = -EIO;
154855d0a513SHarald Freudenberger 			goto out;
154955d0a513SHarald Freudenberger 		}
1550fa6999e3SHarald Freudenberger 		break;
1551fa6999e3SHarald Freudenberger 	case 3: /* EC-P */
1552fa6999e3SHarald Freudenberger 	case 4: /* EC-ED */
1553fa6999e3SHarald Freudenberger 	case 5: /* EC-BP */
1554fa6999e3SHarald Freudenberger 		if (protkeytype)
1555fa6999e3SHarald Freudenberger 			*protkeytype = PKEY_KEYTYPE_ECC;
1556fa6999e3SHarald Freudenberger 		break;
1557fa6999e3SHarald Freudenberger 	case 2: /* TDES */
1558fa6999e3SHarald Freudenberger 	default:
155988e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s unknown/unsupported key type %d\n",
1560fa6999e3SHarald Freudenberger 			       __func__, (int)wki->pkeytype);
1561fa6999e3SHarald Freudenberger 		rc = -EIO;
1562fa6999e3SHarald Freudenberger 		goto out;
1563fa6999e3SHarald Freudenberger 	}
1564fa6999e3SHarald Freudenberger 
1565cada938aSHeiko Carstens 	/* copy the translated protected key */
1566fa6999e3SHarald Freudenberger 	if (wki->pkeysize > *protkeylen) {
156788e4c0daSHarald Freudenberger 		ZCRYPT_DBF_ERR("%s wk info pkeysize %llu > protkeysize %u\n",
1568fa6999e3SHarald Freudenberger 			       __func__, wki->pkeysize, *protkeylen);
1569fa6999e3SHarald Freudenberger 		rc = -EINVAL;
1570fa6999e3SHarald Freudenberger 		goto out;
1571fa6999e3SHarald Freudenberger 	}
157255d0a513SHarald Freudenberger 	memcpy(protkey, wki->pkey, wki->pkeysize);
1573fa6999e3SHarald Freudenberger 	*protkeylen = wki->pkeysize;
157455d0a513SHarald Freudenberger 
157555d0a513SHarald Freudenberger out:
157655d0a513SHarald Freudenberger 	kfree(wkbuf);
157755d0a513SHarald Freudenberger 	return rc;
157855d0a513SHarald Freudenberger }
1579fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_kblob2protkey);
158055d0a513SHarald Freudenberger 
ep11_findcard2(u32 ** apqns,u32 * nr_apqns,u16 cardnr,u16 domain,int minhwtype,int minapi,const u8 * wkvp)158155d0a513SHarald Freudenberger int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
158255d0a513SHarald Freudenberger 		   int minhwtype, int minapi, const u8 *wkvp)
158355d0a513SHarald Freudenberger {
158455d0a513SHarald Freudenberger 	struct zcrypt_device_status_ext *device_status;
158555d0a513SHarald Freudenberger 	u32 *_apqns = NULL, _nr_apqns = 0;
158655d0a513SHarald Freudenberger 	int i, card, dom, rc = -ENOMEM;
158755d0a513SHarald Freudenberger 	struct ep11_domain_info edi;
158855d0a513SHarald Freudenberger 	struct ep11_card_info eci;
158955d0a513SHarald Freudenberger 
159055d0a513SHarald Freudenberger 	/* fetch status of all crypto cards */
1591c1248638SHeiko Carstens 	device_status = kvcalloc(MAX_ZDEV_ENTRIES_EXT,
159255d0a513SHarald Freudenberger 				 sizeof(struct zcrypt_device_status_ext),
159355d0a513SHarald Freudenberger 				 GFP_KERNEL);
159455d0a513SHarald Freudenberger 	if (!device_status)
159555d0a513SHarald Freudenberger 		return -ENOMEM;
159655d0a513SHarald Freudenberger 	zcrypt_device_status_mask_ext(device_status);
159755d0a513SHarald Freudenberger 
159855d0a513SHarald Freudenberger 	/* allocate 1k space for up to 256 apqns */
159955d0a513SHarald Freudenberger 	_apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL);
160055d0a513SHarald Freudenberger 	if (!_apqns) {
160134515df2SHarald Freudenberger 		kvfree(device_status);
160255d0a513SHarald Freudenberger 		return -ENOMEM;
160355d0a513SHarald Freudenberger 	}
160455d0a513SHarald Freudenberger 
160555d0a513SHarald Freudenberger 	/* walk through all the crypto apqnss */
160655d0a513SHarald Freudenberger 	for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
160755d0a513SHarald Freudenberger 		card = AP_QID_CARD(device_status[i].qid);
160855d0a513SHarald Freudenberger 		dom = AP_QID_QUEUE(device_status[i].qid);
160955d0a513SHarald Freudenberger 		/* check online state */
161055d0a513SHarald Freudenberger 		if (!device_status[i].online)
161155d0a513SHarald Freudenberger 			continue;
161255d0a513SHarald Freudenberger 		/* check for ep11 functions */
161355d0a513SHarald Freudenberger 		if (!(device_status[i].functions & 0x01))
161455d0a513SHarald Freudenberger 			continue;
161555d0a513SHarald Freudenberger 		/* check cardnr */
161655d0a513SHarald Freudenberger 		if (cardnr != 0xFFFF && card != cardnr)
161755d0a513SHarald Freudenberger 			continue;
161855d0a513SHarald Freudenberger 		/* check domain */
161955d0a513SHarald Freudenberger 		if (domain != 0xFFFF && dom != domain)
162055d0a513SHarald Freudenberger 			continue;
162155d0a513SHarald Freudenberger 		/* check min hardware type */
162255d0a513SHarald Freudenberger 		if (minhwtype && device_status[i].hwtype < minhwtype)
162355d0a513SHarald Freudenberger 			continue;
162455d0a513SHarald Freudenberger 		/* check min api version if given */
162555d0a513SHarald Freudenberger 		if (minapi > 0) {
162655d0a513SHarald Freudenberger 			if (ep11_get_card_info(card, &eci, 0))
162755d0a513SHarald Freudenberger 				continue;
162855d0a513SHarald Freudenberger 			if (minapi > eci.API_ord_nr)
162955d0a513SHarald Freudenberger 				continue;
163055d0a513SHarald Freudenberger 		}
163155d0a513SHarald Freudenberger 		/* check wkvp if given */
163255d0a513SHarald Freudenberger 		if (wkvp) {
163355d0a513SHarald Freudenberger 			if (ep11_get_domain_info(card, dom, &edi))
163455d0a513SHarald Freudenberger 				continue;
163555d0a513SHarald Freudenberger 			if (edi.cur_wk_state != '1')
163655d0a513SHarald Freudenberger 				continue;
163755d0a513SHarald Freudenberger 			if (memcmp(wkvp, edi.cur_wkvp, 16))
163855d0a513SHarald Freudenberger 				continue;
163955d0a513SHarald Freudenberger 		}
164055d0a513SHarald Freudenberger 		/* apqn passed all filtering criterons, add to the array */
164155d0a513SHarald Freudenberger 		if (_nr_apqns < 256)
164255d0a513SHarald Freudenberger 			_apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom);
164355d0a513SHarald Freudenberger 	}
164455d0a513SHarald Freudenberger 
164555d0a513SHarald Freudenberger 	/* nothing found ? */
164655d0a513SHarald Freudenberger 	if (!_nr_apqns) {
164755d0a513SHarald Freudenberger 		kfree(_apqns);
164855d0a513SHarald Freudenberger 		rc = -ENODEV;
164955d0a513SHarald Freudenberger 	} else {
165055d0a513SHarald Freudenberger 		/* no re-allocation, simple return the _apqns array */
165155d0a513SHarald Freudenberger 		*apqns = _apqns;
165255d0a513SHarald Freudenberger 		*nr_apqns = _nr_apqns;
165355d0a513SHarald Freudenberger 		rc = 0;
165455d0a513SHarald Freudenberger 	}
165555d0a513SHarald Freudenberger 
165634515df2SHarald Freudenberger 	kvfree(device_status);
165755d0a513SHarald Freudenberger 	return rc;
165855d0a513SHarald Freudenberger }
165955d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_findcard2);
166055d0a513SHarald Freudenberger 
zcrypt_ep11misc_exit(void)16617384eb72SHarald Freudenberger void __exit zcrypt_ep11misc_exit(void)
16627384eb72SHarald Freudenberger {
16637384eb72SHarald Freudenberger 	card_cache_free();
16647384eb72SHarald Freudenberger }
1665