summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2009-11-28 19:35:35 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2009-11-28 19:35:35 +0200
commit30181c1a49a63fddc97dd10dbac1b49568aede1f (patch)
treeeaa074d13276370bce20198ccad68c0df25d18b9
parent3c0c804b7ffd37e03e83d486080f65ce2952a2fc (diff)
downloadcryptodev-linux-30181c1a49a63fddc97dd10dbac1b49568aede1f.tar.gz
cryptodev-linux-30181c1a49a63fddc97dd10dbac1b49568aede1f.tar.xz
cryptodev-linux-30181c1a49a63fddc97dd10dbac1b49568aede1f.zip
Added CIOCCRYPTV that will encrypt/hash iovectors.
-rw-r--r--cryptodev.c184
-rw-r--r--cryptodev.h29
-rw-r--r--cryptodev.mod.c57
3 files changed, 139 insertions, 131 deletions
diff --git a/cryptodev.c b/cryptodev.c
index 6007648..76581c4 100644
--- a/cryptodev.c
+++ b/cryptodev.c
@@ -401,10 +401,7 @@ crypto_get_session_by_sid(struct fcrypt *fcr, uint32_t sid)
return ses_ptr;
}
-/* This is the main crypto function - feed it with plaintext
- and get a ciphertext (or vice versa :-) */
-static int
-crypto_run(struct fcrypt *fcr, struct crypt_op *cop)
+static int crypto_runv(struct fcrypt *fcr, struct crypt_opv *copv)
{
char *data, ivp[EALG_MAX_BLOCK_LEN];
char __user *src, __user *dst;
@@ -414,6 +411,7 @@ crypto_run(struct fcrypt *fcr, struct crypt_op *cop)
size_t nbytes, bufsize;
int ret = 0;
uint8_t hash_output[HASH_MAX_LEN];
+ int blocksize=1, i;
struct blkcipher_desc bdesc = {
.flags = CRYPTO_TFM_REQ_MAY_SLEEP,
};
@@ -422,29 +420,27 @@ crypto_run(struct fcrypt *fcr, struct crypt_op *cop)
};
- if (unlikely(cop->op != COP_ENCRYPT && cop->op != COP_DECRYPT)) {
- dprintk(1, KERN_DEBUG, "invalid operation op=%u\n", cop->op);
+ if (unlikely(copv->op != COP_ENCRYPT && copv->op != COP_DECRYPT)) {
+ dprintk(1, KERN_DEBUG, "invalid operation op=%u\n", copv->op);
return -EINVAL;
}
- ses_ptr = crypto_get_session_by_sid(fcr, cop->ses);
+ ses_ptr = crypto_get_session_by_sid(fcr, copv->ses);
if (!ses_ptr) {
- dprintk(1, KERN_ERR, "invalid session ID=0x%08X\n", cop->ses);
+ dprintk(1, KERN_ERR, "invalid session ID=0x%08X\n", copv->ses);
return -EINVAL;
}
- nbytes = cop->len;
data = (char*)__get_free_page(GFP_KERNEL);
if (unlikely(!data)) {
ret = -ENOMEM;
goto out_unlock;
}
- bufsize = PAGE_SIZE < nbytes ? PAGE_SIZE : nbytes;
- nbytes = cop->len;
bdesc.tfm = ses_ptr->tfm;
hdesc.tfm = ses_ptr->hash_tfm;
+
if (hdesc.tfm) {
ret = crypto_hash_init(&hdesc);
if (unlikely(ret)) {
@@ -455,7 +451,21 @@ crypto_run(struct fcrypt *fcr, struct crypt_op *cop)
}
if (ses_ptr->tfm) {
- if (nbytes % crypto_blkcipher_blocksize(ses_ptr->tfm)) {
+ blocksize = crypto_blkcipher_blocksize(ses_ptr->tfm);
+ ivsize = crypto_blkcipher_ivsize(ses_ptr->tfm);
+
+ if (copv->iv) {
+ copy_from_user(ivp, copv->iv, ivsize);
+ crypto_blkcipher_set_iv(ses_ptr->tfm, ivp, ivsize);
+ }
+ }
+
+ dst = copv->dst;
+
+ for (i=0;i<copv->iovec_cnt;i++) {
+ nbytes = copv->iovec[i].len;
+
+ if (unlikely(bdesc.tfm && (nbytes % blocksize))) {
dprintk(1, KERN_ERR,
"data size (%zu) isn't a multiple of block size (%u)\n",
nbytes, crypto_blkcipher_blocksize(ses_ptr->tfm));
@@ -463,70 +473,74 @@ crypto_run(struct fcrypt *fcr, struct crypt_op *cop)
goto out_unlock;
}
- ivsize = crypto_blkcipher_ivsize(ses_ptr->tfm);
-
- if (cop->iv) {
- copy_from_user(ivp, cop->iv, ivsize);
- crypto_blkcipher_set_iv(ses_ptr->tfm, ivp, ivsize);
- }
- }
-
- src = cop->src;
- dst = cop->dst;
+ bufsize = PAGE_SIZE < nbytes ? PAGE_SIZE : nbytes;
+ src = copv->iovec[i].src;
- while(nbytes > 0) {
- size_t current_len = nbytes > bufsize ? bufsize : nbytes;
+ while(nbytes > 0) {
+ size_t current_len = nbytes > bufsize ? bufsize : nbytes;
- copy_from_user(data, src, current_len);
+ copy_from_user(data, src, current_len);
- sg_set_buf(&sg, data, current_len);
+ sg_set_buf(&sg, data, current_len);
- /* Always hash before encryption and after decryption. Maybe
- * we should introduce a flag to switch... TBD later on.
- */
- if (cop->op == COP_ENCRYPT) {
- if (hdesc.tfm) {
- ret = crypto_hash_update(&hdesc, &sg, current_len);
- if (unlikely(ret)) {
- dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
- goto out;
+ /* Always hash before encryption and after decryption. Maybe
+ * we should introduce a flag to switch... TBD later on.
+ */
+ if (copv->op == COP_ENCRYPT) {
+ if (hdesc.tfm && (copv->iovec[i].op_flags & IOP_HASH)) {
+ ret = crypto_hash_update(&hdesc, &sg, current_len);
+ if (unlikely(ret)) {
+ dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
+ goto out;
+ }
}
- }
- if (bdesc.tfm) {
- ret = crypto_blkcipher_encrypt(&bdesc, &sg, &sg, current_len);
-
- if (unlikely(ret)) {
- dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
- goto out;
+ if (bdesc.tfm && (copv->iovec[i].op_flags & IOP_CIPHER)) {
+ ret = crypto_blkcipher_encrypt(&bdesc, &sg, &sg, current_len);
+
+ if (unlikely(ret)) {
+ dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
+ goto out;
+ }
+ copy_to_user(dst, data, current_len);
+ dst += current_len;
}
- copy_to_user(dst, data, current_len);
- dst += current_len;
- }
- } else {
- if (bdesc.tfm) {
- ret = crypto_blkcipher_decrypt(&bdesc, &sg, &sg, current_len);
+ } else {
+ if (bdesc.tfm && (copv->iovec[i].op_flags & IOP_CIPHER)) {
+ ret = crypto_blkcipher_decrypt(&bdesc, &sg, &sg, current_len);
- if (unlikely(ret)) {
- dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
- goto out;
- }
- copy_to_user(dst, data, current_len);
- dst += current_len;
+ if (unlikely(ret)) {
+ dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
+ goto out;
+ }
+ copy_to_user(dst, data, current_len);
+ dst += current_len;
- }
+ }
- if (hdesc.tfm) {
- ret = crypto_hash_update(&hdesc, &sg, current_len);
- if (unlikely(ret)) {
- dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
- goto out;
+ if (hdesc.tfm && (copv->iovec[i].op_flags & IOP_HASH)) {
+ ret = crypto_hash_update(&hdesc, &sg, current_len);
+ if (unlikely(ret)) {
+ dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret);
+ goto out;
+ }
}
}
+
+ nbytes -= current_len;
+ src += current_len;
}
- nbytes -= current_len;
- src += current_len;
+#if defined(CRYPTODEV_STATS)
+ if (enable_stats) {
+ /* this is safe - we check cop->op at the function entry */
+ ses_ptr->stat[copv->op] += copv->iovec[i].len;
+ if (ses_ptr->stat_max_size < copv->iovec[i].len)
+ ses_ptr->stat_max_size = copv->iovec[i].len;
+ ses_ptr->stat_count++;
+ }
+#endif
+
}
if (hdesc.tfm) {
@@ -536,19 +550,9 @@ crypto_run(struct fcrypt *fcr, struct crypt_op *cop)
goto out;
}
- copy_to_user(cop->mac, hash_output, crypto_hash_digestsize(ses_ptr->hash_tfm));
+ copy_to_user(copv->mac, hash_output, crypto_hash_digestsize(ses_ptr->hash_tfm));
}
-#if defined(CRYPTODEV_STATS)
- if (enable_stats) {
- /* this is safe - we check cop->op at the function entry */
- ses_ptr->stat[cop->op] += cop->len;
- if (ses_ptr->stat_max_size < cop->len)
- ses_ptr->stat_max_size = cop->len;
- ses_ptr->stat_count++;
- }
-#endif
-
out:
free_page((unsigned long)data);
@@ -558,6 +562,33 @@ out_unlock:
return ret;
}
+/* This is the main crypto function - feed it with plaintext
+ and get a ciphertext (or vice versa :-) */
+static int crypto_run(struct fcrypt *fcr, struct crypt_op *cop)
+{
+ struct crypt_opv copv;
+ struct crypt_iovec iovec;
+
+ iovec.src = cop->src;
+ iovec.len = cop->len;
+ iovec.op_flags = IOP_CIPHER|IOP_HASH;
+
+ copv.op = cop->op;
+ copv.ses = cop->ses;
+ copv.flags = cop->flags;
+ copv.iovec = &iovec;
+ copv.iovec_cnt = 1;
+
+ copv.dst = cop->dst;
+ copv.mac = cop->mac;
+ copv.iv = cop->iv;
+
+ return crypto_runv(fcr, &copv);
+
+}
+
+
+
/* ====== /dev/crypto ====== */
static int
@@ -613,6 +644,7 @@ cryptodev_ioctl(struct inode *inode, struct file *filp,
int __user *p = (void __user *)arg;
struct session_op sop;
struct crypt_op cop;
+ struct crypt_opv copv;
struct fcrypt *fcr = filp->private_data;
uint32_t ses;
int ret, fd;
@@ -648,6 +680,12 @@ cryptodev_ioctl(struct inode *inode, struct file *filp,
copy_to_user((void*)arg, &cop, sizeof(cop));
return ret;
+ case CIOCCRYPTV:
+ copy_from_user(&cop, (void*)arg, sizeof(copv));
+ ret = crypto_runv(fcr, &copv);
+ copy_to_user((void*)arg, &copv, sizeof(copv));
+ return ret;
+
default:
return -EINVAL;
}
diff --git a/cryptodev.h b/cryptodev.h
index 895ad1c..891ad2a 100644
--- a/cryptodev.h
+++ b/cryptodev.h
@@ -75,7 +75,7 @@ struct crypt_op {
uint32_t ses; /* from session_op->ses */
#define COP_DECRYPT 0
#define COP_ENCRYPT 1
- uint32_t op; /* ie. COP_ENCRYPT */
+ uint16_t op; /* ie. COP_ENCRYPT */
uint32_t flags; /* unused */
size_t len;
@@ -84,6 +84,30 @@ struct crypt_op {
void *iv;
};
+struct crypt_iovec {
+#define IOP_CIPHER 1
+#define IOP_HASH 2
+ uint16_t op_flags; /* ie. IOP_CIPHER|IOP_HASH */
+ void *src;
+ size_t len;
+};
+
+/* ioctl parameter to request a crypt/decrypt operation against a session */
+struct crypt_opv {
+ uint32_t ses; /* from session_op->ses */
+ #define COP_DECRYPT 0
+ #define COP_ENCRYPT 1
+ uint16_t op; /* ie. COP_ENCRYPT */
+ uint32_t flags; /* unused */
+
+ struct crypt_iovec* iovec;
+ uint16_t iovec_cnt;
+
+ void *dst;
+ void *mac;
+ void *iv;
+};
+
/* clone original filedescriptor */
#define CRIOGET _IOWR('c', 101, uint32_t)
@@ -100,6 +124,9 @@ struct crypt_op {
#define CIOCKEY _IOWR('c', 105, void *)
#define CIOCASYMFEAT _IOR('c', 106, uint32_t)
+/* request encryption/decryptions of a given buffer vector */
+#define CIOCCRYPTV _IOWR('c', 107, struct crypt_opv)
+
#endif /* _CRYPTODEV_H */
/* unused structures */
diff --git a/cryptodev.mod.c b/cryptodev.mod.c
deleted file mode 100644
index 983f1f4..0000000
--- a/cryptodev.mod.c
+++ /dev/null
@@ -1,57 +0,0 @@
-#include <linux/module.h>
-#include <linux/vermagic.h>
-#include <linux/compiler.h>
-
-MODULE_INFO(vermagic, VERMAGIC_STRING);
-
-struct module __this_module
-__attribute__((section(".gnu.linkonce.this_module"))) = {
- .name = KBUILD_MODNAME,
- .init = init_module,
-#ifdef CONFIG_MODULE_UNLOAD
- .exit = cleanup_module,
-#endif
- .arch = MODULE_ARCH_INIT,
-};
-
-static const struct modversion_info ____versions[]
-__used
-__attribute__((section("__versions"))) = {
- { 0x903a5ec4, "module_layout" },
- { 0x6980fe91, "param_get_int" },
- { 0xff964b25, "param_set_int" },
- { 0x79aa04a2, "get_random_bytes" },
- { 0x4661e311, "__tracepoint_kmalloc" },
- { 0x893412fe, "kmem_cache_alloc" },
- { 0xadee93f3, "kmalloc_caches" },
- { 0x4e1e7401, "crypto_alloc_base" },
- { 0x4302d0eb, "free_pages" },
- { 0xe52947e7, "__phys_addr" },
- { 0x236c8c64, "memcpy" },
- { 0xbe499d81, "copy_to_user" },
- { 0x93fca811, "__get_free_pages" },
- { 0x37a0cba, "kfree" },
- { 0x3f1899f1, "up" },
- { 0x9bf377f5, "crypto_destroy_tfm" },
- { 0x9ced38aa, "down_trylock" },
- { 0x945bc6a7, "copy_from_user" },
- { 0x748caf40, "down" },
- { 0x6729d3df, "__get_user_4" },
- { 0xf0fdf6cb, "__stack_chk_fail" },
- { 0xb2fd5ceb, "__put_user_4" },
- { 0xa1c76e0a, "_cond_resched" },
- { 0xa62a61be, "fd_install" },
- { 0x99bfbe39, "get_unused_fd" },
- { 0xd8778690, "per_cpu__current_task" },
- { 0x54b8041c, "misc_register" },
- { 0xea147363, "printk" },
- { 0x11cef3ea, "misc_deregister" },
-};
-
-static const char __module_depends[]
-__used
-__attribute__((section(".modinfo"))) =
-"depends=";
-
-
-MODULE_INFO(srcversion, "A0688FBD1488A8A38E2DF83");