s390/pkey: Split pkey_unlocked_ioctl function
authorHarald Freudenberger <freude@linux.ibm.com>
Thu, 22 Aug 2024 09:32:16 +0000 (11:32 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Thu, 29 Aug 2024 20:56:33 +0000 (22:56 +0200)
Split the very huge ioctl handling function pkey_unlocked_ioctl()
into individual functions per each IOCTL command.

There is no change in functional code coming with this patch.
The work is a simple copy-and-paste with the goal to have
the functionality absolutely untouched.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
drivers/s390/crypto/pkey_api.c

index ffc0b5db55c29053ce70a5ec176c4d103fa12df0..f3dca56f0808f87ce29cca51db9cdbe52d5b57e3 100644 (file)
@@ -1344,444 +1344,546 @@ static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns)
        return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn));
 }
 
-static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
-                               unsigned long arg)
+static int pkey_ioctl_genseck(struct pkey_genseck __user *ugs)
 {
+       struct pkey_genseck kgs;
        int rc;
 
-       switch (cmd) {
-       case PKEY_GENSECK: {
-               struct pkey_genseck __user *ugs = (void __user *)arg;
-               struct pkey_genseck kgs;
+       if (copy_from_user(&kgs, ugs, sizeof(kgs)))
+               return -EFAULT;
+       rc = cca_genseckey(kgs.cardnr, kgs.domain,
+                          kgs.keytype, kgs.seckey.seckey);
+       pr_debug("%s cca_genseckey()=%d\n", __func__, rc);
+       if (!rc && copy_to_user(ugs, &kgs, sizeof(kgs)))
+               rc = -EFAULT;
+       memzero_explicit(&kgs, sizeof(kgs));
 
-               if (copy_from_user(&kgs, ugs, sizeof(kgs)))
-                       return -EFAULT;
-               rc = cca_genseckey(kgs.cardnr, kgs.domain,
-                                  kgs.keytype, kgs.seckey.seckey);
-               pr_debug("%s cca_genseckey()=%d\n", __func__, rc);
-               if (!rc && copy_to_user(ugs, &kgs, sizeof(kgs)))
-                       rc = -EFAULT;
-               memzero_explicit(&kgs, sizeof(kgs));
-               break;
-       }
-       case PKEY_CLR2SECK: {
-               struct pkey_clr2seck __user *ucs = (void __user *)arg;
-               struct pkey_clr2seck kcs;
+       return rc;
+}
 
-               if (copy_from_user(&kcs, ucs, sizeof(kcs)))
-                       return -EFAULT;
-               rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype,
-                                   kcs.clrkey.clrkey, kcs.seckey.seckey);
-               pr_debug("%s cca_clr2seckey()=%d\n", __func__, rc);
-               if (!rc && copy_to_user(ucs, &kcs, sizeof(kcs)))
-                       rc = -EFAULT;
-               memzero_explicit(&kcs, sizeof(kcs));
-               break;
-       }
-       case PKEY_SEC2PROTK: {
-               struct pkey_sec2protk __user *usp = (void __user *)arg;
-               struct pkey_sec2protk ksp;
+static int pkey_ioctl_clr2seck(struct pkey_clr2seck __user *ucs)
+{
+       struct pkey_clr2seck kcs;
+       int rc;
 
-               if (copy_from_user(&ksp, usp, sizeof(ksp)))
-                       return -EFAULT;
-               ksp.protkey.len = sizeof(ksp.protkey.protkey);
-               rc = cca_sec2protkey(ksp.cardnr, ksp.domain,
-                                    ksp.seckey.seckey, ksp.protkey.protkey,
-                                    &ksp.protkey.len, &ksp.protkey.type);
-               pr_debug("%s cca_sec2protkey()=%d\n", __func__, rc);
-               if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
-                       rc = -EFAULT;
-               memzero_explicit(&ksp, sizeof(ksp));
-               break;
-       }
-       case PKEY_CLR2PROTK: {
-               struct pkey_clr2protk __user *ucp = (void __user *)arg;
-               struct pkey_clr2protk kcp;
+       if (copy_from_user(&kcs, ucs, sizeof(kcs)))
+               return -EFAULT;
+       rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype,
+                           kcs.clrkey.clrkey, kcs.seckey.seckey);
+       pr_debug("%s cca_clr2seckey()=%d\n", __func__, rc);
+       if (!rc && copy_to_user(ucs, &kcs, sizeof(kcs)))
+               rc = -EFAULT;
+       memzero_explicit(&kcs, sizeof(kcs));
 
-               if (copy_from_user(&kcp, ucp, sizeof(kcp)))
-                       return -EFAULT;
-               kcp.protkey.len = sizeof(kcp.protkey.protkey);
-               rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey,
-                                     kcp.protkey.protkey,
-                                     &kcp.protkey.len, &kcp.protkey.type);
-               pr_debug("%s pkey_clr2protkey()=%d\n", __func__, rc);
-               if (!rc && copy_to_user(ucp, &kcp, sizeof(kcp)))
-                       rc = -EFAULT;
-               memzero_explicit(&kcp, sizeof(kcp));
-               break;
-       }
-       case PKEY_FINDCARD: {
-               struct pkey_findcard __user *ufc = (void __user *)arg;
-               struct pkey_findcard kfc;
+       return rc;
+}
 
