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 if (pflags & PKEY_XFLAG_NOCLEARKEY) { 394 PKEY_DBF_ERR("%s clear key but xflag NOCLEARKEY\n", __func__); 395 return -EINVAL; 396 } 397 398 xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0; 399 400 /* check keytype, subtype, clrkeylen, keybitsize */ 401 switch (keytype) { 402 case PKEY_KEYTYPE_AES_128: 403 case PKEY_KEYTYPE_AES_192: 404 case PKEY_KEYTYPE_AES_256: 405 len = pkey_keytype_aes_to_size(keytype); 406 if (keybitsize && keybitsize != 8 * len) { 407 PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n", 408 __func__, keybitsize); 409 return -EINVAL; 410 } 411 keybitsize = 8 * len; 412 if (clrkeylen != len) { 413 PKEY_DBF_ERR("%s invalid clear key len %d != %d\n", 414 __func__, clrkeylen, len); 415 return -EINVAL; 416 } 417 switch (subtype) { 418 case PKEY_TYPE_CCA_DATA: 419 case PKEY_TYPE_CCA_CIPHER: 420 break; 421 default: 422 PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n", 423 __func__, subtype); 424 return -EINVAL; 425 } 426 break; 427 default: 428 PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n", 429 __func__, keytype); 430 return -EINVAL; 431 } 432 433 zcrypt_wait_api_operational(); 434 435 if (!apqns || (nr_apqns == 1 && 436 apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) { 437 nr_apqns = MAXAPQNSINLIST; 438 rc = cca_apqns4type(subtype, NULL, NULL, 0, 439 _apqns, &nr_apqns, pflags); 440 if (rc) 441 goto out; 442 apqns = _apqns; 443 } 444 445 for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 446 if (subtype == PKEY_TYPE_CCA_CIPHER) { 447 rc = cca_clr2cipherkey(apqns[i].card, apqns[i].domain, 448 keybitsize, flags, clrkey, 449 keybuf, keybuflen, xflags); 450 } else { 451 /* PKEY_TYPE_CCA_DATA */ 452 rc = cca_clr2seckey(apqns[i].card, apqns[i].domain, 453 keybitsize, clrkey, keybuf, xflags); 454 *keybuflen = (rc ? 0 : SECKEYBLOBSIZE); 455 } 456 } 457 458 out: 459 pr_debug("rc=%d\n", rc); 460 return rc; 461 } 462 463 static int cca_verifykey(const u8 *key, u32 keylen, 464 u16 *card, u16 *dom, 465 u32 *keytype, u32 *keybitsize, u32 *flags, u32 pflags) 466 { 467 struct keytoken_header *hdr = (struct keytoken_header *)key; 468 u32 apqns[MAXAPQNSINLIST], nr_apqns = ARRAY_SIZE(apqns); 469 u32 xflags; 470 int rc; 471 472 xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0; 473 474 if (keylen < sizeof(*hdr)) 475 return -EINVAL; 476 477 zcrypt_wait_api_operational(); 478 479 if (hdr->type == TOKTYPE_CCA_INTERNAL && 480 hdr->version == TOKVER_CCA_AES) { 481 struct secaeskeytoken *t = (struct secaeskeytoken *)key; 482 483 rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0); 484 if (rc) 485 goto out; 486 *keytype = PKEY_TYPE_CCA_DATA; 487 *keybitsize = t->bitsize; 488 rc = cca_findcard2(apqns, &nr_apqns, *card, *dom, 489 ZCRYPT_CEX3C, AES_MK_SET, 490 t->mkvp, 0, xflags); 491 if (!rc) 492 *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 493 if (rc == -ENODEV) { 494 nr_apqns = ARRAY_SIZE(apqns); 495 rc = cca_findcard2(apqns, &nr_apqns, *card, *dom, 496 ZCRYPT_CEX3C, AES_MK_SET, 497 0, t->mkvp, xflags); 498 if (!rc) 499 *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 500 } 501 if (rc) 502 goto out; 503 504 *card = ((struct pkey_apqn *)apqns)->card; 505 *dom = ((struct pkey_apqn *)apqns)->domain; 506 507 } else if (hdr->type == TOKTYPE_CCA_INTERNAL && 508 hdr->version == TOKVER_CCA_VLSC) { 509 struct cipherkeytoken *t = (struct cipherkeytoken *)key; 510 511 rc = cca_check_secaescipherkey(pkey_dbf_info, 3, key, 0, 1); 512 if (rc) 513 goto out; 514 *keytype = PKEY_TYPE_CCA_CIPHER; 515 *keybitsize = PKEY_SIZE_UNKNOWN; 516 if (!t->plfver && t->wpllen == 512) 517 *keybitsize = PKEY_SIZE_AES_128; 518 else if (!t->plfver && t->wpllen == 576) 519 *keybitsize = PKEY_SIZE_AES_192; 520 else if (!t->plfver && t->wpllen == 640) 521 *keybitsize = PKEY_SIZE_AES_256; 522 rc = cca_findcard2(apqns, &nr_apqns, *card, *dom, 523 ZCRYPT_CEX6, AES_MK_SET, 524 t->mkvp0, 0, xflags); 525 if (!rc) 526 *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 527 if (rc == -ENODEV) { 528 nr_apqns = ARRAY_SIZE(apqns); 529 rc = cca_findcard2(apqns, &nr_apqns, *card, *dom, 530 ZCRYPT_CEX6, AES_MK_SET, 531 0, t->mkvp0, xflags); 532 if (!rc) 533 *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 534 } 535 if (rc) 536 goto out; 537 538 *card = ((struct pkey_apqn *)apqns)->card; 539 *dom = ((struct pkey_apqn *)apqns)->domain; 540 541 } else { 542 /* unknown/unsupported key blob */ 543 rc = -EINVAL; 544 } 545 546 out: 547 pr_debug("rc=%d\n", rc); 548 return rc; 549 } 550 551 /* 552 * This function provides an alternate but usually slow way 553 * to convert a 'clear key token' with AES key material into 554 * a protected key. This is done via an intermediate step 555 * which creates a CCA AES DATA secure key first and then 556 * derives the protected key from this secure key. 557 */ 558 static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns, 559 size_t nr_apqns, 560 const u8 *key, u32 keylen, 561 u8 *protkey, u32 *protkeylen, 562 u32 *protkeytype, u32 pflags) 563 { 564 const struct keytoken_header *hdr = (const struct keytoken_header *)key; 565 const struct clearkeytoken *t = (const struct clearkeytoken *)key; 566 u8 tmpbuf[SECKEYBLOBSIZE]; /* 64 bytes */ 567 u32 tmplen, keysize = 0; 568 int i, rc; 569 570 if (keylen < sizeof(*hdr)) 571 return -EINVAL; 572 573 if (hdr->type == TOKTYPE_NON_CCA && 574 hdr->version == TOKVER_CLEAR_KEY) 575 keysize = pkey_keytype_aes_to_size(t->keytype); 576 if (!keysize || t->len != keysize) 577 return -EINVAL; 578 579 /* try two times in case of failure */ 580 for (i = 0, rc = -ENODEV; i < 2 && rc; i++) { 581 tmplen = SECKEYBLOBSIZE; 582 rc = cca_clr2key(NULL, 0, t->keytype, PKEY_TYPE_CCA_DATA, 583 8 * keysize, 0, t->clearkey, t->len, 584 tmpbuf, &tmplen, NULL, pflags); 585 pr_debug("cca_clr2key()=%d\n", rc); 586 if (rc) 587 continue; 588 rc = cca_key2protkey(NULL, 0, tmpbuf, tmplen, 589 protkey, protkeylen, protkeytype, pflags); 590 pr_debug("cca_key2protkey()=%d\n", rc); 591 } 592 593 pr_debug("rc=%d\n", rc); 594 return rc; 595 } 596 597 static struct pkey_handler cca_handler = { 598 .module = THIS_MODULE, 599 .name = "PKEY CCA handler", 600 .is_supported_key = is_cca_key, 601 .is_supported_keytype = is_cca_keytype, 602 .key_to_protkey = cca_key2protkey, 603 .slowpath_key_to_protkey = cca_slowpath_key2protkey, 604 .gen_key = cca_gen_key, 605 .clr_to_key = cca_clr2key, 606 .verify_key = cca_verifykey, 607 .apqns_for_key = cca_apqns4key, 608 .apqns_for_keytype = cca_apqns4type, 609 }; 610 611 /* 612 * Module init 613 */ 614 static int __init pkey_cca_init(void) 615 { 616 /* register this module as pkey handler for all the cca stuff */ 617 return pkey_handler_register(&cca_handler); 618 } 619 620 /* 621 * Module exit 622 */ 623 static void __exit pkey_cca_exit(void) 624 { 625 /* unregister this module as pkey handler */ 626 pkey_handler_unregister(&cca_handler); 627 } 628 629 module_init(pkey_cca_init); 630 module_exit(pkey_cca_exit); 631