1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Copyright IBM Corp. 2019 |
4 | * Author(s): Harald Freudenberger <freude@linux.ibm.com> |
5 | * Ingo Franzki <ifranzki@linux.ibm.com> |
6 | * |
7 | * Collection of CCA misc functions used by zcrypt and pkey |
8 | */ |
9 | |
10 | #define KMSG_COMPONENT "zcrypt" |
11 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
12 | |
13 | #include <linux/init.h> |
14 | #include <linux/module.h> |
15 | #include <linux/slab.h> |
16 | #include <linux/random.h> |
17 | #include <asm/zcrypt.h> |
18 | #include <asm/pkey.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_ccamisc.h" |
25 | |
26 | /* Size of parameter block used for all cca requests/replies */ |
27 | #define PARMBSIZE 512 |
28 | |
29 | /* Size of vardata block used for some of the cca requests/replies */ |
30 | #define VARDATASIZE 4096 |
31 | |
32 | struct cca_info_list_entry { |
33 | struct list_head list; |
34 | u16 cardnr; |
35 | u16 domain; |
36 | struct cca_info info; |
37 | }; |
38 | |
39 | /* a list with cca_info_list_entry entries */ |
40 | static LIST_HEAD(cca_info_list); |
41 | static DEFINE_SPINLOCK(cca_info_list_lock); |
42 | |
43 | /* |
44 | * Simple check if the token is a valid CCA secure AES data key |
45 | * token. If keybitsize is given, the bitsize of the key is |
46 | * also checked. Returns 0 on success or errno value on failure. |
47 | */ |
48 | int cca_check_secaeskeytoken(debug_info_t *dbg, int dbflvl, |
49 | const u8 *token, int keybitsize) |
50 | { |
51 | struct secaeskeytoken *t = (struct secaeskeytoken *)token; |
52 | |
53 | #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) |
54 | |
55 | if (t->type != TOKTYPE_CCA_INTERNAL) { |
56 | if (dbg) |
57 | DBF("%s token check failed, type 0x%02x != 0x%02x\n" , |
58 | __func__, (int)t->type, TOKTYPE_CCA_INTERNAL); |
59 | return -EINVAL; |
60 | } |
61 | if (t->version != TOKVER_CCA_AES) { |
62 | if (dbg) |
63 | DBF("%s token check failed, version 0x%02x != 0x%02x\n" , |
64 | __func__, (int)t->version, TOKVER_CCA_AES); |
65 | return -EINVAL; |
66 | } |
67 | if (keybitsize > 0 && t->bitsize != keybitsize) { |
68 | if (dbg) |
69 | DBF("%s token check failed, bitsize %d != %d\n" , |
70 | __func__, (int)t->bitsize, keybitsize); |
71 | return -EINVAL; |
72 | } |
73 | |
74 | #undef DBF |
75 | |
76 | return 0; |
77 | } |
78 | EXPORT_SYMBOL(cca_check_secaeskeytoken); |
79 | |
80 | /* |
81 | * Simple check if the token is a valid CCA secure AES cipher key |
82 | * token. If keybitsize is given, the bitsize of the key is |
83 | * also checked. If checkcpacfexport is enabled, the key is also |
84 | * checked for the export flag to allow CPACF export. |
85 | * Returns 0 on success or errno value on failure. |
86 | */ |
87 | int cca_check_secaescipherkey(debug_info_t *dbg, int dbflvl, |
88 | const u8 *token, int keybitsize, |
89 | int checkcpacfexport) |
90 | { |
91 | struct cipherkeytoken *t = (struct cipherkeytoken *)token; |
92 | bool keybitsizeok = true; |
93 | |
94 | #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) |
95 | |
96 | if (t->type != TOKTYPE_CCA_INTERNAL) { |
97 | if (dbg) |
98 | DBF("%s token check failed, type 0x%02x != 0x%02x\n" , |
99 | __func__, (int)t->type, TOKTYPE_CCA_INTERNAL); |
100 | return -EINVAL; |
101 | } |
102 | if (t->version != TOKVER_CCA_VLSC) { |
103 | if (dbg) |
104 | DBF("%s token check failed, version 0x%02x != 0x%02x\n" , |
105 | __func__, (int)t->version, TOKVER_CCA_VLSC); |
106 | return -EINVAL; |
107 | } |
108 | if (t->algtype != 0x02) { |
109 | if (dbg) |
110 | DBF("%s token check failed, algtype 0x%02x != 0x02\n" , |
111 | __func__, (int)t->algtype); |
112 | return -EINVAL; |
113 | } |
114 | if (t->keytype != 0x0001) { |
115 | if (dbg) |
116 | DBF("%s token check failed, keytype 0x%04x != 0x0001\n" , |
117 | __func__, (int)t->keytype); |
118 | return -EINVAL; |
119 | } |
120 | if (t->plfver != 0x00 && t->plfver != 0x01) { |
121 | if (dbg) |
122 | DBF("%s token check failed, unknown plfver 0x%02x\n" , |
123 | __func__, (int)t->plfver); |
124 | return -EINVAL; |
125 | } |
126 | if (t->wpllen != 512 && t->wpllen != 576 && t->wpllen != 640) { |
127 | if (dbg) |
128 | DBF("%s token check failed, unknown wpllen %d\n" , |
129 | __func__, (int)t->wpllen); |
130 | return -EINVAL; |
131 | } |
132 | if (keybitsize > 0) { |
133 | switch (keybitsize) { |
134 | case 128: |
135 | if (t->wpllen != (t->plfver ? 640 : 512)) |
136 | keybitsizeok = false; |
137 | break; |
138 | case 192: |
139 | if (t->wpllen != (t->plfver ? 640 : 576)) |
140 | keybitsizeok = false; |
141 | break; |
142 | case 256: |
143 | if (t->wpllen != 640) |
144 | keybitsizeok = false; |
145 | break; |
146 | default: |
147 | keybitsizeok = false; |
148 | break; |
149 | } |
150 | if (!keybitsizeok) { |
151 | if (dbg) |
152 | DBF("%s token check failed, bitsize %d\n" , |
153 | __func__, keybitsize); |
154 | return -EINVAL; |
155 | } |
156 | } |
157 | if (checkcpacfexport && !(t->kmf1 & KMF1_XPRT_CPAC)) { |
158 | if (dbg) |
159 | DBF("%s token check failed, XPRT_CPAC bit is 0\n" , |
160 | __func__); |
161 | return -EINVAL; |
162 | } |
163 | |
164 | #undef DBF |
165 | |
166 | return 0; |
167 | } |
168 | EXPORT_SYMBOL(cca_check_secaescipherkey); |
169 | |
170 | /* |
171 | * Simple check if the token is a valid CCA secure ECC private |
172 | * key token. Returns 0 on success or errno value on failure. |
173 | */ |
174 | int cca_check_sececckeytoken(debug_info_t *dbg, int dbflvl, |
175 | const u8 *token, size_t keysize, |
176 | int checkcpacfexport) |
177 | { |
178 | struct eccprivkeytoken *t = (struct eccprivkeytoken *)token; |
179 | |
180 | #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) |
181 | |
182 | if (t->type != TOKTYPE_CCA_INTERNAL_PKA) { |
183 | if (dbg) |
184 | DBF("%s token check failed, type 0x%02x != 0x%02x\n" , |
185 | __func__, (int)t->type, TOKTYPE_CCA_INTERNAL_PKA); |
186 | return -EINVAL; |
187 | } |
188 | if (t->len > keysize) { |
189 | if (dbg) |
190 | DBF("%s token check failed, len %d > keysize %zu\n" , |
191 | __func__, (int)t->len, keysize); |
192 | return -EINVAL; |
193 | } |
194 | if (t->secid != 0x20) { |
195 | if (dbg) |
196 | DBF("%s token check failed, secid 0x%02x != 0x20\n" , |
197 | __func__, (int)t->secid); |
198 | return -EINVAL; |
199 | } |
200 | if (checkcpacfexport && !(t->kutc & 0x01)) { |
201 | if (dbg) |
202 | DBF("%s token check failed, XPRTCPAC bit is 0\n" , |
203 | __func__); |
204 | return -EINVAL; |
205 | } |
206 | |
207 | #undef DBF |
208 | |
209 | return 0; |
210 | } |
211 | EXPORT_SYMBOL(cca_check_sececckeytoken); |
212 | |
213 | /* |
214 | * Allocate consecutive memory for request CPRB, request param |
215 | * block, reply CPRB and reply param block and fill in values |
216 | * for the common fields. Returns 0 on success or errno value |
217 | * on failure. |
218 | */ |
219 | static int alloc_and_prep_cprbmem(size_t paramblen, |
220 | u8 **p_cprb_mem, |
221 | struct CPRBX **p_req_cprb, |
222 | struct CPRBX **p_rep_cprb) |
223 | { |
224 | u8 *cprbmem; |
225 | size_t cprbplusparamblen = sizeof(struct CPRBX) + paramblen; |
226 | struct CPRBX *preqcblk, *prepcblk; |
227 | |
228 | /* |
229 | * allocate consecutive memory for request CPRB, request param |
230 | * block, reply CPRB and reply param block |
231 | */ |
232 | cprbmem = kcalloc(n: 2, size: cprbplusparamblen, GFP_KERNEL); |
233 | if (!cprbmem) |
234 | return -ENOMEM; |
235 | |
236 | preqcblk = (struct CPRBX *)cprbmem; |
237 | prepcblk = (struct CPRBX *)(cprbmem + cprbplusparamblen); |
238 | |
239 | /* fill request cprb struct */ |
240 | preqcblk->cprb_len = sizeof(struct CPRBX); |
241 | preqcblk->cprb_ver_id = 0x02; |
242 | memcpy(preqcblk->func_id, "T2" , 2); |
243 | preqcblk->rpl_msgbl = cprbplusparamblen; |
244 | if (paramblen) { |
245 | preqcblk->req_parmb = |
246 | ((u8 __user *)preqcblk) + sizeof(struct CPRBX); |
247 | preqcblk->rpl_parmb = |
248 | ((u8 __user *)prepcblk) + sizeof(struct CPRBX); |
249 | } |
250 | |
251 | *p_cprb_mem = cprbmem; |
252 | *p_req_cprb = preqcblk; |
253 | *p_rep_cprb = prepcblk; |
254 | |
255 | return 0; |
256 | } |
257 | |
258 | /* |
259 | * Free the cprb memory allocated with the function above. |
260 | * If the scrub value is not zero, the memory is filled |
261 | * with zeros before freeing (useful if there was some |
262 | * clear key material in there). |
263 | */ |
264 | static void free_cprbmem(void *mem, size_t paramblen, int scrub) |
265 | { |
266 | if (scrub) |
267 | memzero_explicit(mem, 2 * (sizeof(struct CPRBX) + paramblen)); |
268 | kfree(objp: mem); |
269 | } |
270 | |
271 | /* |
272 | * Helper function to prepare the xcrb struct |
273 | */ |
274 | static inline void prep_xcrb(struct ica_xcRB *pxcrb, |
275 | u16 cardnr, |
276 | struct CPRBX *preqcblk, |
277 | struct CPRBX *prepcblk) |
278 | { |
279 | memset(pxcrb, 0, sizeof(*pxcrb)); |
280 | pxcrb->agent_ID = 0x4341; /* 'CA' */ |
281 | pxcrb->user_defined = (cardnr == 0xFFFF ? AUTOSELECT : cardnr); |
282 | pxcrb->request_control_blk_length = |
283 | preqcblk->cprb_len + preqcblk->req_parml; |
284 | pxcrb->request_control_blk_addr = (void __user *)preqcblk; |
285 | pxcrb->reply_control_blk_length = preqcblk->rpl_msgbl; |
286 | pxcrb->reply_control_blk_addr = (void __user *)prepcblk; |
287 | } |
288 | |
289 | /* |
290 | * Generate (random) CCA AES DATA secure key. |
291 | */ |
292 | int cca_genseckey(u16 cardnr, u16 domain, |
293 | u32 keybitsize, u8 *seckey) |
294 | { |
295 | int i, rc, keysize; |
296 | int seckeysize; |
297 | u8 *mem, *ptr; |
298 | struct CPRBX *preqcblk, *prepcblk; |
299 | struct ica_xcRB xcrb; |
300 | struct kgreqparm { |
301 | u8 subfunc_code[2]; |
302 | u16 rule_array_len; |
303 | struct lv1 { |
304 | u16 len; |
305 | char key_form[8]; |
306 | char key_length[8]; |
307 | char key_type1[8]; |
308 | char key_type2[8]; |
309 | } lv1; |
310 | struct lv2 { |
311 | u16 len; |
312 | struct keyid { |
313 | u16 len; |
314 | u16 attr; |
315 | u8 data[SECKEYBLOBSIZE]; |
316 | } keyid[6]; |
317 | } lv2; |
318 | } __packed * preqparm; |
319 | struct kgrepparm { |
320 | u8 subfunc_code[2]; |
321 | u16 rule_array_len; |
322 | struct lv3 { |
323 | u16 len; |
324 | u16 keyblocklen; |
325 | struct { |
326 | u16 toklen; |
327 | u16 tokattr; |
328 | u8 tok[]; |
329 | /* ... some more data ... */ |
330 | } keyblock; |
331 | } lv3; |
332 | } __packed * prepparm; |
333 | |
334 | /* get already prepared memory for 2 cprbs with param block each */ |
335 | rc = alloc_and_prep_cprbmem(PARMBSIZE, p_cprb_mem: &mem, p_req_cprb: &preqcblk, p_rep_cprb: &prepcblk); |
336 | if (rc) |
337 | return rc; |
338 | |
339 | /* fill request cprb struct */ |
340 | preqcblk->domain = domain; |
341 | |
342 | /* fill request cprb param block with KG request */ |
343 | preqparm = (struct kgreqparm __force *)preqcblk->req_parmb; |
344 | memcpy(preqparm->subfunc_code, "KG" , 2); |
345 | preqparm->rule_array_len = sizeof(preqparm->rule_array_len); |
346 | preqparm->lv1.len = sizeof(struct lv1); |
347 | memcpy(preqparm->lv1.key_form, "OP " , 8); |
348 | switch (keybitsize) { |
349 | case PKEY_SIZE_AES_128: |
350 | case PKEY_KEYTYPE_AES_128: /* older ioctls used this */ |
351 | keysize = 16; |
352 | memcpy(preqparm->lv1.key_length, "KEYLN16 " , 8); |
353 | break; |
354 | case PKEY_SIZE_AES_192: |
355 | case PKEY_KEYTYPE_AES_192: /* older ioctls used this */ |
356 | keysize = 24; |
357 | memcpy(preqparm->lv1.key_length, "KEYLN24 " , 8); |
358 | break; |
359 | case PKEY_SIZE_AES_256: |
360 | case PKEY_KEYTYPE_AES_256: /* older ioctls used this */ |
361 | keysize = 32; |
362 | memcpy(preqparm->lv1.key_length, "KEYLN32 " , 8); |
363 | break; |
364 | default: |
365 | ZCRYPT_DBF_ERR("%s unknown/unsupported keybitsize %d\n" , |
366 | __func__, keybitsize); |
367 | rc = -EINVAL; |
368 | goto out; |
369 | } |
370 | memcpy(preqparm->lv1.key_type1, "AESDATA " , 8); |
371 | preqparm->lv2.len = sizeof(struct lv2); |
372 | for (i = 0; i < 6; i++) { |
373 | preqparm->lv2.keyid[i].len = sizeof(struct keyid); |
374 | preqparm->lv2.keyid[i].attr = (i == 2 ? 0x30 : 0x10); |
375 | } |
376 | preqcblk->req_parml = sizeof(struct kgreqparm); |
377 | |
378 | /* fill xcrb struct */ |
379 | prep_xcrb(pxcrb: &xcrb, cardnr, preqcblk, prepcblk); |
380 | |
381 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ |
382 | rc = zcrypt_send_cprb(xcRB: &xcrb); |
383 | if (rc) { |
384 | ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, errno %d\n" , |
385 | __func__, (int)cardnr, (int)domain, rc); |
386 | goto out; |
387 | } |
388 | |
389 | /* check response returncode and reasoncode */ |
390 | if (prepcblk->ccp_rtcode != 0) { |
391 | ZCRYPT_DBF_ERR("%s secure key generate failure, card response %d/%d\n" , |
392 | __func__, |
393 | (int)prepcblk->ccp_rtcode, |
394 | (int)prepcblk->ccp_rscode); |
395 | rc = -EIO; |
396 | goto out; |
397 | } |
398 | |
399 | /* process response cprb param block */ |
400 | ptr = ((u8 *)prepcblk) + sizeof(struct CPRBX); |
401 | prepcblk->rpl_parmb = (u8 __user *)ptr; |
402 | prepparm = (struct kgrepparm *)ptr; |
403 | |
404 | /* check length of the returned secure key token */ |
405 | seckeysize = prepparm->lv3.keyblock.toklen |
406 | - sizeof(prepparm->lv3.keyblock.toklen) |
407 | - sizeof(prepparm->lv3.keyblock.tokattr); |
408 | if (seckeysize != SECKEYBLOBSIZE) { |
409 | ZCRYPT_DBF_ERR("%s secure token size mismatch %d != %d bytes\n" , |
410 | __func__, seckeysize, SECKEYBLOBSIZE); |
411 | rc = -EIO; |
412 | goto out; |
413 | } |
414 | |
415 | /* check secure key token */ |
416 | rc = cca_check_secaeskeytoken(zcrypt_dbf_info, DBF_ERR, |
417 | prepparm->lv3.keyblock.tok, 8 * keysize); |
418 | if (rc) { |
419 | rc = -EIO; |
420 | goto out; |
421 | } |
422 | |
423 | /* copy the generated secure key token */ |
424 | memcpy(seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); |
425 | |
426 | out: |
427 | free_cprbmem(mem, PARMBSIZE, scrub: 0); |
428 | return rc; |
429 | } |
430 | EXPORT_SYMBOL(cca_genseckey); |
431 | |
432 | /* |
433 | * Generate an CCA AES DATA secure key with given key value. |
434 | */ |
435 | int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize, |
436 | const u8 *clrkey, u8 *seckey) |
437 | { |
438 | int rc, keysize, seckeysize; |
439 | u8 *mem, *ptr; |
440 | struct CPRBX *preqcblk, *prepcblk; |
441 | struct ica_xcRB xcrb; |
442 | struct cmreqparm { |
443 | u8 subfunc_code[2]; |
444 | u16 rule_array_len; |
445 | char rule_array[8]; |
446 | struct lv1 { |
447 | u16 len; |
448 | u8 clrkey[]; |
449 | } lv1; |
450 | /* followed by struct lv2 */ |
451 | } __packed * preqparm; |
452 | struct lv2 { |
453 | u16 len; |
454 | struct keyid { |
455 | u16 len; |
456 | u16 attr; |
457 | u8 data[SECKEYBLOBSIZE]; |
458 | } keyid; |
459 | } __packed * plv2; |
460 | struct cmrepparm { |
461 | u8 subfunc_code[2]; |
462 | u16 rule_array_len; |
463 | struct lv3 { |
464 | u16 len; |
465 | u16 keyblocklen; |
466 | struct { |
467 | u16 toklen; |
468 | u16 tokattr; |
469 | u8 tok[]; |
470 | /* ... some more data ... */ |
471 | } keyblock; |
472 | } lv3; |
473 | } __packed * prepparm; |
474 | |
475 | /* get already prepared memory for 2 cprbs with param block each */ |
476 | rc = alloc_and_prep_cprbmem(PARMBSIZE, p_cprb_mem: &mem, p_req_cprb: &preqcblk, p_rep_cprb: &prepcblk); |
477 | if (rc) |
478 | return rc; |
479 | |
480 | /* fill request cprb struct */ |
481 | preqcblk->domain = domain; |
482 | |
483 | /* fill request cprb param block with CM request */ |
484 | preqparm = (struct cmreqparm __force *)preqcblk->req_parmb; |
485 | memcpy(preqparm->subfunc_code, "CM" , 2); |
486 | memcpy(preqparm->rule_array, "AES " , 8); |
487 | preqparm->rule_array_len = |
488 | sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); |
489 | switch (keybitsize) { |
490 | case PKEY_SIZE_AES_128: |
491 | case PKEY_KEYTYPE_AES_128: /* older ioctls used this */ |
492 | keysize = 16; |
493 | break; |
494 | case PKEY_SIZE_AES_192: |
495 | case PKEY_KEYTYPE_AES_192: /* older ioctls used this */ |
496 | keysize = 24; |
497 | break; |
498 | case PKEY_SIZE_AES_256: |
499 | case PKEY_KEYTYPE_AES_256: /* older ioctls used this */ |
500 | keysize = 32; |
501 | break; |
502 | default: |
503 | ZCRYPT_DBF_ERR("%s unknown/unsupported keybitsize %d\n" , |
504 | __func__, keybitsize); |
505 | rc = -EINVAL; |
506 | goto out; |
507 | } |
508 | preqparm->lv1.len = sizeof(struct lv1) + keysize; |
509 | memcpy(preqparm->lv1.clrkey, clrkey, keysize); |
510 | plv2 = (struct lv2 *)(((u8 *)preqparm) + sizeof(*preqparm) + keysize); |
511 | plv2->len = sizeof(struct lv2); |
512 | plv2->keyid.len = sizeof(struct keyid); |
513 | plv2->keyid.attr = 0x30; |
514 | preqcblk->req_parml = sizeof(*preqparm) + keysize + sizeof(*plv2); |
515 | |
516 | /* fill xcrb struct */ |
517 | prep_xcrb(pxcrb: &xcrb, cardnr, preqcblk, prepcblk); |
518 | |
519 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ |
520 | rc = zcrypt_send_cprb(xcRB: &xcrb); |
521 | if (rc) { |
522 | ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n" , |
523 | __func__, (int)cardnr, (int)domain, rc); |
524 | goto out; |
525 | } |
526 | |
527 | /* check response returncode and reasoncode */ |
528 | if (prepcblk->ccp_rtcode != 0) { |
529 | ZCRYPT_DBF_ERR("%s clear key import failure, card response %d/%d\n" , |
530 | __func__, |
531 | (int)prepcblk->ccp_rtcode, |
532 | (int)prepcblk->ccp_rscode); |
533 | rc = -EIO; |
534 | goto out; |
535 | } |
536 | |
537 | /* process response cprb param block */ |
538 | ptr = ((u8 *)prepcblk) + sizeof(struct CPRBX); |
539 | prepcblk->rpl_parmb = (u8 __user *)ptr; |
540 | prepparm = (struct cmrepparm *)ptr; |
541 | |
542 | /* check length of the returned secure key token */ |
543 | seckeysize = prepparm->lv3.keyblock.toklen |
544 | - sizeof(prepparm->lv3.keyblock.toklen) |
545 | - sizeof(prepparm->lv3.keyblock.tokattr); |
546 | if (seckeysize != SECKEYBLOBSIZE) { |
547 | ZCRYPT_DBF_ERR("%s secure token size mismatch %d != %d bytes\n" , |
548 | __func__, seckeysize, SECKEYBLOBSIZE); |
549 | rc = -EIO; |
550 | goto out; |
551 | } |
552 | |
553 | /* check secure key token */ |
554 | rc = cca_check_secaeskeytoken(zcrypt_dbf_info, DBF_ERR, |
555 | prepparm->lv3.keyblock.tok, 8 * keysize); |
556 | if (rc) { |
557 | rc = -EIO; |
558 | goto out; |
559 | } |
560 | |
561 | /* copy the generated secure key token */ |
562 | if (seckey) |
563 | memcpy(seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); |
564 | |
565 | out: |
566 | free_cprbmem(mem, PARMBSIZE, scrub: 1); |
567 | return rc; |
568 | } |
569 | EXPORT_SYMBOL(cca_clr2seckey); |
570 | |
571 | /* |
572 | * Derive proteced key from an CCA AES DATA secure key. |
573 | */ |
574 | int cca_sec2protkey(u16 cardnr, u16 domain, |
575 | const u8 *seckey, u8 *protkey, u32 *protkeylen, |
576 | u32 *protkeytype) |
577 | { |
578 | int rc; |
579 | u8 *mem, *ptr; |
580 | struct CPRBX *preqcblk, *prepcblk; |
581 | struct ica_xcRB xcrb; |
582 | struct uskreqparm { |
583 | u8 subfunc_code[2]; |
584 | u16 rule_array_len; |
585 | struct lv1 { |
586 | u16 len; |
587 | u16 attr_len; |
588 | u16 attr_flags; |
589 | } lv1; |
590 | struct lv2 { |
591 | u16 len; |
592 | u16 attr_len; |
593 | u16 attr_flags; |
594 | u8 token[]; /* cca secure key token */ |
595 | } lv2; |
596 | } __packed * preqparm; |
597 | struct uskrepparm { |
598 | u8 subfunc_code[2]; |
599 | u16 rule_array_len; |
600 | struct lv3 { |
601 | u16 len; |
602 | u16 attr_len; |
603 | u16 attr_flags; |
604 | struct cpacfkeyblock { |
605 | u8 version; /* version of this struct */ |
606 | u8 flags[2]; |
607 | u8 algo; |
608 | u8 form; |
609 | u8 pad1[3]; |
610 | u16 len; |
611 | u8 key[64]; /* the key (len bytes) */ |
612 | u16 keyattrlen; |
613 | u8 keyattr[32]; |
614 | u8 pad2[1]; |
615 | u8 vptype; |
616 | u8 vp[32]; /* verification pattern */ |
617 | } ckb; |
618 | } lv3; |
619 | } __packed * prepparm; |
620 | |
621 | /* get already prepared memory for 2 cprbs with param block each */ |
622 | rc = alloc_and_prep_cprbmem(PARMBSIZE, p_cprb_mem: &mem, p_req_cprb: &preqcblk, p_rep_cprb: &prepcblk); |
623 | if (rc) |
624 | return rc; |
625 | |
626 | /* fill request cprb struct */ |
627 | preqcblk->domain = domain; |
628 | |
629 | /* fill request cprb param block with USK request */ |
630 | preqparm = (struct uskreqparm __force *)preqcblk->req_parmb; |
631 | memcpy(preqparm->subfunc_code, "US" , 2); |
632 | preqparm->rule_array_len = sizeof(preqparm->rule_array_len); |
633 | preqparm->lv1.len = sizeof(struct lv1); |
634 | preqparm->lv1.attr_len = sizeof(struct lv1) - sizeof(preqparm->lv1.len); |
635 | preqparm->lv1.attr_flags = 0x0001; |
636 | preqparm->lv2.len = sizeof(struct lv2) + SECKEYBLOBSIZE; |
637 | preqparm->lv2.attr_len = sizeof(struct lv2) |
638 | - sizeof(preqparm->lv2.len) + SECKEYBLOBSIZE; |
639 | preqparm->lv2.attr_flags = 0x0000; |
640 | memcpy(preqparm->lv2.token, seckey, SECKEYBLOBSIZE); |
641 | preqcblk->req_parml = sizeof(struct uskreqparm) + SECKEYBLOBSIZE; |
642 | |
643 | /* fill xcrb struct */ |
644 | prep_xcrb(pxcrb: &xcrb, cardnr, preqcblk, prepcblk); |
645 | |
646 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ |
647 | rc = zcrypt_send_cprb(xcRB: &xcrb); |
648 | if (rc) { |
649 | ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n" , |
650 | __func__, (int)cardnr, (int)domain, rc); |
651 | goto out; |
652 | } |
653 | |
654 | /* check response returncode and reasoncode */ |
655 | if (prepcblk->ccp_rtcode != 0) { |
656 | ZCRYPT_DBF_ERR("%s unwrap secure key failure, card response %d/%d\n" , |
657 | __func__, |
658 | (int)prepcblk->ccp_rtcode, |
659 | (int)prepcblk->ccp_rscode); |
660 | if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290) |
661 | rc = -EAGAIN; |
662 | else |
663 | rc = -EIO; |
664 | goto out; |
665 | } |
666 | if (prepcblk->ccp_rscode != 0) { |
667 | ZCRYPT_DBF_WARN("%s unwrap secure key warning, card response %d/%d\n" , |
668 | __func__, |
669 | (int)prepcblk->ccp_rtcode, |
670 | (int)prepcblk->ccp_rscode); |
671 | } |
672 | |
673 | /* process response cprb param block */ |
674 | ptr = ((u8 *)prepcblk) + sizeof(struct CPRBX); |
675 | prepcblk->rpl_parmb = (u8 __user *)ptr; |
676 | prepparm = (struct uskrepparm *)ptr; |
677 | |
678 | /* check the returned keyblock */ |
679 | if (prepparm->lv3.ckb.version != 0x01 && |
680 | prepparm->lv3.ckb.version != 0x02) { |
681 | ZCRYPT_DBF_ERR("%s reply param keyblock version mismatch 0x%02x\n" , |
682 | __func__, (int)prepparm->lv3.ckb.version); |
683 | rc = -EIO; |
684 | goto out; |
685 | } |
686 | |
687 | /* copy the translated protected key */ |
688 | switch (prepparm->lv3.ckb.len) { |
689 | case 16 + 32: |
690 | /* AES 128 protected key */ |
691 | if (protkeytype) |
692 | *protkeytype = PKEY_KEYTYPE_AES_128; |
693 | break; |
694 | case 24 + 32: |
695 | /* AES 192 protected key */ |
696 | if (protkeytype) |
697 | *protkeytype = PKEY_KEYTYPE_AES_192; |
698 | break; |
699 | case 32 + 32: |
700 | /* AES 256 protected key */ |
701 | if (protkeytype) |
702 | *protkeytype = PKEY_KEYTYPE_AES_256; |
703 | break; |
704 | default: |
705 | ZCRYPT_DBF_ERR("%s unknown/unsupported keylen %d\n" , |
706 | __func__, prepparm->lv3.ckb.len); |
707 | rc = -EIO; |
708 | goto out; |
709 | } |
710 | memcpy(protkey, prepparm->lv3.ckb.key, prepparm->lv3.ckb.len); |
711 | if (protkeylen) |
712 | *protkeylen = prepparm->lv3.ckb.len; |
713 | |
714 | out: |
715 | free_cprbmem(mem, PARMBSIZE, scrub: 0); |
716 | return rc; |
717 | } |
718 | EXPORT_SYMBOL(cca_sec2protkey); |
719 | |
720 | /* |
721 | * AES cipher key skeleton created with CSNBKTB2 with these flags: |
722 | * INTERNAL, NO-KEY, AES, CIPHER, ANY-MODE, NOEX-SYM, NOEXAASY, |
723 | * NOEXUASY, XPRTCPAC, NOEX-RAW, NOEX-DES, NOEX-AES, NOEX-RSA |
724 | * used by cca_gencipherkey() and cca_clr2cipherkey(). |
725 | */ |
726 | static const u8 aes_cipher_key_skeleton[] = { |
727 | 0x01, 0x00, 0x00, 0x38, 0x05, 0x00, 0x00, 0x00, |
728 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
729 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
730 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, |
731 | 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
732 | 0x00, 0x02, 0x00, 0x01, 0x02, 0xc0, 0x00, 0xff, |
733 | 0x00, 0x03, 0x08, 0xc8, 0x00, 0x00, 0x00, 0x00 }; |
734 | #define SIZEOF_SKELETON (sizeof(aes_cipher_key_skeleton)) |
735 | |
736 | /* |
737 | * Generate (random) CCA AES CIPHER secure key. |
738 | */ |
739 | int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags, |
740 | u8 *keybuf, size_t *keybufsize) |
741 | { |
742 | int rc; |
743 | u8 *mem, *ptr; |
744 | struct CPRBX *preqcblk, *prepcblk; |
745 | struct ica_xcRB xcrb; |
746 | struct gkreqparm { |
747 | u8 subfunc_code[2]; |
748 | u16 rule_array_len; |
749 | char rule_array[2 * 8]; |
750 | struct { |
751 | u16 len; |
752 | u8 key_type_1[8]; |
753 | u8 key_type_2[8]; |
754 | u16 clear_key_bit_len; |
755 | u16 key_name_1_len; |
756 | u16 key_name_2_len; |
757 | u16 user_data_1_len; |
758 | u16 user_data_2_len; |
759 | /* u8 key_name_1[]; */ |
760 | /* u8 key_name_2[]; */ |
761 | /* u8 user_data_1[]; */ |
762 | /* u8 user_data_2[]; */ |
763 | } vud; |
764 | struct { |
765 | u16 len; |
766 | struct { |
767 | u16 len; |
768 | u16 flag; |
769 | /* u8 kek_id_1[]; */ |
770 | } tlv1; |
771 | struct { |
772 | u16 len; |
773 | u16 flag; |
774 | /* u8 kek_id_2[]; */ |
775 | } tlv2; |
776 | struct { |
777 | u16 len; |
778 | u16 flag; |
779 | u8 gen_key_id_1[SIZEOF_SKELETON]; |
780 | } tlv3; |
781 | struct { |
782 | u16 len; |
783 | u16 flag; |
784 | /* u8 gen_key_id_1_label[]; */ |
785 | } tlv4; |
786 | struct { |
787 | u16 len; |
788 | u16 flag; |
789 | /* u8 gen_key_id_2[]; */ |
790 | } tlv5; |
791 | struct { |
792 | u16 len; |
793 | u16 flag; |
794 | /* u8 gen_key_id_2_label[]; */ |
795 | } tlv6; |
796 | } kb; |
797 | } __packed * preqparm; |
798 | struct gkrepparm { |
799 | u8 subfunc_code[2]; |
800 | u16 rule_array_len; |
801 | struct { |
802 | u16 len; |
803 | } vud; |
804 | struct { |
805 | u16 len; |
806 | struct { |
807 | u16 len; |
808 | u16 flag; |
809 | u8 gen_key[]; /* 120-136 bytes */ |
810 | } tlv1; |
811 | } kb; |
812 | } __packed * prepparm; |
813 | struct cipherkeytoken *t; |
814 | |
815 | /* get already prepared memory for 2 cprbs with param block each */ |
816 | rc = alloc_and_prep_cprbmem(PARMBSIZE, p_cprb_mem: &mem, p_req_cprb: &preqcblk, p_rep_cprb: &prepcblk); |
817 | if (rc) |
818 | return rc; |
819 | |
820 | /* fill request cprb struct */ |
821 | preqcblk->domain = domain; |
822 | preqcblk->req_parml = sizeof(struct gkreqparm); |
823 | |
824 | /* prepare request param block with GK request */ |
825 | preqparm = (struct gkreqparm __force *)preqcblk->req_parmb; |
826 | memcpy(preqparm->subfunc_code, "GK" , 2); |
827 | preqparm->rule_array_len = sizeof(uint16_t) + 2 * 8; |
828 | memcpy(preqparm->rule_array, "AES OP " , 2 * 8); |
829 | |
830 | /* prepare vud block */ |
831 | preqparm->vud.len = sizeof(preqparm->vud); |
832 | switch (keybitsize) { |
833 | case 128: |
834 | case 192: |
835 | case 256: |
836 | break; |
837 | default: |
838 | ZCRYPT_DBF_ERR("%s unknown/unsupported keybitsize %d\n" , |
839 | __func__, keybitsize); |
840 | rc = -EINVAL; |
841 | goto out; |
842 | } |
843 | preqparm->vud.clear_key_bit_len = keybitsize; |
844 | memcpy(preqparm->vud.key_type_1, "TOKEN " , 8); |
845 | memset(preqparm->vud.key_type_2, ' ', sizeof(preqparm->vud.key_type_2)); |
846 | |
847 | /* prepare kb block */ |
848 | preqparm->kb.len = sizeof(preqparm->kb); |
849 | preqparm->kb.tlv1.len = sizeof(preqparm->kb.tlv1); |
850 | preqparm->kb.tlv1.flag = 0x0030; |
851 | preqparm->kb.tlv2.len = sizeof(preqparm->kb.tlv2); |
852 | preqparm->kb.tlv2.flag = 0x0030; |
853 | preqparm->kb.tlv3.len = sizeof(preqparm->kb.tlv3); |
854 | preqparm->kb.tlv3.flag = 0x0030; |
855 | memcpy(preqparm->kb.tlv3.gen_key_id_1, |
856 | aes_cipher_key_skeleton, SIZEOF_SKELETON); |
857 | preqparm->kb.tlv4.len = sizeof(preqparm->kb.tlv4); |
858 | preqparm->kb.tlv4.flag = 0x0030; |
859 | preqparm->kb.tlv5.len = sizeof(preqparm->kb.tlv5); |
860 | preqparm->kb.tlv5.flag = 0x0030; |
861 | preqparm->kb.tlv6.len = sizeof(preqparm->kb.tlv6); |
862 | preqparm->kb.tlv6.flag = 0x0030; |
863 | |
864 | /* patch the skeleton key token export flags inside the kb block */ |
865 | if (keygenflags) { |
866 | t = (struct cipherkeytoken *)preqparm->kb.tlv3.gen_key_id_1; |
867 | t->kmf1 |= (u16)(keygenflags & 0x0000FF00); |
868 | t->kmf1 &= (u16)~(keygenflags & 0x000000FF); |
869 | } |
870 | |
871 | /* prepare xcrb struct */ |
872 | prep_xcrb(pxcrb: &xcrb, cardnr, preqcblk, prepcblk); |
873 | |
874 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ |
875 | rc = zcrypt_send_cprb(xcRB: &xcrb); |
876 | if (rc) { |
877 | ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n" , |
878 | __func__, (int)cardnr, (int)domain, rc); |
879 | goto out; |
880 | } |
881 | |
882 | /* check response returncode and reasoncode */ |
883 | if (prepcblk->ccp_rtcode != 0) { |
884 | ZCRYPT_DBF_ERR("%s cipher key generate failure, card response %d/%d\n" , |
885 | __func__, |
886 | (int)prepcblk->ccp_rtcode, |
887 | (int)prepcblk->ccp_rscode); |
888 | rc = -EIO; |
889 | goto out; |
890 | } |
891 | |
892 | /* process response cprb param block */ |
893 | ptr = ((u8 *)prepcblk) + sizeof(struct CPRBX); |
894 | prepcblk->rpl_parmb = (u8 __user *)ptr; |
895 | prepparm = (struct gkrepparm *)ptr; |
896 | |
897 | /* do some plausibility checks on the key block */ |
898 | if (prepparm->kb.len < 120 + 5 * sizeof(uint16_t) || |
899 | prepparm->kb.len > 136 + 5 * sizeof(uint16_t)) { |
900 | ZCRYPT_DBF_ERR("%s reply with invalid or unknown key block\n" , |
901 | __func__); |
902 | rc = -EIO; |
903 | goto out; |
904 | } |
905 | |
906 | /* and some checks on the generated key */ |
907 | rc = cca_check_secaescipherkey(zcrypt_dbf_info, DBF_ERR, |
908 | prepparm->kb.tlv1.gen_key, |
909 | keybitsize, 1); |
910 | if (rc) { |
911 | rc = -EIO; |
912 | goto out; |
913 | } |
914 | |
915 | /* copy the generated vlsc key token */ |
916 | t = (struct cipherkeytoken *)prepparm->kb.tlv1.gen_key; |
917 | if (keybuf) { |
918 | if (*keybufsize >= t->len) |
919 | memcpy(keybuf, t, t->len); |
920 | else |
921 | rc = -EINVAL; |
922 | } |
923 | *keybufsize = t->len; |
924 | |
925 | out: |
926 | free_cprbmem(mem, PARMBSIZE, scrub: 0); |
927 | return rc; |
928 | } |
929 | EXPORT_SYMBOL(cca_gencipherkey); |
930 | |
931 | /* |
932 | * Helper function, does a the CSNBKPI2 CPRB. |
933 | */ |
934 | static int _ip_cprb_helper(u16 cardnr, u16 domain, |
935 | const char *rule_array_1, |
936 | const char *rule_array_2, |
937 | const char *rule_array_3, |
938 | const u8 *clr_key_value, |
939 | int clr_key_bit_size, |
940 | u8 *key_token, |
941 | int *key_token_size) |
942 | { |
943 | int rc, n; |
944 | u8 *mem, *ptr; |
945 | struct CPRBX *preqcblk, *prepcblk; |
946 | struct ica_xcRB xcrb; |
947 | struct rule_array_block { |
948 | u8 subfunc_code[2]; |
949 | u16 rule_array_len; |
950 | char rule_array[]; |
951 | } __packed * preq_ra_block; |
952 | struct vud_block { |
953 | u16 len; |
954 | struct { |
955 | u16 len; |
956 | u16 flag; /* 0x0064 */ |
957 | u16 clr_key_bit_len; |
958 | } tlv1; |
959 | struct { |
960 | u16 len; |
961 | u16 flag; /* 0x0063 */ |
962 | u8 clr_key[]; /* clear key value bytes */ |
963 | } tlv2; |
964 | } __packed * preq_vud_block; |
965 | struct key_block { |
966 | u16 len; |
967 | struct { |
968 | u16 len; |
969 | u16 flag; /* 0x0030 */ |
970 | u8 key_token[]; /* key skeleton */ |
971 | } tlv1; |
972 | } __packed * preq_key_block; |
973 | struct iprepparm { |
974 | u8 subfunc_code[2]; |
975 | u16 rule_array_len; |
976 | struct { |
977 | u16 len; |
978 | } vud; |
979 | struct { |
980 | u16 len; |
981 | struct { |
982 | u16 len; |
983 | u16 flag; /* 0x0030 */ |
984 | u8 key_token[]; /* key token */ |
985 | } tlv1; |
986 | } kb; |
987 | } __packed * prepparm; |
988 | struct cipherkeytoken *t; |
989 | int complete = strncmp(rule_array_2, "COMPLETE" , 8) ? 0 : 1; |
990 | |
991 | /* get already prepared memory for 2 cprbs with param block each */ |
992 | rc = alloc_and_prep_cprbmem(PARMBSIZE, p_cprb_mem: &mem, p_req_cprb: &preqcblk, p_rep_cprb: &prepcblk); |
993 | if (rc) |
994 | return rc; |
995 | |
996 | /* fill request cprb struct */ |
997 | preqcblk->domain = domain; |
998 | preqcblk->req_parml = 0; |
999 | |
1000 | /* prepare request param block with IP request */ |
1001 | preq_ra_block = (struct rule_array_block __force *)preqcblk->req_parmb; |
1002 | memcpy(preq_ra_block->subfunc_code, "IP" , 2); |
1003 | preq_ra_block->rule_array_len = sizeof(uint16_t) + 2 * 8; |
1004 | memcpy(preq_ra_block->rule_array, rule_array_1, 8); |
1005 | memcpy(preq_ra_block->rule_array + 8, rule_array_2, 8); |
1006 | preqcblk->req_parml = sizeof(struct rule_array_block) + 2 * 8; |
1007 | if (rule_array_3) { |
1008 | preq_ra_block->rule_array_len += 8; |
1009 | memcpy(preq_ra_block->rule_array + 16, rule_array_3, 8); |
1010 | preqcblk->req_parml += 8; |
1011 | } |
1012 | |
1013 | /* prepare vud block */ |
1014 | preq_vud_block = (struct vud_block __force *) |
1015 | (preqcblk->req_parmb + preqcblk->req_parml); |
1016 | n = complete ? 0 : (clr_key_bit_size + 7) / 8; |
1017 | preq_vud_block->len = sizeof(struct vud_block) + n; |
1018 | preq_vud_block->tlv1.len = sizeof(preq_vud_block->tlv1); |
1019 | preq_vud_block->tlv1.flag = 0x0064; |
1020 | preq_vud_block->tlv1.clr_key_bit_len = complete ? 0 : clr_key_bit_size; |
1021 | preq_vud_block->tlv2.len = sizeof(preq_vud_block->tlv2) + n; |
1022 | preq_vud_block->tlv2.flag = 0x0063; |
1023 | if (!complete) |
1024 | memcpy(preq_vud_block->tlv2.clr_key, clr_key_value, n); |
1025 | preqcblk->req_parml += preq_vud_block->len; |
1026 | |
1027 | /* prepare key block */ |
1028 | preq_key_block = (struct key_block __force *) |
1029 | (preqcblk->req_parmb + preqcblk->req_parml); |
1030 | n = *key_token_size; |
1031 | preq_key_block->len = sizeof(struct key_block) + n; |
1032 | preq_key_block->tlv1.len = sizeof(preq_key_block->tlv1) + n; |
1033 | preq_key_block->tlv1.flag = 0x0030; |
1034 | memcpy(preq_key_block->tlv1.key_token, key_token, *key_token_size); |
1035 | preqcblk->req_parml += preq_key_block->len; |
1036 | |
1037 | /* prepare xcrb struct */ |
1038 | prep_xcrb(pxcrb: &xcrb, cardnr, preqcblk, prepcblk); |
1039 | |
1040 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ |
1041 | rc = zcrypt_send_cprb(xcRB: &xcrb); |
1042 | if (rc) { |
1043 | ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n" , |
1044 | __func__, (int)cardnr, (int)domain, rc); |
1045 | goto out; |
1046 | } |
1047 | |
1048 | /* check response returncode and reasoncode */ |
1049 | if (prepcblk->ccp_rtcode != 0) { |
1050 | ZCRYPT_DBF_ERR("%s CSNBKPI2 failure, card response %d/%d\n" , |
1051 | __func__, |
1052 | (int)prepcblk->ccp_rtcode, |
1053 | (int)prepcblk->ccp_rscode); |
1054 | rc = -EIO; |
1055 | goto out; |
1056 | } |
1057 | |
1058 | /* process response cprb param block */ |
1059 | ptr = ((u8 *)prepcblk) + sizeof(struct CPRBX); |
1060 | prepcblk->rpl_parmb = (u8 __user *)ptr; |
1061 | prepparm = (struct iprepparm *)ptr; |
1062 | |
1063 | /* do some plausibility checks on the key block */ |
1064 | if (prepparm->kb.len < 120 + 3 * sizeof(uint16_t) || |
1065 | prepparm->kb.len > 136 + 3 * sizeof(uint16_t)) { |
1066 | ZCRYPT_DBF_ERR("%s reply with invalid or unknown key block\n" , |
1067 | __func__); |
1068 | rc = -EIO; |
1069 | goto out; |
1070 | } |
1071 | |
1072 | /* do not check the key here, it may be incomplete */ |
1073 | |
1074 | /* copy the vlsc key token back */ |
1075 | t = (struct cipherkeytoken *)prepparm->kb.tlv1.key_token; |
1076 | memcpy(key_token, t, t->len); |
1077 | *key_token_size = t->len; |
1078 | |
1079 | out: |
1080 | free_cprbmem(mem, PARMBSIZE, scrub: 0); |
1081 | return rc; |
1082 | } |
1083 | |
1084 | /* |
1085 | * Build CCA AES CIPHER secure key with a given clear key value. |
1086 | */ |
1087 | int cca_clr2cipherkey(u16 card, u16 dom, u32 keybitsize, u32 keygenflags, |
1088 | const u8 *clrkey, u8 *keybuf, size_t *keybufsize) |
1089 | { |
1090 | int rc; |
1091 | u8 *token; |
1092 | int tokensize; |
1093 | u8 exorbuf[32]; |
1094 | struct cipherkeytoken *t; |
1095 | |
1096 | /* fill exorbuf with random data */ |
1097 | get_random_bytes(buf: exorbuf, len: sizeof(exorbuf)); |
1098 | |
1099 | /* allocate space for the key token to build */ |
1100 | token = kmalloc(MAXCCAVLSCTOKENSIZE, GFP_KERNEL); |
1101 | if (!token) |
1102 | return -ENOMEM; |
1103 | |
1104 | /* prepare the token with the key skeleton */ |
1105 | tokensize = SIZEOF_SKELETON; |
1106 | memcpy(token, aes_cipher_key_skeleton, tokensize); |
1107 | |
1108 | /* patch the skeleton key token export flags */ |
1109 | if (keygenflags) { |
1110 | t = (struct cipherkeytoken *)token; |
1111 | t->kmf1 |= (u16)(keygenflags & 0x0000FF00); |
1112 | t->kmf1 &= (u16)~(keygenflags & 0x000000FF); |
1113 | } |
1114 | |
1115 | /* |
1116 | * Do the key import with the clear key value in 4 steps: |
1117 | * 1/4 FIRST import with only random data |
1118 | * 2/4 EXOR the clear key |
1119 | * 3/4 EXOR the very same random data again |
1120 | * 4/4 COMPLETE the secure cipher key import |
1121 | */ |
1122 | rc = _ip_cprb_helper(cardnr: card, domain: dom, rule_array_1: "AES " , rule_array_2: "FIRST " , rule_array_3: "MIN3PART" , |
1123 | clr_key_value: exorbuf, clr_key_bit_size: keybitsize, key_token: token, key_token_size: &tokensize); |
1124 | if (rc) { |
1125 | ZCRYPT_DBF_ERR("%s clear key import 1/4 with CSNBKPI2 failed, rc=%d\n" , |
1126 | __func__, rc); |
1127 | goto out; |
1128 | } |
1129 | rc = _ip_cprb_helper(cardnr: card, domain: dom, rule_array_1: "AES " , rule_array_2: "ADD-PART" , NULL, |
1130 | clr_key_value: clrkey, clr_key_bit_size: keybitsize, key_token: token, key_token_size: &tokensize); |
1131 | if (rc) { |
1132 | ZCRYPT_DBF_ERR("%s clear key import 2/4 with CSNBKPI2 failed, rc=%d\n" , |
1133 | __func__, rc); |
1134 | goto out; |
1135 | } |
1136 | rc = _ip_cprb_helper(cardnr: card, domain: dom, rule_array_1: "AES " , rule_array_2: "ADD-PART" , NULL, |
1137 | clr_key_value: exorbuf, clr_key_bit_size: keybitsize, key_token: token, key_token_size: &tokensize); |
1138 | if (rc) { |
1139 | ZCRYPT_DBF_ERR("%s clear key import 3/4 with CSNBKPI2 failed, rc=%d\n" , |
1140 | __func__, rc); |
1141 | goto out; |
1142 | } |
1143 | rc = _ip_cprb_helper(cardnr: card, domain: dom, rule_array_1: "AES " , rule_array_2: "COMPLETE" , NULL, |
1144 | NULL, clr_key_bit_size: keybitsize, key_token: token, key_token_size: &tokensize); |
1145 | if (rc) { |
1146 | ZCRYPT_DBF_ERR("%s clear key import 4/4 with CSNBKPI2 failed, rc=%d\n" , |
1147 | __func__, rc); |
1148 | goto out; |
1149 | } |
1150 | |
1151 | /* copy the generated key token */ |
1152 | if (keybuf) { |
1153 | if (tokensize > *keybufsize) |
1154 | rc = -EINVAL; |
1155 | else |
1156 | memcpy(keybuf, token, tokensize); |
1157 | } |
1158 | *keybufsize = tokensize; |
1159 | |
1160 | out: |
1161 | kfree(objp: token); |
1162 | return rc; |
1163 | } |
1164 | EXPORT_SYMBOL(cca_clr2cipherkey); |
1165 | |
1166 | /* |
1167 | * Derive proteced key from CCA AES cipher secure key. |
1168 | */ |
1169 | int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey, |
1170 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) |
1171 | { |
1172 | int rc; |
1173 | u8 *mem, *ptr; |
1174 | struct CPRBX *preqcblk, *prepcblk; |
1175 | struct ica_xcRB xcrb; |
1176 | struct aureqparm { |
1177 | u8 subfunc_code[2]; |
1178 | u16 rule_array_len; |
1179 | u8 rule_array[8]; |
1180 | struct { |
1181 | u16 len; |
1182 | u16 tk_blob_len; |
1183 | u16 tk_blob_tag; |
1184 | u8 tk_blob[66]; |
1185 | } vud; |
1186 | struct { |
1187 | u16 len; |
1188 | u16 cca_key_token_len; |
1189 | u16 cca_key_token_flags; |
1190 | u8 cca_key_token[]; /* 64 or more */ |
1191 | } kb; |
1192 | } __packed * preqparm; |
1193 | struct aurepparm { |
1194 | u8 subfunc_code[2]; |
1195 | u16 rule_array_len; |
1196 | struct { |
1197 | u16 len; |
1198 | u16 sublen; |
1199 | u16 tag; |
1200 | struct cpacfkeyblock { |
1201 | u8 version; /* version of this struct */ |
1202 | u8 flags[2]; |
1203 | u8 algo; |
1204 | u8 form; |
1205 | u8 pad1[3]; |
1206 | u16 keylen; |
1207 | u8 key[64]; /* the key (keylen bytes) */ |
1208 | u16 keyattrlen; |
1209 | u8 keyattr[32]; |
1210 | u8 pad2[1]; |
1211 | u8 vptype; |
1212 | u8 vp[32]; /* verification pattern */ |
1213 | } ckb; |
1214 | } vud; |
1215 | struct { |
1216 | u16 len; |
1217 | } kb; |
1218 | } __packed * prepparm; |
1219 | int keytoklen = ((struct cipherkeytoken *)ckey)->len; |
1220 | |
1221 | /* get already prepared memory for 2 cprbs with param block each */ |
1222 | rc = alloc_and_prep_cprbmem(PARMBSIZE, p_cprb_mem: &mem, p_req_cprb: &preqcblk, p_rep_cprb: &prepcblk); |
1223 | if (rc) |
1224 | return rc; |
1225 | |
1226 | /* fill request cprb struct */ |
1227 | preqcblk->domain = domain; |
1228 | |
1229 | /* fill request cprb param block with AU request */ |
1230 | preqparm = (struct aureqparm __force *)preqcblk->req_parmb; |
1231 | memcpy(preqparm->subfunc_code, "AU" , 2); |
1232 | preqparm->rule_array_len = |
1233 | sizeof(preqparm->rule_array_len) |
1234 | + sizeof(preqparm->rule_array); |
1235 | memcpy(preqparm->rule_array, "EXPT-SK " , 8); |
1236 | /* vud, tk blob */ |
1237 | preqparm->vud.len = sizeof(preqparm->vud); |
1238 | preqparm->vud.tk_blob_len = sizeof(preqparm->vud.tk_blob) |
1239 | + 2 * sizeof(uint16_t); |
1240 | preqparm->vud.tk_blob_tag = 0x00C2; |
1241 | /* kb, cca token */ |
1242 | preqparm->kb.len = keytoklen + 3 * sizeof(uint16_t); |
1243 | preqparm->kb.cca_key_token_len = keytoklen + 2 * sizeof(uint16_t); |
1244 | memcpy(preqparm->kb.cca_key_token, ckey, keytoklen); |
1245 | /* now fill length of param block into cprb */ |
1246 | preqcblk->req_parml = sizeof(struct aureqparm) + keytoklen; |
1247 | |
1248 | /* fill xcrb struct */ |
1249 | prep_xcrb(pxcrb: &xcrb, cardnr, preqcblk, prepcblk); |
1250 | |
1251 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ |
1252 | rc = zcrypt_send_cprb(xcRB: &xcrb); |
1253 | if (rc) { |
1254 | ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n" , |
1255 | __func__, (int)cardnr, (int)domain, rc); |
1256 | goto out; |
1257 | } |
1258 | |
1259 | /* check response returncode and reasoncode */ |
1260 | if (prepcblk->ccp_rtcode != 0) { |
1261 | ZCRYPT_DBF_ERR("%s unwrap secure key failure, card response %d/%d\n" , |
1262 | __func__, |
1263 | (int)prepcblk->ccp_rtcode, |
1264 | (int)prepcblk->ccp_rscode); |
1265 | if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290) |
1266 | rc = -EAGAIN; |
1267 | else |
1268 | rc = -EIO; |
1269 | goto out; |
1270 | } |
1271 | if (prepcblk->ccp_rscode != 0) { |
1272 | ZCRYPT_DBF_WARN("%s unwrap secure key warning, card response %d/%d\n" , |
1273 | __func__, |
1274 | (int)prepcblk->ccp_rtcode, |
1275 | (int)prepcblk->ccp_rscode); |
1276 | } |
1277 | |
1278 | /* process response cprb param block */ |
1279 | ptr = ((u8 *)prepcblk) + sizeof(struct CPRBX); |
1280 | prepcblk->rpl_parmb = (u8 __user *)ptr; |
1281 | prepparm = (struct aurepparm *)ptr; |
1282 | |
1283 | /* check the returned keyblock */ |
1284 | if (prepparm->vud.ckb.version != 0x01 && |
1285 | prepparm->vud.ckb.version != 0x02) { |
1286 | ZCRYPT_DBF_ERR("%s reply param keyblock version mismatch 0x%02x\n" , |
1287 | __func__, (int)prepparm->vud.ckb.version); |
1288 | rc = -EIO; |
1289 | goto out; |
1290 | } |
1291 | if (prepparm->vud.ckb.algo != 0x02) { |
1292 | ZCRYPT_DBF_ERR("%s reply param keyblock algo mismatch 0x%02x != 0x02\n" , |
1293 | __func__, (int)prepparm->vud.ckb.algo); |
1294 | rc = -EIO; |
1295 | goto out; |
1296 | } |
1297 | |
1298 | /* copy the translated protected key */ |
1299 | switch (prepparm->vud.ckb.keylen) { |
1300 | case 16 + 32: |
1301 | /* AES 128 protected key */ |
1302 | if (protkeytype) |
1303 | *protkeytype = PKEY_KEYTYPE_AES_128; |
1304 | break; |
1305 | case 24 + 32: |
1306 | /* AES 192 protected key */ |
1307 | if (protkeytype) |
1308 | *protkeytype = PKEY_KEYTYPE_AES_192; |
1309 | break; |
1310 | case 32 + 32: |
1311 | /* AES 256 protected key */ |
1312 | if (protkeytype) |
1313 | *protkeytype = PKEY_KEYTYPE_AES_256; |
1314 | break; |
1315 | default: |
1316 | ZCRYPT_DBF_ERR("%s unknown/unsupported keylen %d\n" , |
1317 | __func__, prepparm->vud.ckb.keylen); |
1318 | rc = -EIO; |
1319 | goto out; |
1320 | } |
1321 | memcpy(protkey, prepparm->vud.ckb.key, prepparm->vud.ckb.keylen); |
1322 | if (protkeylen) |
1323 | *protkeylen = prepparm->vud.ckb.keylen; |
1324 | |
1325 | out: |
1326 | free_cprbmem(mem, PARMBSIZE, scrub: 0); |
1327 | return rc; |
1328 | } |
1329 | EXPORT_SYMBOL(cca_cipher2protkey); |
1330 | |
1331 | /* |
1332 | * Derive protected key from CCA ECC secure private key. |
1333 | */ |
1334 | int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key, |
1335 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) |
1336 | { |
1337 | int rc; |
1338 | u8 *mem, *ptr; |
1339 | struct CPRBX *preqcblk, *prepcblk; |
1340 | struct ica_xcRB xcrb; |
1341 | struct aureqparm { |
1342 | u8 subfunc_code[2]; |
1343 | u16 rule_array_len; |
1344 | u8 rule_array[8]; |
1345 | struct { |
1346 | u16 len; |
1347 | u16 tk_blob_len; |
1348 | u16 tk_blob_tag; |
1349 | u8 tk_blob[66]; |
1350 | } vud; |
1351 | struct { |
1352 | u16 len; |
1353 | u16 cca_key_token_len; |
1354 | u16 cca_key_token_flags; |
1355 | u8 cca_key_token[]; |
1356 | } kb; |
1357 | } __packed * preqparm; |
1358 | struct aurepparm { |
1359 | u8 subfunc_code[2]; |
1360 | u16 rule_array_len; |
1361 | struct { |
1362 | u16 len; |
1363 | u16 sublen; |
1364 | u16 tag; |
1365 | struct cpacfkeyblock { |
1366 | u8 version; /* version of this struct */ |
1367 | u8 flags[2]; |
1368 | u8 algo; |
1369 | u8 form; |
1370 | u8 pad1[3]; |
1371 | u16 keylen; |
1372 | u8 key[]; /* the key (keylen bytes) */ |
1373 | /* u16 keyattrlen; */ |
1374 | /* u8 keyattr[32]; */ |
1375 | /* u8 pad2[1]; */ |
1376 | /* u8 vptype; */ |
1377 | /* u8 vp[32]; verification pattern */ |
1378 | } ckb; |
1379 | } vud; |
1380 | /* followed by a key block */ |
1381 | } __packed * prepparm; |
1382 | int keylen = ((struct eccprivkeytoken *)key)->len; |
1383 | |
1384 | /* get already prepared memory for 2 cprbs with param block each */ |
1385 | rc = alloc_and_prep_cprbmem(PARMBSIZE, p_cprb_mem: &mem, p_req_cprb: &preqcblk, p_rep_cprb: &prepcblk); |
1386 | if (rc) |
1387 | return rc; |
1388 | |
1389 | /* fill request cprb struct */ |
1390 | preqcblk->domain = domain; |
1391 | |
1392 | /* fill request cprb param block with AU request */ |
1393 | preqparm = (struct aureqparm __force *)preqcblk->req_parmb; |
1394 | memcpy(preqparm->subfunc_code, "AU" , 2); |
1395 | preqparm->rule_array_len = |
1396 | sizeof(preqparm->rule_array_len) |
1397 | + sizeof(preqparm->rule_array); |
1398 | memcpy(preqparm->rule_array, "EXPT-SK " , 8); |
1399 | /* vud, tk blob */ |
1400 | preqparm->vud.len = sizeof(preqparm->vud); |
1401 | preqparm->vud.tk_blob_len = sizeof(preqparm->vud.tk_blob) |
1402 | + 2 * sizeof(uint16_t); |
1403 | preqparm->vud.tk_blob_tag = 0x00C2; |
1404 | /* kb, cca token */ |
1405 | preqparm->kb.len = keylen + 3 * sizeof(uint16_t); |
1406 | preqparm->kb.cca_key_token_len = keylen + 2 * sizeof(uint16_t); |
1407 | memcpy(preqparm->kb.cca_key_token, key, keylen); |
1408 | /* now fill length of param block into cprb */ |
1409 | preqcblk->req_parml = sizeof(struct aureqparm) + keylen; |
1410 | |
1411 | /* fill xcrb struct */ |
1412 | prep_xcrb(pxcrb: &xcrb, cardnr, preqcblk, prepcblk); |
1413 | |
1414 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ |
1415 | rc = zcrypt_send_cprb(xcRB: &xcrb); |
1416 | if (rc) { |
1417 | ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n" , |
1418 | __func__, (int)cardnr, (int)domain, rc); |
1419 | goto out; |
1420 | } |
1421 | |
1422 | /* check response returncode and reasoncode */ |
1423 | if (prepcblk->ccp_rtcode != 0) { |
1424 | ZCRYPT_DBF_ERR("%s unwrap secure key failure, card response %d/%d\n" , |
1425 | __func__, |
1426 | (int)prepcblk->ccp_rtcode, |
1427 | (int)prepcblk->ccp_rscode); |
1428 | if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290) |
1429 | rc = -EAGAIN; |
1430 | else |
1431 | rc = -EIO; |
1432 | goto out; |
1433 | } |
1434 | if (prepcblk->ccp_rscode != 0) { |
1435 | ZCRYPT_DBF_WARN("%s unwrap secure key warning, card response %d/%d\n" , |
1436 | __func__, |
1437 | (int)prepcblk->ccp_rtcode, |
1438 | (int)prepcblk->ccp_rscode); |
1439 | } |
1440 | |
1441 | /* process response cprb param block */ |
1442 | ptr = ((u8 *)prepcblk) + sizeof(struct CPRBX); |
1443 | prepcblk->rpl_parmb = (u8 __user *)ptr; |
1444 | prepparm = (struct aurepparm *)ptr; |
1445 | |
1446 | /* check the returned keyblock */ |
1447 | if (prepparm->vud.ckb.version != 0x02) { |
1448 | ZCRYPT_DBF_ERR("%s reply param keyblock version mismatch 0x%02x != 0x02\n" , |
1449 | __func__, (int)prepparm->vud.ckb.version); |
1450 | rc = -EIO; |
1451 | goto out; |
1452 | } |
1453 | if (prepparm->vud.ckb.algo != 0x81) { |
1454 | ZCRYPT_DBF_ERR("%s reply param keyblock algo mismatch 0x%02x != 0x81\n" , |
1455 | __func__, (int)prepparm->vud.ckb.algo); |
1456 | rc = -EIO; |
1457 | goto out; |
1458 | } |
1459 | |
1460 | /* copy the translated protected key */ |
1461 | if (prepparm->vud.ckb.keylen > *protkeylen) { |
1462 | ZCRYPT_DBF_ERR("%s prot keylen mismatch %d > buffersize %u\n" , |
1463 | __func__, prepparm->vud.ckb.keylen, *protkeylen); |
1464 | rc = -EIO; |
1465 | goto out; |
1466 | } |
1467 | memcpy(protkey, prepparm->vud.ckb.key, prepparm->vud.ckb.keylen); |
1468 | *protkeylen = prepparm->vud.ckb.keylen; |
1469 | if (protkeytype) |
1470 | *protkeytype = PKEY_KEYTYPE_ECC; |
1471 | |
1472 | out: |
1473 | free_cprbmem(mem, PARMBSIZE, scrub: 0); |
1474 | return rc; |
1475 | } |
1476 | EXPORT_SYMBOL(cca_ecc2protkey); |
1477 | |
1478 | /* |
1479 | * query cryptographic facility from CCA adapter |
1480 | */ |
1481 | int cca_query_crypto_facility(u16 cardnr, u16 domain, |
1482 | const char *keyword, |
1483 | u8 *rarray, size_t *rarraylen, |
1484 | u8 *varray, size_t *varraylen) |
1485 | { |
1486 | int rc; |
1487 | u16 len; |
1488 | u8 *mem, *ptr; |
1489 | struct CPRBX *preqcblk, *prepcblk; |
1490 | struct ica_xcRB xcrb; |
1491 | struct fqreqparm { |
1492 | u8 subfunc_code[2]; |
1493 | u16 rule_array_len; |
1494 | char rule_array[8]; |
1495 | struct lv1 { |
1496 | u16 len; |
1497 | u8 data[VARDATASIZE]; |
1498 | } lv1; |
1499 | u16 dummylen; |
1500 | } __packed * preqparm; |
1501 | size_t parmbsize = sizeof(struct fqreqparm); |
1502 | struct fqrepparm { |
1503 | u8 subfunc_code[2]; |
1504 | u8 lvdata[]; |
1505 | } __packed * prepparm; |
1506 | |
1507 | /* get already prepared memory for 2 cprbs with param block each */ |
1508 | rc = alloc_and_prep_cprbmem(paramblen: parmbsize, p_cprb_mem: &mem, p_req_cprb: &preqcblk, p_rep_cprb: &prepcblk); |
1509 | if (rc) |
1510 | return rc; |
1511 | |
1512 | /* fill request cprb struct */ |
1513 | preqcblk->domain = domain; |
1514 | |
1515 | /* fill request cprb param block with FQ request */ |
1516 | preqparm = (struct fqreqparm __force *)preqcblk->req_parmb; |
1517 | memcpy(preqparm->subfunc_code, "FQ" , 2); |
1518 | memcpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array)); |
1519 | preqparm->rule_array_len = |
1520 | sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); |
1521 | preqparm->lv1.len = sizeof(preqparm->lv1); |
1522 | preqparm->dummylen = sizeof(preqparm->dummylen); |
1523 | preqcblk->req_parml = parmbsize; |
1524 | |
1525 | /* fill xcrb struct */ |
1526 | prep_xcrb(pxcrb: &xcrb, cardnr, preqcblk, prepcblk); |
1527 | |
1528 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ |
1529 | rc = zcrypt_send_cprb(xcRB: &xcrb); |
1530 | if (rc) { |
1531 | ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n" , |
1532 | __func__, (int)cardnr, (int)domain, rc); |
1533 | goto out; |
1534 | } |
1535 | |
1536 | /* check response returncode and reasoncode */ |
1537 | if (prepcblk->ccp_rtcode != 0) { |
1538 | ZCRYPT_DBF_ERR("%s unwrap secure key failure, card response %d/%d\n" , |
1539 | __func__, |
1540 | (int)prepcblk->ccp_rtcode, |
1541 | (int)prepcblk->ccp_rscode); |
1542 | rc = -EIO; |
1543 | goto out; |
1544 | } |
1545 | |
1546 | /* process response cprb param block */ |
1547 | ptr = ((u8 *)prepcblk) + sizeof(struct CPRBX); |
1548 | prepcblk->rpl_parmb = (u8 __user *)ptr; |
1549 | prepparm = (struct fqrepparm *)ptr; |
1550 | ptr = prepparm->lvdata; |
1551 | |
1552 | /* check and possibly copy reply rule array */ |
1553 | len = *((u16 *)ptr); |
1554 | if (len > sizeof(u16)) { |
1555 | ptr += sizeof(u16); |
1556 | len -= sizeof(u16); |
1557 | if (rarray && rarraylen && *rarraylen > 0) { |
1558 | *rarraylen = (len > *rarraylen ? *rarraylen : len); |
1559 | memcpy(rarray, ptr, *rarraylen); |
1560 | } |
1561 | ptr += len; |
1562 | } |
1563 | /* check and possible copy reply var array */ |
1564 | len = *((u16 *)ptr); |
1565 | if (len > sizeof(u16)) { |
1566 | ptr += sizeof(u16); |
1567 | len -= sizeof(u16); |
1568 | if (varray && varraylen && *varraylen > 0) { |
1569 | *varraylen = (len > *varraylen ? *varraylen : len); |
1570 | memcpy(varray, ptr, *varraylen); |
1571 | } |
1572 | ptr += len; |
1573 | } |
1574 | |
1575 | out: |
1576 | free_cprbmem(mem, paramblen: parmbsize, scrub: 0); |
1577 | return rc; |
1578 | } |
1579 | EXPORT_SYMBOL(cca_query_crypto_facility); |
1580 | |
1581 | static int cca_info_cache_fetch(u16 cardnr, u16 domain, struct cca_info *ci) |
1582 | { |
1583 | int rc = -ENOENT; |
1584 | struct cca_info_list_entry *ptr; |
1585 | |
1586 | spin_lock_bh(lock: &cca_info_list_lock); |
1587 | list_for_each_entry(ptr, &cca_info_list, list) { |
1588 | if (ptr->cardnr == cardnr && ptr->domain == domain) { |
1589 | memcpy(ci, &ptr->info, sizeof(*ci)); |
1590 | rc = 0; |
1591 | break; |
1592 | } |
1593 | } |
1594 | spin_unlock_bh(lock: &cca_info_list_lock); |
1595 | |
1596 | return rc; |
1597 | } |
1598 | |
1599 | static void cca_info_cache_update(u16 cardnr, u16 domain, |
1600 | const struct cca_info *ci) |
1601 | { |
1602 | int found = 0; |
1603 | struct cca_info_list_entry *ptr; |
1604 | |
1605 | spin_lock_bh(lock: &cca_info_list_lock); |
1606 | list_for_each_entry(ptr, &cca_info_list, list) { |
1607 | if (ptr->cardnr == cardnr && |
1608 | ptr->domain == domain) { |
1609 | memcpy(&ptr->info, ci, sizeof(*ci)); |
1610 | found = 1; |
1611 | break; |
1612 | } |
1613 | } |
1614 | if (!found) { |
1615 | ptr = kmalloc(size: sizeof(*ptr), GFP_ATOMIC); |
1616 | if (!ptr) { |
1617 | spin_unlock_bh(lock: &cca_info_list_lock); |
1618 | return; |
1619 | } |
1620 | ptr->cardnr = cardnr; |
1621 | ptr->domain = domain; |
1622 | memcpy(&ptr->info, ci, sizeof(*ci)); |
1623 | list_add(new: &ptr->list, head: &cca_info_list); |
1624 | } |
1625 | spin_unlock_bh(lock: &cca_info_list_lock); |
1626 | } |
1627 | |
1628 | static void cca_info_cache_scrub(u16 cardnr, u16 domain) |
1629 | { |
1630 | struct cca_info_list_entry *ptr; |
1631 | |
1632 | spin_lock_bh(lock: &cca_info_list_lock); |
1633 | list_for_each_entry(ptr, &cca_info_list, list) { |
1634 | if (ptr->cardnr == cardnr && |
1635 | ptr->domain == domain) { |
1636 | list_del(entry: &ptr->list); |
1637 | kfree(objp: ptr); |
1638 | break; |
1639 | } |
1640 | } |
1641 | spin_unlock_bh(lock: &cca_info_list_lock); |
1642 | } |
1643 | |
1644 | static void __exit mkvp_cache_free(void) |
1645 | { |
1646 | struct cca_info_list_entry *ptr, *pnext; |
1647 | |
1648 | spin_lock_bh(lock: &cca_info_list_lock); |
1649 | list_for_each_entry_safe(ptr, pnext, &cca_info_list, list) { |
1650 | list_del(entry: &ptr->list); |
1651 | kfree(objp: ptr); |
1652 | } |
1653 | spin_unlock_bh(lock: &cca_info_list_lock); |
1654 | } |
1655 | |
1656 | /* |
1657 | * Fetch cca_info values via query_crypto_facility from adapter. |
1658 | */ |
1659 | static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci) |
1660 | { |
1661 | int rc, found = 0; |
1662 | size_t rlen, vlen; |
1663 | u8 *rarray, *varray, *pg; |
1664 | struct zcrypt_device_status_ext devstat; |
1665 | |
1666 | memset(ci, 0, sizeof(*ci)); |
1667 | |
1668 | /* get first info from zcrypt device driver about this apqn */ |
1669 | rc = zcrypt_device_status_ext(card: cardnr, queue: domain, devstatus: &devstat); |
1670 | if (rc) |
1671 | return rc; |
1672 | ci->hwtype = devstat.hwtype; |
1673 | |
1674 | /* prep page for rule array and var array use */ |
1675 | pg = (u8 *)__get_free_page(GFP_KERNEL); |
1676 | if (!pg) |
1677 | return -ENOMEM; |
1678 | rarray = pg; |
1679 | varray = pg + PAGE_SIZE / 2; |
1680 | rlen = vlen = PAGE_SIZE / 2; |
1681 | |
1682 | /* QF for this card/domain */ |
1683 | rc = cca_query_crypto_facility(cardnr, domain, "STATICSA" , |
1684 | rarray, &rlen, varray, &vlen); |
1685 | if (rc == 0 && rlen >= 10 * 8 && vlen >= 204) { |
1686 | memcpy(ci->serial, rarray, 8); |
1687 | ci->new_asym_mk_state = (char)rarray[4 * 8]; |
1688 | ci->cur_asym_mk_state = (char)rarray[5 * 8]; |
1689 | ci->old_asym_mk_state = (char)rarray[6 * 8]; |
1690 | if (ci->old_asym_mk_state == '2') |
1691 | memcpy(ci->old_asym_mkvp, varray + 64, 16); |
1692 | if (ci->cur_asym_mk_state == '2') |
1693 | memcpy(ci->cur_asym_mkvp, varray + 84, 16); |
1694 | if (ci->new_asym_mk_state == '3') |
1695 | memcpy(ci->new_asym_mkvp, varray + 104, 16); |
1696 | ci->new_aes_mk_state = (char)rarray[7 * 8]; |
1697 | ci->cur_aes_mk_state = (char)rarray[8 * 8]; |
1698 | ci->old_aes_mk_state = (char)rarray[9 * 8]; |
1699 | if (ci->old_aes_mk_state == '2') |
1700 | memcpy(&ci->old_aes_mkvp, varray + 172, 8); |
1701 | if (ci->cur_aes_mk_state == '2') |
1702 | memcpy(&ci->cur_aes_mkvp, varray + 184, 8); |
1703 | if (ci->new_aes_mk_state == '3') |
1704 | memcpy(&ci->new_aes_mkvp, varray + 196, 8); |
1705 | found++; |
1706 | } |
1707 | if (!found) |
1708 | goto out; |
1709 | rlen = vlen = PAGE_SIZE / 2; |
1710 | rc = cca_query_crypto_facility(cardnr, domain, "STATICSB" , |
1711 | rarray, &rlen, varray, &vlen); |
1712 | if (rc == 0 && rlen >= 13 * 8 && vlen >= 240) { |
1713 | ci->new_apka_mk_state = (char)rarray[10 * 8]; |
1714 | ci->cur_apka_mk_state = (char)rarray[11 * 8]; |
1715 | ci->old_apka_mk_state = (char)rarray[12 * 8]; |
1716 | if (ci->old_apka_mk_state == '2') |
1717 | memcpy(&ci->old_apka_mkvp, varray + 208, 8); |
1718 | if (ci->cur_apka_mk_state == '2') |
1719 | memcpy(&ci->cur_apka_mkvp, varray + 220, 8); |
1720 | if (ci->new_apka_mk_state == '3') |
1721 | memcpy(&ci->new_apka_mkvp, varray + 232, 8); |
1722 | found++; |
1723 | } |
1724 | |
1725 | out: |
1726 | free_page((unsigned long)pg); |
1727 | return found == 2 ? 0 : -ENOENT; |
1728 | } |
1729 | |
1730 | /* |
1731 | * Fetch cca information about a CCA queue. |
1732 | */ |
1733 | int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify) |
1734 | { |
1735 | int rc; |
1736 | |
1737 | rc = cca_info_cache_fetch(cardnr: card, domain: dom, ci); |
1738 | if (rc || verify) { |
1739 | rc = fetch_cca_info(cardnr: card, domain: dom, ci); |
1740 | if (rc == 0) |
1741 | cca_info_cache_update(cardnr: card, domain: dom, ci); |
1742 | } |
1743 | |
1744 | return rc; |
1745 | } |
1746 | EXPORT_SYMBOL(cca_get_info); |
1747 | |
1748 | /* |
1749 | * Search for a matching crypto card based on the |
1750 | * Master Key Verification Pattern given. |
1751 | */ |
1752 | static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain, |
1753 | int verify, int minhwtype) |
1754 | { |
1755 | struct zcrypt_device_status_ext *device_status; |
1756 | u16 card, dom; |
1757 | struct cca_info ci; |
1758 | int i, rc, oi = -1; |
1759 | |
1760 | /* mkvp must not be zero, minhwtype needs to be >= 0 */ |
1761 | if (mkvp == 0 || minhwtype < 0) |
1762 | return -EINVAL; |
1763 | |
1764 | /* fetch status of all crypto cards */ |
1765 | device_status = kvmalloc_array(MAX_ZDEV_ENTRIES_EXT, |
1766 | sizeof(struct zcrypt_device_status_ext), |
1767 | GFP_KERNEL); |
1768 | if (!device_status) |
1769 | return -ENOMEM; |
1770 | zcrypt_device_status_mask_ext(devstatus: device_status); |
1771 | |
1772 | /* walk through all crypto cards */ |
1773 | for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { |
1774 | card = AP_QID_CARD(device_status[i].qid); |
1775 | dom = AP_QID_QUEUE(device_status[i].qid); |
1776 | if (device_status[i].online && |
1777 | device_status[i].functions & 0x04) { |
1778 | /* enabled CCA card, check current mkvp from cache */ |
1779 | if (cca_info_cache_fetch(card, dom, &ci) == 0 && |
1780 | ci.hwtype >= minhwtype && |
1781 | ci.cur_aes_mk_state == '2' && |
1782 | ci.cur_aes_mkvp == mkvp) { |
1783 | if (!verify) |
1784 | break; |
1785 | /* verify: refresh card info */ |
1786 | if (fetch_cca_info(card, dom, &ci) == 0) { |
1787 | cca_info_cache_update(card, dom, &ci); |
1788 | if (ci.hwtype >= minhwtype && |
1789 | ci.cur_aes_mk_state == '2' && |
1790 | ci.cur_aes_mkvp == mkvp) |
1791 | break; |
1792 | } |
1793 | } |
1794 | } else { |
1795 | /* Card is offline and/or not a CCA card. */ |
1796 | /* del mkvp entry from cache if it exists */ |
1797 | cca_info_cache_scrub(card, dom); |
1798 | } |
1799 | } |
1800 | if (i >= MAX_ZDEV_ENTRIES_EXT) { |
1801 | /* nothing found, so this time without cache */ |
1802 | for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { |
1803 | if (!(device_status[i].online && |
1804 | device_status[i].functions & 0x04)) |
1805 | continue; |
1806 | card = AP_QID_CARD(device_status[i].qid); |
1807 | dom = AP_QID_QUEUE(device_status[i].qid); |
1808 | /* fresh fetch mkvp from adapter */ |
1809 | if (fetch_cca_info(card, dom, &ci) == 0) { |
1810 | cca_info_cache_update(card, dom, &ci); |
1811 | if (ci.hwtype >= minhwtype && |
1812 | ci.cur_aes_mk_state == '2' && |
1813 | ci.cur_aes_mkvp == mkvp) |
1814 | break; |
1815 | if (ci.hwtype >= minhwtype && |
1816 | ci.old_aes_mk_state == '2' && |
1817 | ci.old_aes_mkvp == mkvp && |
1818 | oi < 0) |
1819 | oi = i; |
1820 | } |
1821 | } |
1822 | if (i >= MAX_ZDEV_ENTRIES_EXT && oi >= 0) { |
1823 | /* old mkvp matched, use this card then */ |
1824 | card = AP_QID_CARD(device_status[oi].qid); |
1825 | dom = AP_QID_QUEUE(device_status[oi].qid); |
1826 | } |
1827 | } |
1828 | if (i < MAX_ZDEV_ENTRIES_EXT || oi >= 0) { |
1829 | if (pcardnr) |
1830 | *pcardnr = card; |
1831 | if (pdomain) |
1832 | *pdomain = dom; |
1833 | rc = (i < MAX_ZDEV_ENTRIES_EXT ? 0 : 1); |
1834 | } else { |
1835 | rc = -ENODEV; |
1836 | } |
1837 | |
1838 | kvfree(addr: device_status); |
1839 | return rc; |
1840 | } |
1841 | |
1842 | /* |
1843 | * Search for a matching crypto card based on the Master Key |
1844 | * Verification Pattern provided inside a secure key token. |
1845 | */ |
1846 | int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify) |
1847 | { |
1848 | u64 mkvp; |
1849 | int minhwtype = 0; |
1850 | const struct keytoken_header *hdr = (struct keytoken_header *)key; |
1851 | |
1852 | if (hdr->type != TOKTYPE_CCA_INTERNAL) |
1853 | return -EINVAL; |
1854 | |
1855 | switch (hdr->version) { |
1856 | case TOKVER_CCA_AES: |
1857 | mkvp = ((struct secaeskeytoken *)key)->mkvp; |
1858 | break; |
1859 | case TOKVER_CCA_VLSC: |
1860 | mkvp = ((struct cipherkeytoken *)key)->mkvp0; |
1861 | minhwtype = AP_DEVICE_TYPE_CEX6; |
1862 | break; |
1863 | default: |
1864 | return -EINVAL; |
1865 | } |
1866 | |
1867 | return findcard(mkvp, pcardnr, pdomain, verify, minhwtype); |
1868 | } |
1869 | EXPORT_SYMBOL(cca_findcard); |
1870 | |
1871 | int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain, |
1872 | int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp, |
1873 | int verify) |
1874 | { |
1875 | struct zcrypt_device_status_ext *device_status; |
1876 | u32 *_apqns = NULL, _nr_apqns = 0; |
1877 | int i, card, dom, curmatch, oldmatch, rc = 0; |
1878 | struct cca_info ci; |
1879 | |
1880 | /* fetch status of all crypto cards */ |
1881 | device_status = kvmalloc_array(MAX_ZDEV_ENTRIES_EXT, |
1882 | sizeof(struct zcrypt_device_status_ext), |
1883 | GFP_KERNEL); |
1884 | if (!device_status) |
1885 | return -ENOMEM; |
1886 | zcrypt_device_status_mask_ext(devstatus: device_status); |
1887 | |
1888 | /* allocate 1k space for up to 256 apqns */ |
1889 | _apqns = kmalloc_array(n: 256, size: sizeof(u32), GFP_KERNEL); |
1890 | if (!_apqns) { |
1891 | kvfree(addr: device_status); |
1892 | return -ENOMEM; |
1893 | } |
1894 | |
1895 | /* walk through all the crypto apqnss */ |
1896 | for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { |
1897 | card = AP_QID_CARD(device_status[i].qid); |
1898 | dom = AP_QID_QUEUE(device_status[i].qid); |
1899 | /* check online state */ |
1900 | if (!device_status[i].online) |
1901 | continue; |
1902 | /* check for cca functions */ |
1903 | if (!(device_status[i].functions & 0x04)) |
1904 | continue; |
1905 | /* check cardnr */ |
1906 | if (cardnr != 0xFFFF && card != cardnr) |
1907 | continue; |
1908 | /* check domain */ |
1909 | if (domain != 0xFFFF && dom != domain) |
1910 | continue; |
1911 | /* get cca info on this apqn */ |
1912 | if (cca_get_info(card, dom, &ci, verify)) |
1913 | continue; |
1914 | /* current master key needs to be valid */ |
1915 | if (mktype == AES_MK_SET && ci.cur_aes_mk_state != '2') |
1916 | continue; |
1917 | if (mktype == APKA_MK_SET && ci.cur_apka_mk_state != '2') |
1918 | continue; |
1919 | /* check min hardware type */ |
1920 | if (minhwtype > 0 && minhwtype > ci.hwtype) |
1921 | continue; |
1922 | if (cur_mkvp || old_mkvp) { |
1923 | /* check mkvps */ |
1924 | curmatch = oldmatch = 0; |
1925 | if (mktype == AES_MK_SET) { |
1926 | if (cur_mkvp && cur_mkvp == ci.cur_aes_mkvp) |
1927 | curmatch = 1; |
1928 | if (old_mkvp && ci.old_aes_mk_state == '2' && |
1929 | old_mkvp == ci.old_aes_mkvp) |
1930 | oldmatch = 1; |
1931 | } else { |
1932 | if (cur_mkvp && cur_mkvp == ci.cur_apka_mkvp) |
1933 | curmatch = 1; |
1934 | if (old_mkvp && ci.old_apka_mk_state == '2' && |
1935 | old_mkvp == ci.old_apka_mkvp) |
1936 | oldmatch = 1; |
1937 | } |
1938 | if (curmatch + oldmatch < 1) |
1939 | continue; |
1940 | } |
1941 | /* apqn passed all filtering criterons, add to the array */ |
1942 | if (_nr_apqns < 256) |
1943 | _apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom); |
1944 | } |
1945 | |
1946 | /* nothing found ? */ |
1947 | if (!_nr_apqns) { |
1948 | kfree(objp: _apqns); |
1949 | rc = -ENODEV; |
1950 | } else { |
1951 | /* no re-allocation, simple return the _apqns array */ |
1952 | *apqns = _apqns; |
1953 | *nr_apqns = _nr_apqns; |
1954 | rc = 0; |
1955 | } |
1956 | |
1957 | kvfree(addr: device_status); |
1958 | return rc; |
1959 | } |
1960 | EXPORT_SYMBOL(cca_findcard2); |
1961 | |
1962 | void __exit zcrypt_ccamisc_exit(void) |
1963 | { |
1964 | mkvp_cache_free(); |
1965 | } |
1966 | |