-               if (copy_from_user(&kfc, ufc, sizeof(kfc)))
-                       return -EFAULT;
-               rc = cca_findcard(kfc.seckey.seckey,
-                                 &kfc.cardnr, &kfc.domain, 1);
-               pr_debug("%s cca_findcard()=%d\n", __func__, rc);
-               if (rc < 0)
-                       break;
-               if (copy_to_user(ufc, &kfc, sizeof(kfc)))
-                       return -EFAULT;
-               break;
-       }
-       case PKEY_SKEY2PKEY: {
-               struct pkey_skey2pkey __user *usp = (void __user *)arg;
-               struct pkey_skey2pkey ksp;
+static int pkey_ioctl_sec2protk(struct pkey_sec2protk __user *usp)
+{
+       struct pkey_sec2protk ksp;
+       int rc;
 
-               if (copy_from_user(&ksp, usp, sizeof(ksp)))
-                       return -EFAULT;
-               ksp.protkey.len = sizeof(ksp.protkey.protkey);
-               rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey,
-                                   &ksp.protkey.len, &ksp.protkey.type);
-               pr_debug("%s pkey_skey2pkey()=%d\n", __func__, rc);
-               if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
-                       rc = -EFAULT;
-               memzero_explicit(&ksp, sizeof(ksp));
-               break;
-       }
-       case PKEY_VERIFYKEY: {
-               struct pkey_verifykey __user *uvk = (void __user *)arg;
-               struct pkey_verifykey kvk;
+       if (copy_from_user(&ksp, usp, sizeof(ksp)))
+               return -EFAULT;
+       ksp.protkey.len = sizeof(ksp.protkey.protkey);
+       rc = cca_sec2protkey(ksp.cardnr, ksp.domain,
+                            ksp.seckey.seckey, ksp.protkey.protkey,
+                            &ksp.protkey.len, &ksp.protkey.type);
+       pr_debug("%s cca_sec2protkey()=%d\n", __func__, rc);
+       if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
+               rc = -EFAULT;
+       memzero_explicit(&ksp, sizeof(ksp));
 
-               if (copy_from_user(&kvk, uvk, sizeof(kvk)))
-                       return -EFAULT;
-               rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain,
-                                   &kvk.keysize, &kvk.attributes);
-               pr_debug("%s pkey_verifykey()=%d\n", __func__, rc);
-               if (!rc && copy_to_user(uvk, &kvk, sizeof(kvk)))
-                       rc = -EFAULT;
-               memzero_explicit(&kvk, sizeof(kvk));
-               break;
-       }
-       case PKEY_GENPROTK: {
-               struct pkey_genprotk __user *ugp = (void __user *)arg;
-               struct pkey_genprotk kgp;
+       return rc;
+}
 
