* [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support [not found] ` <DB599F406D04E34389140B7D99C71B1B055EE6B2@SDCEXCHANGE01.ad.amcc.com> @ 2008-05-14 0:00 ` Loc Ho 2008-05-14 10:32 ` Sebastian Siewior 2008-05-14 11:25 ` Evgeniy Polyakov 0 siblings, 2 replies; 13+ messages in thread From: Loc Ho @ 2008-05-14 0:00 UTC (permalink / raw) To: Shasi Pulijala, herbert; +Cc: linux-crypto Hi Herbert, 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. 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. -Loc >From 926bbdedff99b1e8bb25cd685cb7249ba21729d9 Mon Sep 17 00:00:00 2001 From: Shasi Pulijala <spulijala@amcc.com> Date: Thu, 8 May 2008 11:08:26 -0700 Subject: [PATCH] Add CryptoAPI User Interface Support Signed-off-by: Shasi Pulijala <spulijala@amcc.com> --- 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@amcc.com> + * + * 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> +#include <asm-powerpc/unistd.h> + +/********************************************************************** ********* + * Forward declaration + ************************************************************************ ******* + */ +#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)", +}; + +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; +} + +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, + .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@amcc.com>"); +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); +} #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@amcc.com> + * + * 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 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support 2008-05-14 0:00 ` [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support Loc Ho @ 2008-05-14 10:32 ` Sebastian Siewior 2008-05-14 11:03 ` Herbert Xu 2008-05-14 11:25 ` Evgeniy Polyakov 1 sibling, 1 reply; 13+ messages in thread From: Sebastian Siewior @ 2008-05-14 10:32 UTC (permalink / raw) To: Loc Ho; +Cc: Shasi Pulijala, herbert, linux-crypto * 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@amcc.com> >Date: Thu, 8 May 2008 11:08:26 -0700 >Subject: [PATCH] Add CryptoAPI User Interface Support > > >Signed-off-by: Shasi Pulijala <spulijala@amcc.com> >--- > 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@amcc.com> >+ * >+ * 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@amcc.com>"); >+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@amcc.com> >+ * >+ * 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@vger.kernel.org >More majordomo info at http://vger.kernel.org/majordomo-info.html Sebastian ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support 2008-05-14 10:32 ` Sebastian Siewior @ 2008-05-14 11:03 ` Herbert Xu 2008-05-14 11:57 ` Userspace API proposal was: " Sebastian Siewior 2008-05-14 15:04 ` [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support Loc Ho 0 siblings, 2 replies; 13+ messages in thread From: Herbert Xu @ 2008-05-14 11:03 UTC (permalink / raw) To: Sebastian Siewior; +Cc: Loc Ho, Shasi Pulijala, linux-crypto On Wed, May 14, 2008 at 12:32:24PM +0200, Sebastian Siewior wrote: > > >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? I don't think compatibility with OCF is necessary at all. We should create an interface that is suitable for Linux first of all rather than concentrating on OCF. Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt ^ permalink raw reply [flat|nested] 13+ messages in thread
* Userspace API proposal was: Re: [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support 2008-05-14 11:03 ` Herbert Xu @ 2008-05-14 11:57 ` Sebastian Siewior 2008-05-14 12:18 ` Evgeniy Polyakov 2008-05-14 15:04 ` [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support Loc Ho 1 sibling, 1 reply; 13+ messages in thread From: Sebastian Siewior @ 2008-05-14 11:57 UTC (permalink / raw) To: Herbert Xu; +Cc: Loc Ho, Shasi Pulijala, linux-crypto * Herbert Xu | 2008-05-14 19:03:11 [+0800]: >On Wed, May 14, 2008 at 12:32:24PM +0200, Sebastian Siewior wrote: >> >> >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? > >I don't think compatibility with OCF is necessary at all. We >should create an interface that is suitable for Linux first of >all rather than concentrating on OCF. Great. Here a few ideas for a new interface: - /dev/crypto: - open file, creates a new ctx which may be one of crypto/hash/... - set type via ioctl / netlink - set key / other attributes via ioctl - put a block for encryption via write() - wait until it is done. poll() could be used to determine this state - read the result via read(). - ->final() (hash) could be executed on read() - cryptofs attempt (somehow inspired by spufs): - 1 syscall to create a special crypto device (that is aes(cbc), hmac(sha1) or what ever the crypto api offers). - returns a handle and creates a unique folder in cryptfs - the folder is RW to the owner - and contains properties of the algorithm. So we write in the file keysize to specify the size of the key and write to the file key to set the key. This properties are based on the class of the algorithm (should be almost equal I guess). - Every crypto request will be created once a file in the request folder is created. Request is fed with data via the write(). - I'm not sure how we signalize that a request is done. Maybe another file pops up and we can track this via inotify. So I put this two for discussion :) I came up with those two a while ago but never wrote code because I had no use case. > >Cheers, Sebastian ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Userspace API proposal was: Re: [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support 2008-05-14 11:57 ` Userspace API proposal was: " Sebastian Siewior @ 2008-05-14 12:18 ` Evgeniy Polyakov 2008-05-14 15:40 ` Loc Ho 0 siblings, 1 reply; 13+ messages in thread From: Evgeniy Polyakov @ 2008-05-14 12:18 UTC (permalink / raw) To: Sebastian Siewior; +Cc: Herbert Xu, Loc Ho, Shasi Pulijala, linux-crypto On Wed, May 14, 2008 at 01:57:30PM +0200, Sebastian Siewior (linux-crypto@ml.breakpoint.cc) wrote: > Great. Here a few ideas for a new interface: > - /dev/crypto: > - open file, creates a new ctx which may be one of crypto/hash/... > - set type via ioctl / netlink > - set key / other attributes via ioctl > - put a block for encryption via write() > - wait until it is done. poll() could be used to determine this state > - read the result via read(). > - ->final() (hash) could be executed on read() Above but without special device, but syscall instead, which will have all needed parameters like mode string, key, iv and sizes. > - cryptofs attempt (somehow inspired by spufs): > - 1 syscall to create a special crypto device (that is aes(cbc), > hmac(sha1) or what ever the crypto api offers). > - returns a handle and creates a unique folder in cryptfs > - the folder is RW to the owner > - and contains properties of the algorithm. So we write in the file > keysize to specify the size of the key and write to the file key to > set the key. This properties are based on the class of the algorithm > (should be almost equal I guess). > - Every crypto request will be created once a file in the request > folder is created. Request is fed with data via the write(). > - I'm not sure how we signalize that a request is done. Maybe another > file pops up and we can track this via inotify. > > So I put this two for discussion :) > I came up with those two a while ago but never wrote code because I had > no use case. Well, it might be time to start :) I'm not sure virtual filesystem is needed though, but as well can be a good idea. At least not ioctl hell with /dev/crypto -- Evgeniy Polyakov ^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: Userspace API proposal was: Re: [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support 2008-05-14 12:18 ` Evgeniy Polyakov @ 2008-05-14 15:40 ` Loc Ho 2008-05-14 16:09 ` Evgeniy Polyakov 0 siblings, 1 reply; 13+ messages in thread From: Loc Ho @ 2008-05-14 15:40 UTC (permalink / raw) To: Evgeniy Polyakov, Sebastian Siewior, Herbert Xu Cc: Shasi Pulijala, linux-crypto Hi, We here would like to create an user space interface that can be accepted into Linux CryptoAPI. Therefore, let me summary the current suggestion: Option #1: 1. Use file descriptor named '/dev/crypto' or use syscall 2. Each opened file creates a new 'crypto' context that represents a crypto algorithms - crypto, hash, compression, etc 3. The type of algorithm (#2) is selected via IO control call - like I/O control with algorithm ASCII name 4. The key and other attributes are set via I/O control 5. Operation such as encrypt, decrypt, hash, and etc are operated via function write and read. Caller is expected to read the entire result blocks. If not, failed with an error code. 6. It supports asyncrhonous as file descriptor can be in non-blocking mode 7. For hash and possible other operation, a read will also execute final. I don't like this unless it is preceded with a flush call. Option #2: 1. Use syscall with algorithm name and its associated parameters 2. Operation such as encrypt, decrypt, hash, and etc are operated via another two system call - crypto_read and crypto_write 3. For this option, how should one handle asynchronous operation??? Option #3: 1. Use syscall to create a special crypto device folder per an algorithm 2. A handle is returned and a crypto filesystem entry is create for that handle 3. Crypto parameter can be set based on read/write on that folder 4. Crypto operation will be based on file created under that folder. It will inherit all crypto attributes of that folder. 5. And etc... (See previous email) 6. This approach is overkill and totally unnecessary. Does this email summary all suggested solution? If not please add to this list. Which one will like be accepted into the crypto tree??? -Loc ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Userspace API proposal was: Re: [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support 2008-05-14 15:40 ` Loc Ho @ 2008-05-14 16:09 ` Evgeniy Polyakov 2008-05-15 20:16 ` Linux CryptoAPI Userspace API proposal Loc Ho 0 siblings, 1 reply; 13+ messages in thread From: Evgeniy Polyakov @ 2008-05-14 16:09 UTC (permalink / raw) To: Loc Ho; +Cc: Sebastian Siewior, Herbert Xu, Shasi Pulijala, linux-crypto Hi. On Wed, May 14, 2008 at 08:40:43AM -0700, Loc Ho (lho@amcc.com) wrote: > Option #2: > 1. Use syscall with algorithm name and its associated parameters > 2. Operation such as encrypt, decrypt, hash, and etc are operated via > another two system call - crypto_read and crypto_write > 3. For this option, how should one handle asynchronous operation??? No need to read/write syscall, initialization one returns a file descriptor, which can be read/written via usual read/write calls. It is also pollable. > Option #3: > > 1. Use syscall to create a special crypto device folder per an algorithm > 2. A handle is returned and a crypto filesystem entry is create for that > handle > 3. Crypto parameter can be set based on read/write on that folder > 4. Crypto operation will be based on file created under that folder. It > will inherit all crypto attributes of that folder. > 5. And etc... (See previous email) > 6. This approach is overkill and totally unnecessary. > > Does this email summary all suggested solution? If not please add to > this list. Which one will like be accepted into the crypto tree??? Essentially it is the same as second one, but with aditional eye-candies like simplified key management (some file in some dir written and key is being changed). Belive me, there will be always people, who do not like your interface, whatever one you will create, with second or third approach such number will be smaller, so just create what you like and prove your point is strong. New interfaces is such a tasty ground for empty talks :) -- Evgeniy Polyakov ^ permalink raw reply [flat|nested] 13+ messages in thread
* Linux CryptoAPI Userspace API proposal 2008-05-14 16:09 ` Evgeniy Polyakov @ 2008-05-15 20:16 ` Loc Ho 2008-05-20 4:00 ` Herbert Xu 0 siblings, 1 reply; 13+ messages in thread From: Loc Ho @ 2008-05-15 20:16 UTC (permalink / raw) To: Evgeniy Polyakov, Herbert Xu Cc: Sebastian Siewior, Shasi Pulijala, linux-crypto Hi, Linux Crypto User Space Interface Requirement: 1. Support crypto and hashing/digest 2. Flexible to support compression in the future 3. Flexible to support PKA (public key acceleration) in the future 4. A file descriptor per algorithms 5. Key and algorithm attributes provided by user space application (caller) 6. Support non-blocking and blocking mode 7. Support multiple operation requests concurrently 8. Support cancel a pending operation for user space caller 9. Flexible to avoid double memory copy for future 10. scalable - meaning can operate on large amount of data if the underlying algorithm support it. Hardware algorithm (such as HMAC hashing) have a limit. This requirement complicate the interface. May not support initially. Linux Crypto User Space Interface Proposal: 1. Use file descriptor named '/dev/crypto' 2. Each opened file creates a new 'crypto' context that represents a crypto algorithms - crypto, hash, compression, PKA, and etc 3. The type of algorithm, key, and other attributes are selected via IO control call. This will be a single call. 4. Algorithm name maps directly into Linux CryptoAPI algorithm name 5. Interface for per operation (such as encrypt, decrypt, compress, PKA, and hashing) 5a. Read and write functions 5a.1. Read and write functions are stream based. We are packet based. Using this interface isn't quite appropriate. In addition, the input data also has an output data. Read and write doesn't quite correlate properly. This can be a problem as the output buffer isn't available until the read operation is performed. In addition, the caller will have to correlate between the write and read. If it is AIO, then this would be simpler to correlate but still doesn't solve the problem with an output buffer requirement. For crypto, the output can be the input buffer. But what about hashing operation. This model just does fit well. In addition, for PKA, input operands are bundled into a single byte array. This makes it difficults to understand. 5b. I/O control calls 5b.1. The objection to this is 'I/O control hell'. This isn't that bad. To handle asynchronous I/O, once can implement asynchronous I/O control. 5c. System calls 5c.1. This can be used if majority of the community don't like to use I/O control. The first input will be the file descriptor. Any comments or objection? Herbert, I haven't heard your comment. What do you think? -Loc ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Linux CryptoAPI Userspace API proposal 2008-05-15 20:16 ` Linux CryptoAPI Userspace API proposal Loc Ho @ 2008-05-20 4:00 ` Herbert Xu 2008-06-04 21:33 ` Loc Ho 0 siblings, 1 reply; 13+ messages in thread From: Herbert Xu @ 2008-05-20 4:00 UTC (permalink / raw) To: Loc Ho; +Cc: Evgeniy Polyakov, Sebastian Siewior, Shasi Pulijala, linux-crypto On Thu, May 15, 2008 at 01:16:03PM -0700, Loc Ho wrote: > > Linux Crypto User Space Interface Requirement: > > 1. Support crypto and hashing/digest > 2. Flexible to support compression in the future > 3. Flexible to support PKA (public key acceleration) in the future I think extensibility as you've noted is really important. As the crypto API is really an algorithm API, please make this interface generic enough so that adding new (potentially non-crypto) operations is easy. > 4. A file descriptor per algorithms > 5. Key and algorithm attributes provided by user space application > (caller) I would say that a file descriptor per tfm would make more sense. > 8. Support cancel a pending operation for user space caller We don't need to be able to cancel a specific operation. The ability to free a tfm and thereby flushing all requests associated with it should be enough. > 3. The type of algorithm, key, and other attributes are selected via IO > control call. This will be a single call. Being a single call doesn't matter too much here because this is the slow path. > 5. Interface for per operation (such as encrypt, decrypt, compress, PKA, > and hashing) It might be useful to consider an interface that allowed in-place operations. Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt ^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: Linux CryptoAPI Userspace API proposal 2008-05-20 4:00 ` Herbert Xu @ 2008-06-04 21:33 ` Loc Ho 0 siblings, 0 replies; 13+ messages in thread From: Loc Ho @ 2008-06-04 21:33 UTC (permalink / raw) To: Herbert Xu; +Cc: Shasi Pulijala, linux-crypto Hi Herbert, We re-work part of the user space API. I would like to run it by you for comment: The Linux CryptoAPI User Interface behaves as follow: 1. User access via file descriptor /dev/crypto 2. Each opened file dscriptor represents a tfm 3. Algorithm and properties are set via an I/O control function call. 4. Algorithm name is string based and other properties are the same as before 5. Use I/O control for per operation such as encrypt, decrypt, compress, PKA, and hashing. 5a. Synchrnous call supports only (for the moment) as asynchronous requires notification and complicates the design 5b. Operation destinction/result is byte pointer based, which can be in-line 5c. Use direct I/O (no memory copy between user space and kernel space, except key, hash result, IV, and associated data) We will be submitting soon... -Loc -----Original Message----- From: Herbert Xu [mailto:herbert@gondor.apana.org.au] Sent: Monday, May 19, 2008 9:01 PM To: Loc Ho Cc: Evgeniy Polyakov; Sebastian Siewior; Shasi Pulijala; linux-crypto@vger.kernel.org Subject: Re: Linux CryptoAPI Userspace API proposal On Thu, May 15, 2008 at 01:16:03PM -0700, Loc Ho wrote: > > Linux Crypto User Space Interface Requirement: > > 1. Support crypto and hashing/digest > 2. Flexible to support compression in the future 3. Flexible to > support PKA (public key acceleration) in the future I think extensibility as you've noted is really important. As the crypto API is really an algorithm API, please make this interface generic enough so that adding new (potentially non-crypto) operations is easy. > 4. A file descriptor per algorithms > 5. Key and algorithm attributes provided by user space application > (caller) I would say that a file descriptor per tfm would make more sense. > 8. Support cancel a pending operation for user space caller We don't need to be able to cancel a specific operation. The ability to free a tfm and thereby flushing all requests associated with it should be enough. > 3. The type of algorithm, key, and other attributes are selected via > IO control call. This will be a single call. Being a single call doesn't matter too much here because this is the slow path. > 5. Interface for per operation (such as encrypt, decrypt, compress, > PKA, and hashing) It might be useful to consider an interface that allowed in-place operations. ^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support 2008-05-14 11:03 ` Herbert Xu 2008-05-14 11:57 ` Userspace API proposal was: " Sebastian Siewior @ 2008-05-14 15:04 ` Loc Ho 2008-05-14 16:01 ` Herbert Xu 1 sibling, 1 reply; 13+ messages in thread From: Loc Ho @ 2008-05-14 15:04 UTC (permalink / raw) To: Herbert Xu, Sebastian Siewior; +Cc: Shasi Pulijala, linux-crypto Hi, Yes... It is intended not to patch OpenSSL twice. Besides the interface API, the internal does NOT resemble OCF in anyway. -Loc -----Original Message----- From: Herbert Xu [mailto:herbert@gondor.apana.org.au] Sent: Wednesday, May 14, 2008 4:03 AM To: Sebastian Siewior Cc: Loc Ho; Shasi Pulijala; linux-crypto@vger.kernel.org Subject: Re: [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support On Wed, May 14, 2008 at 12:32:24PM +0200, Sebastian Siewior wrote: > > >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? I don't think compatibility with OCF is necessary at all. We should create an interface that is suitable for Linux first of all rather than concentrating on OCF. Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support 2008-05-14 15:04 ` [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support Loc Ho @ 2008-05-14 16:01 ` Herbert Xu 0 siblings, 0 replies; 13+ messages in thread From: Herbert Xu @ 2008-05-14 16:01 UTC (permalink / raw) To: Loc Ho; +Cc: Sebastian Siewior, Shasi Pulijala, linux-crypto On Wed, May 14, 2008 at 08:04:22AM -0700, Loc Ho wrote: > Hi, > > Yes... It is intended not to patch OpenSSL twice. Besides the interface > API, the internal does NOT resemble OCF in anyway. But it's exactly the interface that would tie us down to OCF. For instance, we use strings to locate algorithms rather than hard-coded integer IDs. Compatibility with an interface that was never part of the Linux kernel is simply not an issue. Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support 2008-05-14 0:00 ` [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support Loc Ho 2008-05-14 10:32 ` Sebastian Siewior @ 2008-05-14 11:25 ` Evgeniy Polyakov 1 sibling, 0 replies; 13+ messages in thread From: Evgeniy Polyakov @ 2008-05-14 11:25 UTC (permalink / raw) To: Loc Ho; +Cc: Shasi Pulijala, herbert, linux-crypto On Tue, May 13, 2008 at 05:00:58PM -0700, Loc Ho (lho@amcc.com) wrote: > Hi Herbert, > > 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. > 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. There is number of problems with this patchset: 1. codying style - likely the most harmless 2. on-stack allocation should be dropped where possible 3. session id can be generated as pointer to session, not via getting random bytes in a loop 4. linked list of in-flight session really does not scale 5. session destruction seems to be racy 6. do not use semaphores, mutex works ok here 7. lots of kmalloc/copy_*_user also much slower than single bigger allocation and sinegle copy_*_user 8. use kzalloc instead of kmalloc/memset 9. having pointer in structure shared between kernel and userspace is very wrong 10. userspace does not know about u32 and friends, use __u32 abd others instead Please also provide a high-level description of the protocol used for crypto processing. -- Evgeniy Polyakov ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2008-06-04 21:33 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <DB599F406D04E34389140B7D99C71B1B055EE51E@SDCEXCHANGE01.ad.amcc.com>
[not found] ` <0CA0A16855646F4FA96D25A158E299D60301C29D@SDCEXCHANGE01.ad.amcc.com>
[not found] ` <DB599F406D04E34389140B7D99C71B1B055EE6B2@SDCEXCHANGE01.ad.amcc.com>
2008-05-14 0:00 ` [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support Loc Ho
2008-05-14 10:32 ` Sebastian Siewior
2008-05-14 11:03 ` Herbert Xu
2008-05-14 11:57 ` Userspace API proposal was: " Sebastian Siewior
2008-05-14 12:18 ` Evgeniy Polyakov
2008-05-14 15:40 ` Loc Ho
2008-05-14 16:09 ` Evgeniy Polyakov
2008-05-15 20:16 ` Linux CryptoAPI Userspace API proposal Loc Ho
2008-05-20 4:00 ` Herbert Xu
2008-06-04 21:33 ` Loc Ho
2008-05-14 15:04 ` [PATCH 1/1] RFC: Add CryptoAPI User Space Interface Support Loc Ho
2008-05-14 16:01 ` Herbert Xu
2008-05-14 11:25 ` Evgeniy Polyakov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox