summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Sutter <phil.sutter@viprinet.com>2010-06-15 18:17:50 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-06-16 12:14:11 +0200
commit3f9fef758f04527c063156ed039f61ac575bf379 (patch)
tree10032cad32ffb525749f1a1759730c116333b9e1
parentcd4b075abdc6d2415476df9a0990b55152332e68 (diff)
downloadcryptodev-linux-3f9fef758f04527c063156ed039f61ac575bf379.tar.gz
cryptodev-linux-3f9fef758f04527c063156ed039f61ac575bf379.tar.xz
cryptodev-linux-3f9fef758f04527c063156ed039f61ac575bf379.zip
add compat_ioctl code
-rw-r--r--cryptodev.h38
-rw-r--r--cryptodev_main.c93
2 files changed, 131 insertions, 0 deletions
diff --git a/cryptodev.h b/cryptodev.h
index 84d371b..fc94149 100644
--- a/cryptodev.h
+++ b/cryptodev.h
@@ -150,4 +150,42 @@ typedef enum {
#define CIOCKEY _IOWR('c', 105, struct crypt_kop)
#define CIOCASYMFEAT _IOR('c', 106, uint32_t)
+/* compatibility code for 32bit userlands */
+
+#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
+
+/* input of CIOCGSESSION */
+struct compat_session_op {
+ /* Specify either cipher or mac
+ */
+ uint32_t cipher; /* cryptodev_crypto_op_t */
+ uint32_t mac; /* cryptodev_crypto_op_t */
+
+ uint32_t keylen;
+ uint32_t key; /* pointer to key data */
+ uint32_t mackeylen;
+ uint32_t mackey; /* pointer to mac key data */
+
+ uint32_t ses; /* session identifier */
+};
+
+/* input of CIOCCRYPT */
+ struct compat_crypt_op {
+ uint32_t ses; /* session identifier */
+ uint16_t op; /* COP_ENCRYPT or COP_DECRYPT */
+ uint16_t flags; /* no usage so far, use 0 */
+ uint32_t len; /* length of source data */
+ uint32_t src; /* source data */
+ uint32_t dst; /* pointer to output data */
+ uint32_t mac; /* pointer to output data for hash/MAC operations */
+ uint32_t iv; /* initialization vector for encryption operations */
+};
+
+#define COMPAT_CIOCGSESSION _IOWR('c', 102, struct compat_session_op)
+#define COMPAT_CIOCCRYPT _IOWR('c', 104, struct compat_crypt_op)
+
+#endif /* CONFIG_COMPAT */
+#endif /* __KERNEL__ */
+
#endif /* L_CRYPTODEV_H */
diff --git a/cryptodev_main.c b/cryptodev_main.c
index 4146a3c..f5a2635 100644
--- a/cryptodev_main.c
+++ b/cryptodev_main.c
@@ -582,11 +582,104 @@ cryptodev_ioctl(struct inode *inode, struct file *filp,
}
}
+static inline void
+compat_to_session_op(struct compat_session_op *compat, struct session_op *sop)
+{
+ memcpy(sop, compat, sizeof(uint32_t) * 3);
+ sop->key = (uint8_t *)compat->key;
+ sop->mackeylen = compat->mackeylen;
+ sop->mackey = (uint8_t *)compat->mackey;
+ sop->ses = compat->ses;
+}
+
+static inline void
+session_op_to_compat(struct session_op *sop, struct compat_session_op *compat)
+{
+ memcpy(compat, sop, sizeof(uint32_t) * 3);
+ compat->key = (uint32_t)sop->key;
+ compat->mackeylen = sop->mackeylen;
+ compat->mackey = (uint32_t)sop->mackey;
+ compat->ses = sop->ses;
+}
+
+static inline void
+compat_to_crypt_op(struct compat_crypt_op *compat, struct crypt_op *cop)
+{
+ memcpy(cop, compat, sizeof(uint32_t) * 2 + sizeof(uint16_t) * 2);
+ cop->src = (uint8_t *)compat->src;
+ cop->dst = (uint8_t *)compat->dst;
+ cop->mac = (uint8_t *)compat->mac;
+ cop->iv = (uint8_t *)compat->iv;
+}
+
+static inline void
+crypt_op_to_compat(struct crypt_op *cop, struct compat_crypt_op *compat)
+{
+ memcpy(compat, cop, sizeof(uint32_t) * 2 + sizeof(uint16_t) * 2);
+ compat->src = (uint32_t)cop->src;
+ compat->dst = (uint32_t)cop->dst;
+ compat->mac = (uint32_t)cop->mac;
+ compat->iv = (uint32_t)cop->iv;
+}
+
+static long
+cryptodev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct fcrypt *fcr = file->private_data;
+ struct session_op sop;
+ struct compat_session_op compat_sop;
+ struct crypt_op cop;
+ struct compat_crypt_op compat_cop;
+ int ret;
+
+ if (unlikely(!fcr))
+ BUG();
+
+ switch (cmd) {
+ case CIOCASYMFEAT:
+ case CRIOGET:
+ case CIOCFSESSION:
+ return cryptodev_ioctl(NULL, file, cmd, arg);
+
+ case COMPAT_CIOCGSESSION:
+ copy_from_user(&compat_sop, (void *)arg,
+ sizeof(compat_sop));
+ compat_to_session_op(&compat_sop, &sop);
+
+ ret = crypto_create_session(fcr, &sop);
+ if (unlikely(ret))
+ return ret;
+
+ session_op_to_compat(&sop, &compat_sop);
+ copy_to_user((void*)arg, &compat_sop,
+ sizeof(compat_sop));
+ return 0;
+
+ case COMPAT_CIOCCRYPT:
+ copy_from_user(&compat_cop, (void*)arg,
+ sizeof(compat_cop));
+ compat_to_crypto_op(&compat_op, &cop);
+
+ ret = crypto_run(fcr, &cop);
+ if (unlikely(ret))
+ return ret;
+
+ crypto_op_to_compat(&cop, &compat_op);
+ copy_to_user((void*)arg, &compat_cop,
+ sizeof(compat_cop));
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
struct file_operations cryptodev_fops = {
.owner = THIS_MODULE,
.open = cryptodev_open,
.release = cryptodev_release,
.ioctl = cryptodev_ioctl,
+ .compat_ioctl = cryptodev_compat_ioctl,
};
struct miscdevice cryptodev = {