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