diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-05-26 16:11:47 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-06-17 20:47:37 +0200 |
commit | 573a4c1cb779cb410596149d51cec4b88720a12b (patch) | |
tree | 0858c6b4d77834c2963fa1ab1d9665dec399bfc9 | |
parent | 439e48a6fea573764b4a98f993510e4921f6d7f1 (diff) | |
download | cryptodev-linux-573a4c1cb779cb410596149d51cec4b88720a12b.tar.gz cryptodev-linux-573a4c1cb779cb410596149d51cec4b88720a12b.tar.xz cryptodev-linux-573a4c1cb779cb410596149d51cec4b88720a12b.zip |
Tried to introduce new api.
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | cryptodev_main.c | 53 | ||||
-rw-r--r-- | ncr.c | 141 | ||||
-rw-r--r-- | ncr.h | 325 | ||||
-rw-r--r-- | ncr_int.h | 27 |
5 files changed, 529 insertions, 19 deletions
@@ -1,7 +1,7 @@ KERNEL_DIR = /lib/modules/$(shell uname -r)/build VERSION = 0.1 -cryptodev-objs = cryptodev_main.o cryptodev_cipher.o +cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o obj-m += cryptodev.o diff --git a/cryptodev_main.c b/cryptodev_main.c index 9a1f918..9a6cb1c 100644 --- a/cryptodev_main.c +++ b/cryptodev_main.c @@ -39,6 +39,7 @@ #include <asm/ioctl.h> #include <linux/scatterlist.h> #include "cryptodev_int.h" +#include "ncr_int.h" MODULE_AUTHOR("Nikos Mavrogiannopoulos <nmav@gnutls.org>"); MODULE_DESCRIPTION("CryptoDev driver"); @@ -61,6 +62,15 @@ MODULE_PARM_DESC(enable_stats, "collect statictics about cryptodev usage"); #endif /* ====== CryptoAPI ====== */ +struct fcrypt { + struct list_head list; + struct semaphore sem; +}; + +struct crypt_priv { + void * ncr; + struct fcrypt fcrypt; +}; #define FILL_SG(sg,ptr,len) \ do { \ @@ -85,11 +95,6 @@ struct csession { #endif }; -struct fcrypt { - struct list_head list; - struct semaphore sem; -}; - /* Prepare session for future use. */ static int crypto_create_session(struct fcrypt *fcr, struct session_op *sop) @@ -494,27 +499,36 @@ out_unlock: static int cryptodev_open(struct inode *inode, struct file *filp) { - struct fcrypt *fcr; + struct crypt_priv *pcr; + int ret; - fcr = kmalloc(sizeof(*fcr), GFP_KERNEL); - if(!fcr) + pcr = kmalloc(sizeof(*pcr), GFP_KERNEL); + if(!pcr) return -ENOMEM; - memset(fcr, 0, sizeof(*fcr)); - init_MUTEX(&fcr->sem); - INIT_LIST_HEAD(&fcr->list); - filp->private_data = fcr; + memset(pcr, 0, sizeof(*pcr)); + init_MUTEX(&pcr->fcrypt->sem); + INIT_LIST_HEAD(&fcr->fcrypt->list); + + + pcr->ncr = ncr_init_lists(); + if (pcr->ncr == NULL) { + kfree(pcr); + return -ENOMEM; + } + filp->private_data = pcr; return 0; } static int cryptodev_release(struct inode *inode, struct file *filp) { - struct fcrypt *fcr = filp->private_data; + struct crypt_priv *fcr = filp->private_data; if(fcr) { crypto_finish_all_sessions(fcr); + ncr_deinit_lists(fcr->ncr); kfree(fcr); filp->private_data = NULL; } @@ -544,10 +558,16 @@ cryptodev_ioctl(struct inode *inode, struct file *filp, int __user *p = (void __user *)arg; struct session_op sop; struct crypt_op cop; - struct fcrypt *fcr = filp->private_data; + struct crypt_priv *pcr = filp->private_data; + struct fcrypt * fcr; uint32_t ses; int ret, fd; + if (unlikely(!pcr)) + BUG(); + + fcr = pcr->fcr; + if (unlikely(!fcr)) BUG(); @@ -559,19 +579,16 @@ cryptodev_ioctl(struct inode *inode, struct file *filp, fd = clonefd(filp); put_user(fd, p); return 0; - case CIOCGSESSION: ret = copy_from_user(&sop, (void*)arg, sizeof(sop)); ret |= crypto_create_session(fcr, &sop); if (unlikely(ret)) return ret; return copy_to_user((void*)arg, &sop, sizeof(sop)); - case CIOCFSESSION: get_user(ses, (uint32_t*)arg); ret = crypto_finish_session(fcr, ses); return ret; - case CIOCCRYPT: ret = copy_from_user(&cop, (void*)arg, sizeof(cop)); ret |= crypto_run(fcr, &cop); @@ -580,7 +597,7 @@ cryptodev_ioctl(struct inode *inode, struct file *filp, return copy_to_user((void*)arg, &cop, sizeof(cop)); default: - return -EINVAL; + return ncr_ioctl(file->f_cred->fsuid, pcr->ncr, cmd, arg); } } @@ -0,0 +1,141 @@ +/* + * New driver for /dev/crypto device (aka CryptoDev) + + * Copyright (c) 2009,2010 Nikos Mavrogiannopoulos <nmav@gnutls.org> + * + * This file is part of linux cryptodev. + * + * cryptodev 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 3 of the License, or + * (at your option) any later version. + * + * cryptodev 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/crypto.h> +#include <linux/mm.h> +#include <linux/highmem.h> +#include <linux/random.h> +#include "cryptodev.h" +#include <asm/uaccess.h> +#include <asm/ioctl.h> +#include <linux/scatterlist.h> +#include "ncr.h" +#include "ncr_int.h" + + + +void* ncr_init_lists(void) +{ + struct ncr_lists *lst; + int ret; + + lst = kmalloc(sizeof(*lst), GFP_KERNEL); + if(!lst) + return NULL; + + memset(lst, 0, sizeof(*lst)); + + init_MUTEX(&lst->data_sem); + INIT_LIST_HEAD(&lst->data_list); + + return lst; +} + +void ncr_deinit_lists(struct ncr_lists *lst) +{ + if(lst) { + //data_clear_all(list->data); + kfree(lst); + } + +} + +/* must be called with data semaphore down + */ +static ncr_data_t _ncr_data_get_new_desc( struct ncr_lists* lst) +{ +struct data_item* item; +int mx = 0; + + list_for_each(item, &lst->data_list) { + mx = max(mx, item->desc); + } + mx++; + + return mx; +} + +void* data_alloc(unsigned int uid, size_t size) +{ + /* FIXME: implement a maximum memory limit per user */ + if (size > 64*1024) { + return NULL; + } + return kmalloc(GPF_KERNEL, size); +} + +int ncr_data_new(unsigned int uid, struct ncr_lists* lst, void __user* arg) +{ + struct ncr_data_init_st init; + struct data_item* data; + + copy_from_user( &init, arg, sizeof(init)); + + data = kmalloc(GPF_KERNEL, sizeof(*data)); + if (data == NULL) { + return -ENOMEM; + } + + memset(data, 0, sizeof(*data)); + init_MUTEX(&data->sem); + + data->flags = init.flags; + + data->data = data_alloc(uid, init.max_data_size); + if (data->data == NULL) { + kfree(data); + return -ENOMEM; + } + data->max_data_size = init.max_data_size; + + down(lst->data_sem); + + data->desc = _ncr_data_get_new_desc(lst); + + list_add(data, &list->data_list); + + up(lst->data_sem); + + init.desc = data->desc; + +} + +int +ncr_ioctl(unsigned int uid, struct ncr_lists* lst, + unsigned int cmd, unsigned long arg) +{ + + if (unlikely(!lst)) + BUG(); + + switch (cmd) { + case NCRIO_DATA_INIT: + return ncr_data_new(uid, lst, arg); + case NCRIO_DATA_GET: + case NCRIO_DATA_SET: + case NCRIO_DATA_DEINIT: + default: + return -EINVAL; + } +} + + + @@ -0,0 +1,325 @@ +/* This is a source compatible implementation with the original API of + * cryptodev by Angelos D. Keromytis, found at openbsd cryptodev.h. + * Placed under public domain */ + +#ifndef L_NCRYPTODEV_H +#define L_NCRYPTODEV_H + +#ifndef __KERNEL__ +#include <inttypes.h> +#endif + +typedef enum { + NCR_ALG_3DES_CBC=2, + NCR_ALG_AES_CBC, + NCR_ALG_CAMELLIA_CBC, + NCR_ALG_ARCFOUR, + + NCR_ALG_SHA1=40, + NCR_ALG_MD5, + NCR_ALG_SHA2_224, + NCR_ALG_SHA2_256, + NCR_ALG_SHA2_384, + NCR_ALG_SHA2_512, + + NCR_ALG_HMAC_SHA1=80, + NCR_ALG_HMAC_MD5, + NCR_ALG_HMAC_SHA2_224, + NCR_ALG_HMAC_SHA2_256, + NCR_ALG_HMAC_SHA2_384, + NCR_ALG_HMAC_SHA2_512, +} ncr_algorithm_t; + + +typedef enum { + NCR_KEY_TYPE_SECRET=1; + NCR_KEY_TYPE_PUBLIC=2; + NCR_KEY_TYPE_PRIVATE=3; +} ncr_key_type_t; + +/* Data Handling + */ +#define NCR_DATA_FLAG_EXPORTABLE 1 +#define NCR_DATA_FLAG_SIGN_ONLY 2 /* this object can only be used with hash/sign operations */ + +typedef int ncr_data_t; +#define NCR_DATA_INVALID (ncr_data_t)(-1) + +struct ncr_data_init_st { + ncr_data_t desc; + size_t max_object_size; + unsigned int flags; +}; + +struct ncr_data_st { + ncr_data_t desc; + void* data; + size_t data_size; + unsigned int append_flag; /* only when used with NCRIO_DATA_SET */ +}; + +#define NCRIO_DATA_INIT _IOWR('c', 200, struct ncr_data_init_st) +#define NCRIO_DATA_GET _IOWR('c', 201, struct ncr_data_st) +#define NCRIO_DATA_SET _IOR('c', 202, struct ncr_data_st) +#define NCRIO_DATA_DEINIT _IOR('c', 203, ncr_data_t) + +/* Key handling + */ + +typedef int ncr_key_t; + +#define NCR_KEY_INVALID (api_key_t)(-1) + +#define NCR_KEY_FLAG_EXPORTABLE 1 +#define NCR_KEY_FLAG_WRAPPABLE (1<<1) +/* when generating a pair the flags correspond to private + * and public key usage is implicit. For example when private + * key can decrypt then public key can encrypt. If private key + * can sign then public key can verify. + */ +#define NCR_KEY_FLAG_DECRYPT (1<<2) +#define NCR_KEY_FLAG_SIGN (1<<3) + +struct ncr_key_generate_st { + ncr_key_t desc; + ncr_algorithm_t algorithm; + unsigned int bits; + unsigned int keyflags; +}; + +struct ncr_key_generate_st { + ncr_key_t desc; /* input */ + ncr_algorithm_t algorithm; /* input */ + unsigned int bits; /* input */ + +}; + +struct ncr_key_generate_params_st { + ncr_algorithm_t algorithm; + unsigned int keyflags; + union { + struct { + unsigned int bits; + } cipher; + struct { + unsigned int bits; + void* e; + size_t e_size; + } rsa; + struct { + unsigned int bits; + } dsa; + struct { + unsigned int bits; + } dh; + } params; +}; + +/* used in generation + */ +struct ncr_key_generate_st { + ncr_key_t desc; + ncr_key_t desc2; /* when called with GENERATE_PAIR */ + ncr_key_generate_params_st params; +}; + +/* used in derivation/encryption + */ +struct ncr_key_params_st { + ncr_key_t oldkey; + ncr_key_t newkey; + + unsigned int keyflags; /* for new key */ + + union { + struct { + void* iv; + size_t iv_size; + } cipher; + struct { + void * peer_public; + size_t peer_public_size; + } dh; + } params; +}; + +#define MAX_KEY_ID_SIZE 20 + +struct ncr_key_info_st { + ncr_key_t key; /* input */ + + unsigned int flags; + ncr_key_type_t type; + ncr_algorithm_t algorithm; /* valid for public/private keys */ + + uint8_t key_id[MAX_KEY_ID_SIZE]; + size_t key_id_size; +}; + +struct ncr_key_data_st { + ncr_key_t key; + ncr_data_t data; +}; + +struct ncr_public_key_params_st +{ + ncr_key_t key; + ncr_key_type_t type; + union { + struct { + void* m; + size_t m_size; + void* e; + size_t e_size; + void* p; + size_t p_size; + void* q; + size_t q_size; + void* c; + size_t c_size; + } rsa; + struct { + void* y; + size_t y_size; + void* p; + size_t p_size; + void* q; + size_t q_size; + void* g; + size_t g_size; + } dsa; + struct { + void* public; + size_t public_size; + } dh; + } params; +}; + +#define NCRIO_KEY_INIT _IOW ('c', 204, ncr_key_t) +#define NCRIO_KEY_GENERATE _IOR ('c', 205, struct ncr_key_generate_st) +#define NCRIO_KEY_GENERATE_PAIR _IOR ('c', 206, struct ncr_key_generate_st) +#define NCRIO_KEY_DERIVE _IOR ('c', 207, struct ncr_key_params_st) +#define NCRIO_KEY_GET_INFO _IOWR('c', 208, struct ncr_key_info_st) +#define NCRIO_KEY_EXPORT _IOWR('c', 209, struct ncr_key_data_st) +#define NCRIO_KEY_IMPORT _IOWR('c', 210, struct ncr_key_data_st) +#define NCRIO_KEY_GET_PUBLIC _IOWR('c', 211, struct ncr_public_key_params_st) +#define NCRIO_DATA_DEINIT _IOR ('c', 212, ncr_data_t) + + +/* Storage ioctls + */ +#define MAX_LABEL_SIZE 128 + +struct ncr_storage_st { + ncr_key_t key; + char label[MAX_LABEL_SIZE]; /* or template */ + mode_t mode; +}; + +struct ncr_storage_metadata_st { + char label[MAX_LABEL_SIZE]; + uid_t uid; + gid_t gid; + mode_t mode; + + api_algorithm_t algorithm; + api_key_type_t type; + + uint8_t key_id[MAX_KEY_ID_SIZE]; + size_t key_id_size; +}; + +struct ncr_storage_chown_st { + char label[MAX_LABEL_SIZE]; + uid_t uid; + gid_t gid; +}; + +struct ncr_storage_chmod_st { + char label[MAX_LABEL_SIZE]; + mode_t mode; +}; + +struct ncr_storage_remove_st { + char label[MAX_LABEL_SIZE]; +}; + + +#define NCRIO_STORAGE_STORE _IOW ('c', 220, struct ncr_storage_st) +#define NCRIO_STORAGE_MKSTEMP _IOR ('c', 221, struct ncr_storage_st) +#define NCRIO_STORAGE_LOAD _IOR ('c', 222, struct ncr_storage_st) +#define NCRIO_STORAGE_CHMOD _IOR ('c', 223, struct ncr_storage_chmod_st) +#define NCRIO_STORAGE_CHOWN _IOR ('c', 224, struct ncr_storage_chown_st) +#define NCRIO_STORAGE_REMOVE _IOR('c', 225, struct ncr_storage_remove_st) +#define NCRIO_STORAGE_LOAD_METADATA _IOWR ('c', 226, struct ncr_storage_metadata_st) + +struct ncr_storage_traverse_st { + int traverse_id; + ncr_storage_metadata_st metadata; +}; + + +#define NCRIO_STORAGE_TRAVERSE_INIT _IOW('c', 227, int) +#define NCRIO_STORAGE_TRAVERSE_NEXT _IOWR('c', 228, struct ncr_storage_traverse_st) +#define NCRIO_STORAGE_TRAVERSE_NEXT _IOWR('c', 229, int) + + +/* FIXME key wrap ioctls + */ + + +/* Crypto Operations ioctls + */ + +typedef enum { + NCR_OP_ENCRYPT=1, + NCR_OP_DECRYPT, + NCR_OP_DIGEST, + NCR_OP_MAC, + NCR_OP_SIGN, + NCR_OP_VERIFY, +} ncr_crypto_op_t; + +typedef int ncr_session_t; +#define NCR_SESSION_INVALID (ncr_session_t)-1 + +/* input of CIOCGSESSION */ +struct ncr_session_st { + /* input */ + ncr_algorithm_t algorithm; + ncr_key_params_st params; + ncr_key_t key; + ncr_crypto_op_t op; + + /* output */ + ncr_session_t ses; /* session identifier */ +}; + +typedef enum { + NCR_SUCCESS = 0, + NCR_ERROR_GENERIC = -1, +} ncr_error_t; + +struct ncr_session_op_st { + /* input */ + ncr_session_t ses; + + union { + struct { + ncr_data_t plaintext; + ncr_data_t ciphertext; + } cipher; + struct { + ncr_data_t text; + ncr_data_t output; + } digest; /* mac/hash/sign */ + struct { + ncr_data_t text; + ncr_data_t signature; + } verify; /* mac/hash/sign */ + } data; + + /* output */ + ncr_error_t err; +}; + diff --git a/ncr_int.h b/ncr_int.h new file mode 100644 index 0000000..4e9e25a --- /dev/null +++ b/ncr_int.h @@ -0,0 +1,27 @@ +struct data_item { + struct list_head list; + void* data; + size_t data_size; + size_t max_data_size; + struct semaphore sem; + unsigned int flags; + + ncr_data_t desc; +}; + +/* all the data associated with the open descriptor + * are here. + */ +struct ncr_lists { + struct list_head data_list; + struct semaphore data_sem; + + /* sessions */ + /* keys */ +}; + +void* ncr_init_lists(void); +void ncr_deinit_lists(struct ncr_lists *lst); + +int ncr_ioctl(struct ncr_lists* lists, + unsigned int cmd, unsigned long arg); |