* 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 <[EMAIL PROTECTED]>
>Date: Thu, 8 May 2008 11:08:26 -0700
>Subject: [PATCH] Add CryptoAPI User Interface Support
>
>
>Signed-off-by: Shasi Pulijala <[EMAIL PROTECTED]>
>---
> 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 <[EMAIL PROTECTED]>
>+ *
>+ * 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 <[EMAIL PROTECTED]>");
>+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 <[EMAIL PROTECTED]>
>+ *
>+ * 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 [EMAIL PROTECTED]
>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 [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html