800 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * pkey device driver4 *5 * Copyright IBM Corp. 2017, 20236 *7 * Author(s): Harald Freudenberger8 */9 10#define KMSG_COMPONENT "pkey"11#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt12 13#include <linux/init.h>14#include <linux/miscdevice.h>15#include <linux/slab.h>16 17#include "zcrypt_api.h"18#include "zcrypt_ccamisc.h"19 20#include "pkey_base.h"21 22/*23 * Helper functions24 */25static int key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,26 const u8 *key, size_t keylen,27 u8 *protkey, u32 *protkeylen, u32 *protkeytype)28{29 int rc;30 31 /* try the direct way */32 rc = pkey_handler_key_to_protkey(apqns, nr_apqns,33 key, keylen,34 protkey, protkeylen,35 protkeytype);36 37 /* if this did not work, try the slowpath way */38 if (rc == -ENODEV) {39 rc = pkey_handler_slowpath_key_to_protkey(apqns, nr_apqns,40 key, keylen,41 protkey, protkeylen,42 protkeytype);43 if (rc)44 rc = -ENODEV;45 }46 47 pr_debug("rc=%d\n", rc);48 return rc;49}50 51/*52 * In-Kernel function: Transform a key blob (of any type) into a protected key53 */54int pkey_key2protkey(const u8 *key, u32 keylen,55 u8 *protkey, u32 *protkeylen, u32 *protkeytype)56{57 int rc;58 59 rc = key2protkey(NULL, 0, key, keylen,60 protkey, protkeylen, protkeytype);61 if (rc == -ENODEV) {62 pkey_handler_request_modules();63 rc = key2protkey(NULL, 0, key, keylen,64 protkey, protkeylen, protkeytype);65 }66 67 return rc;68}69EXPORT_SYMBOL(pkey_key2protkey);70 71/*72 * Ioctl functions73 */74 75static void *_copy_key_from_user(void __user *ukey, size_t keylen)76{77 if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE)78 return ERR_PTR(-EINVAL);79 80 return memdup_user(ukey, keylen);81}82 83static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns)84{85 if (!uapqns || nr_apqns == 0)86 return NULL;87 88 return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn));89}90 91static int pkey_ioctl_genseck(struct pkey_genseck __user *ugs)92{93 struct pkey_genseck kgs;94 struct pkey_apqn apqn;95 u32 keybuflen;96 int rc;97 98 if (copy_from_user(&kgs, ugs, sizeof(kgs)))99 return -EFAULT;100 101 apqn.card = kgs.cardnr;102 apqn.domain = kgs.domain;103 keybuflen = sizeof(kgs.seckey.seckey);104 rc = pkey_handler_gen_key(&apqn, 1,105 kgs.keytype, PKEY_TYPE_CCA_DATA, 0, 0,106 kgs.seckey.seckey, &keybuflen, NULL);107 pr_debug("gen_key()=%d\n", rc);108 if (!rc && copy_to_user(ugs, &kgs, sizeof(kgs)))109 rc = -EFAULT;110 memzero_explicit(&kgs, sizeof(kgs));111 112 return rc;113}114 115static int pkey_ioctl_clr2seck(struct pkey_clr2seck __user *ucs)116{117 struct pkey_clr2seck kcs;118 struct pkey_apqn apqn;119 u32 keybuflen;120 int rc;121 122 if (copy_from_user(&kcs, ucs, sizeof(kcs)))123 return -EFAULT;124 125 apqn.card = kcs.cardnr;126 apqn.domain = kcs.domain;127 keybuflen = sizeof(kcs.seckey.seckey);128 rc = pkey_handler_clr_to_key(&apqn, 1,129 kcs.keytype, PKEY_TYPE_CCA_DATA, 0, 0,130 kcs.clrkey.clrkey,131 pkey_keytype_aes_to_size(kcs.keytype),132 kcs.seckey.seckey, &keybuflen, NULL);133 pr_debug("clr_to_key()=%d\n", rc);134 if (!rc && copy_to_user(ucs, &kcs, sizeof(kcs)))135 rc = -EFAULT;136 memzero_explicit(&kcs, sizeof(kcs));137 138 return rc;139}140 141static int pkey_ioctl_sec2protk(struct pkey_sec2protk __user *usp)142{143 struct pkey_sec2protk ksp;144 struct pkey_apqn apqn;145 int rc;146 147 if (copy_from_user(&ksp, usp, sizeof(ksp)))148 return -EFAULT;149 150 apqn.card = ksp.cardnr;151 apqn.domain = ksp.domain;152 ksp.protkey.len = sizeof(ksp.protkey.protkey);153 rc = pkey_handler_key_to_protkey(&apqn, 1,154 ksp.seckey.seckey,155 sizeof(ksp.seckey.seckey),156 ksp.protkey.protkey,157 &ksp.protkey.len, &ksp.protkey.type);158 pr_debug("key_to_protkey()=%d\n", rc);159 if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))160 rc = -EFAULT;161 memzero_explicit(&ksp, sizeof(ksp));162 163 return rc;164}165 166static int pkey_ioctl_clr2protk(struct pkey_clr2protk __user *ucp)167{168 struct pkey_clr2protk kcp;169 struct clearkeytoken *t;170 u32 keylen;171 u8 *tmpbuf;172 int rc;173 174 if (copy_from_user(&kcp, ucp, sizeof(kcp)))175 return -EFAULT;176 177 /* build a 'clear key token' from the clear key value */178 keylen = pkey_keytype_aes_to_size(kcp.keytype);179 if (!keylen) {180 PKEY_DBF_ERR("%s unknown/unsupported keytype %u\n",181 __func__, kcp.keytype);182 memzero_explicit(&kcp, sizeof(kcp));183 return -EINVAL;184 }185 tmpbuf = kzalloc(sizeof(*t) + keylen, GFP_KERNEL);186 if (!tmpbuf) {187 memzero_explicit(&kcp, sizeof(kcp));188 return -ENOMEM;189 }190 t = (struct clearkeytoken *)tmpbuf;191 t->type = TOKTYPE_NON_CCA;192 t->version = TOKVER_CLEAR_KEY;193 t->keytype = (keylen - 8) >> 3;194 t->len = keylen;195 memcpy(t->clearkey, kcp.clrkey.clrkey, keylen);196 kcp.protkey.len = sizeof(kcp.protkey.protkey);197 198 rc = key2protkey(NULL, 0,199 tmpbuf, sizeof(*t) + keylen,200 kcp.protkey.protkey,201 &kcp.protkey.len, &kcp.protkey.type);202 pr_debug("key2protkey()=%d\n", rc);203 204 kfree_sensitive(tmpbuf);205 206 if (!rc && copy_to_user(ucp, &kcp, sizeof(kcp)))207 rc = -EFAULT;208 memzero_explicit(&kcp, sizeof(kcp));209 210 return rc;211}212 213static int pkey_ioctl_findcard(struct pkey_findcard __user *ufc)214{215 struct pkey_findcard kfc;216 struct pkey_apqn *apqns;217 size_t nr_apqns;218 int rc;219 220 if (copy_from_user(&kfc, ufc, sizeof(kfc)))221 return -EFAULT;222 223 nr_apqns = MAXAPQNSINLIST;224 apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), GFP_KERNEL);225 if (!apqns)226 return -ENOMEM;227 228 rc = pkey_handler_apqns_for_key(kfc.seckey.seckey,229 sizeof(kfc.seckey.seckey),230 PKEY_FLAGS_MATCH_CUR_MKVP,231 apqns, &nr_apqns);232 if (rc == -ENODEV)233 rc = pkey_handler_apqns_for_key(kfc.seckey.seckey,234 sizeof(kfc.seckey.seckey),235 PKEY_FLAGS_MATCH_ALT_MKVP,236 apqns, &nr_apqns);237 pr_debug("apqns_for_key()=%d\n", rc);238 if (rc) {239 kfree(apqns);240 return rc;241 }242 kfc.cardnr = apqns[0].card;243 kfc.domain = apqns[0].domain;244 kfree(apqns);245 if (copy_to_user(ufc, &kfc, sizeof(kfc)))246 return -EFAULT;247 248 return 0;249}250 251static int pkey_ioctl_skey2pkey(struct pkey_skey2pkey __user *usp)252{253 struct pkey_skey2pkey ksp;254 int rc;255 256 if (copy_from_user(&ksp, usp, sizeof(ksp)))257 return -EFAULT;258 259 ksp.protkey.len = sizeof(ksp.protkey.protkey);260 rc = pkey_handler_key_to_protkey(NULL, 0,261 ksp.seckey.seckey,262 sizeof(ksp.seckey.seckey),263 ksp.protkey.protkey,264 &ksp.protkey.len,265 &ksp.protkey.type);266 pr_debug("key_to_protkey()=%d\n", rc);267 if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))268 rc = -EFAULT;269 memzero_explicit(&ksp, sizeof(ksp));270 271 return rc;272}273 274static int pkey_ioctl_verifykey(struct pkey_verifykey __user *uvk)275{276 u32 keytype, keybitsize, flags;277 struct pkey_verifykey kvk;278 int rc;279 280 if (copy_from_user(&kvk, uvk, sizeof(kvk)))281 return -EFAULT;282 283 kvk.cardnr = 0xFFFF;284 kvk.domain = 0xFFFF;285 rc = pkey_handler_verify_key(kvk.seckey.seckey,286 sizeof(kvk.seckey.seckey),287 &kvk.cardnr, &kvk.domain,288 &keytype, &keybitsize, &flags);289 pr_debug("verify_key()=%d\n", rc);290 if (!rc && keytype != PKEY_TYPE_CCA_DATA)291 rc = -EINVAL;292 kvk.attributes = PKEY_VERIFY_ATTR_AES;293 kvk.keysize = (u16)keybitsize;294 if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)295 kvk.attributes |= PKEY_VERIFY_ATTR_OLD_MKVP;296 if (!rc && copy_to_user(uvk, &kvk, sizeof(kvk)))297 rc = -EFAULT;298 memzero_explicit(&kvk, sizeof(kvk));299 300 return rc;301}302 303static int pkey_ioctl_genprotk(struct pkey_genprotk __user *ugp)304{305 struct pkey_genprotk kgp;306 int rc;307 308 if (copy_from_user(&kgp, ugp, sizeof(kgp)))309 return -EFAULT;310 311 kgp.protkey.len = sizeof(kgp.protkey.protkey);312 rc = pkey_handler_gen_key(NULL, 0, kgp.keytype,313 PKEY_TYPE_PROTKEY, 0, 0,314 kgp.protkey.protkey, &kgp.protkey.len,315 &kgp.protkey.type);316 pr_debug("gen_key()=%d\n", rc);317 if (!rc && copy_to_user(ugp, &kgp, sizeof(kgp)))318 rc = -EFAULT;319 memzero_explicit(&kgp, sizeof(kgp));320 321 return rc;322}323 324static int pkey_ioctl_verifyprotk(struct pkey_verifyprotk __user *uvp)325{326 struct pkey_verifyprotk kvp;327 struct protaeskeytoken *t;328 u32 keytype;329 u8 *tmpbuf;330 int rc;331 332 if (copy_from_user(&kvp, uvp, sizeof(kvp)))333 return -EFAULT;334 335 keytype = pkey_aes_bitsize_to_keytype(8 * kvp.protkey.len);336 if (!keytype) {337 PKEY_DBF_ERR("%s unknown/unsupported protkey length %u\n",338 __func__, kvp.protkey.len);339 memzero_explicit(&kvp, sizeof(kvp));340 return -EINVAL;341 }342 343 /* build a 'protected key token' from the raw protected key */344 tmpbuf = kzalloc(sizeof(*t), GFP_KERNEL);345 if (!tmpbuf) {346 memzero_explicit(&kvp, sizeof(kvp));347 return -ENOMEM;348 }349 t = (struct protaeskeytoken *)tmpbuf;350 t->type = TOKTYPE_NON_CCA;351 t->version = TOKVER_PROTECTED_KEY;352 t->keytype = keytype;353 t->len = kvp.protkey.len;354 memcpy(t->protkey, kvp.protkey.protkey, kvp.protkey.len);355 356 rc = pkey_handler_verify_key(tmpbuf, sizeof(*t),357 NULL, NULL, NULL, NULL, NULL);358 pr_debug("verify_key()=%d\n", rc);359 360 kfree_sensitive(tmpbuf);361 memzero_explicit(&kvp, sizeof(kvp));362 363 return rc;364}365 366static int pkey_ioctl_kblob2protk(struct pkey_kblob2pkey __user *utp)367{368 struct pkey_kblob2pkey ktp;369 u8 *kkey;370 int rc;371 372 if (copy_from_user(&ktp, utp, sizeof(ktp)))373 return -EFAULT;374 kkey = _copy_key_from_user(ktp.key, ktp.keylen);375 if (IS_ERR(kkey))376 return PTR_ERR(kkey);377 ktp.protkey.len = sizeof(ktp.protkey.protkey);378 rc = key2protkey(NULL, 0, kkey, ktp.keylen,379 ktp.protkey.protkey, &ktp.protkey.len,380 &ktp.protkey.type);381 pr_debug("key2protkey()=%d\n", rc);382 kfree_sensitive(kkey);383 if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))384 rc = -EFAULT;385 memzero_explicit(&ktp, sizeof(ktp));386 387 return rc;388}389 390static int pkey_ioctl_genseck2(struct pkey_genseck2 __user *ugs)391{392 u32 klen = KEYBLOBBUFSIZE;393 struct pkey_genseck2 kgs;394 struct pkey_apqn *apqns;395 u8 *kkey;396 int rc;397 u32 u;398 399 if (copy_from_user(&kgs, ugs, sizeof(kgs)))400 return -EFAULT;401 u = pkey_aes_bitsize_to_keytype(kgs.size);402 if (!u) {403 PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",404 __func__, kgs.size);405 return -EINVAL;406 }407 apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries);408 if (IS_ERR(apqns))409 return PTR_ERR(apqns);410 kkey = kzalloc(klen, GFP_KERNEL);411 if (!kkey) {412 kfree(apqns);413 return -ENOMEM;414 }415 rc = pkey_handler_gen_key(apqns, kgs.apqn_entries,416 u, kgs.type, kgs.size, kgs.keygenflags,417 kkey, &klen, NULL);418 pr_debug("gen_key()=%d\n", rc);419 kfree(apqns);420 if (rc) {421 kfree_sensitive(kkey);422 return rc;423 }424 if (kgs.key) {425 if (kgs.keylen < klen) {426 kfree_sensitive(kkey);427 return -EINVAL;428 }429 if (copy_to_user(kgs.key, kkey, klen)) {430 kfree_sensitive(kkey);431 return -EFAULT;432 }433 }434 kgs.keylen = klen;435 if (copy_to_user(ugs, &kgs, sizeof(kgs)))436 rc = -EFAULT;437 kfree_sensitive(kkey);438 439 return rc;440}441 442static int pkey_ioctl_clr2seck2(struct pkey_clr2seck2 __user *ucs)443{444 u32 klen = KEYBLOBBUFSIZE;445 struct pkey_clr2seck2 kcs;446 struct pkey_apqn *apqns;447 u8 *kkey;448 int rc;449 u32 u;450 451 if (copy_from_user(&kcs, ucs, sizeof(kcs)))452 return -EFAULT;453 u = pkey_aes_bitsize_to_keytype(kcs.size);454 if (!u) {455 PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",456 __func__, kcs.size);457 memzero_explicit(&kcs, sizeof(kcs));458 return -EINVAL;459 }460 apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries);461 if (IS_ERR(apqns)) {462 memzero_explicit(&kcs, sizeof(kcs));463 return PTR_ERR(apqns);464 }465 kkey = kzalloc(klen, GFP_KERNEL);466 if (!kkey) {467 kfree(apqns);468 memzero_explicit(&kcs, sizeof(kcs));469 return -ENOMEM;470 }471 rc = pkey_handler_clr_to_key(apqns, kcs.apqn_entries,472 u, kcs.type, kcs.size, kcs.keygenflags,473 kcs.clrkey.clrkey, kcs.size / 8,474 kkey, &klen, NULL);475 pr_debug("clr_to_key()=%d\n", rc);476 kfree(apqns);477 if (rc) {478 kfree_sensitive(kkey);479 memzero_explicit(&kcs, sizeof(kcs));480 return rc;481 }482 if (kcs.key) {483 if (kcs.keylen < klen) {484 kfree_sensitive(kkey);485 memzero_explicit(&kcs, sizeof(kcs));486 return -EINVAL;487 }488 if (copy_to_user(kcs.key, kkey, klen)) {489 kfree_sensitive(kkey);490 memzero_explicit(&kcs, sizeof(kcs));491 return -EFAULT;492 }493 }494 kcs.keylen = klen;495 if (copy_to_user(ucs, &kcs, sizeof(kcs)))496 rc = -EFAULT;497 memzero_explicit(&kcs, sizeof(kcs));498 kfree_sensitive(kkey);499 500 return rc;501}502 503static int pkey_ioctl_verifykey2(struct pkey_verifykey2 __user *uvk)504{505 struct pkey_verifykey2 kvk;506 u8 *kkey;507 int rc;508 509 if (copy_from_user(&kvk, uvk, sizeof(kvk)))510 return -EFAULT;511 kkey = _copy_key_from_user(kvk.key, kvk.keylen);512 if (IS_ERR(kkey))513 return PTR_ERR(kkey);514 515 rc = pkey_handler_verify_key(kkey, kvk.keylen,516 &kvk.cardnr, &kvk.domain,517 &kvk.type, &kvk.size, &kvk.flags);518 pr_debug("verify_key()=%d\n", rc);519 520 kfree_sensitive(kkey);521 if (!rc && copy_to_user(uvk, &kvk, sizeof(kvk)))522 return -EFAULT;523 524 return rc;525}526 527static int pkey_ioctl_kblob2protk2(struct pkey_kblob2pkey2 __user *utp)528{529 struct pkey_apqn *apqns = NULL;530 struct pkey_kblob2pkey2 ktp;531 u8 *kkey;532 int rc;533 534 if (copy_from_user(&ktp, utp, sizeof(ktp)))535 return -EFAULT;536 apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);537 if (IS_ERR(apqns))538 return PTR_ERR(apqns);539 kkey = _copy_key_from_user(ktp.key, ktp.keylen);540 if (IS_ERR(kkey)) {541 kfree(apqns);542 return PTR_ERR(kkey);543 }544 ktp.protkey.len = sizeof(ktp.protkey.protkey);545 rc = key2protkey(apqns, ktp.apqn_entries, kkey, ktp.keylen,546 ktp.protkey.protkey, &ktp.protkey.len,547 &ktp.protkey.type);548 pr_debug("key2protkey()=%d\n", rc);549 kfree(apqns);550 kfree_sensitive(kkey);551 if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))552 rc = -EFAULT;553 memzero_explicit(&ktp, sizeof(ktp));554 555 return rc;556}557 558static int pkey_ioctl_apqns4k(struct pkey_apqns4key __user *uak)559{560 struct pkey_apqn *apqns = NULL;561 struct pkey_apqns4key kak;562 size_t nr_apqns, len;563 u8 *kkey;564 int rc;565 566 if (copy_from_user(&kak, uak, sizeof(kak)))567 return -EFAULT;568 nr_apqns = kak.apqn_entries;569 if (nr_apqns) {570 apqns = kmalloc_array(nr_apqns,571 sizeof(struct pkey_apqn),572 GFP_KERNEL);573 if (!apqns)574 return -ENOMEM;575 }576 kkey = _copy_key_from_user(kak.key, kak.keylen);577 if (IS_ERR(kkey)) {578 kfree(apqns);579 return PTR_ERR(kkey);580 }581 rc = pkey_handler_apqns_for_key(kkey, kak.keylen, kak.flags,582 apqns, &nr_apqns);583 pr_debug("apqns_for_key()=%d\n", rc);584 kfree_sensitive(kkey);585 if (rc && rc != -ENOSPC) {586 kfree(apqns);587 return rc;588 }589 if (!rc && kak.apqns) {590 if (nr_apqns > kak.apqn_entries) {591 kfree(apqns);592 return -EINVAL;593 }594 len = nr_apqns * sizeof(struct pkey_apqn);595 if (len) {596 if (copy_to_user(kak.apqns, apqns, len)) {597 kfree(apqns);598 return -EFAULT;599 }600 }601 }602 kak.apqn_entries = nr_apqns;603 if (copy_to_user(uak, &kak, sizeof(kak)))604 rc = -EFAULT;605 kfree(apqns);606 607 return rc;608}609 610static int pkey_ioctl_apqns4kt(struct pkey_apqns4keytype __user *uat)611{612 struct pkey_apqn *apqns = NULL;613 struct pkey_apqns4keytype kat;614 size_t nr_apqns, len;615 int rc;616 617 if (copy_from_user(&kat, uat, sizeof(kat)))618 return -EFAULT;619 nr_apqns = kat.apqn_entries;620 if (nr_apqns) {621 apqns = kmalloc_array(nr_apqns,622 sizeof(struct pkey_apqn),623 GFP_KERNEL);624 if (!apqns)625 return -ENOMEM;626 }627 rc = pkey_handler_apqns_for_keytype(kat.type,628 kat.cur_mkvp, kat.alt_mkvp,629 kat.flags, apqns, &nr_apqns);630 pr_debug("apqns_for_keytype()=%d\n", rc);631 if (rc && rc != -ENOSPC) {632 kfree(apqns);633 return rc;634 }635 if (!rc && kat.apqns) {636 if (nr_apqns > kat.apqn_entries) {637 kfree(apqns);638 return -EINVAL;639 }640 len = nr_apqns * sizeof(struct pkey_apqn);641 if (len) {642 if (copy_to_user(kat.apqns, apqns, len)) {643 kfree(apqns);644 return -EFAULT;645 }646 }647 }648 kat.apqn_entries = nr_apqns;649 if (copy_to_user(uat, &kat, sizeof(kat)))650 rc = -EFAULT;651 kfree(apqns);652 653 return rc;654}655 656static int pkey_ioctl_kblob2protk3(struct pkey_kblob2pkey3 __user *utp)657{658 u32 protkeylen = PROTKEYBLOBBUFSIZE;659 struct pkey_apqn *apqns = NULL;660 struct pkey_kblob2pkey3 ktp;661 u8 *kkey, *protkey;662 int rc;663 664 if (copy_from_user(&ktp, utp, sizeof(ktp)))665 return -EFAULT;666 apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);667 if (IS_ERR(apqns))668 return PTR_ERR(apqns);669 kkey = _copy_key_from_user(ktp.key, ktp.keylen);670 if (IS_ERR(kkey)) {671 kfree(apqns);672 return PTR_ERR(kkey);673 }674 protkey = kmalloc(protkeylen, GFP_KERNEL);675 if (!protkey) {676 kfree(apqns);677 kfree_sensitive(kkey);678 return -ENOMEM;679 }680 rc = key2protkey(apqns, ktp.apqn_entries, kkey, ktp.keylen,681 protkey, &protkeylen, &ktp.pkeytype);682 pr_debug("key2protkey()=%d\n", rc);683 kfree(apqns);684 kfree_sensitive(kkey);685 if (rc) {686 kfree_sensitive(protkey);687 return rc;688 }689 if (ktp.pkey && ktp.pkeylen) {690 if (protkeylen > ktp.pkeylen) {691 kfree_sensitive(protkey);692 return -EINVAL;693 }694 if (copy_to_user(ktp.pkey, protkey, protkeylen)) {695 kfree_sensitive(protkey);696 return -EFAULT;697 }698 }699 kfree_sensitive(protkey);700 ktp.pkeylen = protkeylen;701 if (copy_to_user(utp, &ktp, sizeof(ktp)))702 return -EFAULT;703 704 return 0;705}706 707static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,708 unsigned long arg)709{710 int rc;711 712 switch (cmd) {713 case PKEY_GENSECK:714 rc = pkey_ioctl_genseck((struct pkey_genseck __user *)arg);715 break;716 case PKEY_CLR2SECK:717 rc = pkey_ioctl_clr2seck((struct pkey_clr2seck __user *)arg);718 break;719 case PKEY_SEC2PROTK:720 rc = pkey_ioctl_sec2protk((struct pkey_sec2protk __user *)arg);721 break;722 case PKEY_CLR2PROTK:723 rc = pkey_ioctl_clr2protk((struct pkey_clr2protk __user *)arg);724 break;725 case PKEY_FINDCARD:726 rc = pkey_ioctl_findcard((struct pkey_findcard __user *)arg);727 break;728 case PKEY_SKEY2PKEY:729 rc = pkey_ioctl_skey2pkey((struct pkey_skey2pkey __user *)arg);730 break;731 case PKEY_VERIFYKEY:732 rc = pkey_ioctl_verifykey((struct pkey_verifykey __user *)arg);733 break;734 case PKEY_GENPROTK:735 rc = pkey_ioctl_genprotk((struct pkey_genprotk __user *)arg);736 break;737 case PKEY_VERIFYPROTK:738 rc = pkey_ioctl_verifyprotk((struct pkey_verifyprotk __user *)arg);739 break;740 case PKEY_KBLOB2PROTK:741 rc = pkey_ioctl_kblob2protk((struct pkey_kblob2pkey __user *)arg);742 break;743 case PKEY_GENSECK2:744 rc = pkey_ioctl_genseck2((struct pkey_genseck2 __user *)arg);745 break;746 case PKEY_CLR2SECK2:747 rc = pkey_ioctl_clr2seck2((struct pkey_clr2seck2 __user *)arg);748 break;749 case PKEY_VERIFYKEY2:750 rc = pkey_ioctl_verifykey2((struct pkey_verifykey2 __user *)arg);751 break;752 case PKEY_KBLOB2PROTK2:753 rc = pkey_ioctl_kblob2protk2((struct pkey_kblob2pkey2 __user *)arg);754 break;755 case PKEY_APQNS4K:756 rc = pkey_ioctl_apqns4k((struct pkey_apqns4key __user *)arg);757 break;758 case PKEY_APQNS4KT:759 rc = pkey_ioctl_apqns4kt((struct pkey_apqns4keytype __user *)arg);760 break;761 case PKEY_KBLOB2PROTK3:762 rc = pkey_ioctl_kblob2protk3((struct pkey_kblob2pkey3 __user *)arg);763 break;764 default:765 /* unknown/unsupported ioctl cmd */766 return -ENOTTY;767 }768 769 return rc;770}771 772/*773 * File io operations774 */775 776static const struct file_operations pkey_fops = {777 .owner = THIS_MODULE,778 .open = nonseekable_open,779 .unlocked_ioctl = pkey_unlocked_ioctl,780};781 782static struct miscdevice pkey_dev = {783 .name = "pkey",784 .minor = MISC_DYNAMIC_MINOR,785 .mode = 0666,786 .fops = &pkey_fops,787 .groups = pkey_attr_groups,788};789 790int __init pkey_api_init(void)791{792 /* register as a misc device */793 return misc_register(&pkey_dev);794}795 796void __exit pkey_api_exit(void)797{798 misc_deregister(&pkey_dev);799}800