Needed for 64b kernel with 32b user space.

Signed-off-by: Horia Geanta <horia.gea...@freescale.com>
Reviewed-by: Mircea Pop <mircea....@freescale.com>
Reviewed-by: Cristian Stoica <cristian.sto...@freescale.com>
Tested-by: Cristian Stoica <cristian.sto...@freescale.com>
---
 authenc.c       |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 cryptodev_int.h |   41 ++++++++++++++++++++++++++++
 ioctl.c         |   16 +++++++++++
 3 files changed, 137 insertions(+), 0 deletions(-)

diff --git a/authenc.c b/authenc.c
index 759a67d..277baed 100644
--- a/authenc.c
+++ b/authenc.c
@@ -246,6 +246,86 @@ static int fill_caop_from_kcaop(struct 
kernel_crypt_auth_op *kcaop, struct fcryp
        return 0;
 }
 
+/* compatibility code for 32bit userlands */
+#ifdef CONFIG_COMPAT
+
+static inline void
+compat_to_crypt_auth_op(struct compat_crypt_auth_op *compat,
+                       struct crypt_auth_op *caop)
+{
+       caop->ses = compat->ses;
+       caop->op = compat->op;
+       caop->flags = compat->flags;
+       caop->len = compat->len;
+       caop->dst_len = compat->dst_len;
+       caop->auth_len = compat->auth_len;
+       caop->tag_len = compat->tag_len;
+       caop->iv_len = compat->iv_len;
+
+       caop->auth_src = compat_ptr(compat->auth_src);
+       caop->src = compat_ptr(compat->src);
+       caop->dst = compat_ptr(compat->dst);
+       caop->tag = compat_ptr(compat->tag);
+       caop->iv = compat_ptr(compat->iv);
+}
+
+static inline void
+crypt_auth_op_to_compat(struct crypt_auth_op *caop,
+                       struct compat_crypt_auth_op *compat)
+{
+       compat->ses = caop->ses;
+       compat->op = caop->op;
+       compat->flags = caop->flags;
+       compat->len = caop->len;
+       compat->dst_len = caop->dst_len;
+       compat->auth_len = caop->auth_len;
+       compat->tag_len = caop->tag_len;
+       compat->iv_len = caop->iv_len;
+
+       compat->auth_src = ptr_to_compat(caop->auth_src);
+       compat->src = ptr_to_compat(caop->src);
+       compat->dst = ptr_to_compat(caop->dst);
+       compat->tag = ptr_to_compat(caop->tag);
+       compat->iv = ptr_to_compat(caop->iv);
+}
+
+int compat_kcaop_from_user(struct kernel_crypt_auth_op *kcaop,
+                               struct fcrypt *fcr, void __user *arg)
+{
+       struct compat_crypt_auth_op compat_caop;
+
+       if (unlikely(copy_from_user(&compat_caop, arg, sizeof(compat_caop)))) {
+               dprintk(1, KERN_ERR, "Error in copying from userspace\n");
+               return -EFAULT;
+       }
+
+       compat_to_crypt_auth_op(&compat_caop, &kcaop->caop);
+
+       return fill_kcaop_from_caop(kcaop, fcr);
+}
+
+int compat_kcaop_to_user(struct kernel_crypt_auth_op *kcaop,
+                               struct fcrypt *fcr, void __user *arg)
+{
+       int ret;
+       struct compat_crypt_auth_op compat_caop;
+
+       ret = fill_caop_from_kcaop(kcaop, fcr);
+       if (unlikely(ret)) {
+               dprintk(1, KERN_ERR, "fill_caop_from_kcaop\n");
+               return ret;
+       }
+
+       crypt_auth_op_to_compat(&kcaop->caop, &compat_caop);
+
+       if (unlikely(copy_to_user(arg, &compat_caop, sizeof(compat_caop)))) {
+               dprintk(1, KERN_ERR, "Error in copying to userspace\n");
+               return -EFAULT;
+       }
+       return 0;
+}
+
+#endif /* CONFIG_COMPAT */
 
 int kcaop_from_user(struct kernel_crypt_auth_op *kcaop,
                        struct fcrypt *fcr, void __user *arg)
diff --git a/cryptodev_int.h b/cryptodev_int.h
index e3e3e10..29d1113 100644
--- a/cryptodev_int.h
+++ b/cryptodev_int.h
@@ -62,11 +62,43 @@ struct compat_session_op {
        compat_uptr_t   iv;/* initialization vector for encryption operations */
 };
 