-               if (copy_from_user(&kgp, ugp, sizeof(kgp)))
-                       return -EFAULT;
-               kgp.protkey.len = sizeof(kgp.protkey.protkey);
-               rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey,
-                                    &kgp.protkey.len, &kgp.protkey.type);
-               pr_debug("%s pkey_genprotkey()=%d\n", __func__, rc);
-               if (!rc && copy_to_user(ugp, &kgp, sizeof(kgp)))
-                       rc = -EFAULT;
-               memzero_explicit(&kgp, sizeof(kgp));
-               break;
-       }
-       case PKEY_VERIFYPROTK: {
-               struct pkey_verifyprotk __user *uvp = (void __user *)arg;
-               struct pkey_verifyprotk kvp;
+static int pkey_ioctl_clr2protk(struct pkey_clr2protk __user *ucp)
+{
+       struct pkey_clr2protk kcp;
+       int rc;
 
-               if (copy_from_user(&kvp, uvp, sizeof(kvp)))
-                       return -EFAULT;
-               rc = pkey_verifyprotkey(kvp.protkey.protkey,
-                                       kvp.protkey.len, kvp.protkey.type);
-               pr_debug("%s pkey_verifyprotkey()=%d\n", __func__, rc);
-               memzero_explicit(&kvp, sizeof(kvp));
-               break;
-       }
-       case PKEY_KBLOB2PROTK: {
-               struct pkey_kblob2pkey __user *utp = (void __user *)arg;
-               struct pkey_kblob2pkey ktp;
-               u8 *kkey;
+       if (copy_from_user(&kcp, ucp, sizeof(kcp)))
+               return -EFAULT;
+       kcp.protkey.len = sizeof(kcp.protkey.protkey);
+       rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey,
+                             kcp.protkey.protkey,
+                             &kcp.protkey.len, &kcp.protkey.type);
+       pr_debug("%s pkey_clr2protkey()=%d\n", __func__, rc);
+       if (!rc && copy_to_user(ucp, &kcp, sizeof(kcp)))
+               rc = -EFAULT;
+       memzero_explicit(&kcp, sizeof(kcp));
 
-               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 = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey,
-                                      &ktp.protkey.len, &ktp.protkey.type);
-               pr_debug("%s pkey_keyblob2pkey()=%d\n", __func__, rc);
-               kfree_sensitive(kkey);
-               if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))
-                       rc = -EFAULT;
-               memzero_explicit(&ktp, sizeof(ktp));
-               break;
-       }
-       case PKEY_GENSECK2: {
-               struct pkey_genseck2 __user *ugs = (void __user *)arg;
-               size_t klen = KEYBLOBBUFSIZE;
-               struct pkey_genseck2 kgs;
-               struct pkey_apqn *apqns;
-               u8 *kkey;
+       return rc;
+}
 
