Commit 7344eea1 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Vasily Gorbik

s390/pkey: Split pkey_unlocked_ioctl function

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: default avatarHarald Freudenberger <freude@linux.ibm.com>
Reviewed-by: default avatarHolger Dengler <dengler@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent c3dcb058
...@@ -1344,444 +1344,546 @@ static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) ...@@ -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)); return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn));
} }
static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, static int pkey_ioctl_genseck(struct pkey_genseck __user *ugs)
unsigned long arg)
{ {
struct pkey_genseck kgs;
int rc; int rc;
switch (cmd) { if (copy_from_user(&kgs, ugs, sizeof(kgs)))
case PKEY_GENSECK: { return -EFAULT;
struct pkey_genseck __user *ugs = (void __user *)arg; rc = cca_genseckey(kgs.cardnr, kgs.domain,
struct pkey_genseck kgs; 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 rc;
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;
if (copy_from_user(&kcs, ucs, sizeof(kcs))) static int pkey_ioctl_clr2seck(struct pkey_clr2seck __user *ucs)
return -EFAULT; {
rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, struct pkey_clr2seck kcs;
kcs.clrkey.clrkey, kcs.seckey.seckey); int rc;
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;
if (copy_from_user(&ksp, usp, sizeof(ksp))) if (copy_from_user(&kcs, ucs, sizeof(kcs)))
return -EFAULT; return -EFAULT;
ksp.protkey.len = sizeof(ksp.protkey.protkey); rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype,
rc = cca_sec2protkey(ksp.cardnr, ksp.domain, kcs.clrkey.clrkey, kcs.seckey.seckey);
ksp.seckey.seckey, ksp.protkey.protkey, pr_debug("%s cca_clr2seckey()=%d\n", __func__, rc);
&ksp.protkey.len, &ksp.protkey.type); if (!rc && copy_to_user(ucs, &kcs, sizeof(kcs)))
pr_debug("%s cca_sec2protkey()=%d\n", __func__, rc); rc = -EFAULT;
if (!rc && copy_to_user(usp, &ksp, sizeof(ksp))) memzero_explicit(&kcs, sizeof(kcs));
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(&kcp, ucp, sizeof(kcp))) return rc;
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;
if (copy_from_user(&kfc, ufc, sizeof(kfc))) static int pkey_ioctl_sec2protk(struct pkey_sec2protk __user *usp)
return -EFAULT; {
rc = cca_findcard(kfc.seckey.seckey, struct pkey_sec2protk ksp;
&kfc.cardnr, &kfc.domain, 1); int rc;
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;
if (copy_from_user(&ksp, usp, sizeof(ksp))) if (copy_from_user(&ksp, usp, sizeof(ksp)))
return -EFAULT; return -EFAULT;
ksp.protkey.len = sizeof(ksp.protkey.protkey); ksp.protkey.len = sizeof(ksp.protkey.protkey);
rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey, rc = cca_sec2protkey(ksp.cardnr, ksp.domain,
&ksp.protkey.len, &ksp.protkey.type); ksp.seckey.seckey, ksp.protkey.protkey,
pr_debug("%s pkey_skey2pkey()=%d\n", __func__, rc); &ksp.protkey.len, &ksp.protkey.type);
if (!rc && copy_to_user(usp, &ksp, sizeof(ksp))) pr_debug("%s cca_sec2protkey()=%d\n", __func__, rc);
rc = -EFAULT; if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
memzero_explicit(&ksp, sizeof(ksp)); rc = -EFAULT;
break; memzero_explicit(&ksp, sizeof(ksp));
}
case PKEY_VERIFYKEY: {
struct pkey_verifykey __user *uvk = (void __user *)arg;
struct pkey_verifykey kvk;
if (copy_from_user(&kvk, uvk, sizeof(kvk))) return rc;
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;
if (copy_from_user(&kgp, ugp, sizeof(kgp))) static int pkey_ioctl_clr2protk(struct pkey_clr2protk __user *ucp)
return -EFAULT; {
kgp.protkey.len = sizeof(kgp.protkey.protkey); struct pkey_clr2protk kcp;
rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey, int rc;
&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;
if (copy_from_user(&kvp, uvp, sizeof(kvp))) if (copy_from_user(&kcp, ucp, sizeof(kcp)))
return -EFAULT; return -EFAULT;
rc = pkey_verifyprotkey(kvp.protkey.protkey, kcp.protkey.len = sizeof(kcp.protkey.protkey);
kvp.protkey.len, kvp.protkey.type); rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey,
pr_debug("%s pkey_verifyprotkey()=%d\n", __func__, rc); kcp.protkey.protkey,
memzero_explicit(&kvp, sizeof(kvp)); &kcp.protkey.len, &kcp.protkey.type);
break; pr_debug("%s pkey_clr2protkey()=%d\n", __func__, rc);
} if (!rc && copy_to_user(ucp, &kcp, sizeof(kcp)))
case PKEY_KBLOB2PROTK: { rc = -EFAULT;
struct pkey_kblob2pkey __user *utp = (void __user *)arg; memzero_explicit(&kcp, sizeof(kcp));
struct pkey_kblob2pkey ktp;
u8 *kkey;
if (copy_from_user(&ktp, utp, sizeof(ktp))) return rc;
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;
if (copy_from_user(&kgs, ugs, sizeof(kgs))) static int pkey_ioctl_findcard(struct pkey_findcard __user *ufc)
return -EFAULT; {
apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); struct pkey_findcard kfc;
if (IS_ERR(apqns)) int rc;
return PTR_ERR(apqns);
kkey = kzalloc(klen, GFP_KERNEL); if (copy_from_user(&kfc, ufc, sizeof(kfc)))
if (!kkey) { return -EFAULT;
kfree(apqns); rc = cca_findcard(kfc.seckey.seckey,
return -ENOMEM; &kfc.cardnr, &kfc.domain, 1);
} pr_debug("%s cca_findcard()=%d\n", __func__, rc);
rc = pkey_genseckey2(apqns, kgs.apqn_entries, if (rc < 0)
kgs.type, kgs.size, kgs.keygenflags, return rc;
kkey, &klen); if (copy_to_user(ufc, &kfc, sizeof(kfc)))
pr_debug("%s pkey_genseckey2()=%d\n", __func__, rc); 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); 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); kfree_sensitive(kkey);
break; return -EINVAL;
} }
if (kgs.key) { if (copy_to_user(kgs.key, kkey, klen)) {
if (kgs.keylen < klen) { kfree_sensitive(kkey);
kfree_sensitive(kkey); return -EFAULT;
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);
break;
} }
case PKEY_CLR2SECK2: { kgs.keylen = klen;
struct pkey_clr2seck2 __user *ucs = (void __user *)arg; if (copy_to_user(ugs, &kgs, sizeof(kgs)))
size_t klen = KEYBLOBBUFSIZE; rc = -EFAULT;
struct pkey_clr2seck2 kcs; kfree_sensitive(kkey);
struct pkey_apqn *apqns;
u8 *kkey;
if (copy_from_user(&kcs, ucs, sizeof(kcs))) return rc;
return -EFAULT; }
apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries);
if (IS_ERR(apqns)) { static int pkey_ioctl_clr2seck2(struct pkey_clr2seck2 __user *ucs)
memzero_explicit(&kcs, sizeof(kcs)); {
return PTR_ERR(apqns); size_t klen = KEYBLOBBUFSIZE;
} struct pkey_clr2seck2 kcs;
kkey = kzalloc(klen, GFP_KERNEL); struct pkey_apqn *apqns;
if (!kkey) { u8 *kkey;
kfree(apqns); int rc;
memzero_explicit(&kcs, sizeof(kcs));
return -ENOMEM; if (copy_from_user(&kcs, ucs, sizeof(kcs)))
} return -EFAULT;
rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries);
kcs.type, kcs.size, kcs.keygenflags, if (IS_ERR(apqns)) {
kcs.clrkey.clrkey, kkey, &klen); memzero_explicit(&kcs, sizeof(kcs));
pr_debug("%s pkey_clr2seckey2()=%d\n", __func__, rc); return PTR_ERR(apqns);
}
kkey = kzalloc(klen, GFP_KERNEL);
if (!kkey) {
kfree(apqns); 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); kfree_sensitive(kkey);
memzero_explicit(&kcs, sizeof(kcs)); memzero_explicit(&kcs, sizeof(kcs));
break; return -EINVAL;
} }
if (kcs.key) { if (copy_to_user(kcs.key, kkey, klen)) {
if (kcs.keylen < klen) { kfree_sensitive(kkey);
kfree_sensitive(kkey); memzero_explicit(&kcs, sizeof(kcs));
memzero_explicit(&kcs, sizeof(kcs)); return -EFAULT;
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);
break;
} }
case PKEY_VERIFYKEY2: { kcs.keylen = klen;
struct pkey_verifykey2 __user *uvk = (void __user *)arg; if (copy_to_user(ucs, &kcs, sizeof(kcs)))
struct pkey_verifykey2 kvk; rc = -EFAULT;
u8 *kkey; memzero_explicit(&kcs, sizeof(kcs));
kfree_sensitive(kkey);
if (copy_from_user(&kvk, uvk, sizeof(kvk))) return rc;
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;
if (copy_from_user(&ktp, utp, sizeof(ktp))) static int pkey_ioctl_verifykey2(struct pkey_verifykey2 __user *uvk)
return -EFAULT; {
apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); struct pkey_verifykey2 kvk;
if (IS_ERR(apqns)) u8 *kkey;
return PTR_ERR(apqns); int rc;
kkey = _copy_key_from_user(ktp.key, ktp.keylen);
if (IS_ERR(kkey)) { if (copy_from_user(&kvk, uvk, sizeof(kvk)))
kfree(apqns); return -EFAULT;
return PTR_ERR(kkey); kkey = _copy_key_from_user(kvk.key, kvk.keylen);
} if (IS_ERR(kkey))
ktp.protkey.len = sizeof(ktp.protkey.protkey); return PTR_ERR(kkey);
rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, rc = pkey_verifykey2(kkey, kvk.keylen,
kkey, ktp.keylen, &kvk.cardnr, &kvk.domain,
ktp.protkey.protkey, &ktp.protkey.len, &kvk.type, &kvk.size, &kvk.flags);
&ktp.protkey.type); pr_debug("%s pkey_verifykey2()=%d\n", __func__, rc);
pr_debug("%s pkey_keyblob2pkey2()=%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(apqns);
kfree_sensitive(kkey); return PTR_ERR(kkey);
if (!rc && copy_to_user(utp, &ktp, sizeof(ktp))) }
rc = -EFAULT; ktp.protkey.len = sizeof(ktp.protkey.protkey);
memzero_explicit(&ktp, sizeof(ktp)); rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries,
break; kkey, ktp.keylen,
} ktp.protkey.protkey, &ktp.protkey.len,
case PKEY_APQNS4K: { &ktp.protkey.type);
struct pkey_apqns4key __user *uak = (void __user *)arg; pr_debug("%s pkey_keyblob2pkey2()=%d\n", __func__, rc);
struct pkey_apqn *apqns = NULL; kfree(apqns);
struct pkey_apqns4key kak; kfree_sensitive(kkey);
size_t nr_apqns, len; if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))
u8 *kkey; rc = -EFAULT;
memzero_explicit(&ktp, sizeof(ktp));
if (copy_from_user(&kak, uak, sizeof(kak))) return rc;
return -EFAULT; }
nr_apqns = kak.apqn_entries;
if (nr_apqns) { static int pkey_ioctl_apqns4k(struct pkey_apqns4key __user *uak)
apqns = kmalloc_array(nr_apqns, {
sizeof(struct pkey_apqn), struct pkey_apqn *apqns = NULL;
GFP_KERNEL); struct pkey_apqns4key kak;
if (!apqns) size_t nr_apqns, len;
return -ENOMEM; u8 *kkey;
} int rc;
kkey = _copy_key_from_user(kak.key, kak.keylen);
if (IS_ERR(kkey)) { if (copy_from_user(&kak, uak, sizeof(kak)))
kfree(apqns); return -EFAULT;
return PTR_ERR(kkey); nr_apqns = kak.apqn_entries;
} if (nr_apqns) {
rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, apqns = kmalloc_array(nr_apqns,
apqns, &nr_apqns); sizeof(struct pkey_apqn),
pr_debug("%s pkey_apqns4key()=%d\n", __func__, rc); GFP_KERNEL);
kfree_sensitive(kkey); if (!apqns)
if (rc && rc != -ENOSPC) { 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); kfree(apqns);
break; return -EINVAL;
} }
if (!rc && kak.apqns) { len = nr_apqns * sizeof(struct pkey_apqn);
if (nr_apqns > kak.apqn_entries) { if (len) {
if (copy_to_user(kak.apqns, apqns, len)) {
kfree(apqns); kfree(apqns);
return -EINVAL; return -EFAULT;
}
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);
break;
} }
case PKEY_APQNS4KT: { kak.apqn_entries = nr_apqns;
struct pkey_apqns4keytype __user *uat = (void __user *)arg; if (copy_to_user(uak, &kak, sizeof(kak)))
struct pkey_apqn *apqns = NULL; rc = -EFAULT;
struct pkey_apqns4keytype kat; kfree(apqns);
size_t nr_apqns, len;
if (copy_from_user(&kat, uat, sizeof(kat))) return rc;
return -EFAULT; }
nr_apqns = kat.apqn_entries;
if (nr_apqns) { static int pkey_ioctl_apqns4kt(struct pkey_apqns4keytype __user *uat)
apqns = kmalloc_array(nr_apqns, {
sizeof(struct pkey_apqn), struct pkey_apqn *apqns = NULL;
GFP_KERNEL); struct pkey_apqns4keytype kat;
if (!apqns) size_t nr_apqns, len;
return -ENOMEM; int rc;
}
rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, if (copy_from_user(&kat, uat, sizeof(kat)))
kat.flags, apqns, &nr_apqns); return -EFAULT;
pr_debug("%s pkey_apqns4keytype()=%d\n", __func__, rc); nr_apqns = kat.apqn_entries;
if (rc && rc != -ENOSPC) { 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); kfree(apqns);
break; return -EINVAL;
} }
if (!rc && kat.apqns) { len = nr_apqns * sizeof(struct pkey_apqn);
if (nr_apqns > kat.apqn_entries) { if (len) {
if (copy_to_user(kat.apqns, apqns, len)) {
kfree(apqns); kfree(apqns);
return -EINVAL; return -EFAULT;
}
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);
break;
} }
case PKEY_KBLOB2PROTK3: { kat.apqn_entries = nr_apqns;
struct pkey_kblob2pkey3 __user *utp = (void __user *)arg; if (copy_to_user(uat, &kat, sizeof(kat)))
u32 protkeylen = PROTKEYBLOBBUFSIZE; rc = -EFAULT;
struct pkey_apqn *apqns = NULL; kfree(apqns);
struct pkey_kblob2pkey3 ktp;
u8 *kkey, *protkey;
if (copy_from_user(&ktp, utp, sizeof(ktp))) return rc;
return -EFAULT; }
apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);
if (IS_ERR(apqns)) static int pkey_ioctl_kblob2protk3(struct pkey_kblob2pkey3 __user *utp)
return PTR_ERR(apqns); {
kkey = _copy_key_from_user(ktp.key, ktp.keylen); u32 protkeylen = PROTKEYBLOBBUFSIZE;
if (IS_ERR(kkey)) { struct pkey_apqn *apqns = NULL;
kfree(apqns); struct pkey_kblob2pkey3 ktp;
return PTR_ERR(kkey); u8 *kkey, *protkey;
} int rc;
protkey = kmalloc(protkeylen, GFP_KERNEL);
if (!protkey) { if (copy_from_user(&ktp, utp, sizeof(ktp)))
kfree(apqns); return -EFAULT;
kfree_sensitive(kkey); apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);
return -ENOMEM; if (IS_ERR(apqns))
} return PTR_ERR(apqns);
rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, kkey = _copy_key_from_user(ktp.key, ktp.keylen);
kkey, ktp.keylen, if (IS_ERR(kkey)) {
protkey, &protkeylen, &ktp.pkeytype); kfree(apqns);
pr_debug("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); return PTR_ERR(kkey);
}
protkey = kmalloc(protkeylen, GFP_KERNEL);
if (!protkey) {
kfree(apqns); kfree(apqns);
kfree_sensitive(kkey); 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); kfree_sensitive(protkey);
break; return -EINVAL;
}
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); if (copy_to_user(ktp.pkey, protkey, protkeylen)) {
ktp.pkeylen = protkeylen; kfree_sensitive(protkey);
if (copy_to_user(utp, &ktp, sizeof(ktp)))
return -EFAULT; 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: default:
/* unknown/unsupported ioctl cmd */ /* unknown/unsupported ioctl cmd */
return -ENOTTY; return -ENOTTY;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment