Re: [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



* Loc Ho | 2008-05-13 17:00:58 [-0700]:

>I am re-sending this email as I don't believe it got to the mailing
>list. Due to email problem, I am forward this patch on behalf of Shasi
>Pulijala who worked on this user space interface for Linux CryptoAPI.
If you forward patches, you should put your sign-of there as well (so
you would have two).

>This should add support for OpenSSL. Please note that user of this patch
>musts patch OpenSSL. The OpenSSL patch can be found in OCF-Linux as this
>interface uses the same I/O control interface.
So this interface must stay as it in order not to patch openssl twice?

> 
>-Loc
Loc, if you want to send patches that are proper formated please use
git-send-email (this patch looks like it is comming straight from
git-format-patch). You can specify there a smtp server.

There are a few comments below.

>From 926bbdedff99b1e8bb25cd685cb7249ba21729d9 Mon Sep 17 00:00:00 2001
>From: Shasi Pulijala <spulijala@xxxxxxxx>
>Date: Thu, 8 May 2008 11:08:26 -0700
>Subject: [PATCH] Add CryptoAPI User Interface Support
>
>
>Signed-off-by: Shasi Pulijala <spulijala@xxxxxxxx>
>---
> crypto/Kconfig            |    7 +
> crypto/Makefile           |    1 +
> crypto/cryptodev.c        | 1284
>+++++++++++++++++++++++++++++++++++++++++++++
> fs/fcntl.c                |    9 +-
> include/linux/cryptodev.h |  119 +++++
> include/linux/fs.h        |    1 +
> 6 files changed, 1420 insertions(+), 1 deletions(-)
> create mode 100644 crypto/cryptodev.c
> create mode 100644 include/linux/cryptodev.h
>
>diff --git a/crypto/Kconfig b/crypto/Kconfig
>index 69f1be6..de6d623 100644
>--- a/crypto/Kconfig
>+++ b/crypto/Kconfig
>@@ -52,6 +52,13 @@ config CRYPTO_MANAGER
> 	  Create default cryptographic template instantiations such as
> 	  cbc(aes).
> 
>+config CRYPTO_CRYPTODEV
>+	tristate "Cryptodev (/dev/crypto) interface"
>+	depends on CRYPTO
>+	help
>+	  Device /dev/crypto gives userspace programs access to 
>+	  kernel crypto algorithms.
>+
> config CRYPTO_HMAC
> 	tristate "HMAC support"
> 	select CRYPTO_HASH
>diff --git a/crypto/Makefile b/crypto/Makefile
>index 85d0109..3d5251b 100644
>--- a/crypto/Makefile
>+++ b/crypto/Makefile
>@@ -22,6 +22,7 @@ crypto_hash-objs += ahash.o
> obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
> 
> obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o
>+obj-$(CONFIG_CRYPTO_CRYPTODEV) += cryptodev.o
> obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
> obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
> obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o
>diff --git a/crypto/cryptodev.c b/crypto/cryptodev.c
>new file mode 100644
>index 0000000..9175ee0
>--- /dev/null
>+++ b/crypto/cryptodev.c
>@@ -0,0 +1,1284 @@
>+/**********************************************************************
>*********
>+ * cryptodev.c
>+ *
>+ * Linux CryptoAPI user space interface module
>+ *
>+ * Copyright (c) 2008 Shasi Pulijala <spulijala@xxxxxxxx>
>+ *
>+ * This program is free software; you can redistribute it and/or modify
>+ * it under the terms of the GNU General Public License as published by
>+ * the Free Software Foundation; either version 2 of the License, or
>+ * (at your option) any later version.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+ * GNU General Public License for more details.
>+ *
>+ *
>+ * Detail Description:
>+ * This file implements the /dev/crypto interface which is intended to
>+ * provide user space interface to the Linux CryptoAPI.
>+ *
>+
>************************************************************************
>*******
>+ */
>+#include <linux/module.h>
>+#include <linux/moduleparam.h>
>+#include <linux/init.h>
>+#include <linux/sched.h>
>+#include <linux/fs.h>
>+#include <linux/fcntl.h>
>+#include <linux/file.h>
>+#include <linux/miscdevice.h>
>+#include <linux/crypto.h>
>+#include <linux/mm.h>
>+#include <linux/highmem.h>
>+#include <linux/random.h>
>+#include <linux/cryptodev.h>
>+#include <linux/syscalls.h>
>+#include <linux/scatterlist.h>
>+#include <linux/time.h>
>+#include <linux/unistd.h>
>+#include <linux/rtnetlink.h>
>+#include <linux/err.h>
>+#include <crypto/aead.h>
>+#include <crypto/authenc.h>
>+#include <asm/uaccess.h>
>+#include <asm/ioctl.h>
>+#include <asm/scatterlist.h>
Please avoid asm

>+#include <asm-powerpc/unistd.h>
and this is not acceptable at all.

>+
>+/**********************************************************************
>*********
>+ * Forward declaration
>+
>************************************************************************
I personally prefer not having the asterisks all over the place and not
commenting obvious things.

>*******
>+ */
>+#define CRYPTODEV_DEBUG
>+
>+/**********************************************************************
>*********
>+ * Macro declaration
>+
>************************************************************************
>*******
>+ */
>+/* /dev/crypto is a char block device with majar 10 and minor below */
>+#define	CRYPTODEV_MINOR				70
>+
>+#define	CRYPTODEV_UI_SUPPORT_DRIVER		"0.1"
>+
>+/**********************************************************************
>*********
>+ * Module Parameters
>+
>************************************************************************
>*******
>+ */
>+static int debug;
>+module_param(debug, int, 0644);
>+MODULE_PARM_DESC(debug, "0: normal, 1: verbose, 2: debug");
>+
>+static int sg_single;
>+module_param(sg_single, int, 0644);
>+MODULE_PARM_DESC(sg_single, "0: sg array list, 1: single sg entity");
>+
>+#ifdef CRYPTODEV_STATS
>+static int enable_stats;
>+module_param(enable_stats, int, 0644);
>+MODULE_PARM_DESC(enable_stats, "collect statictics about cryptodev
>usage");
>+#endif
>+
>+/**********************************************************************
>*********
>+ * Debugging Macro's
>+
>************************************************************************
>*******
>+ */
>+#define PFX "cryptodev: "
>+
>+#ifndef CRYPTODEV_DEBUG
>+#define CRYPTODEV_HEXDUMP(b, l) \
>+		print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, \
>+				16, 1, (b), (l), false);
>+#define CRYPTODEV_PRINTK(level, severity, format, a...)
>\
>+	do {
>\
>+		if (level <= debug)
>\
>+			printk(severity PFX "%s[%u]: " format,
>\
>+			       current->comm, current->pid, ##a);
>\
>+	} while (0)
>+#else
>+#define CRYPTODEV_HEXDUMP(b, l)
>+#define CRYPTODEV_PRINTK(level, severity, format, a...)
>+#endif
>+
>+/**********************************************************************
>*********
>+ * Helper Structure
>+
>************************************************************************
>*******
>+ */
>+#define CRYPTO_ACIPHER	0
>+#define CRYPTO_AHASH	1
>+#define CRYPTO_AEAD	2
>+
>+#define tfm_ablkcipher	crt_tfm.acipher_tfm
>+#define tfm_aead	crt_tfm.aead_tfm
>+#define tfm_ahash	crt_tfm.ahash_tfm
>+
>+struct csession {
>+	struct list_head entry;
>+	struct semaphore sem;
>+	union {
>+		struct crypto_ablkcipher *acipher_tfm;
>+		struct crypto_ahash 	 *ahash_tfm;
>+		struct crypto_aead 	 *aead_tfm;
>+	} crt_tfm;
>+
>+	int 		mode;
>+	unsigned int 	sid;
>+};
>+
>+/**********************************************************************
>*********
>+ * Table Lookup for Algorithms name(Crypto/hash name)
>+ * Helper Structure
>+
>************************************************************************
>*******
>+ */
>+char *algo_map_tbl[CRYPTO_ALGORITHM_MAX] = {
>+	[CRYPTO_DES_CBC]  	= "cbc(des)",
>+	[CRYPTO_3DES_CBC] 	= "cbc(des3_ede)",
>+	[CRYPTO_MD5_HMAC] 	= "hmac(md5)",
>+	[CRYPTO_BLF_CBC]  	= "cbc(blowfish)",
>+	[CRYPTO_CAST_CBC]		= "cbc(cast5)",
>+	[CRYPTO_SKIPJACK_CBC]	= "camellia",
>+	[CRYPTO_MD5_HMAC]		= "hmac(md5)",
>+	[CRYPTO_SHA1_HMAC]	= "hmac(sha1)",
>+	[CRYPTO_RIPEMD160_HMAC]	= "hmac(rmd160)",
>+	[CRYPTO_MD5_KPDK]		= "",
>+	[CRYPTO_SHA1_KPDK]	= "",
>+	[CRYPTO_RIJNDAEL128_CBC] = "cbc(aes)",
>+	[CRYPTO_AES_CBC]		= "cbc(aes)",
>+	[CRYPTO_ARC4]		= "ecb(arc4)",
>+	[CRYPTO_MD5]		= "md5",
>+	[CRYPTO_SHA1]		= "sha1",
>+	[CRYPTO_NULL_HMAC]	= "",
>+	[CRYPTO_NULL_CBC]		= "",
>+	[CRYPTO_DEFLATE_COMP]	= "deflate",
>+	[CRYPTO_SHA2_256_HMAC]	= "hmac(sha256)",
>+	[CRYPTO_SHA2_384_HMAC]	= "hmac(sha384)",
>+	[CRYPTO_SHA2_512_HMAC]	= "hmac(sha512)",
>+	[CRYPTO_CAMELLIA_CBC]	= "cbc(camellia)",
>+	[CRYPTO_SHA2_256]		= "sha256",
>+	[CRYPTO_SHA2_384]		= "sha384",
>+	[CRYPTO_SHA2_512]		= "sha512",
>+	[CRYPTO_RIPEMD160]	= "rmd160",
>+	[CRYPTO_AES_GCM]		= "gcm(aes)",
>+	[CRYPTO_AES_CCM]		= "ccm(aes)",
>+};

Wouldn't it be better to have dynamic algos? This way you must patch the
driver every single time a new algo is showing up.

>+
>+struct fcrypt {
>+	struct list_head list;
>+	struct semaphore sem;
>+};
>+
>+struct async_result {
>+	struct completion completion;
>+	int err;
>+};
>+
>+/**********************************************************************
>*********
>+ * Function Declarations
>+
>************************************************************************
>*******
>+ */
>+static int create_session_ablkcipher(char *alg_name,
>+				struct fcrypt *fcr,
>+				struct session_op *sop);
>+static int create_session_ahash(char *alg_name,
>+				struct fcrypt *fcr,
>+				struct session_op *sop);
>+static int create_session_aead(char *alg_name,
>+				struct fcrypt *fcr,
>+				struct session_op *sop);
>+static int cryptodev_run_acipher(struct csession *ses_ptr,
>+				struct crypt_op *cop);
>+static int cryptodev_run_ahash(struct csession *ses_ptr,
>+				struct crypt_op *cop);
>+static int cryptodev_run_aead(struct csession *ses_ptr,
>+				struct crypt_op *cop);
>+static int sg_setup(unsigned char *addr, int bufsize, struct
>scatterlist *sg,
>+				int sg_single);
>+
>+/**********************************************************************
>*********
>+ * Asynchronous handling Routine
>+ *
>+
>************************************************************************
>*******
>+ */
>+static void cryptodev_async_complete(struct crypto_async_request *req,
>int err)
>+{
>+	struct async_result *res = req->data;
>+
>+	if (err == -EINPROGRESS)
>+		return;
>+
>+	res->err = err;
>+	complete(&res->completion);
>+}
>+
>+/**********************************************************************
>*********
>+ * Prepare session for future use
>+ *
>+
>************************************************************************
>*******
>+ */
>+static int cryptodev_create_session(struct fcrypt *fcr, struct
>session_op *sop)
>+{
>+	char alg_name[CRYPTO_MAX_ALG_NAME];
>+	int  mode = -1;
>+	int ret =  0;
>+
>+	if (sop->mac > CRYPTO_ALGORITHM_MAX ||
>+		sop->cipher > CRYPTO_ALGORITHM_MAX) {
>+		printk(KERN_INFO PFX "algorithm not supported or "
>+			"not set\n");
>+		return -EINVAL;
>+	}
>+
>+	if (sop->cipher && sop->mac) {
>+		mode = CRYPTO_AEAD;
>+		printk(KERN_INFO PFX "authenc(%s,%s) (Algorithm
>Chanining Mode"
>+			"not yet supported", algo_map_tbl[sop->mac],
>+			algo_map_tbl[sop->cipher]);
>+		return -EINVAL;
>+	} else if (sop->cipher) {
>+		if (sop->cipher == CRYPTO_AES_GCM ||
>+			sop->cipher == CRYPTO_AES_CCM)
>+			mode = CRYPTO_AEAD;
>+		else
>+			mode = CRYPTO_ACIPHER;
>+		strncpy(alg_name, algo_map_tbl[sop->cipher],
>+			 CRYPTO_MAX_ALG_NAME);
>+	} else if (sop->mac) {
>+		mode = CRYPTO_AHASH;
>+		strncpy(alg_name, algo_map_tbl[sop->mac],
>CRYPTO_MAX_ALG_NAME);
>+	}
>+
>+	if (!alg_name)
>+		return -EINVAL;
>+
>+	switch (mode) {
>+	case CRYPTO_ACIPHER:
>+		ret = create_session_ablkcipher(alg_name, fcr, sop);
>+		break;
>+	case CRYPTO_AHASH:
>+		ret = create_session_ahash(alg_name, fcr, sop);
>+		break;
>+	case CRYPTO_AEAD:
>+		ret = create_session_aead(alg_name, fcr, sop);
>+		break;
>+	default:
>+		printk(KERN_INFO PFX "Improper Mode Set(Not
>Cipher/Hash/Aead)");
>+		ret = -EINVAL;
>+		break;
>+	}
>+	return ret;
>+}
>+
>+/**********************************************************************
>*********
>+ * Routine for Creating a Session for the Combined Mode Implementation
>+ *
>+
>************************************************************************
>*******
>+ */
>+static int create_session_aead(char *alg_name, struct fcrypt *fcr,
>+			struct session_op *sop)
>+{
>+	struct csession	*ses_new;
>+	struct csession	*ses_ptr;
>+	struct crypto_aead *tfm;
>+	char *keyp = NULL;
>+	size_t authsize;
>+	int ret = 0;
>+
>+	tfm = crypto_alloc_aead(alg_name, 0, 0);
>+	if (IS_ERR(tfm)) {
>+		printk(KERN_INFO PFX "Failed to load aead"
>+			"transform for %s: %ld \n", alg_name,
>PTR_ERR(tfm));
>+		return -EINVAL;
>+	}
>+
>+	crypto_aead_clear_flags(tfm, ~0);
>+
>+	keyp = kmalloc(sop->keylen, GFP_KERNEL);
>+	if (unlikely(!keyp)) {
>+		crypto_free_aead(tfm);
>+		return -ENOMEM;
>+	}
>+
>+	if (copy_from_user(keyp, sop->key, sop->keylen)) {
>+		printk(KERN_INFO PFX "Copy of Key Failed from"
>+		"User Space for %s\n", alg_name);
>+		kfree(keyp);
>+		crypto_free_aead(tfm);
>+		return -EFAULT;
>+	}
>+
>+	ret = crypto_aead_setkey(tfm, keyp, sop->keylen);
>+	kfree(keyp);
>+	if (ret) {
>+		printk(KERN_INFO PFX
>+			"Setting key failed for %s-%zu: flags=0x%X\n",
>+			alg_name, sop->keylen*8,
>+			crypto_aead_get_flags(tfm));
>+		printk(KERN_INFO PFX
>+			"(see CRYPTO_TFM_RES_* in <linux/crypto.h> "
>+			"for details)\n");
>+
>+		crypto_free_aead(tfm);
>+		return -EINVAL;
>+	}
>+
>+	/* Supporting Authsize for ccm and gcm from mackeylen
>+	(no separate field for authsize) */
>+	authsize = sop->mackeylen;
>+	ret = crypto_aead_setauthsize(tfm, authsize);
>+	if (ret) {
>+		printk(KERN_INFO "failed to set authsize = %u\n",
>authsize);
>+		crypto_free_aead(tfm);
>+		return -EINVAL;
>+	}
>+
>+	ses_new = kmalloc(sizeof(*ses_new), GFP_KERNEL);
>+	if (!ses_new) {
>+		crypto_free_aead(tfm);
>+		return -ENOMEM;
>+	}
>+
>+	memset(ses_new, 0, sizeof(*ses_new));
>+	get_random_bytes(&ses_new->sid, sizeof(ses_new->sid));
>+	ses_new->tfm_aead = tfm;
>+
>+	ses_new->mode = CRYPTO_AEAD;
>+	init_MUTEX(&ses_new->sem);
>+
>+	down(&fcr->sem);
>+
>+restart:
>+	list_for_each_entry(ses_ptr, &fcr->list, entry) {
>+		/* Check for duplicate SID */
>+		if (unlikely(ses_new->sid == ses_ptr->sid)) {
>+			get_random_bytes(&ses_new->sid,
>sizeof(ses_new->sid));
>+			goto restart;
>+		}
>+	}
>+
>+	list_add(&ses_new->entry, &fcr->list);
>+	up(&fcr->sem);
>+
>+	sop->ses = ses_new->sid;
>+
>+	return 0;
>+}
>+
>+/**********************************************************************
>*********
>+ * Routine for Creating a Session for the Hash Implementation
>+ *
>+
>************************************************************************
>*******
>+ */
>+static int create_session_ahash(char *alg_name, struct fcrypt *fcr,
>+			struct session_op *sop)
>+{
>+	struct csession	*ses_new;
>+	struct csession	*ses_ptr;
>+	struct crypto_ahash *tfm;
>+	char *keyp = NULL;
>+	int ret = 0;
>+
>+	tfm = crypto_alloc_ahash(alg_name, 0, 0);
>+	if (IS_ERR(tfm)) {
>+		printk(KERN_INFO PFX "Failed to load ahash "
>+			"transform for %s: %ld \n", alg_name,
>PTR_ERR(tfm));
>+		return -EINVAL;
>+	}
>+	crypto_ahash_clear_flags(tfm, ~0);
>+
>+	/* Copy the key(hmac) from user and set to TFM. */
>+	if (sop->mackey && (sop->mac != CRYPTO_MD5) && (sop->mac !=
>CRYPTO_SHA1)
>+		&& (sop->mac != CRYPTO_SHA2_256)
>+		&& (sop->mac != CRYPTO_SHA2_384)
>+		&& (sop->mac != CRYPTO_SHA2_512)
>+		&& (sop->mac != CRYPTO_RIPEMD160)) {
>+		keyp = kmalloc(sop->mackeylen, GFP_KERNEL);
>+		if (unlikely(!keyp)) {
>+			crypto_free_ahash(tfm);
>+			return -ENOMEM;
>+		}
>+
>+		if (copy_from_user(keyp, sop->mackey, sop->mackeylen)) {
>+			printk(KERN_INFO PFX "Copy of Key Failed from
>User"
>+			"space for %s\n", alg_name);
>+			kfree(keyp);
>+			crypto_free_ahash(tfm);
>+			return -EFAULT;
>+		}
>+
>+		ret = crypto_ahash_setkey(tfm, keyp, sop->mackeylen);
>+		kfree(keyp);
>+		if (ret) {
>+			printk(KERN_INFO PFX
>+				"Setting key failed for %s-%zu:
>flags=0x%X\n",
>+				alg_name, sop->mackeylen * 8,
>+				crypto_ahash_get_flags(tfm));
>+			printk(KERN_INFO PFX
>+				"(see CRYPTO_TFM_RES_* in "
>+				"<linux/crypto.h> for details)\n");
>+
>+			crypto_free_ahash(tfm);
>+			return -EINVAL;
>+		}
>+	}
>+
>+	ses_new = kmalloc(sizeof(*ses_new), GFP_KERNEL);
>+	if (!ses_new) {
>+		crypto_free_ahash(tfm);
>+		return -ENOMEM;
>+	}
>+
>+	memset(ses_new, 0, sizeof(*ses_new));
>+	get_random_bytes(&ses_new->sid, sizeof(ses_new->sid));
>+	ses_new->tfm_ahash = tfm;
>+
>+	ses_new->mode = CRYPTO_AHASH;
>+	init_MUTEX(&ses_new->sem);
>+
>+	down(&fcr->sem);
>+
>+restart:
>+	list_for_each_entry(ses_ptr, &fcr->list, entry) {
>+		/* Check for duplicate SID */
>+		if (unlikely(ses_new->sid == ses_ptr->sid)) {
>+			get_random_bytes(&ses_new->sid,
>sizeof(ses_new->sid));
>+			goto restart;
>+		}
>+	}
>+	list_add(&ses_new->entry, &fcr->list);
>+	up(&fcr->sem);
>+
>+	/* Fill in some values for the user. */
>+	sop->ses = ses_new->sid;
>+
>+	return 0;
>+}
>+
>+/**********************************************************************
>*********
>+ * Routine for Creating a Session for the Crypto Implementation
>+ *
>+
>************************************************************************
>*******
>+ */
>+static int create_session_ablkcipher(char *alg_name, struct fcrypt
>*fcr,
>+			struct session_op *sop)
>+{
>+	struct csession	*ses_new, *ses_ptr;
>+	struct crypto_ablkcipher *tfm;
>+	char *keyp = NULL;
>+	int ret = 0;
>+
>+	tfm = crypto_alloc_ablkcipher(alg_name, 0, 0);
>+	if (IS_ERR(tfm)) {
>+		printk(KERN_INFO PFX "Failed to load crypto "
>+			"transform for %s: %ld\n", alg_name,
>PTR_ERR(tfm));
>+		return -EINVAL;
>+	}
>+
>+	crypto_ablkcipher_clear_flags(tfm, ~0);
>+
>+	/* Copy the key from user and set to TFM. */
>+	keyp = kmalloc(sop->keylen, GFP_KERNEL);
>+	if (unlikely(!keyp)) {
>+		crypto_free_ablkcipher(tfm);
>+		return -ENOMEM;
>+
>+	}
>+
>+	if (copy_from_user(keyp, sop->key, sop->keylen)) {
>+		printk(KERN_INFO PFX "Copy of Key Failed from User"
>+		"space for %s\n", alg_name);
>+		kfree(keyp);
>+		crypto_free_ablkcipher(tfm);
>+		return -EFAULT;
>+	}
>+
>+	ret = crypto_ablkcipher_setkey(tfm, keyp, sop->keylen);
>+	kfree(keyp);
>+	if (ret) {
>+		printk(KERN_INFO PFX
>+			"Setting key failed for %s-%zu: flags=0x%X\n",
>+			alg_name, sop->keylen*8,
>+			crypto_ablkcipher_get_flags(tfm));
>+		printk(KERN_INFO PFX
>+			"(see CRYPTO_TFM_RES_* in <linux/crypto.h> for "
>+			"details)\n");
>+
>+		crypto_free_ablkcipher(tfm);
>+		return -EINVAL;
>+	}
>+
>+	ses_new = kmalloc(sizeof(*ses_new), GFP_KERNEL);
>+	if (!ses_new) {
>+		crypto_free_ablkcipher(tfm);
>+		return -ENOMEM;
>+	}
>+
>+	memset(ses_new, 0, sizeof(*ses_new));
>+	get_random_bytes(&ses_new->sid, sizeof(ses_new->sid));
>+	ses_new->tfm_ablkcipher = tfm;
>+
>+	ses_new->mode = CRYPTO_ACIPHER;
>+	init_MUTEX(&ses_new->sem);
>+
>+	down(&fcr->sem);
>+
>+restart:
>+	list_for_each_entry(ses_ptr, &fcr->list, entry) {
>+		/* Check for duplicate SID */
>+		if (unlikely(ses_new->sid == ses_ptr->sid)) {
>+			get_random_bytes(&ses_new->sid,
>sizeof(ses_new->sid));
>+			goto restart;
>+		}
>+	}
>+	list_add(&ses_new->entry, &fcr->list);
>+	up(&fcr->sem);
>+
>+	/* Fill in some values for the user. */
>+	sop->ses = ses_new->sid;
>+
>+	return 0;
>+}
>+
>+/**********************************************************************
>*********
>+ *  Everything that needs to be done when removing a session.
>+ *
>+
>************************************************************************
>*******
>+ */
>+static inline void cryptodev_destroy_session(struct csession *ses_ptr)
>+{
>+	if (down_trylock(&ses_ptr->sem)) {
>+		CRYPTODEV_PRINTK(2, KERN_DEBUG,
>+			"Waiting for semaphore of sid=0x%08X\n",
>+			ses_ptr->sid);
>+		down(&ses_ptr->sem);
>+	}
>+	CRYPTODEV_PRINTK(2, KERN_DEBUG, "Removed session 0x%08X\n",
>+			 ses_ptr->sid);
>+
>+	/* Check for mode and then delete */
>+	switch (ses_ptr->mode) {
>+	case CRYPTO_ACIPHER:
>+		crypto_free_ablkcipher(ses_ptr->tfm_ablkcipher);
>+		ses_ptr->tfm_ablkcipher = NULL;
>+		break;
>+	case CRYPTO_AHASH:
>+		crypto_free_ahash(ses_ptr->tfm_ahash);
>+		ses_ptr->tfm_ahash = NULL;
>+		break;
>+	case CRYPTO_AEAD:
>+		crypto_free_aead(ses_ptr->tfm_aead);
>+		ses_ptr->tfm_aead = NULL;
>+		break;
>+	}
>+	up(&ses_ptr->sem);
>+	kfree(ses_ptr);
>+}
>+
>+/**********************************************************************
>*********
>+ * Look up a session by ID and remove.
>+ *
>+
>************************************************************************
>*******
>+ */
>+static int cryptodev_finish_session(struct fcrypt *fcr, u32 sid)
>+{
>+	struct csession  *tmp;
>+	struct csession  *ses_ptr;
>+	struct list_head *head;
>+	int ret = 0;
>+
>+	down(&fcr->sem);
>+	head = &fcr->list;
>+	list_for_each_entry_safe(ses_ptr, tmp, head, entry) {
>+		if (ses_ptr->sid == sid) {
>+			list_del(&ses_ptr->entry);
>+			cryptodev_destroy_session(ses_ptr);
>+			break;
>+		}
>+	}
>+
>+	if (!ses_ptr) {
>+		CRYPTODEV_PRINTK(1, KERN_ERR,
>+			"Session with sid=0x%08X not found!\n", sid);
>+		ret = -ENOENT;
>+	}
>+	up(&fcr->sem);
>+
>+	return ret;
>+}
>+
>+/**********************************************************************
>*********
>+ * Remove all sessions when closing the file
>+ *
>+
>************************************************************************
>*******
>+ */
>+static int cryptodev_finish_all_sessions(struct fcrypt *fcr)
>+{
>+	struct csession *tmp;
>+	struct csession *ses_ptr;
>+
>+	down(&fcr->sem);
>+	list_for_each_entry_safe(ses_ptr, tmp, &fcr->list, entry) {
>+		list_del(&ses_ptr->entry);
>+		cryptodev_destroy_session(ses_ptr);
>+	}
>+	up(&fcr->sem);
>+
>+	return 0;
>+}
>+
>+/**********************************************************************
>*********
>+ * Look up session by session ID. The returned session is locked.
>+
>************************************************************************
>*******
>+ */
>+static struct csession *cryptodev_get_session_by_sid(struct fcrypt
>*fcr,
>+							u32 sid)
>+{
>+	struct csession *ses_ptr;
>+
>+	down(&fcr->sem);
>+	list_for_each_entry(ses_ptr, &fcr->list, entry) {
>+		if (ses_ptr->sid == sid) {
>+			down(&ses_ptr->sem);
>+			break;
>+		}
>+	}
>+	up(&fcr->sem);
>+
>+	return ses_ptr;
>+}
>+
>+static void cryptodev_release_session(struct csession *session)
>+{
>+	if (session)
>+		up(&session->sem);
>+}
>+
>+/**********************************************************************
>*********
>+ * This is the main crypto function - feed it with plaintext
>+ * and get a ciphertext
>+
>************************************************************************
>*******
>+ */
>+static int cryptodev_run(struct fcrypt *fcr, struct crypt_op *cop)
>+{
>+
>+	struct csession *ses_ptr;
>+	int ret = 0;
>+
>+	if (cop->op &&
>+	    (cop->op != COP_ENCRYPT && cop->op != COP_DECRYPT)) {
>+		printk(KERN_INFO PFX "invalid operation op=%u\n",
>cop->op);
>+		return -EINVAL;
>+	}
>+
>+	ses_ptr = cryptodev_get_session_by_sid(fcr, cop->ses);
>+	if (!ses_ptr) {
>+		printk(KERN_INFO PFX "invalid session ID=0x%08X\n",
>cop->ses);
>+		return -EINVAL;
>+	}
>+
>+	switch (ses_ptr->mode) {
>+	case CRYPTO_ACIPHER:
>+		ret = cryptodev_run_acipher(ses_ptr, cop);
>+		break;
>+	case CRYPTO_AHASH:
>+		ret = cryptodev_run_ahash(ses_ptr, cop);
>+		break;
>+	case CRYPTO_AEAD:
>+		ret = cryptodev_run_aead(ses_ptr, cop);
>+		break;
>+	}
>+	cryptodev_release_session(ses_ptr);
>+
>+	return ret;
>+
>+}
>+
>+/**********************************************************************
>*********
>+ * This is the routine that splits the user buffer data over
>+ * pages and creates scatterlist
>+
>************************************************************************
>*******
>+ */
>+static int sg_setup(unsigned char *data, int bufsize, struct
>scatterlist *sg,
>+			int sg_single)
>+{
>+	int sg_size, remainder_of_page;
>+	int i = 0;
>+
>+	if (sg_single || (!bufsize)) {
>+		sg_set_buf(&sg[0], data, bufsize);
>+		return 1;
>+	}
>+	sg_size = bufsize % PAGE_SIZE == 0 ? bufsize/PAGE_SIZE :
>+					 bufsize/PAGE_SIZE + 1;
>+	sg_init_table(sg, sg_size);
>+
>+	while (bufsize > 0 && i < sg_size) {
>+		sg_set_buf(&sg[i], data, bufsize);
>+		remainder_of_page = PAGE_SIZE - sg[i].offset;
>+		if (bufsize > remainder_of_page) {
>+			/* the buffer was split over multiple pages */
>+			sg[i].length = remainder_of_page;
>+			bufsize -= remainder_of_page;
>+			data += remainder_of_page;
>+		} else {
>+			bufsize = 0;
>+		}
>+		i++;
>+	}
>+	sg_mark_end(&sg[sg_size - 1]);
>+
>+	return sg_size;
>+}
>+
>+/**********************************************************************
>*********
>+ * This is the actual aead function that implements
>+ * the Combined mode
>+
>************************************************************************
>*******
>+ */
>+static int cryptodev_run_aead(struct csession *ses_ptr, struct crypt_op
>*cop)
>+{
>+	char *data = NULL;
>+	char *ivp  = NULL;
>+	char __user *src;
>+	char __user *dst;
>+	struct scatterlist sg[16];
>+	struct scatterlist asg[1];
>+	struct aead_request *req;
>+	struct async_result result;
>+	size_t bufsize;
>+	size_t ivsize;
>+	size_t order;
>+	size_t authsize;
>+	int ret = 0;
>+	int nsg = 0;
>+
>+	/* Checking the Input Length */
>+	bufsize = cop->len;
>+	if (cop->len > CRYPTO_MAX_DATA_LEN) {
>+		printk(KERN_INFO PFX "Maximum Data Size Exceeded: %d >
>%d\n",
>+			cop->len, CRYPTO_MAX_DATA_LEN);
>+		return -E2BIG;
>+	}
>+
>+	init_completion(&result.completion);
>+
>+	/* Setting the resquest */
>+	req = aead_request_alloc(ses_ptr->tfm_aead, GFP_KERNEL);
>+	if (!req) {
>+		printk(KERN_INFO PFX "failed to allocate request");
>+		return -EINVAL;
>+	}
>+
>+	order = get_order(bufsize);
>+	data = (char *) __get_free_pages(GFP_KERNEL, order);
>+
>+	if (unlikely(!data)) {
>+		ret = -ENOMEM;
>+		goto out_req;
>+	}
>+
>+	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
>+				  cryptodev_async_complete, &result);
>+
>+	src = cop->src;
>+	dst = cop->dst;
>+
>+	authsize = crypto_aead_authsize(ses_ptr->tfm_aead);
>+
>+	if (copy_from_user(data, src, bufsize)) {
>+		printk(KERN_INFO PFX "Copy of src data Failed from User"
>+		"space for aead\n");
>+		free_pages((unsigned long)data, order);
>+		ret = -EFAULT;
>+		goto out_req;
>+	}
>+
>+	ivsize = crypto_aead_ivsize(ses_ptr->tfm_aead);
>+
>+	ivp = kmalloc(ivsize, GFP_KERNEL);
>+	if (unlikely(!ivp)) {
>+		free_pages((unsigned long)data, order);
>+		ret = -ENOMEM;
>+		goto out_req;
>+	}
>+
>+	memset(ivp, 0, ivsize);
>+	if (cop->iv && copy_from_user(ivp, cop->iv, ivsize)) {
>+		printk(KERN_INFO PFX "Copy of src iv Failed from User "
>+		"space for aead\n");
>+		ret = -EFAULT;
>+		goto out;
>+	}
>+
>+	nsg = sg_setup(data, bufsize + authsize, sg, sg_single);
>+	if (!nsg) {
>+		printk("Scatter Allocation failed err due to improper"
>+			"sg size");
>+		goto out;
>+	}
>+
>+	/* Additional Associated data set to 0 bytes */
>+	sg_init_one(&asg[0], ivp, 0);
>+
>+	aead_request_set_crypt(req, sg, sg, bufsize, ivp);
>+	aead_request_set_assoc(req, asg, 0);
>+
>+	if (cop->op == COP_ENCRYPT)
>+		ret = crypto_aead_encrypt(req);
>+	else
>+		ret = crypto_aead_decrypt(req);
>+	switch (ret) {
>+	case 0:
>+		break;
>+	case -EINPROGRESS:
>+	case -EBUSY:
>+		ret = wait_for_completion_interruptible(
>+			&result.completion);
>+		if (!ret)
>+			ret = result.err;
>+		if (!ret) {
>+			INIT_COMPLETION(result.completion);
>+			break;
>+		}
>+		/* fall through */
>+	default:
>+		printk("%s () failed err=%d\n", "enc/dec", -ret);
>+		goto out;
>+	}
>+
>+	CRYPTODEV_HEXDUMP(data, bufsize + authsize);
>+	if (copy_to_user(dst, data, bufsize + authsize)) {
>+		printk(KERN_INFO PFX "Copy of enc data Failed to User"
>+		"space for aead\n");
>+		ret = -EFAULT;
>+	}
>+
>+out:
>+	free_pages((unsigned long)data, order);
>+	kfree(ivp);
>+
>+out_req:
>+	aead_request_free(req);
>+
>+	return ret;
>+}
>+
>+/**********************************************************************
>*********
>+ * This is the actual hash function that creates the
>+ * authenticated data
>+
>************************************************************************
>*******
>+ */
>+static int cryptodev_run_ahash(struct csession *ses_ptr, struct
>crypt_op *cop)
>+{
>+
>+	char *data = NULL;
>+	char __user *src;
>+	char __user *mac;
>+	struct scatterlist sg[16];
>+	struct ahash_request *req;
>+	struct async_result result;
>+	size_t authsize;
>+	size_t bufsize;
>+	size_t order;
>+	int ret = 0;
>+	int nsg = 0;
>+	char digest_result[64];
>+
>+	/* Checking the Input Length */
>+	bufsize = cop->len;
>+	if (cop->len > CRYPTO_MAX_DATA_LEN) {
>+		printk(KERN_INFO PFX "Maximum Data Size Exceeded: %d >
>%d\n",
>+		 cop->len, CRYPTO_MAX_DATA_LEN);
>+		return -E2BIG;
>+	}
>+
>+	init_completion(&result.completion);
>+
>+	/* Setting the resquest */
>+	req = ahash_request_alloc(ses_ptr->tfm_ahash, GFP_KERNEL);
>+	if (!req) {
>+		printk(KERN_INFO PFX "failed to allocate request");
>+		return -EINVAL;
>+	}
>+
>+	order = (!bufsize) ? 0 : get_order(bufsize);
>+	data = (char *) __get_free_pages(GFP_KERNEL, order);
>+
>+	if (unlikely(!data)) {
>+		printk(KERN_INFO PFX "Improper data size "
>+		"set = %d\n", bufsize);
>+		ret = -ENOMEM;
>+		goto out_req;
>+	}
>+
>+	authsize = crypto_ahash_digestsize(ses_ptr->tfm_ahash);
>+	memset(digest_result, 0, 64);
>+
>+	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
>+					cryptodev_async_complete,
>&result);
>+
>+	src = cop->src;
>+	mac = cop->mac;
>+
>+	if (copy_from_user(data, src, bufsize)) {
>+		printk(KERN_INFO PFX "Copy of src data Failed from User"
>+		"space for hash\n");
>+		ret = -EFAULT;
>+		goto out;
>+	}
>+
>+	nsg = sg_setup(data, bufsize, sg, sg_single);
>+	if (!nsg) {
>+		printk("Scatter Allocation () failed err=%d\n", nsg);
>+		goto out;
>+	}
>+
>+	ahash_request_set_crypt(req, sg, digest_result, bufsize);
>+	ret = crypto_ahash_digest(req);
>+
>+	switch (ret) {
>+	case 0:
>+		break;
>+	case -EINPROGRESS:
>+	case -EBUSY:
>+		ret = wait_for_completion_interruptible(
>+			&result.completion);
>+		if (!ret)
>+			ret = result.err;
>+		if (!ret) {
>+			INIT_COMPLETION(result.completion);
>+			break;
>+		}
>+		/* fall through */
>+	default:
>+		printk(KERN_INFO PFX "%s failed err=%d\n", "enc/dec",
>-ret);
>+		goto out;
>+	}
>+
>+	CRYPTODEV_HEXDUMP(digest_result, authsize);
>+	if (copy_to_user(mac, digest_result, authsize)) {
>+		printk(KERN_INFO PFX "Copy of mac data Failed to User"
>+		"space for hash\n");
>+		ret = -EFAULT;
>+	}
>+
>+out:
>+	free_pages((unsigned long)data, order);
>+
>+out_req:
>+	ahash_request_free(req);
>+
>+	return ret;
>+}
>+
>+/**********************************************************************
>*********
>+ * This is the actual crypto function that creates the
>+ * encrypted or decrypted data
>+
>************************************************************************
>*******
>+ */
>+static int cryptodev_run_acipher(struct csession *ses_ptr, struct
>crypt_op *cop)
>+{
>+	char *data = NULL;
>+	char *ivp = NULL;
>+	char __user *src;
>+	char __user *dst;
>+	struct scatterlist sg[16];
>+	struct ablkcipher_request *req;
>+	struct async_result result;
>+	size_t bufsize;
>+	size_t ivsize;
>+	size_t order;
>+	int ret = 0;
>+	int nsg = 0;
>+
>+	/* Checking the Input Length */
>+	bufsize = cop->len;
>+	if (cop->len > CRYPTO_MAX_DATA_LEN) {
>+		printk(KERN_INFO PFX "Maximum Data Size Exceeded: %d >
>%d\n",
>+		 cop->len, CRYPTO_MAX_DATA_LEN);
>+		return -E2BIG;
>+	}
>+
>+	init_completion(&result.completion);
>+
>+	/* Setting the request */
>+	req = ablkcipher_request_alloc(ses_ptr->tfm_ablkcipher,
>GFP_KERNEL);
>+	if (!req) {
>+		printk(KERN_INFO PFX "failed to allocate request\n");
>+		return -EINVAL;
>+	}
>+
>+	if (bufsize %
>crypto_ablkcipher_blocksize(ses_ptr->tfm_ablkcipher)) {
>+		printk(KERN_INFO PFX
>+			"data size (%zu) isn't a multiple of block size
>(%u)\n",
>+			bufsize, crypto_ablkcipher_blocksize
>+			(ses_ptr->tfm_ablkcipher));
>+		ret = -EINVAL;
>+		goto out_req;
>+	}
>+
>+	order = get_order(bufsize);
>+	data = (char *) __get_free_pages(GFP_KERNEL, order);
>+
>+	if (unlikely(!data)) {
>+		ret = -ENOMEM;
>+		goto out_req;
>+	}
>+
>+	ivsize = crypto_ablkcipher_ivsize(ses_ptr->tfm_ablkcipher);
>+
>+	ivp = kmalloc(ivsize, GFP_KERNEL);
>+	if (unlikely(!ivp)) {
>+		free_pages((unsigned long)data, order);
>+		ret = -ENOMEM;
>+		goto out_req;
>+	}
>+
>+	memset(ivp, 0, ivsize);
>+	if (cop->iv && copy_from_user(ivp, cop->iv, ivsize)) {
>+		printk(KERN_INFO PFX "Copy of src iv Failed from User "
>+		"space for crypto\n");
>+		ret = -EFAULT;
>+		goto out;
>+	}
>+
>+	ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
>+					cryptodev_async_complete,
>&result);
>+
>+	src = cop->src;
>+	dst = cop->dst;
>+
>+	if (copy_from_user(data, src, bufsize)) {
>+		printk(KERN_INFO PFX "Copy of src data Failed from User"
>+		"space for crypto\n");
>+		ret = -EFAULT;
>+		goto out;
>+	}
>+
>+	nsg = sg_setup(data, bufsize, sg, sg_single);
>+	if (!nsg) {
>+		printk(KERN_INFO PFX "Scatter Allocation failed
>err=%d\n",
>+			nsg);
>+		goto out;
>+	}
>+	ablkcipher_request_set_crypt(req, sg, sg, bufsize, ivp);
>+
>+	if (cop->op == COP_ENCRYPT)
>+		ret = crypto_ablkcipher_encrypt(req);
>+	else
>+		ret = crypto_ablkcipher_decrypt(req);
>+	switch (ret) {
>+	case 0:
>+		break;
>+	case -EINPROGRESS:
>+	case -EBUSY:
>+		ret = wait_for_completion_interruptible(
>+			&result.completion);
>+		if (!ret)
>+			ret = result.err;
>+		if (!ret) {
>+			INIT_COMPLETION(result.completion);
>+			break;
>+		}
>+		/* fall through */
>+	default:
>+		printk(KERN_INFO PFX "%s failed err=%d\n", "enc/dec",
>-ret);
>+		goto out;
>+	}
>+
>+	CRYPTODEV_HEXDUMP(data, bufsize);
>+	if (copy_to_user(dst, data, bufsize)) {
>+		printk(KERN_INFO PFX "Copy of enc data Failed to User"
>+		"space for crypto\n");
>+		ret = -EFAULT;
>+	}
>+
>+out:
>+	free_pages((unsigned long)data, order);
>+	kfree(ivp);
>+
>+out_req:
>+	ablkcipher_request_free(req);
>+
>+	return ret;
>+}
>+
>+
>/***********************************************************************
>******
>+ * /dev/crypto function operation functions
>+
>************************************************************************
>******
>+ */
>+static int cryptodev_clonefd(struct file *filp)
>+{
>+	mm_segment_t fs;
>+	int fd;
>+
>+	fs = get_fs();
>+	set_fs(get_ds());
>+	for (fd = 0; fd < files_fdtable(current->files)->max_fds; fd++)
>+		if (files_fdtable(current->files)->fd[fd] == filp)
>+			break;
>+	fd = __sys_dup(fd);
>+	set_fs(fs);
>+	return fd;
>+}

