1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * pkey cca specific code
4 *
5 * Copyright IBM Corp. 2024
6 */
7
8 #define KMSG_COMPONENT "pkey"
9 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
10
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/cpufeature.h>
14
15 #include "zcrypt_api.h"
16 #include "zcrypt_ccamisc.h"
17 #include "pkey_base.h"
18
19 MODULE_LICENSE("GPL");
20 MODULE_AUTHOR("IBM Corporation");
21 MODULE_DESCRIPTION("s390 protected key CCA handler");
22
23 #if IS_MODULE(CONFIG_PKEY_CCA)
24 static struct ap_device_id pkey_cca_card_ids[] = {
25 { .dev_type = AP_DEVICE_TYPE_CEX4 },
26 { .dev_type = AP_DEVICE_TYPE_CEX5 },
27 { .dev_type = AP_DEVICE_TYPE_CEX6 },
28 { .dev_type = AP_DEVICE_TYPE_CEX7 },
29 { .dev_type = AP_DEVICE_TYPE_CEX8 },
30 { /* end of list */ },
31 };
32 MODULE_DEVICE_TABLE(ap, pkey_cca_card_ids);
33 #endif
34
35 /*
36 * Check key blob for known and supported CCA key.
37 */
is_cca_key(const u8 * key,u32 keylen)38 static bool is_cca_key(const u8 *key, u32 keylen)
39 {
40 struct keytoken_header *hdr = (struct keytoken_header *)key;
41
42 if (keylen < sizeof(*hdr))
43 return false;
44
45 switch (hdr->type) {
46 case TOKTYPE_CCA_INTERNAL:
47 switch (hdr->version) {
48 case TOKVER_CCA_AES:
49 case TOKVER_CCA_VLSC:
50 return true;
51 default:
52 return false;
53 }
54 case TOKTYPE_CCA_INTERNAL_PKA:
55 return true;
56 default:
57 return false;
58 }
59 }
60
is_cca_keytype(enum pkey_key_type key_type)61 static bool is_cca_keytype(enum pkey_key_type key_type)
62 {
63 switch (key_type) {
64 case PKEY_TYPE_CCA_DATA:
65 case PKEY_TYPE_CCA_CIPHER:
66 case PKEY_TYPE_CCA_ECC:
67 return true;
68 default:
69 return false;
70 }
71 }
72
cca_apqns4key(const u8 * key,u32 keylen,u32 flags,struct pkey_apqn * apqns,size_t * nr_apqns)73 static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
74 struct pkey_apqn *apqns, size_t *nr_apqns)
75 {
76 struct keytoken_header *hdr = (struct keytoken_header *)key;
77 u32 _nr_apqns, *_apqns = NULL;
78 int rc;
79
80 if (!flags)
81 flags = PKEY_FLAGS_MATCH_CUR_MKVP | PKEY_FLAGS_MATCH_ALT_MKVP;
82
83 if (keylen < sizeof(struct keytoken_header))
84 return -EINVAL;
85
86 zcrypt_wait_api_operational();
87
88 if (hdr->type == TOKTYPE_CCA_INTERNAL) {
89 u64 cur_mkvp = 0, old_mkvp = 0;
90 int minhwtype = ZCRYPT_CEX3C;
91
92 if (hdr->version == TOKVER_CCA_AES) {
93 struct secaeskeytoken *t = (struct secaeskeytoken *)key;
94
95 if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
96 cur_mkvp = t->mkvp;
97 if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
98 old_mkvp = t->mkvp;
99 } else if (hdr->version == TOKVER_CCA_VLSC) {
100 struct cipherkeytoken *t = (struct cipherkeytoken *)key;
101
102 minhwtype = ZCRYPT_CEX6;
103 if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
104 cur_mkvp = t->mkvp0;
105 if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
106 old_mkvp = t->mkvp0;
107 } else {
108 /* unknown CCA internal token type */
109 return -EINVAL;
110 }
111 rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
112 minhwtype, AES_MK_SET,
113 cur_mkvp, old_mkvp, 1);
114 if (rc)
115 goto out;
116
117 } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
118 struct eccprivkeytoken *t = (struct eccprivkeytoken *)key;
119 u64 cur_mkvp = 0, old_mkvp = 0;
120
121 if (t->secid == 0x20) {
122 if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
123 cur_mkvp = t->mkvp;
124 if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
125 old_mkvp = t->mkvp;
126 } else {
127 /* unknown CCA internal 2 token type */
128 return -EINVAL;
129 }
130 rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
131 ZCRYPT_CEX7, APKA_MK_SET,
132 cur_mkvp, old_mkvp, 1);
133 if (rc)
134 goto out;
135
136 } else {
137 PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",
138 __func__, hdr->type, hdr->version);
139 return -EINVAL;
140 }
141
142 if (apqns) {
143 if (*nr_apqns < _nr_apqns)
144 rc = -ENOSPC;
145 else
146 memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
147 }
148 *nr_apqns = _nr_apqns;
149
150 out:
151 kfree(_apqns);
152 pr_debug("rc=%d\n", rc);
153 return rc;
154 }
155
cca_apqns4type(enum pkey_key_type ktype,u8 cur_mkvp[32],u8 alt_mkvp[32],u32 flags,struct pkey_apqn * apqns,size_t * nr_apqns)156 static int cca_apqns4type(enum pkey_key_type ktype,
157 u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
158 struct pkey_apqn *apqns, size_t *nr_apqns)
159 {
160 u32 _nr_apqns, *_apqns = NULL;
161 int rc;
162
163 zcrypt_wait_api_operational();
164
165 if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) {
166 u64 cur_mkvp = 0, old_mkvp = 0;
167 int minhwtype = ZCRYPT_CEX3C;
168
169 if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
170 cur_mkvp = *((u64 *)cur_mkvp);
171 if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
172 old_mkvp = *((u64 *)alt_mkvp);
173 if (ktype == PKEY_TYPE_CCA_CIPHER)
174 minhwtype = ZCRYPT_CEX6;
175 rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
176 minhwtype, AES_MK_SET,
177 cur_mkvp, old_mkvp, 1);
178 if (rc)
179 goto out;
180
181 } else if (ktype == PKEY_TYPE_CCA_ECC) {
182 u64 cur_mkvp = 0, old_mkvp = 0;
183
184 if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
185 cur_mkvp = *((u64 *)cur_mkvp);
186 if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
187 old_mkvp = *((u64 *)alt_mkvp);
188 rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
189 ZCRYPT_CEX7, APKA_MK_SET,
190 cur_mkvp, old_mkvp, 1);
191 if (rc)
192 goto out;
193
194 } else {
195 PKEY_DBF_ERR("%s unknown/unsupported key type %d",
196 __func__, (int)ktype);
197 return -EINVAL;
198 }
199
200 if (apqns) {
201 if (*nr_apqns < _nr_apqns)
202 rc = -ENOSPC;
203 else
204 memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
205 }
206 *nr_apqns = _nr_apqns;
207
208 out:
209 kfree(_apqns);
210 pr_debug("rc=%d\n", rc);
211 return rc;
212 }
213
cca_key2protkey(const struct pkey_apqn * apqns,size_t nr_apqns,const u8 * key,u32 keylen,u8 * protkey,u32 * protkeylen,u32 * protkeytype)214 static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
215 const u8 *key, u32 keylen,
216 u8 *protkey, u32 *protkeylen, u32 *protkeytype)
217 {
218 struct keytoken_header *hdr = (struct keytoken_header *)key;
219 struct pkey_apqn *local_apqns = NULL;
220 int i, rc;
221
222 if (keylen < sizeof(*hdr))
223 return -EINVAL;
224
225 if (hdr->type == TOKTYPE_CCA_INTERNAL &&
226 hdr->version == TOKVER_CCA_AES) {
227 /* CCA AES data key */
228 if (keylen != sizeof(struct secaeskeytoken))
229 return -EINVAL;
230 if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0))
231 return -EINVAL;
232 } else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
233 hdr->version == TOKVER_CCA_VLSC) {
234 /* CCA AES cipher key */
235 if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
236 return -EINVAL;
237 if (cca_check_secaescipherkey(pkey_dbf_info,
238 3, key, 0, 1))
239 return -EINVAL;
240 } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
241 /* CCA ECC (private) key */
242 if (keylen < sizeof(struct eccprivkeytoken))
243 return -EINVAL;
244 if (cca_check_sececckeytoken(pkey_dbf_info, 3, key, keylen, 1))
245 return -EINVAL;
246 } else {
247 PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",
248 __func__, hdr->type, hdr->version);
249 return -EINVAL;
250 }
251
252 zcrypt_wait_api_operational();
253
254 if (!apqns || (nr_apqns == 1 &&
255 apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
256 nr_apqns = MAXAPQNSINLIST;
257 local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),
258 GFP_KERNEL);
259 if (!local_apqns)
260 return -ENOMEM;
261 rc = cca_apqns4key(key, keylen, 0, local_apqns, &nr_apqns);
262 if (rc)
263 goto out;
264 apqns = local_apqns;
265 }
266
267 for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
268 if (hdr->type == TOKTYPE_CCA_INTERNAL &&
269 hdr->version == TOKVER_CCA_AES) {
270 rc = cca_sec2protkey(apqns[i].card, apqns[i].domain,
271 key, protkey,
272 protkeylen, protkeytype);
273 } else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
274 hdr->version == TOKVER_CCA_VLSC) {
275 rc = cca_cipher2protkey(apqns[i].card, apqns[i].domain,
276 key, protkey,
277 protkeylen, protkeytype);
278 } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
279 rc = cca_ecc2protkey(apqns[i].card, apqns[i].domain,
280 key, protkey,
281 protkeylen, protkeytype);
282 } else {
283 rc = -EINVAL;
284 break;
285 }
286 }
287
288 out:
289 kfree(local_apqns);
290 pr_debug("rc=%d\n", rc);
291 return rc;
292 }
293
294 /*
295 * Generate CCA secure key.
296 * As of now only CCA AES Data or Cipher secure keys are
297 * supported.
298 * keytype is one of the PKEY_KEYTYPE_* constants,
299 * subtype may be 0 or PKEY_TYPE_CCA_DATA or PKEY_TYPE_CCA_CIPHER,
300 * keybitsize is the bit size of the key (may be 0 for
301 * keytype PKEY_KEYTYPE_AES_*).
302 */
cca_gen_key(const struct pkey_apqn * apqns,size_t nr_apqns,u32 keytype,u32 subtype,u32 keybitsize,u32 flags,u8 * keybuf,u32 * keybuflen,u32 * _keyinfo)303 static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
304 u32 keytype, u32 subtype,
305 u32 keybitsize, u32 flags,
306 u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
307 {
308 struct pkey_apqn *local_apqns = NULL;
309 int i, len, rc;
310
311 /* check keytype, subtype, keybitsize */
312 switch (keytype) {
313 case PKEY_KEYTYPE_AES_128:
314 case PKEY_KEYTYPE_AES_192:
315 case PKEY_KEYTYPE_AES_256:
316 len = pkey_keytype_aes_to_size(keytype);
317 if (keybitsize && keybitsize != 8 * len) {
318 PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
319 __func__, keybitsize);
320 return -EINVAL;
321 }
322 keybitsize = 8 * len;
323 switch (subtype) {
324 case PKEY_TYPE_CCA_DATA:
325 case PKEY_TYPE_CCA_CIPHER:
326 break;
327 default:
328 PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
329 __func__, subtype);
330 return -EINVAL;
331 }
332 break;
333 default:
334 PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
335 __func__, keytype);
336 return -EINVAL;
337 }
338
339 zcrypt_wait_api_operational();
340
341 if (!apqns || (nr_apqns == 1 &&
342 apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
343 nr_apqns = MAXAPQNSINLIST;
344 local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),
345 GFP_KERNEL);
346 if (!local_apqns)
347 return -ENOMEM;
348 rc = cca_apqns4type(subtype, NULL, NULL, 0,
349 local_apqns, &nr_apqns);
350 if (rc)
351 goto out;
352 apqns = local_apqns;
353 }
354
355 for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
356 if (subtype == PKEY_TYPE_CCA_CIPHER) {
357 rc = cca_gencipherkey(apqns[i].card, apqns[i].domain,
358 keybitsize, flags,
359 keybuf, keybuflen);
360 } else {
361 /* PKEY_TYPE_CCA_DATA */
362 rc = cca_genseckey(apqns[i].card, apqns[i].domain,
363 keybitsize, keybuf);
364 *keybuflen = (rc ? 0 : SECKEYBLOBSIZE);
365 }
366 }
367
368 out:
369 kfree(local_apqns);
370 pr_debug("rc=%d\n", rc);
371 return rc;
372 }
373
374 /*
375 * Generate CCA secure key with given clear key value.
376 * As of now only CCA AES Data or Cipher secure keys are
377 * supported.
378 * keytype is one of the PKEY_KEYTYPE_* constants,
379 * subtype may be 0 or PKEY_TYPE_CCA_DATA or PKEY_TYPE_CCA_CIPHER,
380 * keybitsize is the bit size of the key (may be 0 for
381 * keytype PKEY_KEYTYPE_AES_*).
382 */
cca_clr2key(const struct pkey_apqn * apqns,size_t nr_apqns,u32 keytype,u32 subtype,u32 keybitsize,u32 flags,const u8 * clrkey,u32 clrkeylen,u8 * keybuf,u32 * keybuflen,u32 * _keyinfo)383 static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
384 u32 keytype, u32 subtype,
385 u32 keybitsize, u32 flags,
386 const u8 *clrkey, u32 clrkeylen,
387 u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
388 {
389 struct pkey_apqn *local_apqns = NULL;
390 int i, len, rc;
391
392 /* check keytype, subtype, clrkeylen, keybitsize */
393 switch (keytype) {
394 case PKEY_KEYTYPE_AES_128:
395 case PKEY_KEYTYPE_AES_192:
396 case PKEY_KEYTYPE_AES_256:
397 len = pkey_keytype_aes_to_size(keytype);
398 if (keybitsize && keybitsize != 8 * len) {
399 PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
400 __func__, keybitsize);
401 return -EINVAL;
402 }
403 keybitsize = 8 * len;
404 if (clrkeylen != len) {
405 PKEY_DBF_ERR("%s invalid clear key len %d != %d\n",
406 __func__, clrkeylen, len);
407 return -EINVAL;
408 }
409 switch (subtype) {
410 case PKEY_TYPE_CCA_DATA:
411 case PKEY_TYPE_CCA_CIPHER:
412 break;
413 default:
414 PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
415 __func__, subtype);
416 return -EINVAL;
417 }
418 break;
419 default:
420 PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
421 __func__, keytype);
422 return -EINVAL;
423 }
424
425 zcrypt_wait_api_operational();
426
427 if (!apqns || (nr_apqns == 1 &&
428 apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
429 nr_apqns = MAXAPQNSINLIST;
430 local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),
431 GFP_KERNEL);
432 if (!local_apqns)
433 return -ENOMEM;
434 rc = cca_apqns4type(subtype, NULL, NULL, 0,
435 local_apqns, &nr_apqns);
436 if (rc)
437 goto out;
438 apqns = local_apqns;
439 }
440
441 for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
442 if (subtype == PKEY_TYPE_CCA_CIPHER) {
443 rc = cca_clr2cipherkey(apqns[i].card, apqns[i].domain,
444 keybitsize, flags, clrkey,
445 keybuf, keybuflen);
446 } else {
447 /* PKEY_TYPE_CCA_DATA */
448 rc = cca_clr2seckey(apqns[i].card, apqns[i].domain,
449 keybitsize, clrkey, keybuf);
450 *keybuflen = (rc ? 0 : SECKEYBLOBSIZE);
451 }
452 }
453
454 out:
455 kfree(local_apqns);
456 pr_debug("rc=%d\n", rc);
457 return rc;
458 }
459
cca_verifykey(const u8 * key,u32 keylen,u16 * card,u16 * dom,u32 * keytype,u32 * keybitsize,u32 * flags)460 static int cca_verifykey(const u8 *key, u32 keylen,
461 u16 *card, u16 *dom,
462 u32 *keytype, u32 *keybitsize, u32 *flags)
463 {
464 struct keytoken_header *hdr = (struct keytoken_header *)key;
465 u32 nr_apqns, *apqns = NULL;
466 int rc;
467
468 if (keylen < sizeof(*hdr))
469 return -EINVAL;
470
471 zcrypt_wait_api_operational();
472
473 if (hdr->type == TOKTYPE_CCA_INTERNAL &&
474 hdr->version == TOKVER_CCA_AES) {
475 struct secaeskeytoken *t = (struct secaeskeytoken *)key;
476
477 rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0);
478 if (rc)
479 goto out;
480 *keytype = PKEY_TYPE_CCA_DATA;
481 *keybitsize = t->bitsize;
482 rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
483 ZCRYPT_CEX3C, AES_MK_SET,
484 t->mkvp, 0, 1);
485 if (!rc)
486 *flags = PKEY_FLAGS_MATCH_CUR_MKVP;
487 if (rc == -ENODEV) {
488 rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
489 ZCRYPT_CEX3C, AES_MK_SET,
490 0, t->mkvp, 1);
491 if (!rc)
492 *flags = PKEY_FLAGS_MATCH_ALT_MKVP;
493 }
494 if (rc)
495 goto out;
496
497 *card = ((struct pkey_apqn *)apqns)->card;
498 *dom = ((struct pkey_apqn *)apqns)->domain;
499
500 } else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
501 hdr->version == TOKVER_CCA_VLSC) {
502 struct cipherkeytoken *t = (struct cipherkeytoken *)key;
503
504 rc = cca_check_secaescipherkey(pkey_dbf_info, 3, key, 0, 1);
505 if (rc)
506 goto out;
507 *keytype = PKEY_TYPE_CCA_CIPHER;
508 *keybitsize = PKEY_SIZE_UNKNOWN;
509 if (!t->plfver && t->wpllen == 512)
510 *keybitsize = PKEY_SIZE_AES_128;
511 else if (!t->plfver && t->wpllen == 576)
512 *keybitsize = PKEY_SIZE_AES_192;
513 else if (!t->plfver && t->wpllen == 640)
514 *keybitsize = PKEY_SIZE_AES_256;
515 rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
516 ZCRYPT_CEX6, AES_MK_SET,
517 t->mkvp0, 0, 1);
518 if (!rc)
519 *flags = PKEY_FLAGS_MATCH_CUR_MKVP;
520 if (rc == -ENODEV) {
521 rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
522 ZCRYPT_CEX6, AES_MK_SET,
523 0, t->mkvp0, 1);
524 if (!rc)
525 *flags = PKEY_FLAGS_MATCH_ALT_MKVP;
526 }
527 if (rc)
528 goto out;
529
530 *card = ((struct pkey_apqn *)apqns)->card;
531 *dom = ((struct pkey_apqn *)apqns)->domain;
532
533 } else {
534 /* unknown/unsupported key blob */
535 rc = -EINVAL;
536 }
537
538 out:
539 kfree(apqns);
540 pr_debug("rc=%d\n", rc);
541 return rc;
542 }
543
544 /*
545 * This function provides an alternate but usually slow way
546 * to convert a 'clear key token' with AES key material into
547 * a protected key. This is done via an intermediate step
548 * which creates a CCA AES DATA secure key first and then
549 * derives the protected key from this secure key.
550 */
cca_slowpath_key2protkey(const struct pkey_apqn * apqns,size_t nr_apqns,const u8 * key,u32 keylen,u8 * protkey,u32 * protkeylen,u32 * protkeytype)551 static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns,
552 size_t nr_apqns,
553 const u8 *key, u32 keylen,
554 u8 *protkey, u32 *protkeylen,
555 u32 *protkeytype)
556 {
557 const struct keytoken_header *hdr = (const struct keytoken_header *)key;
558 const struct clearkeytoken *t = (const struct clearkeytoken *)key;
559 u32 tmplen, keysize = 0;
560 u8 *tmpbuf;
561 int i, rc;
562
563 if (keylen < sizeof(*hdr))
564 return -EINVAL;
565
566 if (hdr->type == TOKTYPE_NON_CCA &&
567 hdr->version == TOKVER_CLEAR_KEY)
568 keysize = pkey_keytype_aes_to_size(t->keytype);
569 if (!keysize || t->len != keysize)
570 return -EINVAL;
571
572 /* alloc tmp key buffer */
573 tmpbuf = kmalloc(SECKEYBLOBSIZE, GFP_ATOMIC);
574 if (!tmpbuf)
575 return -ENOMEM;
576
577 /* try two times in case of failure */
578 for (i = 0, rc = -ENODEV; i < 2 && rc; i++) {
579 tmplen = SECKEYBLOBSIZE;
580 rc = cca_clr2key(NULL, 0, t->keytype, PKEY_TYPE_CCA_DATA,
581 8 * keysize, 0, t->clearkey, t->len,
582 tmpbuf, &tmplen, NULL);
583 pr_debug("cca_clr2key()=%d\n", rc);
584 if (rc)
585 continue;
586 rc = cca_key2protkey(NULL, 0, tmpbuf, tmplen,
587 protkey, protkeylen, protkeytype);
588 pr_debug("cca_key2protkey()=%d\n", rc);
589 }
590
591 kfree(tmpbuf);
592 pr_debug("rc=%d\n", rc);
593 return rc;
594 }
595
596 static struct pkey_handler cca_handler = {
597 .module = THIS_MODULE,
598 .name = "PKEY CCA handler",
599 .is_supported_key = is_cca_key,
600 .is_supported_keytype = is_cca_keytype,
601 .key_to_protkey = cca_key2protkey,
602 .slowpath_key_to_protkey = cca_slowpath_key2protkey,
603 .gen_key = cca_gen_key,
604 .clr_to_key = cca_clr2key,
605 .verify_key = cca_verifykey,
606 .apqns_for_key = cca_apqns4key,
607 .apqns_for_keytype = cca_apqns4type,
608 };
609
610 /*
611 * Module init
612 */
pkey_cca_init(void)613 static int __init pkey_cca_init(void)
614 {
615 /* register this module as pkey handler for all the cca stuff */
616 return pkey_handler_register(&cca_handler);
617 }
618
619 /*
620 * Module exit
621 */
pkey_cca_exit(void)622 static void __exit pkey_cca_exit(void)
623 {
624 /* unregister this module as pkey handler */
625 pkey_handler_unregister(&cca_handler);
626 }
627
628 module_init(pkey_cca_init);
629 module_exit(pkey_cca_exit);
630