1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Copyright IBM Corp. 2019 |
4 | * Author(s): Harald Freudenberger <freude@linux.ibm.com> |
5 | * |
6 | * Collection of EP11 misc functions used by zcrypt and pkey |
7 | */ |
8 | |
9 | #define KMSG_COMPONENT "zcrypt" |
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
11 | |
12 | #include <linux/init.h> |
13 | #include <linux/module.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/random.h> |
16 | #include <asm/zcrypt.h> |
17 | #include <asm/pkey.h> |
18 | #include <crypto/aes.h> |
19 | |
20 | #include "ap_bus.h" |
21 | #include "zcrypt_api.h" |
22 | #include "zcrypt_debug.h" |
23 | #include "zcrypt_msgtype6.h" |
24 | #include "zcrypt_ep11misc.h" |
25 | #include "zcrypt_ccamisc.h" |
26 | |
27 | #define EP11_PINBLOB_V1_BYTES 56 |
28 | |
29 | /* default iv used here */ |
30 | static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, |
31 | 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; |
32 | |
33 | /* ep11 card info cache */ |
34 | struct card_list_entry { |
35 | struct list_head list; |
36 | u16 cardnr; |
37 | struct ep11_card_info info; |
38 | }; |
39 | static LIST_HEAD(card_list); |
40 | static DEFINE_SPINLOCK(card_list_lock); |
41 | |
42 | static int card_cache_fetch(u16 cardnr, struct ep11_card_info *ci) |
43 | { |
44 | int rc = -ENOENT; |
45 | struct card_list_entry *ptr; |
46 | |
47 | spin_lock_bh(lock: &card_list_lock); |
48 | list_for_each_entry(ptr, &card_list, list) { |
49 | if (ptr->cardnr == cardnr) { |
50 | memcpy(ci, &ptr->info, sizeof(*ci)); |
51 | rc = 0; |
52 | break; |
53 | } |
54 | } |
55 | spin_unlock_bh(lock: &card_list_lock); |
56 | |
57 | return rc; |
58 | } |
59 | |
60 | static void card_cache_update(u16 cardnr, const struct ep11_card_info *ci) |
61 | { |
62 | int found = 0; |
63 | struct card_list_entry *ptr; |
64 | |
65 | spin_lock_bh(lock: &card_list_lock); |
66 | list_for_each_entry(ptr, &card_list, list) { |
67 | if (ptr->cardnr == cardnr) { |
68 | memcpy(&ptr->info, ci, sizeof(*ci)); |
69 | found = 1; |
70 | break; |
71 | } |
72 | } |
73 | if (!found) { |
74 | ptr = kmalloc(size: sizeof(*ptr), GFP_ATOMIC); |
75 | if (!ptr) { |
76 | spin_unlock_bh(lock: &card_list_lock); |
77 | return; |
78 | } |
79 | ptr->cardnr = cardnr; |
80 | memcpy(&ptr->info, ci, sizeof(*ci)); |
81 | list_add(new: &ptr->list, head: &card_list); |
82 | } |
83 | spin_unlock_bh(lock: &card_list_lock); |
84 | } |
85 | |
86 | static void card_cache_scrub(u16 cardnr) |
87 | { |
88 | struct card_list_entry *ptr; |
89 | |
90 | spin_lock_bh(lock: &card_list_lock); |
91 | list_for_each_entry(ptr, &card_list, list) { |
92 | if (ptr->cardnr == cardnr) { |
93 | list_del(entry: &ptr->list); |
94 | kfree(objp: ptr); |
95 | break; |
96 | } |
97 | } |
98 | spin_unlock_bh(lock: &card_list_lock); |
99 | } |
100 | |
101 | static void __exit card_cache_free(void) |
102 | { |
103 | struct card_list_entry *ptr, *pnext; |
104 | |
105 | spin_lock_bh(lock: &card_list_lock); |
106 | list_for_each_entry_safe(ptr, pnext, &card_list, list) { |
107 | list_del(entry: &ptr->list); |
108 | kfree(objp: ptr); |
109 | } |
110 | spin_unlock_bh(lock: &card_list_lock); |
111 | } |
112 | |
113 | static int ep11_kb_split(const u8 *kb, size_t kblen, u32 kbver, |
114 | struct ep11kblob_header **kbhdr, size_t *kbhdrsize, |
115 | u8 **kbpl, size_t *kbplsize) |
116 | { |
117 | struct ep11kblob_header *hdr = NULL; |
118 | size_t hdrsize, plsize = 0; |
119 | int rc = -EINVAL; |
120 | u8 *pl = NULL; |
121 | |
122 | if (kblen < sizeof(struct ep11kblob_header)) |
123 | goto out; |
124 | hdr = (struct ep11kblob_header *)kb; |
125 | |
126 | switch (kbver) { |
127 | case TOKVER_EP11_AES: |
128 | /* header overlays the payload */ |
129 | hdrsize = 0; |
130 | break; |
131 | case TOKVER_EP11_ECC_WITH_HEADER: |
132 | case TOKVER_EP11_AES_WITH_HEADER: |
133 | /* payload starts after the header */ |
134 | hdrsize = sizeof(struct ep11kblob_header); |
135 | break; |
136 | default: |
137 | goto out; |
138 | } |
139 | |
140 | plsize = kblen - hdrsize; |
141 | pl = (u8 *)kb + hdrsize; |
142 | |
143 | if (kbhdr) |
144 | *kbhdr = hdr; |
145 | if (kbhdrsize) |
146 | *kbhdrsize = hdrsize; |
147 | if (kbpl) |
148 | *kbpl = pl; |
149 | if (kbplsize) |
150 | *kbplsize = plsize; |
151 | |
152 | rc = 0; |
153 | out: |
154 | return rc; |
155 | } |
156 | |
157 | static int ep11_kb_decode(const u8 *kb, size_t kblen, |
158 | struct ep11kblob_header **kbhdr, size_t *kbhdrsize, |
159 | struct ep11keyblob **kbpl, size_t *kbplsize) |
160 | { |
161 | struct ep11kblob_header *tmph, *hdr = NULL; |
162 | size_t hdrsize = 0, plsize = 0; |
163 | struct ep11keyblob *pl = NULL; |
164 | int rc = -EINVAL; |
165 | u8 *tmpp; |
166 | |
167 | if (kblen < sizeof(struct ep11kblob_header)) |
168 | goto out; |
169 | tmph = (struct ep11kblob_header *)kb; |
170 | |
171 | if (tmph->type != TOKTYPE_NON_CCA && |
172 | tmph->len > kblen) |
173 | goto out; |
174 | |
175 | if (ep11_kb_split(kb, kblen, kbver: tmph->version, |
176 | kbhdr: &hdr, kbhdrsize: &hdrsize, kbpl: &tmpp, kbplsize: &plsize)) |
177 | goto out; |
178 | |
179 | if (plsize < sizeof(struct ep11keyblob)) |
180 | goto out; |
181 | |
182 | if (!is_ep11_keyblob(key: tmpp)) |
183 | goto out; |
184 | |
185 | pl = (struct ep11keyblob *)tmpp; |
186 | plsize = hdr->len - hdrsize; |
187 | |
188 | if (kbhdr) |
189 | *kbhdr = hdr; |
190 | if (kbhdrsize) |
191 | *kbhdrsize = hdrsize; |
192 | if (kbpl) |
193 | *kbpl = pl; |
194 | if (kbplsize) |
195 | *kbplsize = plsize; |
196 | |
197 | rc = 0; |
198 | out: |
199 | return rc; |
200 | } |
201 | |
202 | /* |
203 | * For valid ep11 keyblobs, returns a reference to the wrappingkey verification |
204 | * pattern. Otherwise NULL. |
205 | */ |
206 | const u8 *ep11_kb_wkvp(const u8 *keyblob, size_t keybloblen) |
207 | { |
208 | struct ep11keyblob *kb; |
209 | |
210 | if (ep11_kb_decode(kb: keyblob, kblen: keybloblen, NULL, NULL, kbpl: &kb, NULL)) |
211 | return NULL; |
212 | return kb->wkvp; |
213 | } |
214 | EXPORT_SYMBOL(ep11_kb_wkvp); |
215 | |
216 | /* |
217 | * Simple check if the key blob is a valid EP11 AES key blob with header. |
218 | */ |
219 | int ep11_check_aes_key_with_hdr(debug_info_t *dbg, int dbflvl, |
220 | const u8 *key, size_t keylen, int checkcpacfexp) |
221 | { |
222 | struct ep11kblob_header *hdr = (struct ep11kblob_header *)key; |
223 | struct ep11keyblob *kb = (struct ep11keyblob *)(key + sizeof(*hdr)); |
224 | |
225 | #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) |
226 | |
227 | if (keylen < sizeof(*hdr) + sizeof(*kb)) { |
228 | DBF("%s key check failed, keylen %zu < %zu\n" , |
229 | __func__, keylen, sizeof(*hdr) + sizeof(*kb)); |
230 | return -EINVAL; |
231 | } |
232 | |
233 | if (hdr->type != TOKTYPE_NON_CCA) { |
234 | if (dbg) |
235 | DBF("%s key check failed, type 0x%02x != 0x%02x\n" , |
236 | __func__, (int)hdr->type, TOKTYPE_NON_CCA); |
237 | return -EINVAL; |
238 | } |
239 | if (hdr->hver != 0x00) { |
240 | if (dbg) |
241 | DBF("%s key check failed, header version 0x%02x != 0x00\n" , |
242 | __func__, (int)hdr->hver); |
243 | return -EINVAL; |
244 | } |
245 | if (hdr->version != TOKVER_EP11_AES_WITH_HEADER) { |
246 | if (dbg) |
247 | DBF("%s key check failed, version 0x%02x != 0x%02x\n" , |
248 | __func__, (int)hdr->version, TOKVER_EP11_AES_WITH_HEADER); |
249 | return -EINVAL; |
250 | } |
251 | if (hdr->len > keylen) { |
252 | if (dbg) |
253 | DBF("%s key check failed, header len %d keylen %zu mismatch\n" , |
254 | __func__, (int)hdr->len, keylen); |
255 | return -EINVAL; |
256 | } |
257 | if (hdr->len < sizeof(*hdr) + sizeof(*kb)) { |
258 | if (dbg) |
259 | DBF("%s key check failed, header len %d < %zu\n" , |
260 | __func__, (int)hdr->len, sizeof(*hdr) + sizeof(*kb)); |
261 | return -EINVAL; |
262 | } |
263 | |
264 | if (kb->version != EP11_STRUCT_MAGIC) { |
265 | if (dbg) |
266 | DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n" , |
267 | __func__, (int)kb->version, EP11_STRUCT_MAGIC); |
268 | return -EINVAL; |
269 | } |
270 | if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) { |
271 | if (dbg) |
272 | DBF("%s key check failed, PKEY_EXTRACTABLE is off\n" , |
273 | __func__); |
274 | return -EINVAL; |
275 | } |
276 | |
277 | #undef DBF |
278 | |
279 | return 0; |
280 | } |
281 | EXPORT_SYMBOL(ep11_check_aes_key_with_hdr); |
282 | |
283 | /* |
284 | * Simple check if the key blob is a valid EP11 ECC key blob with header. |
285 | */ |
286 | int ep11_check_ecc_key_with_hdr(debug_info_t *dbg, int dbflvl, |
287 | const u8 *key, size_t keylen, int checkcpacfexp) |
288 | { |
289 | struct ep11kblob_header *hdr = (struct ep11kblob_header *)key; |
290 | struct ep11keyblob *kb = (struct ep11keyblob *)(key + sizeof(*hdr)); |
291 | |
292 | #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) |
293 | |
294 | if (keylen < sizeof(*hdr) + sizeof(*kb)) { |
295 | DBF("%s key check failed, keylen %zu < %zu\n" , |
296 | __func__, keylen, sizeof(*hdr) + sizeof(*kb)); |
297 | return -EINVAL; |
298 | } |
299 | |
300 | if (hdr->type != TOKTYPE_NON_CCA) { |
301 | if (dbg) |
302 | DBF("%s key check failed, type 0x%02x != 0x%02x\n" , |
303 | __func__, (int)hdr->type, TOKTYPE_NON_CCA); |
304 | return -EINVAL; |
305 | } |
306 | if (hdr->hver != 0x00) { |
307 | if (dbg) |
308 | DBF("%s key check failed, header version 0x%02x != 0x00\n" , |
309 | __func__, (int)hdr->hver); |
310 | return -EINVAL; |
311 | } |
312 | if (hdr->version != TOKVER_EP11_ECC_WITH_HEADER) { |
313 | if (dbg) |
314 | DBF("%s key check failed, version 0x%02x != 0x%02x\n" , |
315 | __func__, (int)hdr->version, TOKVER_EP11_ECC_WITH_HEADER); |
316 | return -EINVAL; |
317 | } |
318 | if (hdr->len > keylen) { |
319 | if (dbg) |
320 | DBF("%s key check failed, header len %d keylen %zu mismatch\n" , |
321 | __func__, (int)hdr->len, keylen); |
322 | return -EINVAL; |
323 | } |
324 | if (hdr->len < sizeof(*hdr) + sizeof(*kb)) { |
325 | if (dbg) |
326 | DBF("%s key check failed, header len %d < %zu\n" , |
327 | __func__, (int)hdr->len, sizeof(*hdr) + sizeof(*kb)); |
328 | return -EINVAL; |
329 | } |
330 | |
331 | if (kb->version != EP11_STRUCT_MAGIC) { |
332 | if (dbg) |
333 | DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n" , |
334 | __func__, (int)kb->version, EP11_STRUCT_MAGIC); |
335 | return -EINVAL; |
336 | } |
337 | if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) { |
338 | if (dbg) |
339 | DBF("%s key check failed, PKEY_EXTRACTABLE is off\n" , |
340 | __func__); |
341 | return -EINVAL; |
342 | } |
343 | |
344 | #undef DBF |
345 | |
346 | return 0; |
347 | } |
348 | EXPORT_SYMBOL(ep11_check_ecc_key_with_hdr); |
349 | |
350 | /* |
351 | * Simple check if the key blob is a valid EP11 AES key blob with |
352 | * the header in the session field (old style EP11 AES key). |
353 | */ |
354 | int ep11_check_aes_key(debug_info_t *dbg, int dbflvl, |
355 | const u8 *key, size_t keylen, int checkcpacfexp) |
356 | { |
357 | struct ep11keyblob *kb = (struct ep11keyblob *)key; |
358 | |
359 | #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) |
360 | |
361 | if (keylen < sizeof(*kb)) { |
362 | DBF("%s key check failed, keylen %zu < %zu\n" , |
363 | __func__, keylen, sizeof(*kb)); |
364 | return -EINVAL; |
365 | } |
366 | |
367 | if (kb->head.type != TOKTYPE_NON_CCA) { |
368 | if (dbg) |
369 | DBF("%s key check failed, type 0x%02x != 0x%02x\n" , |
370 | __func__, (int)kb->head.type, TOKTYPE_NON_CCA); |
371 | return -EINVAL; |
372 | } |
373 | if (kb->head.version != TOKVER_EP11_AES) { |
374 | if (dbg) |
375 | DBF("%s key check failed, version 0x%02x != 0x%02x\n" , |
376 | __func__, (int)kb->head.version, TOKVER_EP11_AES); |
377 | return -EINVAL; |
378 | } |
379 | if (kb->head.len > keylen) { |
380 | if (dbg) |
381 | DBF("%s key check failed, header len %d keylen %zu mismatch\n" , |
382 | __func__, (int)kb->head.len, keylen); |
383 | return -EINVAL; |
384 | } |
385 | if (kb->head.len < sizeof(*kb)) { |
386 | if (dbg) |
387 | DBF("%s key check failed, header len %d < %zu\n" , |
388 | __func__, (int)kb->head.len, sizeof(*kb)); |
389 | return -EINVAL; |
390 | } |
391 | |
392 | if (kb->version != EP11_STRUCT_MAGIC) { |
393 | if (dbg) |
394 | DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n" , |
395 | __func__, (int)kb->version, EP11_STRUCT_MAGIC); |
396 | return -EINVAL; |
397 | } |
398 | if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) { |
399 | if (dbg) |
400 | DBF("%s key check failed, PKEY_EXTRACTABLE is off\n" , |
401 | __func__); |
402 | return -EINVAL; |
403 | } |
404 | |
405 | #undef DBF |
406 | |
407 | return 0; |
408 | } |
409 | EXPORT_SYMBOL(ep11_check_aes_key); |
410 | |
411 | /* |
412 | * Allocate and prepare ep11 cprb plus additional payload. |
413 | */ |
414 | static inline struct ep11_cprb *alloc_cprb(size_t payload_len) |
415 | { |
416 | size_t len = sizeof(struct ep11_cprb) + payload_len; |
417 | struct ep11_cprb *cprb; |
418 | |
419 | cprb = kzalloc(size: len, GFP_KERNEL); |
420 | if (!cprb) |
421 | return NULL; |
422 | |
423 | cprb->cprb_len = sizeof(struct ep11_cprb); |
424 | cprb->cprb_ver_id = 0x04; |
425 | memcpy(cprb->func_id, "T4" , 2); |
426 | cprb->ret_code = 0xFFFFFFFF; |
427 | cprb->payload_len = payload_len; |
428 | |
429 | return cprb; |
430 | } |
431 | |
432 | /* |
433 | * Some helper functions related to ASN1 encoding. |
434 | * Limited to length info <= 2 byte. |
435 | */ |
436 | |
437 | #define ASN1TAGLEN(x) (2 + (x) + ((x) > 127 ? 1 : 0) + ((x) > 255 ? 1 : 0)) |
438 | |
439 | static int asn1tag_write(u8 *ptr, u8 tag, const u8 *pvalue, u16 valuelen) |
440 | { |
441 | ptr[0] = tag; |
442 | if (valuelen > 255) { |
443 | ptr[1] = 0x82; |
444 | *((u16 *)(ptr + 2)) = valuelen; |
445 | memcpy(ptr + 4, pvalue, valuelen); |
446 | return 4 + valuelen; |
447 | } |
448 | if (valuelen > 127) { |
449 | ptr[1] = 0x81; |
450 | ptr[2] = (u8)valuelen; |
451 | memcpy(ptr + 3, pvalue, valuelen); |
452 | return 3 + valuelen; |
453 | } |
454 | ptr[1] = (u8)valuelen; |
455 | memcpy(ptr + 2, pvalue, valuelen); |
456 | return 2 + valuelen; |
457 | } |
458 | |
459 | /* EP11 payload > 127 bytes starts with this struct */ |
460 | struct pl_head { |
461 | u8 tag; |
462 | u8 lenfmt; |
463 | u16 len; |
464 | u8 func_tag; |
465 | u8 func_len; |
466 | u32 func; |
467 | u8 dom_tag; |
468 | u8 dom_len; |
469 | u32 dom; |
470 | } __packed; |
471 | |
472 | /* prep ep11 payload head helper function */ |
473 | static inline void prep_head(struct pl_head *h, |
474 | size_t pl_size, int api, int func) |
475 | { |
476 | h->tag = 0x30; |
477 | h->lenfmt = 0x82; |
478 | h->len = pl_size - 4; |
479 | h->func_tag = 0x04; |
480 | h->func_len = sizeof(u32); |
481 | h->func = (api << 16) + func; |
482 | h->dom_tag = 0x04; |
483 | h->dom_len = sizeof(u32); |
484 | } |
485 | |
486 | /* prep urb helper function */ |
487 | static inline void prep_urb(struct ep11_urb *u, |
488 | struct ep11_target_dev *t, int nt, |
489 | struct ep11_cprb *req, size_t req_len, |
490 | struct ep11_cprb *rep, size_t rep_len) |
491 | { |
492 | u->targets = (u8 __user *)t; |
493 | u->targets_num = nt; |
494 | u->req = (u8 __user *)req; |
495 | u->req_len = req_len; |
496 | u->resp = (u8 __user *)rep; |
497 | u->resp_len = rep_len; |
498 | } |
499 | |
500 | /* Check ep11 reply payload, return 0 or suggested errno value. */ |
501 | static int check_reply_pl(const u8 *pl, const char *func) |
502 | { |
503 | int len; |
504 | u32 ret; |
505 | |
506 | /* start tag */ |
507 | if (*pl++ != 0x30) { |
508 | ZCRYPT_DBF_ERR("%s reply start tag mismatch\n" , func); |
509 | return -EIO; |
510 | } |
511 | |
512 | /* payload length format */ |
513 | if (*pl < 127) { |
514 | len = *pl; |
515 | pl++; |
516 | } else if (*pl == 0x81) { |
517 | pl++; |
518 | len = *pl; |
519 | pl++; |
520 | } else if (*pl == 0x82) { |
521 | pl++; |
522 | len = *((u16 *)pl); |
523 | pl += 2; |
524 | } else { |
525 | ZCRYPT_DBF_ERR("%s reply start tag lenfmt mismatch 0x%02hhx\n" , |
526 | func, *pl); |
527 | return -EIO; |
528 | } |
529 | |
530 | /* len should cover at least 3 fields with 32 bit value each */ |
531 | if (len < 3 * 6) { |
532 | ZCRYPT_DBF_ERR("%s reply length %d too small\n" , func, len); |
533 | return -EIO; |
534 | } |
535 | |
536 | /* function tag, length and value */ |
537 | if (pl[0] != 0x04 || pl[1] != 0x04) { |
538 | ZCRYPT_DBF_ERR("%s function tag or length mismatch\n" , func); |
539 | return -EIO; |
540 | } |
541 | pl += 6; |
542 | |
543 | /* dom tag, length and value */ |
544 | if (pl[0] != 0x04 || pl[1] != 0x04) { |
545 | ZCRYPT_DBF_ERR("%s dom tag or length mismatch\n" , func); |
546 | return -EIO; |
547 | } |
548 | pl += 6; |
549 | |
550 | /* return value tag, length and value */ |
551 | if (pl[0] != 0x04 || pl[1] != 0x04) { |
552 | ZCRYPT_DBF_ERR("%s return value tag or length mismatch\n" , |
553 | func); |
554 | return -EIO; |
555 | } |
556 | pl += 2; |
557 | ret = *((u32 *)pl); |
558 | if (ret != 0) { |
559 | ZCRYPT_DBF_ERR("%s return value 0x%04x != 0\n" , func, ret); |
560 | return -EIO; |
561 | } |
562 | |
563 | return 0; |
564 | } |
565 | |
566 | /* |
567 | * Helper function which does an ep11 query with given query type. |
568 | */ |
569 | static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type, |
570 | size_t buflen, u8 *buf) |
571 | { |
572 | struct ep11_info_req_pl { |
573 | struct pl_head head; |
574 | u8 query_type_tag; |
575 | u8 query_type_len; |
576 | u32 query_type; |
577 | u8 query_subtype_tag; |
578 | u8 query_subtype_len; |
579 | u32 query_subtype; |
580 | } __packed * req_pl; |
581 | struct ep11_info_rep_pl { |
582 | struct pl_head head; |
583 | u8 rc_tag; |
584 | u8 rc_len; |
585 | u32 rc; |
586 | u8 data_tag; |
587 | u8 data_lenfmt; |
588 | u16 data_len; |
589 | } __packed * rep_pl; |
590 | struct ep11_cprb *req = NULL, *rep = NULL; |
591 | struct ep11_target_dev target; |
592 | struct ep11_urb *urb = NULL; |
593 | int api = EP11_API_V1, rc = -ENOMEM; |
594 | |
595 | /* request cprb and payload */ |
596 | req = alloc_cprb(payload_len: sizeof(struct ep11_info_req_pl)); |
597 | if (!req) |
598 | goto out; |
599 | req_pl = (struct ep11_info_req_pl *)(((u8 *)req) + sizeof(*req)); |
600 | prep_head(h: &req_pl->head, pl_size: sizeof(*req_pl), api, func: 38); /* get xcp info */ |
601 | req_pl->query_type_tag = 0x04; |
602 | req_pl->query_type_len = sizeof(u32); |
603 | req_pl->query_type = query_type; |
604 | req_pl->query_subtype_tag = 0x04; |
605 | req_pl->query_subtype_len = sizeof(u32); |
606 | |
607 | /* reply cprb and payload */ |
608 | rep = alloc_cprb(payload_len: sizeof(struct ep11_info_rep_pl) + buflen); |
609 | if (!rep) |
610 | goto out; |
611 | rep_pl = (struct ep11_info_rep_pl *)(((u8 *)rep) + sizeof(*rep)); |
612 | |
613 | /* urb and target */ |
614 | urb = kmalloc(sizeof(*urb), GFP_KERNEL); |
615 | if (!urb) |
616 | goto out; |
617 | target.ap_id = cardnr; |
618 | target.dom_id = domain; |
619 | prep_urb(urb, &target, 1, |
620 | req, sizeof(*req) + sizeof(*req_pl), |
621 | rep, sizeof(*rep) + sizeof(*rep_pl) + buflen); |
622 | |
623 | rc = zcrypt_send_ep11_cprb(urb); |
624 | if (rc) { |
625 | ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n" , |
626 | __func__, (int)cardnr, (int)domain, rc); |
627 | goto out; |
628 | } |
629 | |
630 | rc = check_reply_pl(pl: (u8 *)rep_pl, func: __func__); |
631 | if (rc) |
632 | goto out; |
633 | if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { |
634 | ZCRYPT_DBF_ERR("%s unknown reply data format\n" , __func__); |
635 | rc = -EIO; |
636 | goto out; |
637 | } |
638 | if (rep_pl->data_len > buflen) { |
639 | ZCRYPT_DBF_ERR("%s mismatch between reply data len and buffer len\n" , |
640 | __func__); |
641 | rc = -ENOSPC; |
642 | goto out; |
643 | } |
644 | |
645 | memcpy(buf, ((u8 *)rep_pl) + sizeof(*rep_pl), rep_pl->data_len); |
646 | |
647 | out: |
648 | kfree(objp: req); |
649 | kfree(objp: rep); |
650 | kfree(objp: urb); |
651 | return rc; |
652 | } |
653 | |
654 | /* |
655 | * Provide information about an EP11 card. |
656 | */ |
657 | int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify) |
658 | { |
659 | int rc; |
660 | struct ep11_module_query_info { |
661 | u32 API_ord_nr; |
662 | u32 firmware_id; |
663 | u8 FW_major_vers; |
664 | u8 FW_minor_vers; |
665 | u8 CSP_major_vers; |
666 | u8 CSP_minor_vers; |
667 | u8 fwid[32]; |
668 | u8 xcp_config_hash[32]; |
669 | u8 CSP_config_hash[32]; |
670 | u8 serial[16]; |
671 | u8 module_date_time[16]; |
672 | u64 op_mode; |
673 | u32 PKCS11_flags; |
674 | u32 ext_flags; |
675 | u32 domains; |
676 | u32 sym_state_bytes; |
677 | u32 digest_state_bytes; |
678 | u32 pin_blob_bytes; |
679 | u32 SPKI_bytes; |
680 | u32 priv_key_blob_bytes; |
681 | u32 sym_blob_bytes; |
682 | u32 max_payload_bytes; |
683 | u32 CP_profile_bytes; |
684 | u32 max_CP_index; |
685 | } __packed * pmqi = NULL; |
686 | |
687 | rc = card_cache_fetch(cardnr: card, ci: info); |
688 | if (rc || verify) { |
689 | pmqi = kmalloc(size: sizeof(*pmqi), GFP_KERNEL); |
690 | if (!pmqi) |
691 | return -ENOMEM; |
692 | rc = ep11_query_info(cardnr: card, domain: AUTOSEL_DOM, |
693 | query_type: 0x01 /* module info query */, |
694 | buflen: sizeof(*pmqi), buf: (u8 *)pmqi); |
695 | if (rc) { |
696 | if (rc == -ENODEV) |
697 | card_cache_scrub(cardnr: card); |
698 | goto out; |
699 | } |
700 | memset(info, 0, sizeof(*info)); |
701 | info->API_ord_nr = pmqi->API_ord_nr; |
702 | info->FW_version = |
703 | (pmqi->FW_major_vers << 8) + pmqi->FW_minor_vers; |
704 | memcpy(info->serial, pmqi->serial, sizeof(info->serial)); |
705 | info->op_mode = pmqi->op_mode; |
706 | card_cache_update(cardnr: card, ci: info); |
707 | } |
708 | |
709 | out: |
710 | kfree(objp: pmqi); |
711 | return rc; |
712 | } |
713 | EXPORT_SYMBOL(ep11_get_card_info); |
714 | |
715 | /* |
716 | * Provide information about a domain within an EP11 card. |
717 | */ |
718 | int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info) |
719 | { |
720 | int rc; |
721 | struct ep11_domain_query_info { |
722 | u32 dom_index; |
723 | u8 cur_WK_VP[32]; |
724 | u8 new_WK_VP[32]; |
725 | u32 dom_flags; |
726 | u64 op_mode; |
727 | } __packed * p_dom_info; |
728 | |
729 | p_dom_info = kmalloc(size: sizeof(*p_dom_info), GFP_KERNEL); |
730 | if (!p_dom_info) |
731 | return -ENOMEM; |
732 | |
733 | rc = ep11_query_info(cardnr: card, domain, query_type: 0x03 /* domain info query */, |
734 | buflen: sizeof(*p_dom_info), buf: (u8 *)p_dom_info); |
735 | if (rc) |
736 | goto out; |
737 | |
738 | memset(info, 0, sizeof(*info)); |
739 | info->cur_wk_state = '0'; |
740 | info->new_wk_state = '0'; |
741 | if (p_dom_info->dom_flags & 0x10 /* left imprint mode */) { |
742 | if (p_dom_info->dom_flags & 0x02 /* cur wk valid */) { |
743 | info->cur_wk_state = '1'; |
744 | memcpy(info->cur_wkvp, p_dom_info->cur_WK_VP, 32); |
745 | } |
746 | if (p_dom_info->dom_flags & 0x04 || /* new wk present */ |
747 | p_dom_info->dom_flags & 0x08 /* new wk committed */) { |
748 | info->new_wk_state = |
749 | p_dom_info->dom_flags & 0x08 ? '2' : '1'; |
750 | memcpy(info->new_wkvp, p_dom_info->new_WK_VP, 32); |
751 | } |
752 | } |
753 | info->op_mode = p_dom_info->op_mode; |
754 | |
755 | out: |
756 | kfree(objp: p_dom_info); |
757 | return rc; |
758 | } |
759 | EXPORT_SYMBOL(ep11_get_domain_info); |
760 | |
761 | /* |
762 | * Default EP11 AES key generate attributes, used when no keygenflags given: |
763 | * XCP_BLOB_ENCRYPT | XCP_BLOB_DECRYPT | XCP_BLOB_PROTKEY_EXTRACTABLE |
764 | */ |
765 | #define KEY_ATTR_DEFAULTS 0x00200c00 |
766 | |
767 | static int _ep11_genaeskey(u16 card, u16 domain, |
768 | u32 keybitsize, u32 keygenflags, |
769 | u8 *keybuf, size_t *keybufsize) |
770 | { |
771 | struct keygen_req_pl { |
772 | struct pl_head head; |
773 | u8 var_tag; |
774 | u8 var_len; |
775 | u32 var; |
776 | u8 keybytes_tag; |
777 | u8 keybytes_len; |
778 | u32 keybytes; |
779 | u8 mech_tag; |
780 | u8 mech_len; |
781 | u32 mech; |
782 | u8 attr_tag; |
783 | u8 attr_len; |
784 | u32 ; |
785 | u32 attr_bool_mask; |
786 | u32 attr_bool_bits; |
787 | u32 attr_val_len_type; |
788 | u32 attr_val_len_value; |
789 | /* followed by empty pin tag or empty pinblob tag */ |
790 | } __packed * req_pl; |
791 | struct keygen_rep_pl { |
792 | struct pl_head head; |
793 | u8 rc_tag; |
794 | u8 rc_len; |
795 | u32 rc; |
796 | u8 data_tag; |
797 | u8 data_lenfmt; |
798 | u16 data_len; |
799 | u8 data[512]; |
800 | } __packed * rep_pl; |
801 | struct ep11_cprb *req = NULL, *rep = NULL; |
802 | size_t req_pl_size, pinblob_size = 0; |
803 | struct ep11_target_dev target; |
804 | struct ep11_urb *urb = NULL; |
805 | int api, rc = -ENOMEM; |
806 | u8 *p; |
807 | |
808 | switch (keybitsize) { |
809 | case 128: |
810 | case 192: |
811 | case 256: |
812 | break; |
813 | default: |
814 | ZCRYPT_DBF_ERR("%s unknown/unsupported keybitsize %d\n" , |
815 | __func__, keybitsize); |
816 | rc = -EINVAL; |
817 | goto out; |
818 | } |
819 | |
820 | /* request cprb and payload */ |
821 | api = (!keygenflags || keygenflags & 0x00200000) ? |
822 | EP11_API_V4 : EP11_API_V1; |
823 | if (ap_is_se_guest()) { |
824 | /* |
825 | * genkey within SE environment requires API ordinal 6 |
826 | * with empty pinblob |
827 | */ |
828 | api = EP11_API_V6; |
829 | pinblob_size = EP11_PINBLOB_V1_BYTES; |
830 | } |
831 | req_pl_size = sizeof(struct keygen_req_pl) + ASN1TAGLEN(pinblob_size); |
832 | req = alloc_cprb(payload_len: req_pl_size); |
833 | if (!req) |
834 | goto out; |
835 | req_pl = (struct keygen_req_pl *)(((u8 *)req) + sizeof(*req)); |
836 | prep_head(h: &req_pl->head, pl_size: req_pl_size, api, func: 21); /* GenerateKey */ |
837 | req_pl->var_tag = 0x04; |
838 | req_pl->var_len = sizeof(u32); |
839 | req_pl->keybytes_tag = 0x04; |
840 | req_pl->keybytes_len = sizeof(u32); |
841 | req_pl->keybytes = keybitsize / 8; |
842 | req_pl->mech_tag = 0x04; |
843 | req_pl->mech_len = sizeof(u32); |
844 | req_pl->mech = 0x00001080; /* CKM_AES_KEY_GEN */ |
845 | req_pl->attr_tag = 0x04; |
846 | req_pl->attr_len = 5 * sizeof(u32); |
847 | req_pl->attr_header = 0x10010000; |
848 | req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; |
849 | req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; |
850 | req_pl->attr_val_len_type = 0x00000161; /* CKA_VALUE_LEN */ |
851 | req_pl->attr_val_len_value = keybitsize / 8; |
852 | p = ((u8 *)req_pl) + sizeof(*req_pl); |
853 | /* pin tag */ |
854 | *p++ = 0x04; |
855 | *p++ = pinblob_size; |
856 | |
857 | /* reply cprb and payload */ |
858 | rep = alloc_cprb(payload_len: sizeof(struct keygen_rep_pl)); |
859 | if (!rep) |
860 | goto out; |
861 | rep_pl = (struct keygen_rep_pl *)(((u8 *)rep) + sizeof(*rep)); |
862 | |
863 | /* urb and target */ |
864 | urb = kmalloc(sizeof(*urb), GFP_KERNEL); |
865 | if (!urb) |
866 | goto out; |
867 | target.ap_id = card; |
868 | target.dom_id = domain; |
869 | prep_urb(urb, &target, 1, |
870 | req, sizeof(*req) + req_pl_size, |
871 | rep, sizeof(*rep) + sizeof(*rep_pl)); |
872 | |
873 | rc = zcrypt_send_ep11_cprb(urb); |
874 | if (rc) { |
875 | ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n" , |
876 | __func__, (int)card, (int)domain, rc); |
877 | goto out; |
878 | } |
879 | |
880 | rc = check_reply_pl(pl: (u8 *)rep_pl, func: __func__); |
881 | if (rc) |
882 | goto out; |
883 | if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { |
884 | ZCRYPT_DBF_ERR("%s unknown reply data format\n" , __func__); |
885 | rc = -EIO; |
886 | goto out; |
887 | } |
888 | if (rep_pl->data_len > *keybufsize) { |
889 | ZCRYPT_DBF_ERR("%s mismatch reply data len / key buffer len\n" , |
890 | __func__); |
891 | rc = -ENOSPC; |
892 | goto out; |
893 | } |
894 | |
895 | /* copy key blob */ |
896 | memcpy(keybuf, rep_pl->data, rep_pl->data_len); |
897 | *keybufsize = rep_pl->data_len; |
898 | |
899 | out: |
900 | kfree(objp: req); |
901 | kfree(objp: rep); |
902 | kfree(objp: urb); |
903 | return rc; |
904 | } |
905 | |
906 | int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, |
907 | u8 *keybuf, size_t *keybufsize, u32 keybufver) |
908 | { |
909 | struct ep11kblob_header *hdr; |
910 | size_t hdr_size, pl_size; |
911 | u8 *pl; |
912 | int rc; |
913 | |
914 | switch (keybufver) { |
915 | case TOKVER_EP11_AES: |
916 | case TOKVER_EP11_AES_WITH_HEADER: |
917 | break; |
918 | default: |
919 | return -EINVAL; |
920 | } |
921 | |
922 | rc = ep11_kb_split(kb: keybuf, kblen: *keybufsize, kbver: keybufver, |
923 | kbhdr: &hdr, kbhdrsize: &hdr_size, kbpl: &pl, kbplsize: &pl_size); |
924 | if (rc) |
925 | return rc; |
926 | |
927 | rc = _ep11_genaeskey(card, domain, keybitsize, keygenflags, |
928 | keybuf: pl, keybufsize: &pl_size); |
929 | if (rc) |
930 | return rc; |
931 | |
932 | *keybufsize = hdr_size + pl_size; |
933 | |
934 | /* update header information */ |
935 | hdr->type = TOKTYPE_NON_CCA; |
936 | hdr->len = *keybufsize; |
937 | hdr->version = keybufver; |
938 | hdr->bitlen = keybitsize; |
939 | |
940 | return 0; |
941 | } |
942 | EXPORT_SYMBOL(ep11_genaeskey); |
943 | |
944 | static int ep11_cryptsingle(u16 card, u16 domain, |
945 | u16 mode, u32 mech, const u8 *iv, |
946 | const u8 *key, size_t keysize, |
947 | const u8 *inbuf, size_t inbufsize, |
948 | u8 *outbuf, size_t *outbufsize) |
949 | { |
950 | struct crypt_req_pl { |
951 | struct pl_head head; |
952 | u8 var_tag; |
953 | u8 var_len; |
954 | u32 var; |
955 | u8 mech_tag; |
956 | u8 mech_len; |
957 | u32 mech; |
958 | /* |
959 | * maybe followed by iv data |
960 | * followed by key tag + key blob |
961 | * followed by plaintext tag + plaintext |
962 | */ |
963 | } __packed * req_pl; |
964 | struct crypt_rep_pl { |
965 | struct pl_head head; |
966 | u8 rc_tag; |
967 | u8 rc_len; |
968 | u32 rc; |
969 | u8 data_tag; |
970 | u8 data_lenfmt; |
971 | /* data follows */ |
972 | } __packed * rep_pl; |
973 | struct ep11_cprb *req = NULL, *rep = NULL; |
974 | struct ep11_target_dev target; |
975 | struct ep11_urb *urb = NULL; |
976 | size_t req_pl_size, rep_pl_size; |
977 | int n, api = EP11_API_V1, rc = -ENOMEM; |
978 | u8 *p; |
979 | |
980 | /* the simple asn1 coding used has length limits */ |
981 | if (keysize > 0xFFFF || inbufsize > 0xFFFF) |
982 | return -EINVAL; |
983 | |
984 | /* request cprb and payload */ |
985 | req_pl_size = sizeof(struct crypt_req_pl) + (iv ? 16 : 0) |
986 | + ASN1TAGLEN(keysize) + ASN1TAGLEN(inbufsize); |
987 | req = alloc_cprb(payload_len: req_pl_size); |
988 | if (!req) |
989 | goto out; |
990 | req_pl = (struct crypt_req_pl *)(((u8 *)req) + sizeof(*req)); |
991 | prep_head(h: &req_pl->head, pl_size: req_pl_size, api, func: (mode ? 20 : 19)); |
992 | req_pl->var_tag = 0x04; |
993 | req_pl->var_len = sizeof(u32); |
994 | /* mech is mech + mech params (iv here) */ |
995 | req_pl->mech_tag = 0x04; |
996 | req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0); |
997 | req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */ |
998 | p = ((u8 *)req_pl) + sizeof(*req_pl); |
999 | if (iv) { |
1000 | memcpy(p, iv, 16); |
1001 | p += 16; |
1002 | } |
1003 | /* key and input data */ |
1004 | p += asn1tag_write(ptr: p, tag: 0x04, pvalue: key, valuelen: keysize); |
1005 | p += asn1tag_write(ptr: p, tag: 0x04, pvalue: inbuf, valuelen: inbufsize); |
1006 | |
1007 | /* reply cprb and payload, assume out data size <= in data size + 32 */ |
1008 | rep_pl_size = sizeof(struct crypt_rep_pl) + ASN1TAGLEN(inbufsize + 32); |
1009 | rep = alloc_cprb(payload_len: rep_pl_size); |
1010 | if (!rep) |
1011 | goto out; |
1012 | rep_pl = (struct crypt_rep_pl *)(((u8 *)rep) + sizeof(*rep)); |
1013 | |
1014 | /* urb and target */ |
1015 | urb = kmalloc(sizeof(*urb), GFP_KERNEL); |
1016 | if (!urb) |
1017 | goto out; |
1018 | target.ap_id = card; |
1019 | target.dom_id = domain; |
1020 | prep_urb(urb, &target, 1, |
1021 | req, sizeof(*req) + req_pl_size, |
1022 | rep, sizeof(*rep) + rep_pl_size); |
1023 | |
1024 | rc = zcrypt_send_ep11_cprb(urb); |
1025 | if (rc) { |
1026 | ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n" , |
1027 | __func__, (int)card, (int)domain, rc); |
1028 | goto out; |
1029 | } |
1030 | |
1031 | rc = check_reply_pl(pl: (u8 *)rep_pl, func: __func__); |
1032 | if (rc) |
1033 | goto out; |
1034 | if (rep_pl->data_tag != 0x04) { |
1035 | ZCRYPT_DBF_ERR("%s unknown reply data format\n" , __func__); |
1036 | rc = -EIO; |
1037 | goto out; |
1038 | } |
1039 | p = ((u8 *)rep_pl) + sizeof(*rep_pl); |
1040 | if (rep_pl->data_lenfmt <= 127) { |
1041 | n = rep_pl->data_lenfmt; |
1042 | } else if (rep_pl->data_lenfmt == 0x81) { |
1043 | n = *p++; |
1044 | } else if (rep_pl->data_lenfmt == 0x82) { |
1045 | n = *((u16 *)p); |
1046 | p += 2; |
1047 | } else { |
1048 | ZCRYPT_DBF_ERR("%s unknown reply data length format 0x%02hhx\n" , |
1049 | __func__, rep_pl->data_lenfmt); |
1050 | rc = -EIO; |
1051 | goto out; |
1052 | } |
1053 | if (n > *outbufsize) { |
1054 | ZCRYPT_DBF_ERR("%s mismatch reply data len %d / output buffer %zu\n" , |
1055 | __func__, n, *outbufsize); |
1056 | rc = -ENOSPC; |
1057 | goto out; |
1058 | } |
1059 | |
1060 | memcpy(outbuf, p, n); |
1061 | *outbufsize = n; |
1062 | |
1063 | out: |
1064 | kfree(objp: req); |
1065 | kfree(objp: rep); |
1066 | kfree(objp: urb); |
1067 | return rc; |
1068 | } |
1069 | |
1070 | static int _ep11_unwrapkey(u16 card, u16 domain, |
1071 | const u8 *kek, size_t keksize, |
1072 | const u8 *enckey, size_t enckeysize, |
1073 | u32 mech, const u8 *iv, |
1074 | u32 keybitsize, u32 keygenflags, |
1075 | u8 *keybuf, size_t *keybufsize) |
1076 | { |
1077 | struct uw_req_pl { |
1078 | struct pl_head head; |
1079 | u8 attr_tag; |
1080 | u8 attr_len; |
1081 | u32 ; |
1082 | u32 attr_bool_mask; |
1083 | u32 attr_bool_bits; |
1084 | u32 attr_key_type; |
1085 | u32 attr_key_type_value; |
1086 | u32 attr_val_len; |
1087 | u32 attr_val_len_value; |
1088 | u8 mech_tag; |
1089 | u8 mech_len; |
1090 | u32 mech; |
1091 | /* |
1092 | * maybe followed by iv data |
1093 | * followed by kek tag + kek blob |
1094 | * followed by empty mac tag |
1095 | * followed by empty pin tag or empty pinblob tag |
1096 | * followed by encryted key tag + bytes |
1097 | */ |
1098 | } __packed * req_pl; |
1099 | struct uw_rep_pl { |
1100 | struct pl_head head; |
1101 | u8 rc_tag; |
1102 | u8 rc_len; |
1103 | u32 rc; |
1104 | u8 data_tag; |
1105 | u8 data_lenfmt; |
1106 | u16 data_len; |
1107 | u8 data[512]; |
1108 | } __packed * rep_pl; |
1109 | struct ep11_cprb *req = NULL, *rep = NULL; |
1110 | size_t req_pl_size, pinblob_size = 0; |
1111 | struct ep11_target_dev target; |
1112 | struct ep11_urb *urb = NULL; |
1113 | int api, rc = -ENOMEM; |
1114 | u8 *p; |
1115 | |
1116 | /* request cprb and payload */ |
1117 | api = (!keygenflags || keygenflags & 0x00200000) ? |
1118 | EP11_API_V4 : EP11_API_V1; |
1119 | if (ap_is_se_guest()) { |
1120 | /* |
1121 | * unwrap within SE environment requires API ordinal 6 |
1122 | * with empty pinblob |
1123 | */ |
1124 | api = EP11_API_V6; |
1125 | pinblob_size = EP11_PINBLOB_V1_BYTES; |
1126 | } |
1127 | req_pl_size = sizeof(struct uw_req_pl) + (iv ? 16 : 0) |
1128 | + ASN1TAGLEN(keksize) + ASN1TAGLEN(0) |
1129 | + ASN1TAGLEN(pinblob_size) + ASN1TAGLEN(enckeysize); |
1130 | req = alloc_cprb(payload_len: req_pl_size); |
1131 | if (!req) |
1132 | goto out; |
1133 | req_pl = (struct uw_req_pl *)(((u8 *)req) + sizeof(*req)); |
1134 | prep_head(h: &req_pl->head, pl_size: req_pl_size, api, func: 34); /* UnwrapKey */ |
1135 | req_pl->attr_tag = 0x04; |
1136 | req_pl->attr_len = 7 * sizeof(u32); |
1137 | req_pl->attr_header = 0x10020000; |
1138 | req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; |
1139 | req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; |
1140 | req_pl->attr_key_type = 0x00000100; /* CKA_KEY_TYPE */ |
1141 | req_pl->attr_key_type_value = 0x0000001f; /* CKK_AES */ |
1142 | req_pl->attr_val_len = 0x00000161; /* CKA_VALUE_LEN */ |
1143 | req_pl->attr_val_len_value = keybitsize / 8; |
1144 | /* mech is mech + mech params (iv here) */ |
1145 | req_pl->mech_tag = 0x04; |
1146 | req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0); |
1147 | req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */ |
1148 | p = ((u8 *)req_pl) + sizeof(*req_pl); |
1149 | if (iv) { |
1150 | memcpy(p, iv, 16); |
1151 | p += 16; |
1152 | } |
1153 | /* kek */ |
1154 | p += asn1tag_write(ptr: p, tag: 0x04, pvalue: kek, valuelen: keksize); |
1155 | /* empty mac key tag */ |
1156 | *p++ = 0x04; |
1157 | *p++ = 0; |
1158 | /* pin tag */ |
1159 | *p++ = 0x04; |
1160 | *p++ = pinblob_size; |
1161 | p += pinblob_size; |
1162 | /* encrypted key value tag and bytes */ |
1163 | p += asn1tag_write(ptr: p, tag: 0x04, pvalue: enckey, valuelen: enckeysize); |
1164 | |
1165 | /* reply cprb and payload */ |
1166 | rep = alloc_cprb(payload_len: sizeof(struct uw_rep_pl)); |
1167 | if (!rep) |
1168 | goto out; |
1169 | rep_pl = (struct uw_rep_pl *)(((u8 *)rep) + sizeof(*rep)); |
1170 | |
1171 | /* urb and target */ |
1172 | urb = kmalloc(sizeof(*urb), GFP_KERNEL); |
1173 | if (!urb) |
1174 | goto out; |
1175 | target.ap_id = card; |
1176 | target.dom_id = domain; |
1177 | prep_urb(urb, &target, 1, |
1178 | req, sizeof(*req) + req_pl_size, |
1179 | rep, sizeof(*rep) + sizeof(*rep_pl)); |
1180 | |
1181 | rc = zcrypt_send_ep11_cprb(urb); |
1182 | if (rc) { |
1183 | ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n" , |
1184 | __func__, (int)card, (int)domain, rc); |
1185 | goto out; |
1186 | } |
1187 | |
1188 | rc = check_reply_pl(pl: (u8 *)rep_pl, func: __func__); |
1189 | if (rc) |
1190 | goto out; |
1191 | if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { |
1192 | ZCRYPT_DBF_ERR("%s unknown reply data format\n" , __func__); |
1193 | rc = -EIO; |
1194 | goto out; |
1195 | } |
1196 | if (rep_pl->data_len > *keybufsize) { |
1197 | ZCRYPT_DBF_ERR("%s mismatch reply data len / key buffer len\n" , |
1198 | __func__); |
1199 | rc = -ENOSPC; |
1200 | goto out; |
1201 | } |
1202 | |
1203 | /* copy key blob */ |
1204 | memcpy(keybuf, rep_pl->data, rep_pl->data_len); |
1205 | *keybufsize = rep_pl->data_len; |
1206 | |
1207 | out: |
1208 | kfree(objp: req); |
1209 | kfree(objp: rep); |
1210 | kfree(objp: urb); |
1211 | return rc; |
1212 | } |
1213 | |
1214 | static int ep11_unwrapkey(u16 card, u16 domain, |
1215 | const u8 *kek, size_t keksize, |
1216 | const u8 *enckey, size_t enckeysize, |
1217 | u32 mech, const u8 *iv, |
1218 | u32 keybitsize, u32 keygenflags, |
1219 | u8 *keybuf, size_t *keybufsize, |
1220 | u8 keybufver) |
1221 | { |
1222 | struct ep11kblob_header *hdr; |
1223 | size_t hdr_size, pl_size; |
1224 | u8 *pl; |
1225 | int rc; |
1226 | |
1227 | rc = ep11_kb_split(kb: keybuf, kblen: *keybufsize, kbver: keybufver, |
1228 | kbhdr: &hdr, kbhdrsize: &hdr_size, kbpl: &pl, kbplsize: &pl_size); |
1229 | if (rc) |
1230 | return rc; |
1231 | |
1232 | rc = _ep11_unwrapkey(card, domain, kek, keksize, enckey, enckeysize, |
1233 | mech, iv, keybitsize, keygenflags, |
1234 | keybuf: pl, keybufsize: &pl_size); |
1235 | if (rc) |
1236 | return rc; |
1237 | |
1238 | *keybufsize = hdr_size + pl_size; |
1239 | |
1240 | /* update header information */ |
1241 | hdr = (struct ep11kblob_header *)keybuf; |
1242 | hdr->type = TOKTYPE_NON_CCA; |
1243 | hdr->len = *keybufsize; |
1244 | hdr->version = keybufver; |
1245 | hdr->bitlen = keybitsize; |
1246 | |
1247 | return 0; |
1248 | } |
1249 | |
1250 | static int _ep11_wrapkey(u16 card, u16 domain, |
1251 | const u8 *key, size_t keysize, |
1252 | u32 mech, const u8 *iv, |
1253 | u8 *databuf, size_t *datasize) |
1254 | { |
1255 | struct wk_req_pl { |
1256 | struct pl_head head; |
1257 | u8 var_tag; |
1258 | u8 var_len; |
1259 | u32 var; |
1260 | u8 mech_tag; |
1261 | u8 mech_len; |
1262 | u32 mech; |
1263 | /* |
1264 | * followed by iv data |
1265 | * followed by key tag + key blob |
1266 | * followed by dummy kek param |
1267 | * followed by dummy mac param |
1268 | */ |
1269 | } __packed * req_pl; |
1270 | struct wk_rep_pl { |
1271 | struct pl_head head; |
1272 | u8 rc_tag; |
1273 | u8 rc_len; |
1274 | u32 rc; |
1275 | u8 data_tag; |
1276 | u8 data_lenfmt; |
1277 | u16 data_len; |
1278 | u8 data[1024]; |
1279 | } __packed * rep_pl; |
1280 | struct ep11_cprb *req = NULL, *rep = NULL; |
1281 | struct ep11_target_dev target; |
1282 | struct ep11_urb *urb = NULL; |
1283 | size_t req_pl_size; |
1284 | int api, rc = -ENOMEM; |
1285 | u8 *p; |
1286 | |
1287 | /* request cprb and payload */ |
1288 | req_pl_size = sizeof(struct wk_req_pl) + (iv ? 16 : 0) |
1289 | + ASN1TAGLEN(keysize) + 4; |
1290 | req = alloc_cprb(payload_len: req_pl_size); |
1291 | if (!req) |
1292 | goto out; |
1293 | if (!mech || mech == 0x80060001) |
1294 | req->flags |= 0x20; /* CPACF_WRAP needs special bit */ |
1295 | req_pl = (struct wk_req_pl *)(((u8 *)req) + sizeof(*req)); |
1296 | api = (!mech || mech == 0x80060001) ? /* CKM_IBM_CPACF_WRAP */ |
1297 | EP11_API_V4 : EP11_API_V1; |
1298 | prep_head(h: &req_pl->head, pl_size: req_pl_size, api, func: 33); /* WrapKey */ |
1299 | req_pl->var_tag = 0x04; |
1300 | req_pl->var_len = sizeof(u32); |
1301 | /* mech is mech + mech params (iv here) */ |
1302 | req_pl->mech_tag = 0x04; |
1303 | req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0); |
1304 | req_pl->mech = (mech ? mech : 0x80060001); /* CKM_IBM_CPACF_WRAP */ |
1305 | p = ((u8 *)req_pl) + sizeof(*req_pl); |
1306 | if (iv) { |
1307 | memcpy(p, iv, 16); |
1308 | p += 16; |
1309 | } |
1310 | /* key blob */ |
1311 | p += asn1tag_write(ptr: p, tag: 0x04, pvalue: key, valuelen: keysize); |
1312 | /* empty kek tag */ |
1313 | *p++ = 0x04; |
1314 | *p++ = 0; |
1315 | /* empty mac tag */ |
1316 | *p++ = 0x04; |
1317 | *p++ = 0; |
1318 | |
1319 | /* reply cprb and payload */ |
1320 | rep = alloc_cprb(payload_len: sizeof(struct wk_rep_pl)); |
1321 | if (!rep) |
1322 | goto out; |
1323 | rep_pl = (struct wk_rep_pl *)(((u8 *)rep) + sizeof(*rep)); |
1324 | |
1325 | /* urb and target */ |
1326 | urb = kmalloc(sizeof(*urb), GFP_KERNEL); |
1327 | if (!urb) |
1328 | goto out; |
1329 | target.ap_id = card; |
1330 | target.dom_id = domain; |
1331 | prep_urb(urb, &target, 1, |
1332 | req, sizeof(*req) + req_pl_size, |
1333 | rep, sizeof(*rep) + sizeof(*rep_pl)); |
1334 | |
1335 | rc = zcrypt_send_ep11_cprb(urb); |
1336 | if (rc) { |
1337 | ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n" , |
1338 | __func__, (int)card, (int)domain, rc); |
1339 | goto out; |
1340 | } |
1341 | |
1342 | rc = check_reply_pl(pl: (u8 *)rep_pl, func: __func__); |
1343 | if (rc) |
1344 | goto out; |
1345 | if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { |
1346 | ZCRYPT_DBF_ERR("%s unknown reply data format\n" , __func__); |
1347 | rc = -EIO; |
1348 | goto out; |
1349 | } |
1350 | if (rep_pl->data_len > *datasize) { |
1351 | ZCRYPT_DBF_ERR("%s mismatch reply data len / data buffer len\n" , |
1352 | __func__); |
1353 | rc = -ENOSPC; |
1354 | goto out; |
1355 | } |
1356 | |
1357 | /* copy the data from the cprb to the data buffer */ |
1358 | memcpy(databuf, rep_pl->data, rep_pl->data_len); |
1359 | *datasize = rep_pl->data_len; |
1360 | |
1361 | out: |
1362 | kfree(objp: req); |
1363 | kfree(objp: rep); |
1364 | kfree(objp: urb); |
1365 | return rc; |
1366 | } |
1367 | |
1368 | int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, |
1369 | const u8 *clrkey, u8 *keybuf, size_t *keybufsize, |
1370 | u32 keytype) |
1371 | { |
1372 | int rc; |
1373 | u8 encbuf[64], *kek = NULL; |
1374 | size_t clrkeylen, keklen, encbuflen = sizeof(encbuf); |
1375 | |
1376 | if (keybitsize == 128 || keybitsize == 192 || keybitsize == 256) { |
1377 | clrkeylen = keybitsize / 8; |
1378 | } else { |
1379 | ZCRYPT_DBF_ERR("%s unknown/unsupported keybitsize %d\n" , |
1380 | __func__, keybitsize); |
1381 | return -EINVAL; |
1382 | } |
1383 | |
1384 | /* allocate memory for the temp kek */ |
1385 | keklen = MAXEP11AESKEYBLOBSIZE; |
1386 | kek = kmalloc(size: keklen, GFP_ATOMIC); |
1387 | if (!kek) { |
1388 | rc = -ENOMEM; |
1389 | goto out; |
1390 | } |
1391 | |
1392 | /* Step 1: generate AES 256 bit random kek key */ |
1393 | rc = _ep11_genaeskey(card, domain, keybitsize: 256, |
1394 | keygenflags: 0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */ |
1395 | keybuf: kek, keybufsize: &keklen); |
1396 | if (rc) { |
1397 | ZCRYPT_DBF_ERR("%s generate kek key failed, rc=%d\n" , |
1398 | __func__, rc); |
1399 | goto out; |
1400 | } |
1401 | |
1402 | /* Step 2: encrypt clear key value with the kek key */ |
1403 | rc = ep11_cryptsingle(card, domain, mode: 0, mech: 0, iv: def_iv, key: kek, keysize: keklen, |
1404 | inbuf: clrkey, inbufsize: clrkeylen, outbuf: encbuf, outbufsize: &encbuflen); |
1405 | if (rc) { |
1406 | ZCRYPT_DBF_ERR("%s encrypting key value with kek key failed, rc=%d\n" , |
1407 | __func__, rc); |
1408 | goto out; |
1409 | } |
1410 | |
1411 | /* Step 3: import the encrypted key value as a new key */ |
1412 | rc = ep11_unwrapkey(card, domain, kek, keksize: keklen, |
1413 | enckey: encbuf, enckeysize: encbuflen, mech: 0, iv: def_iv, |
1414 | keybitsize, keygenflags: 0, keybuf, keybufsize, keybufver: keytype); |
1415 | if (rc) { |
1416 | ZCRYPT_DBF_ERR("%s importing key value as new key failed,, rc=%d\n" , |
1417 | __func__, rc); |
1418 | goto out; |
1419 | } |
1420 | |
1421 | out: |
1422 | kfree(objp: kek); |
1423 | return rc; |
1424 | } |
1425 | EXPORT_SYMBOL(ep11_clr2keyblob); |
1426 | |
1427 | int ep11_kblob2protkey(u16 card, u16 dom, |
1428 | const u8 *keyblob, size_t keybloblen, |
1429 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) |
1430 | { |
1431 | struct ep11kblob_header *hdr; |
1432 | struct ep11keyblob *key; |
1433 | size_t wkbuflen, keylen; |
1434 | struct wk_info { |
1435 | u16 version; |
1436 | u8 res1[16]; |
1437 | u32 pkeytype; |
1438 | u32 pkeybitsize; |
1439 | u64 pkeysize; |
1440 | u8 res2[8]; |
1441 | u8 pkey[]; |
1442 | } __packed * wki; |
1443 | u8 *wkbuf = NULL; |
1444 | int rc = -EIO; |
1445 | |
1446 | if (ep11_kb_decode(kb: (u8 *)keyblob, kblen: keybloblen, kbhdr: &hdr, NULL, kbpl: &key, kbplsize: &keylen)) |
1447 | return -EINVAL; |
1448 | |
1449 | if (hdr->version == TOKVER_EP11_AES) { |
1450 | /* wipe overlayed header */ |
1451 | memset(hdr, 0, sizeof(*hdr)); |
1452 | } |
1453 | /* !!! hdr is no longer a valid header !!! */ |
1454 | |
1455 | /* alloc temp working buffer */ |
1456 | wkbuflen = (keylen + AES_BLOCK_SIZE) & (~(AES_BLOCK_SIZE - 1)); |
1457 | wkbuf = kmalloc(size: wkbuflen, GFP_ATOMIC); |
1458 | if (!wkbuf) |
1459 | return -ENOMEM; |
1460 | |
1461 | /* ep11 secure key -> protected key + info */ |
1462 | rc = _ep11_wrapkey(card, domain: dom, key: (u8 *)key, keysize: keylen, |
1463 | mech: 0, iv: def_iv, databuf: wkbuf, datasize: &wkbuflen); |
1464 | if (rc) { |
1465 | ZCRYPT_DBF_ERR("%s rewrapping ep11 key to pkey failed, rc=%d\n" , |
1466 | __func__, rc); |
1467 | goto out; |
1468 | } |
1469 | wki = (struct wk_info *)wkbuf; |
1470 | |
1471 | /* check struct version and pkey type */ |
1472 | if (wki->version != 1 || wki->pkeytype < 1 || wki->pkeytype > 5) { |
1473 | ZCRYPT_DBF_ERR("%s wk info version %d or pkeytype %d mismatch.\n" , |
1474 | __func__, (int)wki->version, (int)wki->pkeytype); |
1475 | rc = -EIO; |
1476 | goto out; |
1477 | } |
1478 | |
1479 | /* check protected key type field */ |
1480 | switch (wki->pkeytype) { |
1481 | case 1: /* AES */ |
1482 | switch (wki->pkeysize) { |
1483 | case 16 + 32: |
1484 | /* AES 128 protected key */ |
1485 | if (protkeytype) |
1486 | *protkeytype = PKEY_KEYTYPE_AES_128; |
1487 | break; |
1488 | case 24 + 32: |
1489 | /* AES 192 protected key */ |
1490 | if (protkeytype) |
1491 | *protkeytype = PKEY_KEYTYPE_AES_192; |
1492 | break; |
1493 | case 32 + 32: |
1494 | /* AES 256 protected key */ |
1495 | if (protkeytype) |
1496 | *protkeytype = PKEY_KEYTYPE_AES_256; |
1497 | break; |
1498 | default: |
1499 | ZCRYPT_DBF_ERR("%s unknown/unsupported AES pkeysize %d\n" , |
1500 | __func__, (int)wki->pkeysize); |
1501 | rc = -EIO; |
1502 | goto out; |
1503 | } |
1504 | break; |
1505 | case 3: /* EC-P */ |
1506 | case 4: /* EC-ED */ |
1507 | case 5: /* EC-BP */ |
1508 | if (protkeytype) |
1509 | *protkeytype = PKEY_KEYTYPE_ECC; |
1510 | break; |
1511 | case 2: /* TDES */ |
1512 | default: |
1513 | ZCRYPT_DBF_ERR("%s unknown/unsupported key type %d\n" , |
1514 | __func__, (int)wki->pkeytype); |
1515 | rc = -EIO; |
1516 | goto out; |
1517 | } |
1518 | |
1519 | /* copy the translated protected key */ |
1520 | if (wki->pkeysize > *protkeylen) { |
1521 | ZCRYPT_DBF_ERR("%s wk info pkeysize %llu > protkeysize %u\n" , |
1522 | __func__, wki->pkeysize, *protkeylen); |
1523 | rc = -EINVAL; |
1524 | goto out; |
1525 | } |
1526 | memcpy(protkey, wki->pkey, wki->pkeysize); |
1527 | *protkeylen = wki->pkeysize; |
1528 | |
1529 | out: |
1530 | kfree(objp: wkbuf); |
1531 | return rc; |
1532 | } |
1533 | EXPORT_SYMBOL(ep11_kblob2protkey); |
1534 | |
1535 | int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain, |
1536 | int minhwtype, int minapi, const u8 *wkvp) |
1537 | { |
1538 | struct zcrypt_device_status_ext *device_status; |
1539 | u32 *_apqns = NULL, _nr_apqns = 0; |
1540 | int i, card, dom, rc = -ENOMEM; |
1541 | struct ep11_domain_info edi; |
1542 | struct ep11_card_info eci; |
1543 | |
1544 | /* fetch status of all crypto cards */ |
1545 | device_status = kvmalloc_array(MAX_ZDEV_ENTRIES_EXT, |
1546 | sizeof(struct zcrypt_device_status_ext), |
1547 | GFP_KERNEL); |
1548 | if (!device_status) |
1549 | return -ENOMEM; |
1550 | zcrypt_device_status_mask_ext(devstatus: device_status); |
1551 | |
1552 | /* allocate 1k space for up to 256 apqns */ |
1553 | _apqns = kmalloc_array(n: 256, size: sizeof(u32), GFP_KERNEL); |
1554 | if (!_apqns) { |
1555 | kvfree(addr: device_status); |
1556 | return -ENOMEM; |
1557 | } |
1558 | |
1559 | /* walk through all the crypto apqnss */ |
1560 | for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { |
1561 | card = AP_QID_CARD(device_status[i].qid); |
1562 | dom = AP_QID_QUEUE(device_status[i].qid); |
1563 | /* check online state */ |
1564 | if (!device_status[i].online) |
1565 | continue; |
1566 | /* check for ep11 functions */ |
1567 | if (!(device_status[i].functions & 0x01)) |
1568 | continue; |
1569 | /* check cardnr */ |
1570 | if (cardnr != 0xFFFF && card != cardnr) |
1571 | continue; |
1572 | /* check domain */ |
1573 | if (domain != 0xFFFF && dom != domain) |
1574 | continue; |
1575 | /* check min hardware type */ |
1576 | if (minhwtype && device_status[i].hwtype < minhwtype) |
1577 | continue; |
1578 | /* check min api version if given */ |
1579 | if (minapi > 0) { |
1580 | if (ep11_get_card_info(card, &eci, 0)) |
1581 | continue; |
1582 | if (minapi > eci.API_ord_nr) |
1583 | continue; |
1584 | } |
1585 | /* check wkvp if given */ |
1586 | if (wkvp) { |
1587 | if (ep11_get_domain_info(card, dom, &edi)) |
1588 | continue; |
1589 | if (edi.cur_wk_state != '1') |
1590 | continue; |
1591 | if (memcmp(p: wkvp, q: edi.cur_wkvp, size: 16)) |
1592 | continue; |
1593 | } |
1594 | /* apqn passed all filtering criterons, add to the array */ |
1595 | if (_nr_apqns < 256) |
1596 | _apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom); |
1597 | } |
1598 | |
1599 | /* nothing found ? */ |
1600 | if (!_nr_apqns) { |
1601 | kfree(objp: _apqns); |
1602 | rc = -ENODEV; |
1603 | } else { |
1604 | /* no re-allocation, simple return the _apqns array */ |
1605 | *apqns = _apqns; |
1606 | *nr_apqns = _nr_apqns; |
1607 | rc = 0; |
1608 | } |
1609 | |
1610 | kvfree(addr: device_status); |
1611 | return rc; |
1612 | } |
1613 | EXPORT_SYMBOL(ep11_findcard2); |
1614 | |
1615 | void __exit zcrypt_ep11misc_exit(void) |
1616 | { |
1617 | card_cache_free(); |
1618 | } |
1619 | |