* Loc Ho | 2008-05-13 17:00:58 [-0700]: >I am re-sending this email as I don't believe it got to the mailing >list. Due to email problem, I am forward this patch on behalf of Shasi >Pulijala who worked on this user space interface for Linux CryptoAPI. If you forward patches, you should put your sign-of there as well (so you would have two). >This should add support for OpenSSL. Please note that user of this patch >musts patch OpenSSL. The OpenSSL patch can be found in OCF-Linux as this >interface uses the same I/O control interface. So this interface must stay as it in order not to patch openssl twice? > >-Loc Loc, if you want to send patches that are proper formated please use git-send-email (this patch looks like it is comming straight from git-format-patch). You can specify there a smtp server. There are a few comments below. >From 926bbdedff99b1e8bb25cd685cb7249ba21729d9 Mon Sep 17 00:00:00 2001 >From: Shasi Pulijala <spulijala@xxxxxxxx> >Date: Thu, 8 May 2008 11:08:26 -0700 >Subject: [PATCH] Add CryptoAPI User Interface Support > > >Signed-off-by: Shasi Pulijala <spulijala@xxxxxxxx> >--- > crypto/Kconfig | 7 + > crypto/Makefile | 1 + > crypto/cryptodev.c | 1284 >+++++++++++++++++++++++++++++++++++++++++++++ > fs/fcntl.c | 9 +- > include/linux/cryptodev.h | 119 +++++ > include/linux/fs.h | 1 + > 6 files changed, 1420 insertions(+), 1 deletions(-) > create mode 100644 crypto/cryptodev.c > create mode 100644 include/linux/cryptodev.h > >diff --git a/crypto/Kconfig b/crypto/Kconfig >index 69f1be6..de6d623 100644 >--- a/crypto/Kconfig >+++ b/crypto/Kconfig >@@ -52,6 +52,13 @@ config CRYPTO_MANAGER > Create default cryptographic template instantiations such as > cbc(aes). > >+config CRYPTO_CRYPTODEV >+ tristate "Cryptodev (/dev/crypto) interface" >+ depends on CRYPTO >+ help >+ Device /dev/crypto gives userspace programs access to >+ kernel crypto algorithms. >+ > config CRYPTO_HMAC > tristate "HMAC support" > select CRYPTO_HASH >diff --git a/crypto/Makefile b/crypto/Makefile >index 85d0109..3d5251b 100644 >--- a/crypto/Makefile >+++ b/crypto/Makefile >@@ -22,6 +22,7 @@ crypto_hash-objs += ahash.o > obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o > > obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o >+obj-$(CONFIG_CRYPTO_CRYPTODEV) += cryptodev.o > obj-$(CONFIG_CRYPTO_HMAC) += hmac.o > obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o > obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o >diff --git a/crypto/cryptodev.c b/crypto/cryptodev.c >new file mode 100644 >index 0000000..9175ee0 >--- /dev/null >+++ b/crypto/cryptodev.c >@@ -0,0 +1,1284 @@ >+/********************************************************************** >********* >+ * cryptodev.c >+ * >+ * Linux CryptoAPI user space interface module >+ * >+ * Copyright (c) 2008 Shasi Pulijala <spulijala@xxxxxxxx> >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 2 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * >+ * Detail Description: >+ * This file implements the /dev/crypto interface which is intended to >+ * provide user space interface to the Linux CryptoAPI. >+ * >+ >************************************************************************ >******* >+ */ >+#include <linux/module.h> >+#include <linux/moduleparam.h> >+#include <linux/init.h> >+#include <linux/sched.h> >+#include <linux/fs.h> >+#include <linux/fcntl.h> >+#include <linux/file.h> >+#include <linux/miscdevice.h> >+#include <linux/crypto.h> >+#include <linux/mm.h> >+#include <linux/highmem.h> >+#include <linux/random.h> >+#include <linux/cryptodev.h> >+#include <linux/syscalls.h> >+#include <linux/scatterlist.h> >+#include <linux/time.h> >+#include <linux/unistd.h> >+#include <linux/rtnetlink.h> >+#include <linux/err.h> >+#include <crypto/aead.h> >+#include <crypto/authenc.h> >+#include <asm/uaccess.h> >+#include <asm/ioctl.h> >+#include <asm/scatterlist.h> Please avoid asm >+#include <asm-powerpc/unistd.h> and this is not acceptable at all. >+ >+/********************************************************************** >********* >+ * Forward declaration >+ >************************************************************************ I personally prefer not having the asterisks all over the place and not commenting obvious things. >******* >+ */ >+#define CRYPTODEV_DEBUG >+ >+/********************************************************************** >********* >+ * Macro declaration >+ >************************************************************************ >******* >+ */ >+/* /dev/crypto is a char block device with majar 10 and minor below */ >+#define CRYPTODEV_MINOR 70 >+ >+#define CRYPTODEV_UI_SUPPORT_DRIVER "0.1" >+ >+/********************************************************************** >********* >+ * Module Parameters >+ >************************************************************************ >******* >+ */ >+static int debug; >+module_param(debug, int, 0644); >+MODULE_PARM_DESC(debug, "0: normal, 1: verbose, 2: debug"); >+ >+static int sg_single; >+module_param(sg_single, int, 0644); >+MODULE_PARM_DESC(sg_single, "0: sg array list, 1: single sg entity"); >+ >+#ifdef CRYPTODEV_STATS >+static int enable_stats; >+module_param(enable_stats, int, 0644); >+MODULE_PARM_DESC(enable_stats, "collect statictics about cryptodev >usage"); >+#endif >+ >+/********************************************************************** >********* >+ * Debugging Macro's >+ >************************************************************************ >******* >+ */ >+#define PFX "cryptodev: " >+ >+#ifndef CRYPTODEV_DEBUG >+#define CRYPTODEV_HEXDUMP(b, l) \ >+ print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, \ >+ 16, 1, (b), (l), false); >+#define CRYPTODEV_PRINTK(level, severity, format, a...) >\ >+ do { >\ >+ if (level <= debug) >\ >+ printk(severity PFX "%s[%u]: " format, >\ >+ current->comm, current->pid, ##a); >\ >+ } while (0) >+#else >+#define CRYPTODEV_HEXDUMP(b, l) >+#define CRYPTODEV_PRINTK(level, severity, format, a...) >+#endif >+ >+/********************************************************************** >********* >+ * Helper Structure >+ >************************************************************************ >******* >+ */ >+#define CRYPTO_ACIPHER 0 >+#define CRYPTO_AHASH 1 >+#define CRYPTO_AEAD 2 >+ >+#define tfm_ablkcipher crt_tfm.acipher_tfm >+#define tfm_aead crt_tfm.aead_tfm >+#define tfm_ahash crt_tfm.ahash_tfm >+ >+struct csession { >+ struct list_head entry; >+ struct semaphore sem; >+ union { >+ struct crypto_ablkcipher *acipher_tfm; >+ struct crypto_ahash *ahash_tfm; >+ struct crypto_aead *aead_tfm; >+ } crt_tfm; >+ >+ int mode; >+ unsigned int sid; >+}; >+ >+/********************************************************************** >********* >+ * Table Lookup for Algorithms name(Crypto/hash name) >+ * Helper Structure >+ >************************************************************************ >******* >+ */ >+char *algo_map_tbl[CRYPTO_ALGORITHM_MAX] = { >+ [CRYPTO_DES_CBC] = "cbc(des)", >+ [CRYPTO_3DES_CBC] = "cbc(des3_ede)", >+ [CRYPTO_MD5_HMAC] = "hmac(md5)", >+ [CRYPTO_BLF_CBC] = "cbc(blowfish)", >+ [CRYPTO_CAST_CBC] = "cbc(cast5)", >+ [CRYPTO_SKIPJACK_CBC] = "camellia", >+ [CRYPTO_MD5_HMAC] = "hmac(md5)", >+ [CRYPTO_SHA1_HMAC] = "hmac(sha1)", >+ [CRYPTO_RIPEMD160_HMAC] = "hmac(rmd160)", >+ [CRYPTO_MD5_KPDK] = "", >+ [CRYPTO_SHA1_KPDK] = "", >+ [CRYPTO_RIJNDAEL128_CBC] = "cbc(aes)", >+ [CRYPTO_AES_CBC] = "cbc(aes)", >+ [CRYPTO_ARC4] = "ecb(arc4)", >+ [CRYPTO_MD5] = "md5", >+ [CRYPTO_SHA1] = "sha1", >+ [CRYPTO_NULL_HMAC] = "", >+ [CRYPTO_NULL_CBC] = "", >+ [CRYPTO_DEFLATE_COMP] = "deflate", >+ [CRYPTO_SHA2_256_HMAC] = "hmac(sha256)", >+ [CRYPTO_SHA2_384_HMAC] = "hmac(sha384)", >+ [CRYPTO_SHA2_512_HMAC] = "hmac(sha512)", >+ [CRYPTO_CAMELLIA_CBC] = "cbc(camellia)", >+ [CRYPTO_SHA2_256] = "sha256", >+ [CRYPTO_SHA2_384] = "sha384", >+ [CRYPTO_SHA2_512] = "sha512", >+ [CRYPTO_RIPEMD160] = "rmd160", >+ [CRYPTO_AES_GCM] = "gcm(aes)", >+ [CRYPTO_AES_CCM] = "ccm(aes)", >+}; Wouldn't it be better to have dynamic algos? This way you must patch the driver every single time a new algo is showing up. >+ >+struct fcrypt { >+ struct list_head list; >+ struct semaphore sem; >+}; >+ >+struct async_result { >+ struct completion completion; >+ int err; >+}; >+ >+/********************************************************************** >********* >+ * Function Declarations >+ >************************************************************************ >******* >+ */ >+static int create_session_ablkcipher(char *alg_name, >+ struct fcrypt *fcr, >+ struct session_op *sop); >+static int create_session_ahash(char *alg_name, >+ struct fcrypt *fcr, >+ struct session_op *sop); >+static int create_session_aead(char *alg_name, >+ struct fcrypt *fcr, >+ struct session_op *sop); >+static int cryptodev_run_acipher(struct csession *ses_ptr, >+ struct crypt_op *cop); >+static int cryptodev_run_ahash(struct csession *ses_ptr, >+ struct crypt_op *cop); >+static int cryptodev_run_aead(struct csession *ses_ptr, >+ struct crypt_op *cop); >+static int sg_setup(unsigned char *addr, int bufsize, struct >scatterlist *sg, >+ int sg_single); >+ >+/********************************************************************** >********* >+ * Asynchronous handling Routine >+ * >+ >************************************************************************ >******* >+ */ >+static void cryptodev_async_complete(struct crypto_async_request *req, >int err) >+{ >+ struct async_result *res = req->data; >+ >+ if (err == -EINPROGRESS) >+ return; >+ >+ res->err = err; >+ complete(&res->completion); >+} >+ >+/********************************************************************** >********* >+ * Prepare session for future use >+ * >+ >************************************************************************ >******* >+ */ >+static int cryptodev_create_session(struct fcrypt *fcr, struct >session_op *sop) >+{ >+ char alg_name[CRYPTO_MAX_ALG_NAME]; >+ int mode = -1; >+ int ret = 0; >+ >+ if (sop->mac > CRYPTO_ALGORITHM_MAX || >+ sop->cipher > CRYPTO_ALGORITHM_MAX) { >+ printk(KERN_INFO PFX "algorithm not supported or " >+ "not set\n"); >+ return -EINVAL; >+ } >+ >+ if (sop->cipher && sop->mac) { >+ mode = CRYPTO_AEAD; >+ printk(KERN_INFO PFX "authenc(%s,%s) (Algorithm >Chanining Mode" >+ "not yet supported", algo_map_tbl[sop->mac], >+ algo_map_tbl[sop->cipher]); >+ return -EINVAL; >+ } else if (sop->cipher) { >+ if (sop->cipher == CRYPTO_AES_GCM || >+ sop->cipher == CRYPTO_AES_CCM) >+ mode = CRYPTO_AEAD; >+ else >+ mode = CRYPTO_ACIPHER; >+ strncpy(alg_name, algo_map_tbl[sop->cipher], >+ CRYPTO_MAX_ALG_NAME); >+ } else if (sop->mac) { >+ mode = CRYPTO_AHASH; >+ strncpy(alg_name, algo_map_tbl[sop->mac], >CRYPTO_MAX_ALG_NAME); >+ } >+ >+ if (!alg_name) >+ return -EINVAL; >+ >+ switch (mode) { >+ case CRYPTO_ACIPHER: >+ ret = create_session_ablkcipher(alg_name, fcr, sop); >+ break; >+ case CRYPTO_AHASH: >+ ret = create_session_ahash(alg_name, fcr, sop); >+ break; >+ case CRYPTO_AEAD: >+ ret = create_session_aead(alg_name, fcr, sop); >+ break; >+ default: >+ printk(KERN_INFO PFX "Improper Mode Set(Not >Cipher/Hash/Aead)"); >+ ret = -EINVAL; >+ break; >+ } >+ return ret; >+} >+ >+/********************************************************************** >********* >+ * Routine for Creating a Session for the Combined Mode Implementation >+ * >+ >************************************************************************ >******* >+ */ >+static int create_session_aead(char *alg_name, struct fcrypt *fcr, >+ struct session_op *sop) >+{ >+ struct csession *ses_new; >+ struct csession *ses_ptr; >+ struct crypto_aead *tfm; >+ char *keyp = NULL; >+ size_t authsize; >+ int ret = 0; >+ >+ tfm = crypto_alloc_aead(alg_name, 0, 0); >+ if (IS_ERR(tfm)) { >+ printk(KERN_INFO PFX "Failed to load aead" >+ "transform for %s: %ld \n", alg_name, >PTR_ERR(tfm)); >+ return -EINVAL; >+ } >+ >+ crypto_aead_clear_flags(tfm, ~0); >+ >+ keyp = kmalloc(sop->keylen, GFP_KERNEL); >+ if (unlikely(!keyp)) { >+ crypto_free_aead(tfm); >+ return -ENOMEM; >+ } >+ >+ if (copy_from_user(keyp, sop->key, sop->keylen)) { >+ printk(KERN_INFO PFX "Copy of Key Failed from" >+ "User Space for %s\n", alg_name); >+ kfree(keyp); >+ crypto_free_aead(tfm); >+ return -EFAULT; >+ } >+ >+ ret = crypto_aead_setkey(tfm, keyp, sop->keylen); >+ kfree(keyp); >+ if (ret) { >+ printk(KERN_INFO PFX >+ "Setting key failed for %s-%zu: flags=0x%X\n", >+ alg_name, sop->keylen*8, >+ crypto_aead_get_flags(tfm)); >+ printk(KERN_INFO PFX >+ "(see CRYPTO_TFM_RES_* in <linux/crypto.h> " >+ "for details)\n"); >+ >+ crypto_free_aead(tfm); >+ return -EINVAL; >+ } >+ >+ /* Supporting Authsize for ccm and gcm from mackeylen >+ (no separate field for authsize) */ >+ authsize = sop->mackeylen; >+ ret = crypto_aead_setauthsize(tfm, authsize); >+ if (ret) { >+ printk(KERN_INFO "failed to set authsize = %u\n", >authsize); >+ crypto_free_aead(tfm); >+ return -EINVAL; >+ } >+ >+ ses_new = kmalloc(sizeof(*ses_new), GFP_KERNEL); >+ if (!ses_new) { >+ crypto_free_aead(tfm); >+ return -ENOMEM; >+ } >+ >+ memset(ses_new, 0, sizeof(*ses_new)); >+ get_random_bytes(&ses_new->sid, sizeof(ses_new->sid)); >+ ses_new->tfm_aead = tfm; >+ >+ ses_new->mode = CRYPTO_AEAD; >+ init_MUTEX(&ses_new->sem); >+ >+ down(&fcr->sem); >+ >+restart: >+ list_for_each_entry(ses_ptr, &fcr->list, entry) { >+ /* Check for duplicate SID */ >+ if (unlikely(ses_new->sid == ses_ptr->sid)) { >+ get_random_bytes(&ses_new->sid, >sizeof(ses_new->sid)); >+ goto restart; >+ } >+ } >+ >+ list_add(&ses_new->entry, &fcr->list); >+ up(&fcr->sem); >+ >+ sop->ses = ses_new->sid; >+ >+ return 0; >+} >+ >+/********************************************************************** >********* >+ * Routine for Creating a Session for the Hash Implementation >+ * >+ >************************************************************************ >******* >+ */ >+static int create_session_ahash(char *alg_name, struct fcrypt *fcr, >+ struct session_op *sop) >+{ >+ struct csession *ses_new; >+ struct csession *ses_ptr; >+ struct crypto_ahash *tfm; >+ char *keyp = NULL; >+ int ret = 0; >+ >+ tfm = crypto_alloc_ahash(alg_name, 0, 0); >+ if (IS_ERR(tfm)) { >+ printk(KERN_INFO PFX "Failed to load ahash " >+ "transform for %s: %ld \n", alg_name, >PTR_ERR(tfm)); >+ return -EINVAL; >+ } >+ crypto_ahash_clear_flags(tfm, ~0); >+ >+ /* Copy the key(hmac) from user and set to TFM. */ >+ if (sop->mackey && (sop->mac != CRYPTO_MD5) && (sop->mac != >CRYPTO_SHA1) >+ && (sop->mac != CRYPTO_SHA2_256) >+ && (sop->mac != CRYPTO_SHA2_384) >+ && (sop->mac != CRYPTO_SHA2_512) >+ && (sop->mac != CRYPTO_RIPEMD160)) { >+ keyp = kmalloc(sop->mackeylen, GFP_KERNEL); >+ if (unlikely(!keyp)) { >+ crypto_free_ahash(tfm); >+ return -ENOMEM; >+ } >+ >+ if (copy_from_user(keyp, sop->mackey, sop->mackeylen)) { >+ printk(KERN_INFO PFX "Copy of Key Failed from >User" >+ "space for %s\n", alg_name); >+ kfree(keyp); >+ crypto_free_ahash(tfm); >+ return -EFAULT; >+ } >+ >+ ret = crypto_ahash_setkey(tfm, keyp, sop->mackeylen); >+ kfree(keyp); >+ if (ret) { >+ printk(KERN_INFO PFX >+ "Setting key failed for %s-%zu: >flags=0x%X\n", >+ alg_name, sop->mackeylen * 8, >+ crypto_ahash_get_flags(tfm)); >+ printk(KERN_INFO PFX >+ "(see CRYPTO_TFM_RES_* in " >+ "<linux/crypto.h> for details)\n"); >+ >+ crypto_free_ahash(tfm); >+ return -EINVAL; >+ } >+ } >+ >+ ses_new = kmalloc(sizeof(*ses_new), GFP_KERNEL); >+ if (!ses_new) { >+ crypto_free_ahash(tfm); >+ return -ENOMEM; >+ } >+ >+ memset(ses_new, 0, sizeof(*ses_new)); >+ get_random_bytes(&ses_new->sid, sizeof(ses_new->sid)); >+ ses_new->tfm_ahash = tfm; >+ >+ ses_new->mode = CRYPTO_AHASH; >+ init_MUTEX(&ses_new->sem); >+ >+ down(&fcr->sem); >+ >+restart: >+ list_for_each_entry(ses_ptr, &fcr->list, entry) { >+ /* Check for duplicate SID */ >+ if (unlikely(ses_new->sid == ses_ptr->sid)) { >+ get_random_bytes(&ses_new->sid, >sizeof(ses_new->sid)); >+ goto restart; >+ } >+ } >+ list_add(&ses_new->entry, &fcr->list); >+ up(&fcr->sem); >+ >+ /* Fill in some values for the user. */ >+ sop->ses = ses_new->sid; >+ >+ return 0; >+} >+ >+/********************************************************************** >********* >+ * Routine for Creating a Session for the Crypto Implementation >+ * >+ >************************************************************************ >******* >+ */ >+static int create_session_ablkcipher(char *alg_name, struct fcrypt >*fcr, >+ struct session_op *sop) >+{ >+ struct csession *ses_new, *ses_ptr; >+ struct crypto_ablkcipher *tfm; >+ char *keyp = NULL; >+ int ret = 0; >+ >+ tfm = crypto_alloc_ablkcipher(alg_name, 0, 0); >+ if (IS_ERR(tfm)) { >+ printk(KERN_INFO PFX "Failed to load crypto " >+ "transform for %s: %ld\n", alg_name, >PTR_ERR(tfm)); >+ return -EINVAL; >+ } >+ >+ crypto_ablkcipher_clear_flags(tfm, ~0); >+ >+ /* Copy the key from user and set to TFM. */ >+ keyp = kmalloc(sop->keylen, GFP_KERNEL); >+ if (unlikely(!keyp)) { >+ crypto_free_ablkcipher(tfm); >+ return -ENOMEM; >+ >+ } >+ >+ if (copy_from_user(keyp, sop->key, sop->keylen)) { >+ printk(KERN_INFO PFX "Copy of Key Failed from User" >+ "space for %s\n", alg_name); >+ kfree(keyp); >+ crypto_free_ablkcipher(tfm); >+ return -EFAULT; >+ } >+ >+ ret = crypto_ablkcipher_setkey(tfm, keyp, sop->keylen); >+ kfree(keyp); >+ if (ret) { >+ printk(KERN_INFO PFX >+ "Setting key failed for %s-%zu: flags=0x%X\n", >+ alg_name, sop->keylen*8, >+ crypto_ablkcipher_get_flags(tfm)); >+ printk(KERN_INFO PFX >+ "(see CRYPTO_TFM_RES_* in <linux/crypto.h> for " >+ "details)\n"); >+ >+ crypto_free_ablkcipher(tfm); >+ return -EINVAL; >+ } >+ >+ ses_new = kmalloc(sizeof(*ses_new), GFP_KERNEL); >+ if (!ses_new) { >+ crypto_free_ablkcipher(tfm); >+ return -ENOMEM; >+ } >+ >+ memset(ses_new, 0, sizeof(*ses_new)); >+ get_random_bytes(&ses_new->sid, sizeof(ses_new->sid)); >+ ses_new->tfm_ablkcipher = tfm; >+ >+ ses_new->mode = CRYPTO_ACIPHER; >+ init_MUTEX(&ses_new->sem); >+ >+ down(&fcr->sem); >+ >+restart: >+ list_for_each_entry(ses_ptr, &fcr->list, entry) { >+ /* Check for duplicate SID */ >+ if (unlikely(ses_new->sid == ses_ptr->sid)) { >+ get_random_bytes(&ses_new->sid, >sizeof(ses_new->sid)); >+ goto restart; >+ } >+ } >+ list_add(&ses_new->entry, &fcr->list); >+ up(&fcr->sem); >+ >+ /* Fill in some values for the user. */ >+ sop->ses = ses_new->sid; >+ >+ return 0; >+} >+ >+/********************************************************************** >********* >+ * Everything that needs to be done when removing a session. >+ * >+ >************************************************************************ >******* >+ */ >+static inline void cryptodev_destroy_session(struct csession *ses_ptr) >+{ >+ if (down_trylock(&ses_ptr->sem)) { >+ CRYPTODEV_PRINTK(2, KERN_DEBUG, >+ "Waiting for semaphore of sid=0x%08X\n", >+ ses_ptr->sid); >+ down(&ses_ptr->sem); >+ } >+ CRYPTODEV_PRINTK(2, KERN_DEBUG, "Removed session 0x%08X\n", >+ ses_ptr->sid); >+ >+ /* Check for mode and then delete */ >+ switch (ses_ptr->mode) { >+ case CRYPTO_ACIPHER: >+ crypto_free_ablkcipher(ses_ptr->tfm_ablkcipher); >+ ses_ptr->tfm_ablkcipher = NULL; >+ break; >+ case CRYPTO_AHASH: >+ crypto_free_ahash(ses_ptr->tfm_ahash); >+ ses_ptr->tfm_ahash = NULL; >+ break; >+ case CRYPTO_AEAD: >+ crypto_free_aead(ses_ptr->tfm_aead); >+ ses_ptr->tfm_aead = NULL; >+ break; >+ } >+ up(&ses_ptr->sem); >+ kfree(ses_ptr); >+} >+ >+/********************************************************************** >********* >+ * Look up a session by ID and remove. >+ * >+ >************************************************************************ >******* >+ */ >+static int cryptodev_finish_session(struct fcrypt *fcr, u32 sid) >+{ >+ struct csession *tmp; >+ struct csession *ses_ptr; >+ struct list_head *head; >+ int ret = 0; >+ >+ down(&fcr->sem); >+ head = &fcr->list; >+ list_for_each_entry_safe(ses_ptr, tmp, head, entry) { >+ if (ses_ptr->sid == sid) { >+ list_del(&ses_ptr->entry); >+ cryptodev_destroy_session(ses_ptr); >+ break; >+ } >+ } >+ >+ if (!ses_ptr) { >+ CRYPTODEV_PRINTK(1, KERN_ERR, >+ "Session with sid=0x%08X not found!\n", sid); >+ ret = -ENOENT; >+ } >+ up(&fcr->sem); >+ >+ return ret; >+} >+ >+/********************************************************************** >********* >+ * Remove all sessions when closing the file >+ * >+ >************************************************************************ >******* >+ */ >+static int cryptodev_finish_all_sessions(struct fcrypt *fcr) >+{ >+ struct csession *tmp; >+ struct csession *ses_ptr; >+ >+ down(&fcr->sem); >+ list_for_each_entry_safe(ses_ptr, tmp, &fcr->list, entry) { >+ list_del(&ses_ptr->entry); >+ cryptodev_destroy_session(ses_ptr); >+ } >+ up(&fcr->sem); >+ >+ return 0; >+} >+ >+/********************************************************************** >********* >+ * Look up session by session ID. The returned session is locked. >+ >************************************************************************ >******* >+ */ >+static struct csession *cryptodev_get_session_by_sid(struct fcrypt >*fcr, >+ u32 sid) >+{ >+ struct csession *ses_ptr; >+ >+ down(&fcr->sem); >+ list_for_each_entry(ses_ptr, &fcr->list, entry) { >+ if (ses_ptr->sid == sid) { >+ down(&ses_ptr->sem); >+ break; >+ } >+ } >+ up(&fcr->sem); >+ >+ return ses_ptr; >+} >+ >+static void cryptodev_release_session(struct csession *session) >+{ >+ if (session) >+ up(&session->sem); >+} >+ >+/********************************************************************** >********* >+ * This is the main crypto function - feed it with plaintext >+ * and get a ciphertext >+ >************************************************************************ >******* >+ */ >+static int cryptodev_run(struct fcrypt *fcr, struct crypt_op *cop) >+{ >+ >+ struct csession *ses_ptr; >+ int ret = 0; >+ >+ if (cop->op && >+ (cop->op != COP_ENCRYPT && cop->op != COP_DECRYPT)) { >+ printk(KERN_INFO PFX "invalid operation op=%u\n", >cop->op); >+ return -EINVAL; >+ } >+ >+ ses_ptr = cryptodev_get_session_by_sid(fcr, cop->ses); >+ if (!ses_ptr) { >+ printk(KERN_INFO PFX "invalid session ID=0x%08X\n", >cop->ses); >+ return -EINVAL; >+ } >+ >+ switch (ses_ptr->mode) { >+ case CRYPTO_ACIPHER: >+ ret = cryptodev_run_acipher(ses_ptr, cop); >+ break; >+ case CRYPTO_AHASH: >+ ret = cryptodev_run_ahash(ses_ptr, cop); >+ break; >+ case CRYPTO_AEAD: >+ ret = cryptodev_run_aead(ses_ptr, cop); >+ break; >+ } >+ cryptodev_release_session(ses_ptr); >+ >+ return ret; >+ >+} >+ >+/********************************************************************** >********* >+ * This is the routine that splits the user buffer data over >+ * pages and creates scatterlist >+ >************************************************************************ >******* >+ */ >+static int sg_setup(unsigned char *data, int bufsize, struct >scatterlist *sg, >+ int sg_single) >+{ >+ int sg_size, remainder_of_page; >+ int i = 0; >+ >+ if (sg_single || (!bufsize)) { >+ sg_set_buf(&sg[0], data, bufsize); >+ return 1; >+ } >+ sg_size = bufsize % PAGE_SIZE == 0 ? bufsize/PAGE_SIZE : >+ bufsize/PAGE_SIZE + 1; >+ sg_init_table(sg, sg_size); >+ >+ while (bufsize > 0 && i < sg_size) { >+ sg_set_buf(&sg[i], data, bufsize); >+ remainder_of_page = PAGE_SIZE - sg[i].offset; >+ if (bufsize > remainder_of_page) { >+ /* the buffer was split over multiple pages */ >+ sg[i].length = remainder_of_page; >+ bufsize -= remainder_of_page; >+ data += remainder_of_page; >+ } else { >+ bufsize = 0; >+ } >+ i++; >+ } >+ sg_mark_end(&sg[sg_size - 1]); >+ >+ return sg_size; >+} >+ >+/********************************************************************** >********* >+ * This is the actual aead function that implements >+ * the Combined mode >+ >************************************************************************ >******* >+ */ >+static int cryptodev_run_aead(struct csession *ses_ptr, struct crypt_op >*cop) >+{ >+ char *data = NULL; >+ char *ivp = NULL; >+ char __user *src; >+ char __user *dst; >+ struct scatterlist sg[16]; >+ struct scatterlist asg[1]; >+ struct aead_request *req; >+ struct async_result result; >+ size_t bufsize; >+ size_t ivsize; >+ size_t order; >+ size_t authsize; >+ int ret = 0; >+ int nsg = 0; >+ >+ /* Checking the Input Length */ >+ bufsize = cop->len; >+ if (cop->len > CRYPTO_MAX_DATA_LEN) { >+ printk(KERN_INFO PFX "Maximum Data Size Exceeded: %d > >%d\n", >+ cop->len, CRYPTO_MAX_DATA_LEN); >+ return -E2BIG; >+ } >+ >+ init_completion(&result.completion); >+ >+ /* Setting the resquest */ >+ req = aead_request_alloc(ses_ptr->tfm_aead, GFP_KERNEL); >+ if (!req) { >+ printk(KERN_INFO PFX "failed to allocate request"); >+ return -EINVAL; >+ } >+ >+ order = get_order(bufsize); >+ data = (char *) __get_free_pages(GFP_KERNEL, order); >+ >+ if (unlikely(!data)) { >+ ret = -ENOMEM; >+ goto out_req; >+ } >+ >+ aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, >+ cryptodev_async_complete, &result); >+ >+ src = cop->src; >+ dst = cop->dst; >+ >+ authsize = crypto_aead_authsize(ses_ptr->tfm_aead); >+ >+ if (copy_from_user(data, src, bufsize)) { >+ printk(KERN_INFO PFX "Copy of src data Failed from User" >+ "space for aead\n"); >+ free_pages((unsigned long)data, order); >+ ret = -EFAULT; >+ goto out_req; >+ } >+ >+ ivsize = crypto_aead_ivsize(ses_ptr->tfm_aead); >+ >+ ivp = kmalloc(ivsize, GFP_KERNEL); >+ if (unlikely(!ivp)) { >+ free_pages((unsigned long)data, order); >+ ret = -ENOMEM; >+ goto out_req; >+ } >+ >+ memset(ivp, 0, ivsize); >+ if (cop->iv && copy_from_user(ivp, cop->iv, ivsize)) { >+ printk(KERN_INFO PFX "Copy of src iv Failed from User " >+ "space for aead\n"); >+ ret = -EFAULT; >+ goto out; >+ } >+ >+ nsg = sg_setup(data, bufsize + authsize, sg, sg_single); >+ if (!nsg) { >+ printk("Scatter Allocation failed err due to improper" >+ "sg size"); >+ goto out; >+ } >+ >+ /* Additional Associated data set to 0 bytes */ >+ sg_init_one(&asg[0], ivp, 0); >+ >+ aead_request_set_crypt(req, sg, sg, bufsize, ivp); >+ aead_request_set_assoc(req, asg, 0); >+ >+ if (cop->op == COP_ENCRYPT) >+ ret = crypto_aead_encrypt(req); >+ else >+ ret = crypto_aead_decrypt(req); >+ switch (ret) { >+ case 0: >+ break; >+ case -EINPROGRESS: >+ case -EBUSY: >+ ret = wait_for_completion_interruptible( >+ &result.completion); >+ if (!ret) >+ ret = result.err; >+ if (!ret) { >+ INIT_COMPLETION(result.completion); >+ break; >+ } >+ /* fall through */ >+ default: >+ printk("%s () failed err=%d\n", "enc/dec", -ret); >+ goto out; >+ } >+ >+ CRYPTODEV_HEXDUMP(data, bufsize + authsize); >+ if (copy_to_user(dst, data, bufsize + authsize)) { >+ printk(KERN_INFO PFX "Copy of enc data Failed to User" >+ "space for aead\n"); >+ ret = -EFAULT; >+ } >+ >+out: >+ free_pages((unsigned long)data, order); >+ kfree(ivp); >+ >+out_req: >+ aead_request_free(req); >+ >+ return ret; >+} >+ >+/********************************************************************** >********* >+ * This is the actual hash function that creates the >+ * authenticated data >+ >************************************************************************ >******* >+ */ >+static int cryptodev_run_ahash(struct csession *ses_ptr, struct >crypt_op *cop) >+{ >+ >+ char *data = NULL; >+ char __user *src; >+ char __user *mac; >+ struct scatterlist sg[16]; >+ struct ahash_request *req; >+ struct async_result result; >+ size_t authsize; >+ size_t bufsize; >+ size_t order; >+ int ret = 0; >+ int nsg = 0; >+ char digest_result[64]; >+ >+ /* Checking the Input Length */ >+ bufsize = cop->len; >+ if (cop->len > CRYPTO_MAX_DATA_LEN) { >+ printk(KERN_INFO PFX "Maximum Data Size Exceeded: %d > >%d\n", >+ cop->len, CRYPTO_MAX_DATA_LEN); >+ return -E2BIG; >+ } >+ >+ init_completion(&result.completion); >+ >+ /* Setting the resquest */ >+ req = ahash_request_alloc(ses_ptr->tfm_ahash, GFP_KERNEL); >+ if (!req) { >+ printk(KERN_INFO PFX "failed to allocate request"); >+ return -EINVAL; >+ } >+ >+ order = (!bufsize) ? 0 : get_order(bufsize); >+ data = (char *) __get_free_pages(GFP_KERNEL, order); >+ >+ if (unlikely(!data)) { >+ printk(KERN_INFO PFX "Improper data size " >+ "set = %d\n", bufsize); >+ ret = -ENOMEM; >+ goto out_req; >+ } >+ >+ authsize = crypto_ahash_digestsize(ses_ptr->tfm_ahash); >+ memset(digest_result, 0, 64); >+ >+ ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, >+ cryptodev_async_complete, >&result); >+ >+ src = cop->src; >+ mac = cop->mac; >+ >+ if (copy_from_user(data, src, bufsize)) { >+ printk(KERN_INFO PFX "Copy of src data Failed from User" >+ "space for hash\n"); >+ ret = -EFAULT; >+ goto out; >+ } >+ >+ nsg = sg_setup(data, bufsize, sg, sg_single); >+ if (!nsg) { >+ printk("Scatter Allocation () failed err=%d\n", nsg); >+ goto out; >+ } >+ >+ ahash_request_set_crypt(req, sg, digest_result, bufsize); >+ ret = crypto_ahash_digest(req); >+ >+ switch (ret) { >+ case 0: >+ break; >+ case -EINPROGRESS: >+ case -EBUSY: >+ ret = wait_for_completion_interruptible( >+ &result.completion); >+ if (!ret) >+ ret = result.err; >+ if (!ret) { >+ INIT_COMPLETION(result.completion); >+ break; >+ } >+ /* fall through */ >+ default: >+ printk(KERN_INFO PFX "%s failed err=%d\n", "enc/dec", >-ret); >+ goto out; >+ } >+ >+ CRYPTODEV_HEXDUMP(digest_result, authsize); >+ if (copy_to_user(mac, digest_result, authsize)) { >+ printk(KERN_INFO PFX "Copy of mac data Failed to User" >+ "space for hash\n"); >+ ret = -EFAULT; >+ } >+ >+out: >+ free_pages((unsigned long)data, order); >+ >+out_req: >+ ahash_request_free(req); >+ >+ return ret; >+} >+ >+/********************************************************************** >********* >+ * This is the actual crypto function that creates the >+ * encrypted or decrypted data >+ >************************************************************************ >******* >+ */ >+static int cryptodev_run_acipher(struct csession *ses_ptr, struct >crypt_op *cop) >+{ >+ char *data = NULL; >+ char *ivp = NULL; >+ char __user *src; >+ char __user *dst; >+ struct scatterlist sg[16]; >+ struct ablkcipher_request *req; >+ struct async_result result; >+ size_t bufsize; >+ size_t ivsize; >+ size_t order; >+ int ret = 0; >+ int nsg = 0; >+ >+ /* Checking the Input Length */ >+ bufsize = cop->len; >+ if (cop->len > CRYPTO_MAX_DATA_LEN) { >+ printk(KERN_INFO PFX "Maximum Data Size Exceeded: %d > >%d\n", >+ cop->len, CRYPTO_MAX_DATA_LEN); >+ return -E2BIG; >+ } >+ >+ init_completion(&result.completion); >+ >+ /* Setting the request */ >+ req = ablkcipher_request_alloc(ses_ptr->tfm_ablkcipher, >GFP_KERNEL); >+ if (!req) { >+ printk(KERN_INFO PFX "failed to allocate request\n"); >+ return -EINVAL; >+ } >+ >+ if (bufsize % >crypto_ablkcipher_blocksize(ses_ptr->tfm_ablkcipher)) { >+ printk(KERN_INFO PFX >+ "data size (%zu) isn't a multiple of block size >(%u)\n", >+ bufsize, crypto_ablkcipher_blocksize >+ (ses_ptr->tfm_ablkcipher)); >+ ret = -EINVAL; >+ goto out_req; >+ } >+ >+ order = get_order(bufsize); >+ data = (char *) __get_free_pages(GFP_KERNEL, order); >+ >+ if (unlikely(!data)) { >+ ret = -ENOMEM; >+ goto out_req; >+ } >+ >+ ivsize = crypto_ablkcipher_ivsize(ses_ptr->tfm_ablkcipher); >+ >+ ivp = kmalloc(ivsize, GFP_KERNEL); >+ if (unlikely(!ivp)) { >+ free_pages((unsigned long)data, order); >+ ret = -ENOMEM; >+ goto out_req; >+ } >+ >+ memset(ivp, 0, ivsize); >+ if (cop->iv && copy_from_user(ivp, cop->iv, ivsize)) { >+ printk(KERN_INFO PFX "Copy of src iv Failed from User " >+ "space for crypto\n"); >+ ret = -EFAULT; >+ goto out; >+ } >+ >+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, >+ cryptodev_async_complete, >&result); >+ >+ src = cop->src; >+ dst = cop->dst; >+ >+ if (copy_from_user(data, src, bufsize)) { >+ printk(KERN_INFO PFX "Copy of src data Failed from User" >+ "space for crypto\n"); >+ ret = -EFAULT; >+ goto out; >+ } >+ >+ nsg = sg_setup(data, bufsize, sg, sg_single); >+ if (!nsg) { >+ printk(KERN_INFO PFX "Scatter Allocation failed >err=%d\n", >+ nsg); >+ goto out; >+ } >+ ablkcipher_request_set_crypt(req, sg, sg, bufsize, ivp); >+ >+ if (cop->op == COP_ENCRYPT) >+ ret = crypto_ablkcipher_encrypt(req); >+ else >+ ret = crypto_ablkcipher_decrypt(req); >+ switch (ret) { >+ case 0: >+ break; >+ case -EINPROGRESS: >+ case -EBUSY: >+ ret = wait_for_completion_interruptible( >+ &result.completion); >+ if (!ret) >+ ret = result.err; >+ if (!ret) { >+ INIT_COMPLETION(result.completion); >+ break; >+ } >+ /* fall through */ >+ default: >+ printk(KERN_INFO PFX "%s failed err=%d\n", "enc/dec", >-ret); >+ goto out; >+ } >+ >+ CRYPTODEV_HEXDUMP(data, bufsize); >+ if (copy_to_user(dst, data, bufsize)) { >+ printk(KERN_INFO PFX "Copy of enc data Failed to User" >+ "space for crypto\n"); >+ ret = -EFAULT; >+ } >+ >+out: >+ free_pages((unsigned long)data, order); >+ kfree(ivp); >+ >+out_req: >+ ablkcipher_request_free(req); >+ >+ return ret; >+} >+ >+ >/*********************************************************************** >****** >+ * /dev/crypto function operation functions >+ >************************************************************************ >****** >+ */ >+static int cryptodev_clonefd(struct file *filp) >+{ >+ mm_segment_t fs; >+ int fd; >+ >+ fs = get_fs(); >+ set_fs(get_ds()); >+ for (fd = 0; fd < files_fdtable(current->files)->max_fds; fd++) >+ if (files_fdtable(current->files)->fd[fd] == filp) >+ break; >+ fd = __sys_dup(fd); >+ set_fs(fs); >+ return fd; >+} This is so broke. Why does dup() not work? It is allready available in userspace. >+ >+static int cryptodev_open(struct inode *inode, struct file *filp) >+{ >+ struct fcrypt *fcr; >+ >+ fcr = kmalloc(sizeof(*fcr), GFP_KERNEL); >+ if (!fcr) >+ return -ENOMEM; >+ >+ memset(fcr, 0, sizeof(*fcr)); >+ init_MUTEX(&fcr->sem); >+ INIT_LIST_HEAD(&fcr->list); >+ filp->private_data = fcr; >+ >+ return 0; >+} >+ >+static int cryptodev_release(struct inode *inode, struct file *filp) >+{ >+ struct fcrypt *fcr = filp->private_data; >+ >+ if (fcr) { >+ cryptodev_finish_all_sessions(fcr); >+ kfree(fcr); >+ filp->private_data = NULL; >+ } >+ return 0; >+} >+ >+static int cryptodev_ioctl(struct inode *inode, struct file *filp, >+ unsigned int cmd, unsigned long arg) >+{ >+ struct session_op sop; >+ struct crypt_op cop; >+ struct fcrypt *fcr = filp->private_data; >+ unsigned int ses; >+ int ret; >+ int fd, feat; >+ >+ if (!fcr) >+ BUG(); >+ >+ switch (cmd) { >+ case CRIOGET: >+ fd = cryptodev_clonefd(filp); >+ put_user(fd, (int *) arg); >+ return IS_ERR_VALUE(fd) ? fd : 0; >+ >+ case CIOCGSESSION: >+ if (copy_from_user(&sop, (void *) arg, sizeof(sop))) { >+ printk(KERN_INFO PFX "Copy of Session data >failed" >+ "at CIOCGSESSION from user space\n"); >+ return -EFAULT; >+ } >+ ret = cryptodev_create_session(fcr, &sop); >+ if (ret) >+ return ret; >+ if (copy_to_user((void *)arg, &sop, sizeof(sop))) { >+ printk(KERN_INFO PFX "Copy of Session data >failed" >+ "at CIOCGSESSION to user space\n"); >+ return -EFAULT; >+ } >+ return 0; >+ >+ case CIOCFSESSION: >+ get_user(ses, (u32 *) arg); >+ return cryptodev_finish_session(fcr, ses); >+ >+ case CIOCCRYPT: >+ if (copy_from_user(&cop, (void *) arg, sizeof(cop))) { >+ printk(KERN_INFO PFX "Copy of src data failed" >+ "at CIOCCRYPT from user space\n"); >+ return -EFAULT; >+ } >+ ret = cryptodev_run(fcr, &cop); >+ if (copy_to_user((void *) arg, &cop, sizeof(cop))) { >+ printk(KERN_INFO PFX "Copy of enc/dec/hash data >failed" >+ "at CIOCCRYPT to user space\n"); >+ return -EFAULT; >+ } >+ return ret; >+ >+ case CIOCASYMFEAT: >+ /* No Asymmetric Algorithms Supported */ >+ feat = 0; >+ if (copy_to_user((void *)arg, &feat, sizeof(feat))) { >+ printk(KERN_INFO PFX "Copy of asymm algorithm >data" >+ " failed at CIOCASYMFEAT to user >space\n"); >+ return -EFAULT; >+ } >+ return 0; >+ >+ default: >+ printk(KERN_ERR PFX "un-supported command 0x%08X\n", >cmd); >+ return -EINVAL; >+ } >+} >+ >+struct file_operations cryptodev_fops = { >+ .owner = THIS_MODULE, >+ .open = cryptodev_open, >+ .release = cryptodev_release, >+ .ioctl = cryptodev_ioctl, >+}; >+ >+struct miscdevice cryptodev = { >+ .minor = CRYPTODEV_MINOR, couldn't you use a dynamic minor? >+ .name = "crypto", >+ .fops = &cryptodev_fops, >+}; >+ >+static int cryptodev_register(void) >+{ >+ int rc; >+ >+ rc = misc_register(&cryptodev); >+ if (rc) { >+ printk(KERN_ERR PFX "registeration of /dev/crypto >failed\n"); >+ return rc; >+ } >+ >+ return 0; >+} >+ >+static void cryptodev_deregister(void) >+{ >+ misc_deregister(&cryptodev); >+} >+ >+/********************************************************************** >********* >+ * Module init/exit >+ >************************************************************************ >******* >+ */ >+int __init init_cryptodev(void) >+{ >+ int rc; >+ >+ rc = cryptodev_register(); >+ if (rc) >+ return rc; >+ >+ printk(KERN_INFO PFX "CryptoAPI driver v%s loaded\n", >+ CRYPTODEV_UI_SUPPORT_DRIVER); >+ >+ return 0; >+} >+ >+void __exit exit_cryptodev(void) >+{ >+ cryptodev_deregister(); >+ printk(KERN_INFO PFX "CryptoAPI driver v%s unloaded\n", >+ CRYPTODEV_UI_SUPPORT_DRIVER); >+} >+ >+module_init(init_cryptodev); >+module_exit(exit_cryptodev); >+ >+MODULE_AUTHOR("Shasi Pulijala <spulijala@xxxxxxxx>"); >+MODULE_DESCRIPTION("CryptoDev driver"); >+MODULE_LICENSE("Dual BSD/GPL"); >diff --git a/fs/fcntl.c b/fs/fcntl.c >index e632da7..5afec53 100644 >--- a/fs/fcntl.c >+++ b/fs/fcntl.c >@@ -137,6 +137,7 @@ static int dupfd(struct file *file, unsigned int >start, int cloexec) > return fd; > } > >+ > asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) > { > int err = -EBADF; >@@ -193,7 +194,7 @@ out_fput: > goto out; > } > >-asmlinkage long sys_dup(unsigned int fildes) >+asmlinkage long __sys_dup(unsigned int fildes) > { > int ret = -EBADF; > struct file * file = fget(fildes); >@@ -202,6 +203,12 @@ asmlinkage long sys_dup(unsigned int fildes) > ret = dupfd(file, 0, 0); > return ret; > } >+EXPORT_SYMBOL(__sys_dup); >+ >+asmlinkage long sys_dup(unsigned int fildes) >+{ >+ return __sys_dup(fildes); >+} I don't see the difference between sys_dup() & __sys_dup() > > #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | >O_DIRECT | O_NOATIME) > >diff --git a/include/linux/cryptodev.h b/include/linux/cryptodev.h >new file mode 100644 >index 0000000..46466d4 >--- /dev/null >+++ b/include/linux/cryptodev.h >@@ -0,0 +1,119 @@ >+/********************************************************************** >********* >+ * cryptodev.h >+ * >+ * Linux CryptoAPI user space interface module >+ * >+ * Copyright (c) 2008 Shasi Pulijala <spulijala@xxxxxxxx> >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 2 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * >+ * Detail Description: >+ * This file defines ioctl structures for the Linux CryptoAPI >interface. It >+ * provides user space applications accesss into the Linux CryptoAPI >+ * functionalities. >+ * >+ >************************************************************************ >******* >+ */ >+#ifndef __CRYPTODEV_H__ >+#define __CRYPTODEV_H__ >+ >+/* Crypto and Hash Algorithms */ >+ >+#define CRYPTO_ALGORITHM_MIN 1 >+#define CRYPTO_DES_CBC 1 >+#define CRYPTO_3DES_CBC 2 >+#define CRYPTO_BLF_CBC 3 >+#define CRYPTO_CAST_CBC 4 >+#define CRYPTO_SKIPJACK_CBC 5 >+#define CRYPTO_MD5_HMAC 6 >+#define CRYPTO_SHA1_HMAC 7 >+#define CRYPTO_RIPEMD160_HMAC 8 >+#define CRYPTO_MD5_KPDK 9 >+#define CRYPTO_SHA1_KPDK 10 >+#define CRYPTO_RIJNDAEL128_CBC 11 /* 128 bit blocksize */ >+#define CRYPTO_AES_CBC 11 /* 128 bit blocksize */ >+#define CRYPTO_ARC4 12 >+#define CRYPTO_MD5 13 >+#define CRYPTO_SHA1 14 >+#define CRYPTO_NULL_HMAC 15 >+#define CRYPTO_NULL_CBC 16 >+#define CRYPTO_DEFLATE_COMP 17 /* Deflate compression >algorithm */ >+#define CRYPTO_SHA2_256_HMAC 18 >+#define CRYPTO_SHA2_384_HMAC 19 >+#define CRYPTO_SHA2_512_HMAC 20 >+#define CRYPTO_CAMELLIA_CBC 21 >+#define CRYPTO_SHA2_256 22 >+#define CRYPTO_SHA2_384 23 >+#define CRYPTO_SHA2_512 24 >+#define CRYPTO_RIPEMD160 25 >+#define CRYPTO_AES_GCM 26 >+#define CRYPTO_AES_CCM 27 >+#define CRYPTO_ALGORITHM_MAX 28 /* Keep last */ >+ >+/** >+ * @struct session_op >+ * @brief ioctl parameter to create a session >+ * >+ >************************************************************************ >******* >+ */ >+struct session_op { >+ u32 cipher; /* e.g. CRYPTO_DES_CBC >*/ >+ u32 mac; /* e.g. CRYPTO_MD5_HMAC >*/ >+ u32 keylen; /* cipher key */ >+ char *key; >+ int mackeylen; /* mac key length*/ >+ char *mackey; /* mackey(hmac)/authsize >+ (ccm, gcm) */ >+ >+ /* Return values */ >+ u32 ses; /* session ID */ >+}; >+ >+#define CRYPTO_MAX_DATA_LEN 64*1024 - 1 >+/** >+ * @struct crypt_op >+ * @brief ioctl parameter to request a crypt/decrypt operation against >a session >+ * >+ >************************************************************************ >******* >+ */ >+struct crypt_op { >+ u32 ses; >+ u16 op; /* i.e. COP_ENCRYPT */ >+#define COP_NONE 0 >+#define COP_ENCRYPT 1 >+#define COP_DECRYPT 2 >+ u16 flags; >+#define COP_F_BATCH 0x0008 /* Batch op if >possible */ >+ u_int len; >+ caddr_t src, dst; /* become sg inside >kernel */ >+ caddr_t mac; /* must be big enough >for >+ chosen MAC */ >+ caddr_t iv; >+}; >+ >+/* clone original filedescriptor */ >+#define CRIOGET _IOWR('c', 100, unsigned int) >+ >+/* create crypto session */ >+#define CIOCGSESSION _IOWR('c', 101, struct session_op) >+ >+/* finish crypto session */ >+#define CIOCFSESSION _IOW('c', 102, unsigned int) >+ >+/* request encryption/decryptions of a given buffer */ >+#define CIOCCRYPT _IOWR('c', 103, struct crypt_op) >+ >+/* ioctl()s for asym-crypto. Not yet supported. */ >+#define CIOCKEY _IOWR('c', 104, void *) >+#define CIOCASYMFEAT _IOR('c', 105, unsigned int) >+ >+#endif >diff --git a/include/linux/fs.h b/include/linux/fs.h >index b84b848..e9dc39e 100644 >--- a/include/linux/fs.h >+++ b/include/linux/fs.h >@@ -962,6 +962,7 @@ extern void __kill_fasync(struct fasync_struct *, >int, int); > > extern int __f_setown(struct file *filp, struct pid *, enum pid_type, >int force); > extern int f_setown(struct file *filp, unsigned long arg, int force); >+extern long __sys_dup(unsigned int fildes); > extern void f_delown(struct file *filp); > extern pid_t f_getown(struct file *filp); > extern int send_sigurg(struct fown_struct *fown); >-- >1.5.4.4 >-- >To unsubscribe from this list: send the line "unsubscribe linux-crypto" in >the body of a message to majordomo@xxxxxxxxxxxxxxx >More majordomo info at http://vger.kernel.org/majordomo-info.html Sebastian -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html