* 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

Reply via email to