-               if (copy_from_user(&kgs, ugs, sizeof(kgs)))
-                       return -EFAULT;
-               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_genseckey2(apqns, kgs.apqn_entries,
-                                    kgs.type, kgs.size, kgs.keygenflags,
-                                    kkey, &klen);
-               pr_debug("%s pkey_genseckey2()=%d\n", __func__, rc);
+static int pkey_ioctl_findcard(struct pkey_findcard __user *ufc)
+{
+       struct pkey_findcard kfc;
+       int rc;
+
+       if (copy_from_user(&kfc, ufc, sizeof(kfc)))
+               return -EFAULT;
+       rc = cca_findcard(kfc.seckey.seckey,
+                         &kfc.cardnr, &kfc.domain, 1);
+       pr_debug("%s cca_findcard()=%d\n", __func__, rc);
+       if (rc < 0)
+               return rc;
+       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_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey,
+                           &ksp.protkey.len, &ksp.protkey.type);
+       pr_debug("%s pkey_skey2pkey()=%d\n", __func__, 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)
+{
+       struct pkey_verifykey kvk;
+       int rc;
+
+       if (copy_from_user(&kvk, uvk, sizeof(kvk)))
+               return -EFAULT;
+       rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain,
+                           &kvk.keysize, &kvk.attributes);
+       pr_debug("%s pkey_verifykey()=%d\n", __func__, rc);
+       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_genprotkey(kgp.keytype, kgp.protkey.protkey,
+                            &kgp.protkey.len, &kgp.protkey.type);
+       pr_debug("%s pkey_genprotkey()=%d\n", __func__, 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;
+       int rc;
+
+       if (copy_from_user(&kvp, uvp, sizeof(kvp)))
+               return -EFAULT;
+       rc = pkey_verifyprotkey(kvp.protkey.protkey,
+                               kvp.protkey.len, kvp.protkey.type);
+       pr_debug("%s pkey_verifyprotkey()=%d\n", __func__, rc);
+       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 = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey,
+                              &ktp.protkey.len, &ktp.protkey.type);
+       pr_debug("%s pkey_keyblob2pkey()=%d\n", __func__, 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)
+{
+       size_t klen = KEYBLOBBUFSIZE;
+       struct pkey_genseck2 kgs;
+       struct pkey_apqn *apqns;
+       u8 *kkey;
+       int rc;
+
+       if (copy_from_user(&kgs, ugs, sizeof(kgs)))
+               return -EFAULT;
+       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);
-               if (rc) {
+               return -ENOMEM;
+       }
+       rc = pkey_genseckey2(apqns, kgs.apqn_entries,
+                            kgs.type, kgs.size, kgs.keygenflags,
+                            kkey, &klen);
+       pr_debug("%s pkey_genseckey2()=%d\n", __func__, rc);
+       kfree(apqns);
+       if (rc) {
+               kfree_sensitive(kkey);
+               return rc;
+       }
+       if (kgs.key) {
+               if (kgs.keylen < klen) {
                        kfree_sensitive(kkey);
-                       break;
+                       return -EINVAL;
                }
-               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;
-                       }
+               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);
-               break;
        }
-       case PKEY_CLR2SECK2: {
-               struct pkey_clr2seck2 __user *ucs = (void __user *)arg;
-               size_t klen = KEYBLOBBUFSIZE;
-               struct pkey_clr2seck2 kcs;
-               struct pkey_apqn *apqns;
-               u8 *kkey;
+       kgs.keylen = klen;
+       if (copy_to_user(ugs, &kgs, sizeof(kgs)))
+               rc = -EFAULT;
+       kfree_sensitive(kkey);
 
-               if (copy_from_user(&kcs, ucs, sizeof(kcs)))
-                       return -EFAULT;
-               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_clr2seckey2(apqns, kcs.apqn_entries,
-                                     kcs.type, kcs.size, kcs.keygenflags,
-                                     kcs.clrkey.clrkey, kkey, &klen);
-               pr_debug("%s pkey_clr2seckey2()=%d\n", __func__, rc);
+       return rc;
+}
+
+static int pkey_ioctl_clr2seck2(struct pkey_clr2seck2 __user *ucs)
+{
+       size_t klen = KEYBLOBBUFSIZE;
+       struct pkey_clr2seck2 kcs;
+       struct pkey_apqn *apqns;
+       u8 *kkey;
+       int rc;
+
+       if (copy_from_user(&kcs, ucs, sizeof(kcs)))
+               return -EFAULT;
+       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);
-               if (rc) {
+               memzero_explicit(&kcs, sizeof(kcs));
+               return -ENOMEM;
+       }
+       rc = pkey_clr2seckey2(apqns, kcs.apqn_entries,
+                             kcs.type, kcs.size, kcs.keygenflags,
+                             kcs.clrkey.clrkey, kkey, &klen);
+       pr_debug("%s pkey_clr2seckey2()=%d\n", __func__, 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));
-                       break;
+                       return -EINVAL;
                }
-               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;
-                       }
+               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);
-               break;
        }
