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