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