diff options
-rw-r--r-- | cryptodev.h | 38 | ||||
-rw-r--r-- | cryptodev_main.c | 93 |
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 = { |