diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | ncr-key-storage.c | 9 | ||||
-rw-r--r-- | ncr-key.c | 106 | ||||
-rw-r--r-- | ncr-pk.c | 195 | ||||
-rw-r--r-- | ncr.h | 8 | ||||
-rwxr-xr-x | ncr_int.h | 15 |
6 files changed, 309 insertions, 26 deletions
@@ -65,7 +65,7 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.o libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.o libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.o cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \ - ncr-data.o ncr-key.o ncr-limits.o ncr-sessions.o \ + ncr-data.o ncr-key.o ncr-limits.o ncr-sessions.o ncr-pk.o \ ncr-key-wrap.o ncr-key-storage.o $(TOMMATH_OBJECTS) \ $(TOMCRYPT_OBJECTS) diff --git a/ncr-key-storage.c b/ncr-key-storage.c index a7b995d..bd39a33 100644 --- a/ncr-key-storage.c +++ b/ncr-key-storage.c @@ -28,8 +28,6 @@ #include "ncr_int.h" #include "cryptodev_int.h" -#define KEY_DATA_MAX_SIZE 2048 - struct packed_key { uint8_t type; uint32_t flags; @@ -61,6 +59,13 @@ int key_to_storage_data( uint8_t** sdata, size_t * sdata_size, const struct key_ if (key->type == NCR_KEY_TYPE_SECRET) { pkey->raw_size = key->key.secret.size; memcpy(pkey->raw, key->key.secret.data, pkey->raw_size); + } else if (key->type == NCR_KEY_TYPE_PRIVATE || key->type == NCR_KEY_TYPE_PUBLIC) { + pkey->raw_size = sizeof(pkey->raw); + ret = ncr_pk_pack( key, pkey->raw, &pkey->raw_size); + if (ret < 0) { + err(); + goto fail; + } } else { err(); ret = -EINVAL; @@ -20,7 +20,6 @@ */ #include <linux/mm.h> -#include <linux/highmem.h> #include <linux/random.h> #include "cryptodev.h" #include <asm/uaccess.h> @@ -29,6 +28,8 @@ #include "ncr.h" #include "ncr_int.h" +static void ncr_key_clear(struct key_item_st* item); + void ncr_key_list_deinit(struct list_sem_st* lst) { if(lst) { @@ -81,6 +82,7 @@ void _ncr_key_item_put( struct key_item_st* item) { if (atomic_dec_and_test(&item->refcnt)) { ncr_limits_remove(item->uid, item->pid, LIMIT_TYPE_KEY); + ncr_key_clear(item); kfree(item); } } @@ -299,6 +301,17 @@ fail: return ret; } +static void ncr_key_clear(struct key_item_st* item) +{ + /* clears any previously allocated parameters */ + if (item->type == NCR_KEY_TYPE_PRIVATE || + item->type == NCR_KEY_TYPE_PUBLIC) { + + ncr_pk_clear(item); + } + memset(&item->key, 0, sizeof(item->key)); +} + /* Generate a secret key */ int ncr_key_generate(struct list_sem_st* lst, void __user* arg) @@ -320,31 +333,33 @@ size_t size; return -EINVAL; } + ncr_key_clear(item); + /* we generate only secret keys */ + item->flags = gen.params.keyflags; item->type = ncr_algorithm_to_key_type(gen.params.algorithm); - if (item->type != NCR_KEY_TYPE_SECRET) { - err(); - ret = -EINVAL; - goto fail; - } + if (item->type == NCR_KEY_TYPE_SECRET) { + item->algorithm = /* arbitrary */ NCR_ALG_AES_CBC; - item->flags = gen.params.keyflags; - item->algorithm = /* arbitrary */ NCR_ALG_AES_CBC; + size = gen.params.params.secret.bits/8; + if ((gen.params.params.secret.bits % 8 != 0) || + (size > NCR_CIPHER_MAX_KEY_LEN)) { + err(); + ret = -EINVAL; + goto fail; + } + + get_random_bytes(item->key.secret.data, size); + item->key.secret.size = size; - size = gen.params.params.secret.bits/8; - if ((gen.params.params.secret.bits % 8 != 0) || - (size > NCR_CIPHER_MAX_KEY_LEN)) { + /* generate random key id */ + item->key_id_size = 5; + get_random_bytes(item->key_id, item->key_id_size); + } else { err(); ret = -EINVAL; goto fail; } - - get_random_bytes(item->key.secret.data, size); - item->key.secret.size = size; - - /* generate random key id */ - item->key_id_size = 5; - get_random_bytes(item->key_id, item->key_id_size); _ncr_key_item_put( item); @@ -386,7 +401,60 @@ int ret; /* FIXME those require public key subsystem */ int ncr_key_generate_pair(struct list_sem_st* lst, void __user* arg) { - return -EINVAL; +struct ncr_key_generate_st gen; +struct key_item_st* private = NULL; +struct key_item_st* public = NULL; +int ret; + + ret = copy_from_user( &gen, arg, sizeof(gen)); + if (unlikely(ret)) { + err(); + return ret; + } + + private = ncr_key_item_get( lst, gen.desc); + if (private == NULL) { + err(); + return -EINVAL; + } + + public = ncr_key_item_get( lst, gen.desc2); + if (public == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + + ncr_key_clear(public); + ncr_key_clear(private); + + /* we generate only secret keys */ + private->flags = public->flags = gen.params.keyflags; + public->type = ncr_algorithm_to_key_type(gen.params.algorithm); + private->type = NCR_KEY_TYPE_PRIVATE; + private->algorithm = public->algorithm = gen.params.algorithm; + public->flags |= (NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE); + + if (public->type == NCR_KEY_TYPE_PUBLIC) { + ret = ncr_pk_generate(gen.params.algorithm, &gen.params, private, public); + + if (ret < 0) { + err(); + goto fail; + } + } else { + err(); + ret = -EINVAL; + goto fail; + } + + ret = 0; +fail: + if (public) + _ncr_key_item_put(public); + if (private) + _ncr_key_item_put(private); + return ret; } int ncr_key_derive(struct list_sem_st* lst, void __user* arg) diff --git a/ncr-pk.c b/ncr-pk.c new file mode 100644 index 0000000..4cc2d23 --- /dev/null +++ b/ncr-pk.c @@ -0,0 +1,195 @@ +/* + * 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/random.h> +#include "cryptodev.h" +#include <asm/uaccess.h> +#include <asm/ioctl.h> +#include <linux/scatterlist.h> +#include "ncr.h" +#include "ncr_int.h" +#include <tomcrypt.h> + +static int tomerr(int err) +{ + switch (err) { + case CRYPT_BUFFER_OVERFLOW: + return -EOVERFLOW; + case CRYPT_MEM: + return -ENOMEM; + default: + return -EINVAL; + } +} + +void ncr_pk_clear(struct key_item_st* key) +{ + switch(key->algorithm) { + case NCR_ALG_RSA: + rsa_free(&key->key.pk.rsa); + break; + case NCR_ALG_DSA: + dsa_free(&key->key.pk.dsa); + break; + default: + return; + } +} + +static int ncr_pk_make_public_and_id( struct key_item_st * private, struct key_item_st * public) +{ + uint8_t * tmp; + long max_size; + int ret, cret; + unsigned long key_id_size = MAX_KEY_ID_SIZE; + + max_size = KEY_DATA_MAX_SIZE; + tmp = kmalloc(max_size, GFP_KERNEL); + if (tmp == NULL) { + err(); + return -ENOMEM; + } + + switch(private->algorithm) { + case NCR_ALG_RSA: + cret = rsa_export(tmp, &max_size, PK_PUBLIC, &private->key.pk.rsa); + if (cret != CRYPT_OK) { + err(); + ret = tomerr(cret); + goto fail; + } + + cret = rsa_import(tmp, max_size, &public->key.pk.rsa); + if (cret != CRYPT_OK) { + err(); + ret = tomerr(cret); + goto fail; + } + break; + case NCR_ALG_DSA: + cret = dsa_export(tmp, &max_size, PK_PUBLIC, &private->key.pk.dsa); + if (cret != CRYPT_OK) { + err(); + ret = tomerr(cret); + goto fail; + } + + cret = dsa_import(tmp, max_size, &public->key.pk.dsa); + if (cret != CRYPT_OK) { + err(); + ret = tomerr(cret); + goto fail; + } + break; + default: + err(); + ret = -EINVAL; + goto fail; + } + + cret = hash_memory(NCR_ALG_SHA1, tmp, max_size, private->key_id, &key_id_size); + if (cret != CRYPT_OK) { + err(); + ret = tomerr(cret); + goto fail; + } + private->key_id_size = public->key_id_size = key_id_size; + memcpy(public->key_id, private->key_id, key_id_size); + + ret = 0; +fail: + kfree(tmp); + + return ret; +} + +int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * packed_size) +{ + long max_size = *packed_size; + int cret; + + switch(key->algorithm) { + case NCR_ALG_RSA: + cret = rsa_export(packed, &max_size, key->key.pk.rsa.type, (void*)&key->key.pk.rsa); + if (cret != CRYPT_OK) { + *packed_size = max_size; + err(); + return tomerr(cret); + } + break; + case NCR_ALG_DSA: + cret = dsa_export(packed, &max_size, key->key.pk.dsa.type, (void*)&key->key.pk.dsa); + if (cret != CRYPT_OK) { + *packed_size = max_size; + err(); + return tomerr(cret); + } + break; + default: + err(); + return -EINVAL; + } + + *packed_size = max_size; + return 0; +} + +int ncr_pk_generate(ncr_algorithm_t algo, + struct ncr_key_generate_params_st * params, + struct key_item_st* private, struct key_item_st* public) +{ +int cret, ret; +unsigned long e; + private->algorithm = public->algorithm = algo; + + switch(algo) { + case NCR_ALG_RSA: + e = params->params.rsa.e; + + if (e == 0) + e = 65537; + cret = rsa_make_key(params->params.rsa.bits, e, &private->key.pk.rsa); + if (cret != CRYPT_OK) { + err(); + return tomerr(cret); + } + + break; + case NCR_ALG_DSA: + cret = dsa_make_key(params->params.dsa.q_bits, params->params.dsa.p_bits, &private->key.pk.dsa); + if (cret != CRYPT_OK) { + err(); + return tomerr(cret); + } + break; + default: + return -EINVAL; + } + + ret = ncr_pk_make_public_and_id(private, public); + if (ret < 0) { + err(); + return ret; + } + + return 0; +} @@ -106,11 +106,11 @@ struct ncr_key_generate_params_st { } secret; struct { unsigned int bits; - void* e; - size_t e_size; + unsigned long e; } rsa; struct { - unsigned int bits; + unsigned int q_bits; + unsigned int p_bits; } dsa; struct { unsigned int bits; @@ -122,7 +122,7 @@ struct ncr_key_generate_params_st { */ struct ncr_key_generate_st { ncr_key_t desc; - ncr_key_t desc2; /* when called with GENERATE_PAIR */ + ncr_key_t desc2; /* public key when called with GENERATE_PAIR */ struct ncr_key_generate_params_st params; }; @@ -4,6 +4,9 @@ #include "ncr.h" #include <asm/atomic.h> #include "cryptodev_int.h" +#include <tomcrypt.h> + +#define KEY_DATA_MAX_SIZE 3*1024 #define err() printk(KERN_DEBUG"ncr: %s: %s: %d\n", __FILE__, __func__, __LINE__) @@ -54,6 +57,10 @@ struct key_item_st { uint8_t data[NCR_CIPHER_MAX_KEY_LEN]; size_t size; } secret; + union { + rsa_key rsa; + dsa_key dsa; + } pk; } key; atomic_t refcnt; @@ -174,4 +181,12 @@ inline static unsigned int data_flags_to_key(unsigned int data_flags) const char* _ncr_algo_to_str(ncr_algorithm_t algo); int _ncr_algo_digest_size(ncr_algorithm_t algo); +/* PK */ +void ncr_pk_clear(struct key_item_st* key); +int ncr_pk_generate(ncr_algorithm_t algo, + struct ncr_key_generate_params_st * params, + struct key_item_st* private, struct key_item_st* public); +int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * packed_size); + + #endif |