-       case PKEY_VERIFYKEY2: {
-               struct pkey_verifykey2 __user *uvk = (void __user *)arg;
-               struct pkey_verifykey2 kvk;
-               u8 *kkey;
+       kcs.keylen = klen;
+       if (copy_to_user(ucs, &kcs, sizeof(kcs)))
+               rc = -EFAULT;
+       memzero_explicit(&kcs, sizeof(kcs));
+       kfree_sensitive(kkey);
 
-               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_verifykey2(kkey, kvk.keylen,
-                                    &kvk.cardnr, &kvk.domain,
-                                    &kvk.type, &kvk.size, &kvk.flags);
-               pr_debug("%s pkey_verifykey2()=%d\n", __func__, rc);
-               kfree_sensitive(kkey);
-               if (rc)
-                       break;
-               if (copy_to_user(uvk, &kvk, sizeof(kvk)))
-                       return -EFAULT;
-               break;
-       }
-       case PKEY_KBLOB2PROTK2: {
-               struct pkey_kblob2pkey2 __user *utp = (void __user *)arg;
-               struct pkey_apqn *apqns = NULL;
-               struct pkey_kblob2pkey2 ktp;
-               u8 *kkey;
+       return 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 = pkey_keyblob2pkey2(apqns, ktp.apqn_entries,
-                                       kkey, ktp.keylen,
-                                       ktp.protkey.protkey, &ktp.protkey.len,
-                                       &ktp.protkey.type);
-               pr_debug("%s pkey_keyblob2pkey2()=%d\n", __func__, 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_verifykey2(kkey, kvk.keylen,
+                            &kvk.cardnr, &kvk.domain,
+                            &kvk.type, &kvk.size, &kvk.flags);
+       pr_debug("%s pkey_verifykey2()=%d\n", __func__, rc);
+       kfree_sensitive(kkey);
+       if (rc)
+               return rc;
+       if (copy_to_user(uvk, &kvk, sizeof(kvk)))
+               return -EFAULT;
+
+       return 0;
+}
+
+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);
-               kfree_sensitive(kkey);
-               if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))
-                       rc = -EFAULT;
-               memzero_explicit(&ktp, sizeof(ktp));
-               break;
-       }
-       case PKEY_APQNS4K: {
-               struct pkey_apqns4key __user *uak = (void __user *)arg;
-               struct pkey_apqn *apqns = NULL;
-               struct pkey_apqns4key kak;
-               size_t nr_apqns, len;
-               u8 *kkey;
+               return PTR_ERR(kkey);
+       }
+       ktp.protkey.len = sizeof(ktp.protkey.protkey);
+       rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries,
+                               kkey, ktp.keylen,
+                               ktp.protkey.protkey, &ktp.protkey.len,
+                               &ktp.protkey.type);
+       pr_debug("%s pkey_keyblob2pkey2()=%d\n", __func__, rc);
+       kfree(apqns);
+       kfree_sensitive(kkey);
+       if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))
+               rc = -EFAULT;
+       memzero_explicit(&ktp, sizeof(ktp));
 