+ /* input of CIOCAUTHCRYPT */
+struct compat_crypt_auth_op {
+       uint32_t        ses;            /* session identifier */
+       uint16_t        op;             /* COP_ENCRYPT or COP_DECRYPT */
+       uint16_t        flags;          /* see COP_FLAG_AEAD_* */
+       uint32_t        len;            /* length of source data */
+       uint32_t        dst_len;        /* length of result data */
+       uint32_t        auth_len;       /* length of auth data */
+       compat_uptr_t   auth_src;       /* authenticated-only data */
+
+       /* The current implementation is more efficient if data are
+        * encrypted in-place (src==dst). */
+       compat_uptr_t   src;            /* data to be encrypted and
+       authenticated */
+       compat_uptr_t   dst;            /* pointer to output data. Must have
+                                        * space for tag. For TLS this should be
+                                        * at least len + tag_size + block_size
+                                        * for padding */
+
+       compat_uptr_t   tag;            /* where the tag will be copied to. TLS
+                                        * mode doesn't use that as tag is
+                                        * copied to dst.
+                                        * SRTP mode copies tag there. */
+       uint32_t        tag_len;        /* the length of the tag. Use zero for
+                                        * digest size or max tag. */
+
+       /* initialization vector for encryption operations */
+       compat_uptr_t   iv;
+       uint32_t        iv_len;
+};
+
 /* compat ioctls, defined for the above structs */
 #define COMPAT_CIOCGSESSION    _IOWR('c', 102, struct compat_session_op)
 #define COMPAT_CIOCCRYPT       _IOWR('c', 104, struct compat_crypt_op)
 #define COMPAT_CIOCASYNCCRYPT  _IOW('c', 107, struct compat_crypt_op)
 #define COMPAT_CIOCASYNCFETCH  _IOR('c', 108, struct compat_crypt_op)
+#define COMPAT_CIOCAUTHCRYPT   _IOWR('c', 109, struct compat_crypt_auth_op)
 
 #endif /* CONFIG_COMPAT */
 
@@ -97,6 +129,15 @@ struct kernel_crypt_auth_op {
 
 /* auth */
 
+#ifdef CONFIG_COMPAT
+int compat_kcaop_from_user(struct kernel_crypt_auth_op *kcaop,
+                               struct fcrypt *fcr, void __user *arg);
+
+int compat_kcaop_to_user(struct kernel_crypt_auth_op *kcaop,
+                               struct fcrypt *fcr, void __user *arg);
+#endif /* CONFIG_COMPAT */
+
+
 int kcaop_from_user(struct kernel_crypt_auth_op *kcop,
                        struct fcrypt *fcr, void __user *arg);
 int kcaop_to_user(struct kernel_crypt_auth_op *kcaop,
diff --git a/ioctl.c b/ioctl.c
index 0ee447a..ae27293 100644
--- a/ioctl.c
+++ b/ioctl.c
@@ -998,6 +998,7 @@ cryptodev_compat_ioctl(struct file *file, unsigned int cmd, 
unsigned long arg_)
        struct session_op sop;
        struct compat_session_op compat_sop;
        struct kernel_crypt_op kcop;
+       struct kernel_crypt_auth_op kcaop;
        int ret;
 
        if (unlikely(!pcr))
@@ -1040,6 +1041,21 @@ cryptodev_compat_ioctl(struct file *file, unsigned int 
cmd, unsigned long arg_)
                        return ret;
 
                return compat_kcop_to_user(&kcop, fcr, arg);
+
+       case COMPAT_CIOCAUTHCRYPT:
+               if (unlikely(ret = compat_kcaop_from_user(&kcaop, fcr, arg))) {
+                       dprintk(1, KERN_WARNING, "Error copying from user\n");
+                       return ret;
+               }
+
+               ret = crypto_auth_run(fcr, &kcaop);
+               if (unlikely(ret)) {
+                       dprintk(1, KERN_WARNING, "Error in crypto_auth_run\n");
+                       return ret;
+               }
+
+               return compat_kcaop_to_user(&kcaop, fcr, arg);
+
 #ifdef ENABLE_ASYNC
        case COMPAT_CIOCASYNCCRYPT:
                if (unlikely(ret = compat_kcop_from_user(&kcop, fcr, arg)))
-- 
1.7.7.6



_______________________________________________
Cryptodev-linux-devel mailing list
Cryptodev-linux-devel@gna.org
https://mail.gna.org/listinfo/cryptodev-linux-devel

Reply via email to