diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | ncr-data.c | 20 | ||||
-rw-r--r-- | ncr-key.c | 31 | ||||
-rw-r--r-- | ncr-limits.c | 2 | ||||
-rw-r--r-- | ncr-storage-low.c | 48 | ||||
-rw-r--r-- | ncr-storage.c | 193 | ||||
-rw-r--r-- | ncr-storage.h | 37 | ||||
-rw-r--r-- | ncr.c | 28 | ||||
-rw-r--r-- | ncr.h | 69 | ||||
-rw-r--r-- | ncr_int.h | 13 |
10 files changed, 397 insertions, 47 deletions
@@ -2,7 +2,8 @@ KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build VERSION = 0.1 cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \ - ncr-data.o ncr-key.o ncr-limits.o + ncr-data.o ncr-key.o ncr-limits.o ncr-storage.o \ + ncr-storage-low.o obj-m += cryptodev.o @@ -29,12 +29,10 @@ #include "ncr.h" #include "ncr_int.h" -#define err() printk(KERN_DEBUG"ncr: %s: %d\n", __func__, __LINE__) - void ncr_data_list_deinit(struct list_sem_st* lst) { if(lst) { - struct data_item * item, *tmp; + struct data_item_st * item, *tmp; down(&lst->sem); @@ -51,7 +49,7 @@ void ncr_data_list_deinit(struct list_sem_st* lst) */ static ncr_data_t _ncr_data_get_new_desc( struct list_sem_st* lst) { -struct data_item* item; +struct data_item_st* item; int mx = 0; list_for_each_entry(item, &lst->list, list) { @@ -63,9 +61,9 @@ int mx = 0; } /* returns the data item corresponding to desc */ -struct data_item* ncr_data_item_get( struct list_sem_st* lst, ncr_data_t desc) +struct data_item_st* ncr_data_item_get( struct list_sem_st* lst, ncr_data_t desc) { -struct data_item* item; +struct data_item_st* item; down(&lst->sem); list_for_each_entry(item, &lst->list, list) { @@ -91,7 +89,7 @@ static void* data_alloc(size_t size) return kmalloc(size, GFP_KERNEL); } -void _ncr_data_item_put( struct data_item* item) +void _ncr_data_item_put( struct data_item_st* item) { if (atomic_dec_and_test(&item->refcnt)) { ncr_limits_remove(item->filp, LIMIT_TYPE_DATA); @@ -103,7 +101,7 @@ void _ncr_data_item_put( struct data_item* item) int ncr_data_init(struct file *filp, struct list_sem_st* lst, void __user* arg) { struct ncr_data_init_st init; - struct data_item* data; + struct data_item_st* data; int ret; ret = ncr_limits_add_and_check(filp, LIMIT_TYPE_DATA); @@ -158,7 +156,7 @@ int ncr_data_init(struct file *filp, struct list_sem_st* lst, void __user* arg) int ncr_data_deinit(struct list_sem_st* lst, void __user* arg) { ncr_data_t desc; - struct data_item * item, *tmp; + struct data_item_st * item, *tmp; copy_from_user( &desc, arg, sizeof(desc)); @@ -180,7 +178,7 @@ int ncr_data_deinit(struct list_sem_st* lst, void __user* arg) int ncr_data_get(struct list_sem_st* lst, void __user* arg) { struct ncr_data_st get; - struct data_item * data; + struct data_item_st * data; size_t len; int ret; @@ -219,7 +217,7 @@ cleanup: int ncr_data_set(struct list_sem_st* lst, void __user* arg) { struct ncr_data_st get; - struct data_item * data; + struct data_item_st * data; int ret; copy_from_user( &get, arg, sizeof(get)); @@ -19,7 +19,6 @@ * 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> @@ -30,14 +29,10 @@ #include "ncr.h" #include "ncr_int.h" -#define err() printk(KERN_DEBUG"ncr: %s: %d\n", __func__, __LINE__) - -static void _ncr_key_item_put( struct key_item* item); - void ncr_key_list_deinit(struct list_sem_st* lst) { if(lst) { - struct key_item * item, *tmp; + struct key_item_st * item, *tmp; down(&lst->sem); @@ -53,7 +48,7 @@ void ncr_key_list_deinit(struct list_sem_st* lst) */ static ncr_key_t _ncr_key_get_new_desc( struct list_sem_st* lst) { -struct key_item* item; +struct key_item_st* item; int mx = 0; list_for_each_entry(item, &lst->list, list) { @@ -65,9 +60,9 @@ int mx = 0; } /* returns the data item corresponding to desc */ -static struct key_item* ncr_key_item_get( struct list_sem_st* lst, ncr_key_t desc) +struct key_item_st* ncr_key_item_get( struct list_sem_st* lst, ncr_key_t desc) { -struct key_item* item; +struct key_item_st* item; down(&lst->sem); list_for_each_entry(item, &lst->list, list) { @@ -83,7 +78,7 @@ struct key_item* item; return NULL; } -static void _ncr_key_item_put( struct key_item* item) +void _ncr_key_item_put( struct key_item_st* item) { if (atomic_dec_and_test(&item->refcnt)) { ncr_limits_remove(item->filp, LIMIT_TYPE_KEY); @@ -94,7 +89,7 @@ static void _ncr_key_item_put( struct key_item* item) int ncr_key_init(struct file *filp, struct list_sem_st* lst, void __user* arg) { ncr_key_t desc; - struct key_item* key; + struct key_item_st* key; int ret; ret = ncr_limits_add_and_check(filp, LIMIT_TYPE_KEY); @@ -134,7 +129,7 @@ int ncr_key_init(struct file *filp, struct list_sem_st* lst, void __user* arg) int ncr_key_deinit(struct list_sem_st* lst, void __user* arg) { ncr_key_t desc; - struct key_item * item, *tmp; + struct key_item_st * item, *tmp; copy_from_user( &desc, arg, sizeof(desc)); @@ -160,8 +155,8 @@ int ncr_key_export(struct list_sem_st* data_lst, struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_data_st data; -struct key_item* item = NULL; -struct data_item* ditem = NULL; +struct key_item_st* item = NULL; +struct data_item_st* ditem = NULL; int ret; copy_from_user( &data, arg, sizeof(data)); @@ -227,8 +222,8 @@ int ncr_key_import(struct list_sem_st* data_lst, struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_data_st data; -struct key_item* item = NULL; -struct data_item* ditem = NULL; +struct key_item_st* item = NULL; +struct data_item_st* ditem = NULL; int ret; copy_from_user( &data, arg, sizeof(data)); @@ -303,7 +298,7 @@ fail: int ncr_key_generate(struct list_sem_st* lst, void __user* arg) { struct ncr_key_generate_st gen; -struct key_item* item = NULL; +struct key_item_st* item = NULL; int ret; size_t size; @@ -354,7 +349,7 @@ fail: int ncr_key_info(struct list_sem_st* lst, void __user* arg) { struct ncr_key_info_st info; -struct key_item* item = NULL; +struct key_item_st* item = NULL; copy_from_user( &info, arg, sizeof(info)); diff --git a/ncr-limits.c b/ncr-limits.c index 63b4d8b..857fc2e 100644 --- a/ncr-limits.c +++ b/ncr-limits.c @@ -112,7 +112,7 @@ int add = 1; list_for_each_entry(uitem, &limits.users.list, list) { if (uitem->uid == uid && uitem->type == type) { add = 0; -printk("user: %d max: %d, count: %d\n", (int)uid, max_per_user[type], atomic_read(&uitem->cnt)); + if (atomic_add_unless(&uitem->cnt, 1, max_per_user[type])==0) { err(); up(&limits.users.sem); diff --git a/ncr-storage-low.c b/ncr-storage-low.c new file mode 100644 index 0000000..d55356d --- /dev/null +++ b/ncr-storage-low.c @@ -0,0 +1,48 @@ +/* + * New driver for /dev/crypto device (aka CryptoDev) + + * Copyright (c) 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/mm.h> +#include <linux/highmem.h> +#include "cryptodev.h" +#include <asm/uaccess.h> +#include <asm/ioctl.h> +#include <linux/scatterlist.h> +#include "ncr.h" +#include "ncr_int.h" +#include "ncr-storage.h" + +/* Actual storage to somewhere function + */ +int _ncr_store(const struct storage_item_st * tostore) +{ + + +} + +/* Loading from somewhere function + */ +int _ncr_load(struct storage_item_st * loaded) +{ +/* loaded must have owner and group set. + */ + +} + diff --git a/ncr-storage.c b/ncr-storage.c new file mode 100644 index 0000000..b5db4b1 --- /dev/null +++ b/ncr-storage.c @@ -0,0 +1,193 @@ +/* + * New driver for /dev/crypto device (aka CryptoDev) + + * Copyright (c) 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/mm.h> +#include <linux/highmem.h> +#include "cryptodev.h" +#include <asm/uaccess.h> +#include <asm/ioctl.h> +#include <linux/scatterlist.h> +#include <linux/version.h> +#include "ncr.h" +#include "ncr_int.h" +#include "ncr-storage.h" + +/* Convert a ncr key to a raw one ready for storage. + */ +int _ncr_key_to_store(const struct key_item_st *key, const char* label, + mode_t mode, struct storage_item_st* output) +{ +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27) + uid_t uid = key->filp->f_uid; + gid_t gid = key->filp->f_gid; +#else + gid_t gid = key->filp->f_cred->fsgid; + gid_t gid = key->filp->f_cred->fsgid; +#endif + /* copy metadata first */ + memcpy(output->key_id, key->key_id, sizeof(output->key_id)); + output->key_id_size = key->key_id_size; + + output->algorithm = key->algorithm; + output->type = key->type; + output->owner = uid; + output->group = gid; + + strlcpy(output->label, label, sizeof(output->label)); + output->mode = mode; + + /* format is type (uint8_t) + ... */ + switch(key->type) { + case NCR_KEY_TYPE_SECRET: + /* uint16_t size + raw key */ + output->raw_key = kmalloc(sizeof(uint8_t)+sizeof(uint16_t)+MAX_KEY_SIZE, GFP_KERNEL); + if (output->raw_key == NULL) { + err(); + return -ENOMEM; + } + output->raw_key[0] = (key->key.secret.size >> 8) & 0xff; + output->raw_key[1] = (key->key.secret.size) & 0xff; + memcpy(&output->raw_key[2], key->key.secret.data, key->key.secret.size); + + return 0; + default: + return -EINVAL; + } +} + +int _ncr_store_to_key(const struct storage_item_st* raw, struct key_item_st *key) +{ + /* copy metadata first */ + memcpy(key->key_id, raw->key_id, sizeof(key->key_id)); + key->key_id_size = raw->key_id_size; + + key->algorithm = raw->algorithm; + key->type = raw->type; + + switch(key->type) { + case NCR_KEY_TYPE_SECRET: + /* uint16_t size + raw key */ + key->key.secret.size = (raw->raw_key[0] << 8) | raw->raw_key[1]; + if (key->key.secret.size > MAX_KEY_SIZE) { + err(); + return -EFAULT; + } + memcpy(key->key.secret.data, &raw->raw_key[2], key->key.secret.size); + + return 0; + default: + return -EINVAL; + } + +} + +int ncr_storage_store(struct list_sem_st* key_lst, void __user* arg) +{ + struct ncr_storage_st sinfo; + struct key_item_st * key; + struct storage_item_st tostore; + int ret; + + copy_from_user( &sinfo, arg, sizeof(sinfo)); + + key = ncr_key_item_get( key_lst, sinfo.key); + if (key == NULL) { + err(); + return -EINVAL; + } + + ret = _ncr_key_to_store(key, sinfo.label, sinfo.mode, &tostore); + if (ret < 0) { + err(); + goto fail; + } + + ret = _ncr_store(&tostore); + kfree(tostore.raw_key); + + if (ret < 0) { + err(); + goto fail; + } + + ret = 0; + +fail: + _ncr_key_item_put(key); + + return ret; +} + + +int ncr_storage_load(struct list_sem_st* key_lst, void __user* arg) +{ + gid_t gid; + uid_t uid; + struct ncr_storage_st sinfo; + struct key_item_st * key; + struct storage_item_st loaded; + int ret; + + copy_from_user( &sinfo, arg, sizeof(sinfo)); + + key = ncr_key_item_get( key_lst, sinfo.key); + if (key == NULL) { + err(); + return -EINVAL; + } + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27) + uid = key->filp->f_uid; + gid = key->filp->f_gid; +#else + gid = key->filp->f_cred->fsgid; + gid = key->filp->f_cred->fsgid; +#endif + + /* we set the current user uid and gid + * to allow permission checking + */ + loaded.owner = uid; + loaded.group = gid; + + ret = _ncr_load(&loaded); + if (ret < 0) { + err(); + goto fail; + } + + ret = _ncr_store_to_key(&loaded, key); + kfree(loaded.raw_key); + + if (ret < 0) { + err(); + goto fail; + } + + ret = 0; + +fail: + _ncr_key_item_put(key); + + return ret; +} + + diff --git a/ncr-storage.h b/ncr-storage.h new file mode 100644 index 0000000..74a5838 --- /dev/null +++ b/ncr-storage.h @@ -0,0 +1,37 @@ +#ifndef NCR_STORAGE_H +# define NCR_STORAGE_H + +struct storage_item_st { + /* metadata */ + char label[MAX_LABEL_SIZE]; + uid_t owner; + gid_t group; + mode_t mode; + + uint16_t algorithm; + uint8_t type; + + uint8_t key_id[MAX_KEY_ID_SIZE]; + uint8_t key_id_size; + + /* data */ + uint8_t * raw_key; + size_t raw_key_size; +}; + +int ncr_storage_store(struct list_sem_st* key_lst, void __user* arg); +int ncr_storage_load(struct list_sem_st* key_lst, void __user* arg); + +int ncr_storage_mkstemp(struct list_sem_st* key_lst, void __user* arg); +int ncr_storage_chmod(void __user* arg); +int ncr_storage_chown(void __user* arg); +int ncr_storage_remove(void __user* arg); +int ncr_storage_metadata_load(void __user* arg); +int ncr_storage_traverse_init(struct list_sem_st* tr_lst, void __user* arg); +int ncr_storage_traverse_next(struct list_sem_st* tr_lst, void __user* arg); +int ncr_storage_traverse_deinit(struct list_sem_st* tr_lst, void __user* arg); + +int _ncr_store(const struct storage_item_st * tostore); +int _ncr_load(struct storage_item_st * loaded); + +#endif /* NCR_STORAGE_H */ @@ -99,6 +99,34 @@ ncr_ioctl(struct ncr_lists* lst, struct file *filp, return ncr_key_derive(&lst->key, (void*)arg); case NCRIO_KEY_GET_PUBLIC: return ncr_key_get_public(&lst->key, (void*)arg); + case NCRIO_KEY_SET_PUBLIC: + return ncr_key_set_public(&lst->key, (void*)arg); + case NCRIO_KEY_GET_PRIVATE: + return ncr_key_get_private(&lst->key, (void*)arg); + case NCRIO_KEY_SET_PRIVATE: + return ncr_key_set_private(&lst->key, (void*)arg); +#endif + case NCRIO_STORAGE_STORE: + return ncr_storage_store(&lst->key, (void*)arg); + case NCRIO_STORAGE_LOAD: + return ncr_storage_load(&lst->key, (void*)arg); +#if 0 + case NCRIO_STORAGE_MKSTEMP: + return ncr_storage_mkstemp(&lst->key, (void*)arg); + case NCRIO_STORAGE_CHMOD: + return ncr_storage_chmod((void*)arg); + case NCRIO_STORAGE_CHOWN: + return ncr_storage_chown((void*)arg); + case NCRIO_STORAGE_REMOVE: + return ncr_storage_remove((void*)arg); + case NCRIO_STORAGE_LOAD_METADATA: + return ncr_storage_metadata_load((void*)arg); + case NCRIO_STORAGE_TRAVERSE_INIT: + return ncr_storage_traverse_init(&lst->traverse, (void*)arg); + case NCRIO_STORAGE_TRAVERSE_NEXT: + return ncr_storage_traverse_next(&lst->traverse, (void*)arg); + case NCRIO_STORAGE_TRAVERSE_DEINIT: + return ncr_storage_traverse_deinit(&lst->traverse, (void*)arg); #endif default: return -EINVAL; @@ -160,7 +160,7 @@ struct ncr_key_data_st { struct ncr_public_key_params_st { ncr_key_t key; - ncr_key_type_t type; + ncr_algorithm_t algorithm; union { struct { void* m; @@ -191,6 +191,48 @@ struct ncr_public_key_params_st } params; }; +struct ncr_private_key_params_st +{ + ncr_key_t key; + ncr_algorithm_t algorithm; + union { + struct { + void* m; + size_t m_size; + void* e; + size_t e_size; + void* d; + size_t d_size; + void* p; + size_t p_size; + void* q; + size_t q_size; + void* c; + size_t c_size; + void* exp1; + size_t exp1_size; + void* exp2; + size_t exp2_size; + } rsa; + struct { + void* y; + size_t y_size; + void* x; + size_t x_size; + void* p; + size_t p_size; + void* q; + size_t q_size; + void* g; + size_t g_size; + } dsa; + struct { + void* private; + size_t private_size; + } dh; + } params; +}; + #define NCRIO_KEY_INIT _IOW ('c', 204, ncr_key_t) /* generate a secret key */ #define NCRIO_KEY_GENERATE _IOR ('c', 205, struct ncr_key_generate_st) @@ -206,8 +248,11 @@ struct ncr_public_key_params_st #define NCRIO_KEY_IMPORT _IOWR('c', 210, struct ncr_key_data_st) /* return/set public /private paramters */ #define NCRIO_KEY_GET_PUBLIC _IOWR('c', 211, struct ncr_public_key_params_st) +#define NCRIO_KEY_SET_PUBLIC _IOWR('c', 212, struct ncr_public_key_params_st) +#define NCRIO_KEY_GET_PRIVATE _IOWR('c', 213, struct ncr_private_key_params_st) +#define NCRIO_KEY_SET_PRIVATE _IOWR('c', 214, struct ncr_private_key_params_st) -#define NCRIO_KEY_DEINIT _IOR ('c', 212, ncr_key_t) +#define NCRIO_KEY_DEINIT _IOR ('c', 215, ncr_key_t) /* Storage ioctls @@ -249,13 +294,13 @@ struct ncr_storage_remove_st { }; -#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) +#define NCRIO_STORAGE_STORE _IOW ('c', 230, struct ncr_storage_st) +#define NCRIO_STORAGE_MKSTEMP _IOR ('c', 231, struct ncr_storage_st) +#define NCRIO_STORAGE_LOAD _IOR ('c', 232, struct ncr_storage_st) +#define NCRIO_STORAGE_CHMOD _IOR ('c', 233, struct ncr_storage_chmod_st) +#define NCRIO_STORAGE_CHOWN _IOR ('c', 234, struct ncr_storage_chown_st) +#define NCRIO_STORAGE_REMOVE _IOR('c', 235, struct ncr_storage_remove_st) +#define NCRIO_STORAGE_LOAD_METADATA _IOWR ('c', 236, struct ncr_storage_metadata_st) struct ncr_storage_traverse_st { int traverse_id; @@ -263,9 +308,9 @@ struct ncr_storage_traverse_st { }; -#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_DEINIT _IOWR('c', 229, int) +#define NCRIO_STORAGE_TRAVERSE_INIT _IOW('c', 237, int) +#define NCRIO_STORAGE_TRAVERSE_NEXT _IOWR('c', 238, struct ncr_storage_traverse_st) +#define NCRIO_STORAGE_TRAVERSE_DEINIT _IOWR('c', 239, int) /* FIXME key wrap ioctls @@ -6,7 +6,7 @@ #define err() printk(KERN_DEBUG"ncr: %s: %d\n", __func__, __LINE__) -struct data_item { +struct data_item_st { struct list_head list; /* This object is not protected from concurrent access. * I see no reason to allow concurrent writes (reads are @@ -24,7 +24,7 @@ struct data_item { #define MAX_KEY_SIZE 32 /* in bytes */ -struct key_item { +struct key_item_st { struct list_head list; /* This object is also not protected from concurrent access. */ @@ -73,8 +73,8 @@ int ncr_data_get(struct list_sem_st*, void __user* arg); int ncr_data_deinit(struct list_sem_st*, void __user* arg); int ncr_data_init(struct file* filp, struct list_sem_st*, void __user* arg); void ncr_data_list_deinit(struct list_sem_st*); -struct data_item* ncr_data_item_get( struct list_sem_st* lst, ncr_data_t desc); -void _ncr_data_item_put( struct data_item* item); +struct data_item_st* ncr_data_item_get( struct list_sem_st* lst, ncr_data_t desc); +void _ncr_data_item_put( struct data_item_st* item); int ncr_key_init(struct file* filp, struct list_sem_st*, void __user* arg); int ncr_key_deinit(struct list_sem_st*, void __user* arg); @@ -90,6 +90,9 @@ int ncr_key_generate_pair(struct list_sem_st* lst, void __user* arg); int ncr_key_derive(struct list_sem_st*, void __user* arg); int ncr_key_get_public(struct list_sem_st* lst, void __user* arg); +struct key_item_st* ncr_key_item_get( struct list_sem_st* lst, ncr_key_t desc); +void _ncr_key_item_put( struct key_item_st* item); + typedef enum { LIMIT_TYPE_KEY, LIMIT_TYPE_DATA @@ -102,4 +105,6 @@ void ncr_limits_deinit(void); ncr_key_type_t ncr_algorithm_to_key_type(ncr_algorithm_t algo); +#include "ncr-storage.h" + #endif |