-               if (copy_from_user(&kak, uak, sizeof(kak)))
-                       return -EFAULT;
-               nr_apqns = kak.apqn_entries;
-               if (nr_apqns) {
-                       apqns = kmalloc_array(nr_apqns,
-                                             sizeof(struct pkey_apqn),
-                                             GFP_KERNEL);
-                       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_apqns4key(kkey, kak.keylen, kak.flags,
-                                   apqns, &nr_apqns);
-               pr_debug("%s pkey_apqns4key()=%d\n", __func__, rc);
-               kfree_sensitive(kkey);
-               if (rc && rc != -ENOSPC) {
+       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_array(nr_apqns,
+                                     sizeof(struct pkey_apqn),
+                                     GFP_KERNEL);
+               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_apqns4key(kkey, kak.keylen, kak.flags,
+                           apqns, &nr_apqns);
+       pr_debug("%s pkey_apqns4key()=%d\n", __func__, rc);
+       kfree_sensitive(kkey);
+       if (rc && rc != -ENOSPC) {
+               kfree(apqns);
+               return rc;
+       }
+       if (!rc && kak.apqns) {
+               if (nr_apqns > kak.apqn_entries) {
                        kfree(apqns);
-                       break;
+                       return -EINVAL;
                }
-               if (!rc && kak.apqns) {
-                       if (nr_apqns > kak.apqn_entries) {
+               len = nr_apqns * sizeof(struct pkey_apqn);
+               if (len) {
+                       if (copy_to_user(kak.apqns, apqns, len)) {
                                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;
-                               }
+                               return -EFAULT;
                        }
                }
-               kak.apqn_entries = nr_apqns;
-               if (copy_to_user(uak, &kak, sizeof(kak)))
-                       rc = -EFAULT;
-               kfree(apqns);
-               break;
        }
-       case PKEY_APQNS4KT: {
-               struct pkey_apqns4keytype __user *uat = (void __user *)arg;
-               struct pkey_apqn *apqns = NULL;
-               struct pkey_apqns4keytype kat;
-               size_t nr_apqns, len;
+       kak.apqn_entries = nr_apqns;
+       if (copy_to_user(uak, &kak, sizeof(kak)))
+               rc = -EFAULT;
+       kfree(apqns);
 
-               if (copy_from_user(&kat, uat, sizeof(kat)))
-                       return -EFAULT;
-               nr_apqns = kat.apqn_entries;
-               if (nr_apqns) {
-                       apqns = kmalloc_array(nr_apqns,
-                                             sizeof(struct pkey_apqn),
-                                             GFP_KERNEL);
-                       if (!apqns)
-                               return -ENOMEM;
-               }
-               rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp,
-                                       kat.flags, apqns, &nr_apqns);
-               pr_debug("%s pkey_apqns4keytype()=%d\n", __func__, rc);
-               if (rc && rc != -ENOSPC) {
+       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_array(nr_apqns,
+                                     sizeof(struct pkey_apqn),
+                                     GFP_KERNEL);
+               if (!apqns)
+                       return -ENOMEM;
+       }
+       rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp,
+                               kat.flags, apqns, &nr_apqns);
+       pr_debug("%s pkey_apqns4keytype()=%d\n", __func__, rc);
+       if (rc && rc != -ENOSPC) {
+               kfree(apqns);
+               return rc;
+       }
+       if (!rc && kat.apqns) {
+               if (nr_apqns > kat.apqn_entries) {
                        kfree(apqns);
-                       break;
+                       return -EINVAL;
                }
-               if (!rc && kat.apqns) {
-                       if (nr_apqns > kat.apqn_entries) {
+               len = nr_apqns * sizeof(struct pkey_apqn);
+               if (len) {
+                       if (copy_to_user(kat.apqns, apqns, len)) {
                                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;
-                               }
+                               return -EFAULT;
                        }
                }
-               kat.apqn_entries = nr_apqns;
-               if (copy_to_user(uat, &kat, sizeof(kat)))
-                       rc = -EFAULT;
-               kfree(apqns);
-               break;
        }
-       case PKEY_KBLOB2PROTK3: {
-               struct pkey_kblob2pkey3 __user *utp = (void __user *)arg;
-               u32 protkeylen = PROTKEYBLOBBUFSIZE;
-               struct pkey_apqn *apqns = NULL;
-               struct pkey_kblob2pkey3 ktp;
-               u8 *kkey, *protkey;
+       kat.apqn_entries = nr_apqns;
+       if (copy_to_user(uat, &kat, sizeof(kat)))
+               rc = -EFAULT;
+       kfree(apqns);
 
-               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 = pkey_keyblob2pkey3(apqns, ktp.apqn_entries,
-                                       kkey, ktp.keylen,
-                                       protkey, &protkeylen, &ktp.pkeytype);
-               pr_debug("%s pkey_keyblob2pkey3()=%d\n", __func__, rc);
+       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);
-               if (rc) {
+               return -ENOMEM;
+       }
+       rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries,
+                               kkey, ktp.keylen,
+                               protkey, &protkeylen, &ktp.pkeytype);
+       pr_debug("%s pkey_keyblob2pkey3()=%d\n", __func__, 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);
-                       break;
-               }
-               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;
-                       }
+                       return -EINVAL;
                }
-               kfree_sensitive(protkey);
-               ktp.pkeylen = protkeylen;
-               if (copy_to_user(utp, &ktp, sizeof(ktp)))
+               if (copy_to_user(ktp.pkey, protkey, protkeylen)) {
+                       kfree_sensitive(protkey);
                        return -EFAULT;
-               break;
+               }
        }
+       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;