From c43fa74b9ed11f0183d25b21486b71fe02d84de7 Mon Sep 17 00:00:00 2001 From: Cristian Stoica Date: Tue, 15 Dec 2015 15:31:47 +0200 Subject: [PATCH 34/38] extend API with CIOCHASH to support direct hash operations Signed-off-by: Cristian Stoica --- crypto/cryptodev.h | 16 ++++++++++++++++ ioctl.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/crypto/cryptodev.h b/crypto/cryptodev.h index f6058ca..c6083f7 100644 --- a/crypto/cryptodev.h +++ b/crypto/cryptodev.h @@ -167,6 +167,19 @@ struct crypt_auth_op { __u32 iv_len; }; +/* data container for CIOCHASH operations */ +struct hash_op_data { + __u32 ses; /* session identifier */ + __u32 mac_op; /* cryptodev_crypto_op_t */ + __u8 *mackey; + __u32 mackeylen; + + __u16 flags; /* see COP_FLAG_* */ + __u32 len; /* length of source data */ + __u8 *src; /* source data */ + __u8 *mac_result; +}; + /* In plain AEAD mode the following are required: * flags : 0 * iv : the initialization vector (12 bytes) @@ -325,4 +338,7 @@ enum cryptodev_crk_op_t { /* additional ioctls for asynchronous operation for asymmetric ciphers*/ #define CIOCASYMASYNCRYPT _IOW('c', 112, struct crypt_kop) #define CIOCASYMFETCHCOOKIE _IOR('c', 113, struct pkc_cookie_list_s) + +#define CIOCHASH _IOWR('c', 114, struct hash_op_data) + #endif /* L_CRYPTODEV_H */ diff --git a/ioctl.c b/ioctl.c index 7adde75..3763954 100644 --- a/ioctl.c +++ b/ioctl.c @@ -960,6 +960,7 @@ cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_) void __user *arg = (void __user *)arg_; int __user *p = arg; struct session_op sop; + struct hash_op_data hash_op; struct kernel_crypt_op kcop; struct kernel_crypt_auth_op kcaop; struct crypt_priv *pcr = filp->private_data; @@ -1049,6 +1050,54 @@ cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_) } return kcop_to_user(&kcop, fcr, arg); + case CIOCHASH: + /* get session */ + if (unlikely(copy_from_user(&hash_op, arg, sizeof(struct hash_op_data)))) { + pr_err("copy from user fault\n"); + return -EFAULT; + } + + sop.cipher = 0; + sop.mac = hash_op.mac_op; + sop.mackey = hash_op.mackey; + sop.mackeylen = hash_op.mackeylen; + + /* writes sop.ses as a side-effect */ + ret = crypto_create_session(fcr, &sop); + if (unlikely(ret)) { + pr_err("can't get session\n"); + return ret; + } + + /* do hashing */ + kcop.cop.ses = sop.ses; + kcop.cop.flags = hash_op.flags; + kcop.cop.len = hash_op.len; + kcop.cop.src = hash_op.src; + kcop.cop.mac = hash_op.mac_result; + kcop.cop.dst = 0; + kcop.cop.op = 0; + kcop.cop.iv = 0; + kcop.ivlen = 0; + kcop.digestsize = 0; /* will be updated during operation */ + kcop.task = current; + kcop.mm = current->mm; + + ret = crypto_run(fcr, &kcop); + if (unlikely(ret)) { + dwarning(1, "Error in hash run"); + return ret; + } + + ret = copy_to_user(kcop.cop.mac, kcop.hash_output, kcop.digestsize); + if (unlikely(ret)) { + dwarning(1, "Error in copy to user"); + return ret; + } + + /* put session */ + ret = crypto_finish_session(fcr, sop.ses); + return 0; case CIOCAUTHCRYPT: if (unlikely(ret = kcaop_from_user(&kcaop, fcr, arg))) { dwarning(1, "Error copying from user"); -- 2.7.0