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
17 MODULE_LICENSE("GPL");
18 MODULE_AUTHOR("IBM Corporation");
19 MODULE_DESCRIPTION("s390 protected key CCA handler");
20
21 #if IS_MODULE(CONFIG_PKEY_CCA)
22 static 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 };
30 MODULE_DEVICE_TABLE(ap, pkey_cca_card_ids);
31 #endif
32
33 /*
34 * Check key blob for known and supported CCA key.
35 */
is_cca_key(const u8 * key,u32 keylen)36 static 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
is_cca_keytype(enum pkey_key_type key_type)59 static 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
cca_apqns4key(const u8 * key,u32 keylen,u32 flags,struct pkey_apqn * apqns,size_t * nr_apqns,u32 pflags)71 static 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
153 out:
154 pr_debug("rc=%d\n", rc);
155 return rc;
156 }
157
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,u32 pflags)158 static 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
216 out:
217 pr_debug("rc=%d\n", rc);
218 return rc;
219 }
220
cca_key2protkey(const struct pkey_apqn * apqns,size_t nr_apqns,const u8 * key,u32 keylen,u8 * protkey,u32 * protkeylen,u32 * protkeytype,u32 pflags)221 static 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 (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, keylen, 0))
240 return -EINVAL;
241 } else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
242 hdr->version == TOKVER_CCA_VLSC) {
243 /* CCA AES cipher key */
244 if (cca_check_secaescipherkey(pkey_dbf_info,
245 3, key, keylen, 0, 1))
246 return -EINVAL;
247 } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
248 /* CCA ECC (private) key */
249 if (cca_check_sececckeytoken(pkey_dbf_info, 3, key, keylen, 1))
250 return -EINVAL;
251 } else {
252 PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",
253 __func__, hdr->type, hdr->version);
254 return -EINVAL;
255 }
256
257 zcrypt_wait_api_operational();
258
259 if (!apqns || (nr_apqns == 1 &&
260 apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
261 nr_apqns = MAXAPQNSINLIST;
262 rc = cca_apqns4key(key, keylen, 0, _apqns, &nr_apqns, pflags);
263 if (rc)
264 goto out;
265 apqns = _apqns;
266 }
267
268 for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
269 if (hdr->type == TOKTYPE_CCA_INTERNAL &&
270 hdr->version == TOKVER_CCA_AES) {
271 rc = cca_sec2protkey(apqns[i].card, apqns[i].domain,
272 key, protkey,
273 protkeylen, protkeytype, xflags);
274 } else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
275 hdr->version == TOKVER_CCA_VLSC) {
276 rc = cca_cipher2protkey(apqns[i].card, apqns[i].domain,
277 key, protkey,
278 protkeylen, protkeytype, xflags);
279 } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
280 rc = cca_ecc2protkey(apqns[i].card, apqns[i].domain,
281 key, protkey,
282 protkeylen, protkeytype, xflags);
283 } else {
284 rc = -EINVAL;
285 break;
286 }
287 }
288
289 out:
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,u32 pflags)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, u32 pflags)
307 {
308 struct pkey_apqn _apqns[MAXAPQNSINLIST];
309 int i, len, rc;
310 u32 xflags;
311
312 xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;
313
314 /* check keytype, subtype, keybitsize */
315 switch (keytype) {
316 case PKEY_KEYTYPE_AES_128:
317 case PKEY_KEYTYPE_AES_192:
318 case PKEY_KEYTYPE_AES_256:
319 len = pkey_keytype_aes_to_size(keytype);
320 if (keybitsize && keybitsize != 8 * len) {
321 PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
322 __func__, keybitsize);
323 return -EINVAL;
324 }
325 keybitsize = 8 * len;
326 switch (subtype) {
327 case PKEY_TYPE_CCA_DATA:
328 case PKEY_TYPE_CCA_CIPHER:
329 break;
330 default:
331 PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
332 __func__, subtype);
333 return -EINVAL;
334 }
335 break;
336 default:
337 PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
338 __func__, keytype);
339 return -EINVAL;
340 }
341
342 zcrypt_wait_api_operational();
343
344 if (!apqns || (nr_apqns == 1 &&
345 apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
346 nr_apqns = MAXAPQNSINLIST;
347 rc = cca_apqns4type(subtype, NULL, NULL, 0,
348 _apqns, &nr_apqns, pflags);
349 if (rc)
350 goto out;
351 apqns = _apqns;
352 }
353
354 for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
355 if (subtype == PKEY_TYPE_CCA_CIPHER) {
356 rc = cca_gencipherkey(apqns[i].card, apqns[i].domain,
357 keybitsize, flags,
358 keybuf, keybuflen, xflags);
359 } else {
360 /* PKEY_TYPE_CCA_DATA */
361 rc = cca_genseckey(apqns[i].card, apqns[i].domain,
362 keybitsize, keybuf, xflags);
363 *keybuflen = (rc ? 0 : SECKEYBLOBSIZE);
364 }
365 }
366
367 out:
368 pr_debug("rc=%d\n", rc);
369 return rc;
370 }
371
372 /*
373 * Generate CCA secure key with given clear key value.
374 * As of now only CCA AES Data or Cipher secure keys are
375 * supported.
376 * keytype is one of the PKEY_KEYTYPE_* constants,
377 * subtype may be 0 or PKEY_TYPE_CCA_DATA or PKEY_TYPE_CCA_CIPHER,
378 * keybitsize is the bit size of the key (may be 0 for
379 * keytype PKEY_KEYTYPE_AES_*).
380 */
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,u32 pflags)381 static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
382 u32 keytype, u32 subtype,
383 u32 keybitsize, u32 flags,
384 const u8 *clrkey, u32 clrkeylen,
385 u8 *keybuf, u32 *keybuflen, u32 *_keyinfo, u32 pflags)
386 {
387 struct pkey_apqn _apqns[MAXAPQNSINLIST];
388 int i, len, rc;
389 u32 xflags;
390
391 if (pflags & PKEY_XFLAG_NOCLEARKEY) {
392 PKEY_DBF_ERR("%s clear key but xflag NOCLEARKEY\n", __func__);
393 return -EINVAL;
394 }
395
396 xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;
397
398 /* check keytype, subtype, clrkeylen, keybitsize */
399 switch (keytype) {
400 case PKEY_KEYTYPE_AES_128:
401 case PKEY_KEYTYPE_AES_192:
402 case PKEY_KEYTYPE_AES_256:
403 len = pkey_keytype_aes_to_size(keytype);
404 if (keybitsize && keybitsize != 8 * len) {
405 PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
406 __func__, keybitsize);
407 return -EINVAL;
408 }
409 keybitsize = 8 * len;
410 if (clrkeylen != len) {
411 PKEY_DBF_ERR("%s invalid clear key len %d != %d\n",
412 __func__, clrkeylen, len);
413 return -EINVAL;
414 }
415 switch (subtype) {
416 case PKEY_TYPE_CCA_DATA:
417 case PKEY_TYPE_CCA_CIPHER:
418 break;
419 default:
420 PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
421 __func__, subtype);
422 return -EINVAL;
423 }
424 break;
425 default:
426 PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
427 __func__, keytype);
428 return -EINVAL;
429 }
430
431 zcrypt_wait_api_operational();
432
433 if (!apqns || (nr_apqns == 1 &&
434 apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
435 nr_apqns = MAXAPQNSINLIST;
436 rc = cca_apqns4type(subtype, NULL, NULL, 0,
437 _apqns, &nr_apqns, pflags);
438 if (rc)
439 goto out;
440 apqns = _apqns;
441 }
442
443 for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
444 if (subtype == PKEY_TYPE_CCA_CIPHER) {
445 rc = cca_clr2cipherkey(apqns[i].card, apqns[i].domain,
446 keybitsize, flags, clrkey,
447 keybuf, keybuflen, xflags);
448 } else {
449 /* PKEY_TYPE_CCA_DATA */
450 rc = cca_clr2seckey(apqns[i].card, apqns[i].domain,
451 keybitsize, clrkey, keybuf, xflags);
452 *keybuflen = (rc ? 0 : SECKEYBLOBSIZE);
453 }
454 }
455
456 out:
457 pr_debug("rc=%d\n", rc);
458 return rc;
459 }
460
cca_verifykey(const u8 * key,u32 keylen,u16 * card,u16 * dom,u32 * keytype,u32 * keybitsize,u32 * flags,u32 pflags)461 static int cca_verifykey(const u8 *key, u32 keylen,
462 u16 *card, u16 *dom,
463 u32 *keytype, u32 *keybitsize, u32 *flags, u32 pflags)
464 {
465 struct keytoken_header *hdr = (struct keytoken_header *)key;
466 u32 apqns[MAXAPQNSINLIST], nr_apqns = ARRAY_SIZE(apqns);
467 u32 xflags;
468 int rc;
469
470 xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;
471
472 if (keylen < sizeof(*hdr))
473 return -EINVAL;
474
475 zcrypt_wait_api_operational();
476
477 if (hdr->type == TOKTYPE_CCA_INTERNAL &&
478 hdr->version == TOKVER_CCA_AES) {
479 struct secaeskeytoken *t = (struct secaeskeytoken *)key;
480
481 rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, keylen, 0);
482 if (rc)
483 goto out;
484 *keytype = PKEY_TYPE_CCA_DATA;
485 *keybitsize = t->bitsize;
486 rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
487 ZCRYPT_CEX3C, AES_MK_SET,
488 t->mkvp, NULL, xflags);
489 if (!rc)
490 *flags = PKEY_FLAGS_MATCH_CUR_MKVP;
491 if (rc == -ENODEV) {
492 nr_apqns = ARRAY_SIZE(apqns);
493 rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
494 ZCRYPT_CEX3C, AES_MK_SET,
495 NULL, t->mkvp, xflags);
496 if (!rc)
497 *flags = PKEY_FLAGS_MATCH_ALT_MKVP;
498 }
499 if (rc)
500 goto out;
501
502 *card = ((struct pkey_apqn *)apqns)->card;
503 *dom = ((struct pkey_apqn *)apqns)->domain;
504
505 } else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
506 hdr->version == TOKVER_CCA_VLSC) {
507 struct cipherkeytoken *t = (struct cipherkeytoken *)key;
508
509 rc = cca_check_secaescipherkey(pkey_dbf_info, 3,
510 key, keylen, 0, 1);
511 if (rc)
512 goto out;
513 *keytype = PKEY_TYPE_CCA_CIPHER;
514 *keybitsize = PKEY_SIZE_UNKNOWN;
515 if (!t->plfver && t->wpllen == 512)
516 *keybitsize = PKEY_SIZE_AES_128;
517 else if (!t->plfver && t->wpllen == 576)
518 *keybitsize = PKEY_SIZE_AES_192;
519 else if (!t->plfver && t->wpllen == 640)
520 *keybitsize = PKEY_SIZE_AES_256;
521 rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
522 ZCRYPT_CEX6, AES_MK_SET,
523 t->mkvp0, NULL, xflags);
524 if (!rc)
525 *flags = PKEY_FLAGS_MATCH_CUR_MKVP;
526 if (rc == -ENODEV) {
527 nr_apqns = ARRAY_SIZE(apqns);
528 rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
529 ZCRYPT_CEX6, AES_MK_SET,
530 NULL, t->mkvp0, xflags);
531 if (!rc)
532 *flags = PKEY_FLAGS_MATCH_ALT_MKVP;
533 }
534 if (rc)
535 goto out;
536
537 *card = ((struct pkey_apqn *)apqns)->card;
538 *dom = ((struct pkey_apqn *)apqns)->domain;
539
540 } else {
541 /* unknown/unsupported key blob */
542 rc = -EINVAL;
543 }
544
545 out:
546 pr_debug("rc=%d\n", rc);
547 return rc;
548 }
549
550 /*
551 * This function provides an alternate but usually slow way
552 * to convert a 'clear key token' with AES key material into
553 * a protected key. This is done via an intermediate step
554 * which creates a CCA AES DATA secure key first and then
555 * derives the protected key from this secure key.
556 */
cca_slowpath_key2protkey(const struct pkey_apqn * apqns,size_t nr_apqns,const u8 * key,u32 keylen,u8 * protkey,u32 * protkeylen,u32 * protkeytype,u32 pflags)557 static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns,
558 size_t nr_apqns,
559 const u8 *key, u32 keylen,
560 u8 *protkey, u32 *protkeylen,
561 u32 *protkeytype, u32 pflags)
562 {
563 const struct keytoken_header *hdr = (const struct keytoken_header *)key;
564 const struct clearkeytoken *t = (const struct clearkeytoken *)key;
565 u8 tmpbuf[SECKEYBLOBSIZE]; /* 64 bytes */
566 u32 tmplen, keysize = 0;
567 int i, rc;
568
569 if (keylen < sizeof(*hdr))
570 return -EINVAL;
571
572 if (hdr->type == TOKTYPE_NON_CCA &&
573 hdr->version == TOKVER_CLEAR_KEY)
574 keysize = pkey_keytype_aes_to_size(t->keytype);
575 if (!keysize || t->len != keysize)
576 return -EINVAL;
577
578 /* try two times in case of failure */
579 for (i = 0, rc = -ENODEV; i < 2 && rc; i++) {
580 tmplen = SECKEYBLOBSIZE;
581 rc = cca_clr2key(NULL, 0, t->keytype, PKEY_TYPE_CCA_DATA,
582 8 * keysize, 0, t->clearkey, t->len,
583 tmpbuf, &tmplen, NULL, pflags);
584 pr_debug("cca_clr2key()=%d\n", rc);
585 if (rc)
586 continue;
587 rc = cca_key2protkey(NULL, 0, tmpbuf, tmplen,
588 protkey, protkeylen, protkeytype, pflags);
589 pr_debug("cca_key2protkey()=%d\n", rc);
590 }
591
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