diff options
Diffstat (limited to 'drivers/s390/crypto')
-rw-r--r-- | drivers/s390/crypto/pkey_api.c | 878 |
1 files changed, 490 insertions, 388 deletions
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index ffc0b5db55c2..f3dca56f0808 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -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; |