This is so broke. Why does dup() not work? It is allready available in
userspace.

>+
>+static int cryptodev_open(struct inode *inode, struct file *filp)
>+{
>+	struct fcrypt *fcr;
>+
>+	fcr = kmalloc(sizeof(*fcr), GFP_KERNEL);
>+	if (!fcr)
>+		return -ENOMEM;
>+
>+	memset(fcr, 0, sizeof(*fcr));
>+	init_MUTEX(&fcr->sem);
>+	INIT_LIST_HEAD(&fcr->list);
>+	filp->private_data = fcr;
>+
>+	return 0;
>+}
>+
>+static int cryptodev_release(struct inode *inode, struct file *filp)
>+{
>+	struct fcrypt *fcr = filp->private_data;
>+
>+	if (fcr) {
>+		cryptodev_finish_all_sessions(fcr);
>+		kfree(fcr);
>+		filp->private_data = NULL;
>+	}
>+	return 0;
>+}
>+
>+static int cryptodev_ioctl(struct inode *inode, struct file *filp,
>+		unsigned int cmd, unsigned long arg)
>+{
>+	struct session_op sop;
>+	struct crypt_op   cop;
>+	struct fcrypt *fcr = filp->private_data;
>+	unsigned int  ses;
>+	int ret;
>+	int fd, feat;
>+
>+	if (!fcr)
>+		BUG();
>+
>+	switch (cmd) {
>+	case CRIOGET:
>+		fd = cryptodev_clonefd(filp);
>+		put_user(fd, (int *) arg);
>+		return IS_ERR_VALUE(fd) ? fd : 0;
>+
>+	case CIOCGSESSION:
>+		if (copy_from_user(&sop, (void *) arg, sizeof(sop))) {
>+			printk(KERN_INFO PFX "Copy of Session data
>failed"
>+				"at CIOCGSESSION from user space\n");
>+			return -EFAULT;
>+		}
>+		ret = cryptodev_create_session(fcr, &sop);
>+		if (ret)
>+			return ret;
>+		if (copy_to_user((void *)arg, &sop, sizeof(sop))) {
>+			printk(KERN_INFO PFX "Copy of Session data
>failed"
>+				"at CIOCGSESSION to user space\n");
>+			return -EFAULT;
>+		}
>+		return 0;
>+
>+	case CIOCFSESSION:
>+		get_user(ses, (u32 *) arg);
>+		return cryptodev_finish_session(fcr, ses);
>+
>+	case CIOCCRYPT:
>+		if (copy_from_user(&cop, (void *) arg, sizeof(cop))) {
>+			printk(KERN_INFO PFX "Copy of src data failed"
>+				"at CIOCCRYPT from user space\n");
>+			return -EFAULT;
>+		}
>+		ret = cryptodev_run(fcr, &cop);
>+		if (copy_to_user((void *) arg, &cop, sizeof(cop))) {
>+			printk(KERN_INFO PFX "Copy of enc/dec/hash data
>failed"
>+				"at CIOCCRYPT to user space\n");
>+			return -EFAULT;
>+		}
>+		return ret;
>+
>+	case CIOCASYMFEAT:
>+		/* No Asymmetric Algorithms Supported */
>+		feat = 0;
>+		if (copy_to_user((void *)arg, &feat, sizeof(feat))) {
>+			printk(KERN_INFO PFX "Copy of asymm algorithm
>data"
>+				" failed at CIOCASYMFEAT to user
>space\n");
>+			return -EFAULT;
>+		}
>+		return 0;
>+
>+	default:
>+		printk(KERN_ERR PFX "un-supported command 0x%08X\n",
>cmd);
>+		return -EINVAL;
>+	}
>+}
>+
>+struct file_operations cryptodev_fops = {
>+	.owner   = THIS_MODULE,
>+	.open    = cryptodev_open,
>+	.release = cryptodev_release,
>+	.ioctl   = cryptodev_ioctl,
>+};
>+
>+struct miscdevice cryptodev = {
>+	.minor = CRYPTODEV_MINOR,
couldn't you use a dynamic minor?

>+	.name  = "crypto",
>+	.fops  = &cryptodev_fops,
>+};
>+
>+static int cryptodev_register(void)
>+{
>+	int rc;
>+
>+	rc = misc_register(&cryptodev);
>+	if (rc) {
>+		printk(KERN_ERR PFX "registeration of /dev/crypto
>failed\n");
>+		return rc;
>+	}
>+
>+	return 0;
>+}
>+
>+static void cryptodev_deregister(void)
>+{
>+	misc_deregister(&cryptodev);
>+}
>+
>+/**********************************************************************
>*********
>+ * Module init/exit
>+
>************************************************************************
>*******
>+ */
>+int __init init_cryptodev(void)
>+{
>+	int rc;
>+
>+	rc = cryptodev_register();
>+	if (rc)
>+		return rc;
>+
>+	printk(KERN_INFO PFX "CryptoAPI driver v%s loaded\n",
>+		CRYPTODEV_UI_SUPPORT_DRIVER);
>+
>+	return 0;
>+}
>+
>+void __exit exit_cryptodev(void)
>+{
>+	cryptodev_deregister();
>+	printk(KERN_INFO PFX "CryptoAPI driver v%s unloaded\n",
>+		CRYPTODEV_UI_SUPPORT_DRIVER);
>+}
>+
>+module_init(init_cryptodev);
>+module_exit(exit_cryptodev);
>+
>+MODULE_AUTHOR("Shasi Pulijala <spulijala@xxxxxxxx>");
>+MODULE_DESCRIPTION("CryptoDev driver");
>+MODULE_LICENSE("Dual BSD/GPL");
>diff --git a/fs/fcntl.c b/fs/fcntl.c
>index e632da7..5afec53 100644
>--- a/fs/fcntl.c
>+++ b/fs/fcntl.c
>@@ -137,6 +137,7 @@ static int dupfd(struct file *file, unsigned int
>start, int cloexec)
> 	return fd;
> }
> 
>+
> asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
> {
> 	int err = -EBADF;
>@@ -193,7 +194,7 @@ out_fput:
> 	goto out;
> }
> 
>-asmlinkage long sys_dup(unsigned int fildes)
>+asmlinkage long __sys_dup(unsigned int fildes)
> {
> 	int ret = -EBADF;
> 	struct file * file = fget(fildes);
>@@ -202,6 +203,12 @@ asmlinkage long sys_dup(unsigned int fildes)
> 		ret = dupfd(file, 0, 0);
> 	return ret;
> }
>+EXPORT_SYMBOL(__sys_dup);
>+
>+asmlinkage long sys_dup(unsigned int fildes)
>+{
>+	return __sys_dup(fildes);
>+}

I don't see the difference between sys_dup() & __sys_dup()

> 
> #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC |
>O_DIRECT | O_NOATIME)
> 
>diff --git a/include/linux/cryptodev.h b/include/linux/cryptodev.h
>new file mode 100644
>index 0000000..46466d4
>--- /dev/null
>+++ b/include/linux/cryptodev.h
>@@ -0,0 +1,119 @@
>+/**********************************************************************
>*********
>+ * cryptodev.h
>+ *
>+ * Linux CryptoAPI user space interface module
>+ *
>+ * Copyright (c) 2008 Shasi Pulijala <spulijala@xxxxxxxx>
>+ *
>+ * This program is free software; you can redistribute it and/or modify
>+ * it under the terms of the GNU General Public License as published by
>+ * the Free Software Foundation; either version 2 of the License, or
>+ * (at your option) any later version.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+ * GNU General Public License for more details.
>+ *
>+ *
>+ * Detail Description:
>+ * This file defines ioctl structures for the Linux CryptoAPI
>interface. It
>+ * provides user space applications accesss into the Linux CryptoAPI
>+ * functionalities.
>+ *
>+
>************************************************************************
>*******
>+ */
>+#ifndef __CRYPTODEV_H__
>+#define __CRYPTODEV_H__
>+
>+/* Crypto and Hash Algorithms */
>+
>+#define CRYPTO_ALGORITHM_MIN		1
>+#define CRYPTO_DES_CBC			1
>+#define CRYPTO_3DES_CBC		2
>+#define CRYPTO_BLF_CBC			3
>+#define CRYPTO_CAST_CBC		4
>+#define CRYPTO_SKIPJACK_CBC		5
>+#define CRYPTO_MD5_HMAC		6
>+#define CRYPTO_SHA1_HMAC		7
>+#define CRYPTO_RIPEMD160_HMAC	8
>+#define CRYPTO_MD5_KPDK		9
>+#define CRYPTO_SHA1_KPDK		10
>+#define CRYPTO_RIJNDAEL128_CBC	11 /* 128 bit blocksize */
>+#define CRYPTO_AES_CBC			11 /* 128 bit blocksize  */
>+#define CRYPTO_ARC4			12
>+#define CRYPTO_MD5			13
>+#define CRYPTO_SHA1			14
>+#define CRYPTO_NULL_HMAC		15
>+#define CRYPTO_NULL_CBC		16
>+#define CRYPTO_DEFLATE_COMP		17 /* Deflate compression
>algorithm */
>+#define CRYPTO_SHA2_256_HMAC		18
>+#define CRYPTO_SHA2_384_HMAC		19
>+#define CRYPTO_SHA2_512_HMAC		20
>+#define CRYPTO_CAMELLIA_CBC		21
>+#define CRYPTO_SHA2_256		22
>+#define CRYPTO_SHA2_384		23
>+#define CRYPTO_SHA2_512		24
>+#define CRYPTO_RIPEMD160		25
>+#define CRYPTO_AES_GCM			26
>+#define CRYPTO_AES_CCM			27
>+#define CRYPTO_ALGORITHM_MAX		28 /* Keep last */
>+
>+/**
>+ * @struct session_op
>+ * @brief ioctl parameter to create a session
>+ *
>+
>************************************************************************
>*******
>+ */
>+struct session_op {
>+	u32	cipher;				/* e.g. CRYPTO_DES_CBC
>*/
>+	u32	mac;				/* e.g. CRYPTO_MD5_HMAC
>*/
>+	u32	keylen;				/* cipher key */
>+	char	*key;
>+	int	mackeylen;			/* mac key length*/
>+	char	*mackey;			/* mackey(hmac)/authsize
>+						(ccm, gcm) */
>+
>+	/* Return values */
>+	u32 	ses;				/* session ID */
>+};
>+
>+#define CRYPTO_MAX_DATA_LEN		64*1024 - 1
>+/**
>+ * @struct crypt_op
>+ * @brief ioctl parameter to request a crypt/decrypt operation against
>a session
>+ *
>+
>************************************************************************
>*******
>+ */
>+struct crypt_op {
>+	u32	ses;
>+	u16	op;				/* i.e. COP_ENCRYPT */
>+#define COP_NONE	0
>+#define COP_ENCRYPT	1
>+#define COP_DECRYPT	2
>+	u16	flags;
>+#define	COP_F_BATCH	0x0008			/* Batch op if
>possible */
>+	u_int		len;
>+	caddr_t		src, dst;		/* become sg inside
>kernel */
>+	caddr_t		mac;			/* must be big enough
>for
>+						chosen MAC */
>+	caddr_t		iv;
>+};
>+
>+/* clone original filedescriptor */
>+#define CRIOGET         _IOWR('c', 100, unsigned int)
>+
>+/* create crypto session */
>+#define CIOCGSESSION    _IOWR('c', 101, struct session_op)
>+
>+/* finish crypto session */
>+#define CIOCFSESSION    _IOW('c', 102, unsigned int)
>+
>+/* request encryption/decryptions of a given buffer */
>+#define CIOCCRYPT       _IOWR('c', 103, struct crypt_op)
>+
>+/* ioctl()s for asym-crypto. Not yet supported. */
>+#define CIOCKEY         _IOWR('c', 104, void *)
>+#define CIOCASYMFEAT    _IOR('c', 105, unsigned int)
>+
>+#endif
>diff --git a/include/linux/fs.h b/include/linux/fs.h
>index b84b848..e9dc39e 100644
>--- a/include/linux/fs.h
>+++ b/include/linux/fs.h
>@@ -962,6 +962,7 @@ extern void __kill_fasync(struct fasync_struct *,
>int, int);
> 
> extern int __f_setown(struct file *filp, struct pid *, enum pid_type,
>int force);
> extern int f_setown(struct file *filp, unsigned long arg, int force);
>+extern long __sys_dup(unsigned int fildes);
> extern void f_delown(struct file *filp);
> extern pid_t f_getown(struct file *filp);
> extern int send_sigurg(struct fown_struct *fown);
>-- 
>1.5.4.4
>--
>To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
>the body of a message to majordomo@xxxxxxxxxxxxxxx
>More majordomo info at  http://vger.kernel.org/majordomo-info.html

Sebastian
--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux