| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * pkey device driver
- *
- * Copyright IBM Corp. 2017, 2023
- *
- * Author(s): Harald Freudenberger
- */
- #define pr_fmt(fmt) "pkey: " fmt
- #include <linux/init.h>
- #include <linux/miscdevice.h>
- #include <linux/export.h>
- #include <linux/slab.h>
- #include "zcrypt_api.h"
- #include "zcrypt_ccamisc.h"
- #include "pkey_base.h"
- /*
- * Helper functions
- */
- static int key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
- const u8 *key, size_t keylen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype,
- u32 xflags)
- {
- int rc;
- /* try the direct way */
- rc = pkey_handler_key_to_protkey(apqns, nr_apqns,
- key, keylen,
- protkey, protkeylen,
- protkeytype, xflags);
- /* if this did not work, try the slowpath way */
- if (rc == -ENODEV) {
- rc = pkey_handler_slowpath_key_to_protkey(apqns, nr_apqns,
- key, keylen,
- protkey, protkeylen,
- protkeytype, xflags);
- if (rc)
- rc = -ENODEV;
- }
- pr_debug("rc=%d\n", rc);
- return rc;
- }
- /*
- * In-Kernel function: Transform a key blob (of any type) into a protected key
- */
- int pkey_key2protkey(const u8 *key, u32 keylen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype, u32 xflags)
- {
- int rc;
- rc = key2protkey(NULL, 0, key, keylen,
- protkey, protkeylen, protkeytype, xflags);
- if (rc == -ENODEV) {
- pkey_handler_request_modules();
- rc = key2protkey(NULL, 0, key, keylen,
- protkey, protkeylen, protkeytype, xflags);
- }
- return rc;
- }
- EXPORT_SYMBOL(pkey_key2protkey);
- /*
- * Ioctl functions
- */
- static void *_copy_key_from_user(void __user *ukey, size_t keylen)
- {
- if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE)
- return ERR_PTR(-EINVAL);
- return memdup_user(ukey, keylen);
- }
- static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns)
- {
- if (!uapqns || nr_apqns == 0)
- return NULL;
- return memdup_array_user(uapqns, nr_apqns, sizeof(struct pkey_apqn));
- }
- static int pkey_ioctl_genseck(struct pkey_genseck __user *ugs)
- {
- struct pkey_genseck kgs;
- struct pkey_apqn apqn;
- u32 keybuflen;
- int rc;
- if (copy_from_user(&kgs, ugs, sizeof(kgs)))
- return -EFAULT;
- apqn.card = kgs.cardnr;
- apqn.domain = kgs.domain;
- keybuflen = sizeof(kgs.seckey.seckey);
- rc = pkey_handler_gen_key(&apqn, 1,
- kgs.keytype, PKEY_TYPE_CCA_DATA, 0, 0,
- kgs.seckey.seckey, &keybuflen, NULL, 0);
- pr_debug("gen_key()=%d\n", rc);
- if (!rc && copy_to_user(ugs, &kgs, sizeof(kgs)))
- rc = -EFAULT;
- memzero_explicit(&kgs, sizeof(kgs));
- return rc;
- }
- static int pkey_ioctl_clr2seck(struct pkey_clr2seck __user *ucs)
- {
- struct pkey_clr2seck kcs;
- struct pkey_apqn apqn;
- u32 keybuflen;
- int rc;
- if (copy_from_user(&kcs, ucs, sizeof(kcs)))
- return -EFAULT;
- apqn.card = kcs.cardnr;
- apqn.domain = kcs.domain;
- keybuflen = sizeof(kcs.seckey.seckey);
- rc = pkey_handler_clr_to_key(&apqn, 1,
- kcs.keytype, PKEY_TYPE_CCA_DATA, 0, 0,
- kcs.clrkey.clrkey,
- pkey_keytype_aes_to_size(kcs.keytype),
- kcs.seckey.seckey, &keybuflen, NULL, 0);
- pr_debug("clr_to_key()=%d\n", rc);
- if (!rc && copy_to_user(ucs, &kcs, sizeof(kcs)))
- rc = -EFAULT;
- memzero_explicit(&kcs, sizeof(kcs));
- return rc;
- }
- static int pkey_ioctl_sec2protk(struct pkey_sec2protk __user *usp)
- {
- struct pkey_sec2protk ksp;
- struct pkey_apqn apqn;
- int rc;
- if (copy_from_user(&ksp, usp, sizeof(ksp)))
- return -EFAULT;
- apqn.card = ksp.cardnr;
- apqn.domain = ksp.domain;
- ksp.protkey.len = sizeof(ksp.protkey.protkey);
- rc = pkey_handler_key_to_protkey(&apqn, 1,
- ksp.seckey.seckey,
- sizeof(ksp.seckey.seckey),
- ksp.protkey.protkey,
- &ksp.protkey.len, &ksp.protkey.type,
- 0);
- pr_debug("key_to_protkey()=%d\n", rc);
- if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
- rc = -EFAULT;
- memzero_explicit(&ksp, sizeof(ksp));
- return rc;
- }
- static int pkey_ioctl_clr2protk(struct pkey_clr2protk __user *ucp)
- {
- struct pkey_clr2protk kcp;
- struct clearkeytoken *t;
- u32 keylen;
- u8 *tmpbuf;
- int rc;
- if (copy_from_user(&kcp, ucp, sizeof(kcp)))
- return -EFAULT;
- /* build a 'clear key token' from the clear key value */
- keylen = pkey_keytype_aes_to_size(kcp.keytype);
- if (!keylen) {
- PKEY_DBF_ERR("%s unknown/unsupported keytype %u\n",
- __func__, kcp.keytype);
- memzero_explicit(&kcp, sizeof(kcp));
- return -EINVAL;
- }
- tmpbuf = kzalloc(sizeof(*t) + keylen, GFP_KERNEL);
- if (!tmpbuf) {
- memzero_explicit(&kcp, sizeof(kcp));
- return -ENOMEM;
- }
- t = (struct clearkeytoken *)tmpbuf;
- t->type = TOKTYPE_NON_CCA;
- t->version = TOKVER_CLEAR_KEY;
- t->keytype = (keylen - 8) >> 3;
- t->len = keylen;
- memcpy(t->clearkey, kcp.clrkey.clrkey, keylen);
- kcp.protkey.len = sizeof(kcp.protkey.protkey);
- rc = key2protkey(NULL, 0,
- tmpbuf, sizeof(*t) + keylen,
- kcp.protkey.protkey,
- &kcp.protkey.len, &kcp.protkey.type, 0);
- pr_debug("key2protkey()=%d\n", rc);
- kfree_sensitive(tmpbuf);
- if (!rc && copy_to_user(ucp, &kcp, sizeof(kcp)))
- rc = -EFAULT;
- memzero_explicit(&kcp, sizeof(kcp));
- return rc;
- }
- static int pkey_ioctl_findcard(struct pkey_findcard __user *ufc)
- {
- struct pkey_findcard kfc;
- struct pkey_apqn *apqns;
- size_t nr_apqns;
- int rc;
- if (copy_from_user(&kfc, ufc, sizeof(kfc)))
- return -EFAULT;
- nr_apqns = MAXAPQNSINLIST;
- apqns = kmalloc_objs(struct pkey_apqn, nr_apqns);
- if (!apqns)
- return -ENOMEM;
- rc = pkey_handler_apqns_for_key(kfc.seckey.seckey,
- sizeof(kfc.seckey.seckey),
- PKEY_FLAGS_MATCH_CUR_MKVP,
- apqns, &nr_apqns, 0);
- if (rc == -ENODEV)
- rc = pkey_handler_apqns_for_key(kfc.seckey.seckey,
- sizeof(kfc.seckey.seckey),
- PKEY_FLAGS_MATCH_ALT_MKVP,
- apqns, &nr_apqns, 0);
- pr_debug("apqns_for_key()=%d\n", rc);
- if (rc) {
- kfree(apqns);
- return rc;
- }
- kfc.cardnr = apqns[0].card;
- kfc.domain = apqns[0].domain;
- kfree(apqns);
- if (copy_to_user(ufc, &kfc, sizeof(kfc)))
- return -EFAULT;
- return 0;
- }
- static int pkey_ioctl_skey2pkey(struct pkey_skey2pkey __user *usp)
- {
- struct pkey_skey2pkey ksp;
- int rc;
- if (copy_from_user(&ksp, usp, sizeof(ksp)))
- return -EFAULT;
- ksp.protkey.len = sizeof(ksp.protkey.protkey);
- rc = pkey_handler_key_to_protkey(NULL, 0,
- ksp.seckey.seckey,
- sizeof(ksp.seckey.seckey),
- ksp.protkey.protkey,
- &ksp.protkey.len,
- &ksp.protkey.type, 0);
- pr_debug("key_to_protkey()=%d\n", rc);
- if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
- rc = -EFAULT;
- memzero_explicit(&ksp, sizeof(ksp));
- return rc;
- }
- static int pkey_ioctl_verifykey(struct pkey_verifykey __user *uvk)
- {
- u32 keytype, keybitsize, flags;
- struct pkey_verifykey kvk;
- int rc;
- if (copy_from_user(&kvk, uvk, sizeof(kvk)))
- return -EFAULT;
- kvk.cardnr = 0xFFFF;
- kvk.domain = 0xFFFF;
- rc = pkey_handler_verify_key(kvk.seckey.seckey,
- sizeof(kvk.seckey.seckey),
- &kvk.cardnr, &kvk.domain,
- &keytype, &keybitsize, &flags, 0);
- pr_debug("verify_key()=%d\n", rc);
- if (!rc && keytype != PKEY_TYPE_CCA_DATA)
- rc = -EINVAL;
- kvk.attributes = PKEY_VERIFY_ATTR_AES;
- kvk.keysize = (u16)keybitsize;
- if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
- kvk.attributes |= PKEY_VERIFY_ATTR_OLD_MKVP;
- if (!rc && copy_to_user(uvk, &kvk, sizeof(kvk)))
- rc = -EFAULT;
- memzero_explicit(&kvk, sizeof(kvk));
- return rc;
- }
- static int pkey_ioctl_genprotk(struct pkey_genprotk __user *ugp)
- {
- struct pkey_genprotk kgp;
- int rc;
- if (copy_from_user(&kgp, ugp, sizeof(kgp)))
- return -EFAULT;
- kgp.protkey.len = sizeof(kgp.protkey.protkey);
- rc = pkey_handler_gen_key(NULL, 0, kgp.keytype,
- PKEY_TYPE_PROTKEY, 0, 0,
- kgp.protkey.protkey, &kgp.protkey.len,
- &kgp.protkey.type, 0);
- pr_debug("gen_key()=%d\n", rc);
- if (!rc && copy_to_user(ugp, &kgp, sizeof(kgp)))
- rc = -EFAULT;
- memzero_explicit(&kgp, sizeof(kgp));
- return rc;
- }
- static int pkey_ioctl_verifyprotk(struct pkey_verifyprotk __user *uvp)
- {
- struct pkey_verifyprotk kvp;
- struct protaeskeytoken *t;
- u32 keytype;
- u8 *tmpbuf;
- int rc;
- if (copy_from_user(&kvp, uvp, sizeof(kvp)))
- return -EFAULT;
- keytype = pkey_aes_bitsize_to_keytype(8 * kvp.protkey.len);
- if (!keytype) {
- PKEY_DBF_ERR("%s unknown/unsupported protkey length %u\n",
- __func__, kvp.protkey.len);
- memzero_explicit(&kvp, sizeof(kvp));
- return -EINVAL;
- }
- /* build a 'protected key token' from the raw protected key */
- tmpbuf = kzalloc(sizeof(*t), GFP_KERNEL);
- if (!tmpbuf) {
- memzero_explicit(&kvp, sizeof(kvp));
- return -ENOMEM;
- }
- t = (struct protaeskeytoken *)tmpbuf;
- t->type = TOKTYPE_NON_CCA;
- t->version = TOKVER_PROTECTED_KEY;
- t->keytype = keytype;
- t->len = kvp.protkey.len;
- memcpy(t->protkey, kvp.protkey.protkey, kvp.protkey.len);
- rc = pkey_handler_verify_key(tmpbuf, sizeof(*t),
- NULL, NULL, NULL, NULL, NULL, 0);
- pr_debug("verify_key()=%d\n", rc);
- kfree_sensitive(tmpbuf);
- memzero_explicit(&kvp, sizeof(kvp));
- return rc;
- }
- static int pkey_ioctl_kblob2protk(struct pkey_kblob2pkey __user *utp)
- {
- struct pkey_kblob2pkey ktp;
- u8 *kkey;
- int rc;
- if (copy_from_user(&ktp, utp, sizeof(ktp)))
- return -EFAULT;
- kkey = _copy_key_from_user(ktp.key, ktp.keylen);
- if (IS_ERR(kkey))
- return PTR_ERR(kkey);
- ktp.protkey.len = sizeof(ktp.protkey.protkey);
- rc = key2protkey(NULL, 0, kkey, ktp.keylen,
- ktp.protkey.protkey, &ktp.protkey.len,
- &ktp.protkey.type, 0);
- pr_debug("key2protkey()=%d\n", rc);
- kfree_sensitive(kkey);
- if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))
- rc = -EFAULT;
- memzero_explicit(&ktp, sizeof(ktp));
- return rc;
- }
- static int pkey_ioctl_genseck2(struct pkey_genseck2 __user *ugs)
- {
- u32 klen = KEYBLOBBUFSIZE;
- struct pkey_genseck2 kgs;
- struct pkey_apqn *apqns;
- u8 *kkey;
- int rc;
- u32 u;
- if (copy_from_user(&kgs, ugs, sizeof(kgs)))
- return -EFAULT;
- u = pkey_aes_bitsize_to_keytype(kgs.size);
- if (!u) {
- PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
- __func__, kgs.size);
- return -EINVAL;
- }
- apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries);
- if (IS_ERR(apqns))
- return PTR_ERR(apqns);
- kkey = kzalloc(klen, GFP_KERNEL);
- if (!kkey) {
- kfree(apqns);
- return -ENOMEM;
- }
- rc = pkey_handler_gen_key(apqns, kgs.apqn_entries,
- u, kgs.type, kgs.size, kgs.keygenflags,
- kkey, &klen, NULL, 0);
- pr_debug("gen_key()=%d\n", rc);
- kfree(apqns);
- if (rc) {
- kfree_sensitive(kkey);
- return rc;
- }
- if (kgs.key) {
- if (kgs.keylen < klen) {
- kfree_sensitive(kkey);
- return -EINVAL;
- }
- if (copy_to_user(kgs.key, kkey, klen)) {
- kfree_sensitive(kkey);
- return -EFAULT;
- }
- }
- kgs.keylen = klen;
- if (copy_to_user(ugs, &kgs, sizeof(kgs)))
- rc = -EFAULT;
- kfree_sensitive(kkey);
- return rc;
- }
- static int pkey_ioctl_clr2seck2(struct pkey_clr2seck2 __user *ucs)
- {
- u32 klen = KEYBLOBBUFSIZE;
- struct pkey_clr2seck2 kcs;
- struct pkey_apqn *apqns;
- u8 *kkey;
- int rc;
- u32 u;
- if (copy_from_user(&kcs, ucs, sizeof(kcs)))
- return -EFAULT;
- u = pkey_aes_bitsize_to_keytype(kcs.size);
- if (!u) {
- PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
- __func__, kcs.size);
- memzero_explicit(&kcs, sizeof(kcs));
- return -EINVAL;
- }
- apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries);
- if (IS_ERR(apqns)) {
- memzero_explicit(&kcs, sizeof(kcs));
- return PTR_ERR(apqns);
- }
- kkey = kzalloc(klen, GFP_KERNEL);
- if (!kkey) {
- kfree(apqns);
- memzero_explicit(&kcs, sizeof(kcs));
- return -ENOMEM;
- }
- rc = pkey_handler_clr_to_key(apqns, kcs.apqn_entries,
- u, kcs.type, kcs.size, kcs.keygenflags,
- kcs.clrkey.clrkey, kcs.size / 8,
- kkey, &klen, NULL, 0);
- pr_debug("clr_to_key()=%d\n", rc);
- kfree(apqns);
- if (rc) {
- kfree_sensitive(kkey);
- memzero_explicit(&kcs, sizeof(kcs));
- return rc;
- }
- if (kcs.key) {
- if (kcs.keylen < klen) {
- kfree_sensitive(kkey);
- memzero_explicit(&kcs, sizeof(kcs));
- return -EINVAL;
- }
- if (copy_to_user(kcs.key, kkey, klen)) {
- kfree_sensitive(kkey);
- memzero_explicit(&kcs, sizeof(kcs));
- return -EFAULT;
- }
- }
- kcs.keylen = klen;
- if (copy_to_user(ucs, &kcs, sizeof(kcs)))
- rc = -EFAULT;
- memzero_explicit(&kcs, sizeof(kcs));
- kfree_sensitive(kkey);
- return rc;
- }
- static int pkey_ioctl_verifykey2(struct pkey_verifykey2 __user *uvk)
- {
- struct pkey_verifykey2 kvk;
- u8 *kkey;
- int rc;
- if (copy_from_user(&kvk, uvk, sizeof(kvk)))
- return -EFAULT;
- kkey = _copy_key_from_user(kvk.key, kvk.keylen);
- if (IS_ERR(kkey))
- return PTR_ERR(kkey);
- rc = pkey_handler_verify_key(kkey, kvk.keylen,
- &kvk.cardnr, &kvk.domain,
- &kvk.type, &kvk.size, &kvk.flags, 0);
- pr_debug("verify_key()=%d\n", rc);
- kfree_sensitive(kkey);
- if (!rc && copy_to_user(uvk, &kvk, sizeof(kvk)))
- return -EFAULT;
- return rc;
- }
- static int pkey_ioctl_kblob2protk2(struct pkey_kblob2pkey2 __user *utp)
- {
- struct pkey_apqn *apqns = NULL;
- struct pkey_kblob2pkey2 ktp;
- u8 *kkey;
- int rc;
- if (copy_from_user(&ktp, utp, sizeof(ktp)))
- return -EFAULT;
- apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);
- if (IS_ERR(apqns))
- return PTR_ERR(apqns);
- kkey = _copy_key_from_user(ktp.key, ktp.keylen);
- if (IS_ERR(kkey)) {
- kfree(apqns);
- return PTR_ERR(kkey);
- }
- ktp.protkey.len = sizeof(ktp.protkey.protkey);
- rc = key2protkey(apqns, ktp.apqn_entries, kkey, ktp.keylen,
- ktp.protkey.protkey, &ktp.protkey.len,
- &ktp.protkey.type, 0);
- pr_debug("key2protkey()=%d\n", rc);
- kfree(apqns);
- kfree_sensitive(kkey);
- if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))
- rc = -EFAULT;
- memzero_explicit(&ktp, sizeof(ktp));
- return rc;
- }
- static int pkey_ioctl_apqns4k(struct pkey_apqns4key __user *uak)
- {
- struct pkey_apqn *apqns = NULL;
- struct pkey_apqns4key kak;
- size_t nr_apqns, len;
- u8 *kkey;
- int rc;
- if (copy_from_user(&kak, uak, sizeof(kak)))
- return -EFAULT;
- nr_apqns = kak.apqn_entries;
- if (nr_apqns) {
- apqns = kmalloc_objs(struct pkey_apqn, nr_apqns);
- if (!apqns)
- return -ENOMEM;
- }
- kkey = _copy_key_from_user(kak.key, kak.keylen);
- if (IS_ERR(kkey)) {
- kfree(apqns);
- return PTR_ERR(kkey);
- }
- rc = pkey_handler_apqns_for_key(kkey, kak.keylen, kak.flags,
- apqns, &nr_apqns, 0);
- pr_debug("apqns_for_key()=%d\n", rc);
- kfree_sensitive(kkey);
- if (rc && rc != -ENOSPC) {
- kfree(apqns);
- return rc;
- }
- if (!rc && kak.apqns) {
- if (nr_apqns > kak.apqn_entries) {
- kfree(apqns);
- return -EINVAL;
- }
- len = nr_apqns * sizeof(struct pkey_apqn);
- if (len) {
- if (copy_to_user(kak.apqns, apqns, len)) {
- kfree(apqns);
- return -EFAULT;
- }
- }
- }
- kak.apqn_entries = nr_apqns;
- if (copy_to_user(uak, &kak, sizeof(kak)))
- rc = -EFAULT;
- kfree(apqns);
- return rc;
- }
- static int pkey_ioctl_apqns4kt(struct pkey_apqns4keytype __user *uat)
- {
- struct pkey_apqn *apqns = NULL;
- struct pkey_apqns4keytype kat;
- size_t nr_apqns, len;
- int rc;
- if (copy_from_user(&kat, uat, sizeof(kat)))
- return -EFAULT;
- nr_apqns = kat.apqn_entries;
- if (nr_apqns) {
- apqns = kmalloc_objs(struct pkey_apqn, nr_apqns);
- if (!apqns)
- return -ENOMEM;
- }
- rc = pkey_handler_apqns_for_keytype(kat.type,
- kat.cur_mkvp, kat.alt_mkvp,
- kat.flags, apqns, &nr_apqns, 0);
- pr_debug("apqns_for_keytype()=%d\n", rc);
- if (rc && rc != -ENOSPC) {
- kfree(apqns);
- return rc;
- }
- if (!rc && kat.apqns) {
- if (nr_apqns > kat.apqn_entries) {
- kfree(apqns);
- return -EINVAL;
- }
- len = nr_apqns * sizeof(struct pkey_apqn);
- if (len) {
- if (copy_to_user(kat.apqns, apqns, len)) {
- kfree(apqns);
- return -EFAULT;
- }
- }
- }
- kat.apqn_entries = nr_apqns;
- if (copy_to_user(uat, &kat, sizeof(kat)))
- rc = -EFAULT;
- kfree(apqns);
- return rc;
- }
- static int pkey_ioctl_kblob2protk3(struct pkey_kblob2pkey3 __user *utp)
- {
- u32 protkeylen = PROTKEYBLOBBUFSIZE;
- struct pkey_apqn *apqns = NULL;
- struct pkey_kblob2pkey3 ktp;
- u8 *kkey, *protkey;
- int rc;
- if (copy_from_user(&ktp, utp, sizeof(ktp)))
- return -EFAULT;
- apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);
- if (IS_ERR(apqns))
- return PTR_ERR(apqns);
- kkey = _copy_key_from_user(ktp.key, ktp.keylen);
- if (IS_ERR(kkey)) {
- kfree(apqns);
- return PTR_ERR(kkey);
- }
- protkey = kmalloc(protkeylen, GFP_KERNEL);
- if (!protkey) {
- kfree(apqns);
- kfree_sensitive(kkey);
- return -ENOMEM;
- }
- rc = key2protkey(apqns, ktp.apqn_entries, kkey, ktp.keylen,
- protkey, &protkeylen, &ktp.pkeytype, 0);
- pr_debug("key2protkey()=%d\n", rc);
- kfree(apqns);
- kfree_sensitive(kkey);
- if (rc) {
- kfree_sensitive(protkey);
- return rc;
- }
- if (ktp.pkey && ktp.pkeylen) {
- if (protkeylen > ktp.pkeylen) {
- kfree_sensitive(protkey);
- return -EINVAL;
- }
- if (copy_to_user(ktp.pkey, protkey, protkeylen)) {
- kfree_sensitive(protkey);
- return -EFAULT;
- }
- }
- kfree_sensitive(protkey);
- ktp.pkeylen = protkeylen;
- if (copy_to_user(utp, &ktp, sizeof(ktp)))
- return -EFAULT;
- return 0;
- }
- static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
- {
- int rc;
- switch (cmd) {
- case PKEY_GENSECK:
- rc = pkey_ioctl_genseck((struct pkey_genseck __user *)arg);
- break;
- case PKEY_CLR2SECK:
- rc = pkey_ioctl_clr2seck((struct pkey_clr2seck __user *)arg);
- break;
- case PKEY_SEC2PROTK:
- rc = pkey_ioctl_sec2protk((struct pkey_sec2protk __user *)arg);
- break;
- case PKEY_CLR2PROTK:
- rc = pkey_ioctl_clr2protk((struct pkey_clr2protk __user *)arg);
- break;
- case PKEY_FINDCARD:
- rc = pkey_ioctl_findcard((struct pkey_findcard __user *)arg);
- break;
- case PKEY_SKEY2PKEY:
- rc = pkey_ioctl_skey2pkey((struct pkey_skey2pkey __user *)arg);
- break;
- case PKEY_VERIFYKEY:
- rc = pkey_ioctl_verifykey((struct pkey_verifykey __user *)arg);
- break;
- case PKEY_GENPROTK:
- rc = pkey_ioctl_genprotk((struct pkey_genprotk __user *)arg);
- break;
- case PKEY_VERIFYPROTK:
- rc = pkey_ioctl_verifyprotk((struct pkey_verifyprotk __user *)arg);
- break;
- case PKEY_KBLOB2PROTK:
- rc = pkey_ioctl_kblob2protk((struct pkey_kblob2pkey __user *)arg);
- break;
- case PKEY_GENSECK2:
- rc = pkey_ioctl_genseck2((struct pkey_genseck2 __user *)arg);
- break;
- case PKEY_CLR2SECK2:
- rc = pkey_ioctl_clr2seck2((struct pkey_clr2seck2 __user *)arg);
- break;
- case PKEY_VERIFYKEY2:
- rc = pkey_ioctl_verifykey2((struct pkey_verifykey2 __user *)arg);
- break;
- case PKEY_KBLOB2PROTK2:
- rc = pkey_ioctl_kblob2protk2((struct pkey_kblob2pkey2 __user *)arg);
- break;
- case PKEY_APQNS4K:
- rc = pkey_ioctl_apqns4k((struct pkey_apqns4key __user *)arg);
- break;
- case PKEY_APQNS4KT:
- rc = pkey_ioctl_apqns4kt((struct pkey_apqns4keytype __user *)arg);
- break;
- case PKEY_KBLOB2PROTK3:
- rc = pkey_ioctl_kblob2protk3((struct pkey_kblob2pkey3 __user *)arg);
- break;
- default:
- /* unknown/unsupported ioctl cmd */
- return -ENOTTY;
- }
- return rc;
- }
- /*
- * File io operations
- */
- static const struct file_operations pkey_fops = {
- .owner = THIS_MODULE,
- .open = nonseekable_open,
- .unlocked_ioctl = pkey_unlocked_ioctl,
- };
- static struct miscdevice pkey_dev = {
- .name = "pkey",
- .minor = MISC_DYNAMIC_MINOR,
- .mode = 0666,
- .fops = &pkey_fops,
- .groups = pkey_attr_groups,
- };
- int __init pkey_api_init(void)
- {
- /* register as a misc device */
- return misc_register(&pkey_dev);
- }
- void __exit pkey_api_exit(void)
- {
- misc_deregister(&pkey_dev);
- }
|