diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-07-27 13:47:06 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-07-27 13:47:06 +0200 |
commit | c0c14cb837e6ea4a1c4ec0f8888f500c78ccdbf6 (patch) | |
tree | 82f4a723fe8c0f1e4c02e044012d4fcb1a945dee | |
parent | 81633c5ffee3806a7195258122fe8e7e337c8c54 (diff) | |
download | cryptodev-linux-c0c14cb837e6ea4a1c4ec0f8888f500c78ccdbf6.tar.gz cryptodev-linux-c0c14cb837e6ea4a1c4ec0f8888f500c78ccdbf6.tar.xz cryptodev-linux-c0c14cb837e6ea4a1c4ec0f8888f500c78ccdbf6.zip |
Added Diffie Hellman key generation.
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | examples/pk.c | 79 | ||||
-rw-r--r-- | ncr-dh.c | 145 | ||||
-rw-r--r-- | ncr-dh.h | 21 | ||||
-rw-r--r-- | ncr-int.h | 3 | ||||
-rw-r--r-- | ncr-key.c | 11 | ||||
-rw-r--r-- | ncr-pk.c | 96 | ||||
-rw-r--r-- | ncr-pk.h | 2 | ||||
-rw-r--r-- | ncr-sessions.c | 2 | ||||
-rw-r--r-- | ncr.h | 17 |
10 files changed, 354 insertions, 24 deletions
@@ -67,7 +67,7 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.o cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \ - ncr-key.o ncr-limits.o ncr-pk.o ncr-sessions.o \ + ncr-key.o ncr-limits.o ncr-pk.o ncr-sessions.o ncr-dh.o \ ncr-key-wrap.o ncr-key-storage.o $(TOMMATH_OBJECTS) \ $(TOMCRYPT_OBJECTS) diff --git a/examples/pk.c b/examples/pk.c index 1aa4c5a..1385a0e 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -297,6 +297,82 @@ int pubkey_info(void* data, int data_size, int verbose) return 0; } +/* Diffie Hellman */ +const char dh_params_txt[] = "-----BEGIN DH PARAMETERS-----\n"\ +"MIGHAoGBAKMox0/IjuGqSaGMJESYMhdmXiTe1pY8gkSzWZ/ktWaUdaYAzgAZp7r3\n"\ +"OCh68YslS9Oi7/UQjmBbgGuOucMKgq3tYeYzY8G2epIuIzM4TAogaEqwkdSrXlth\n"\ +"MMsP2FhLhHg8m6V6iItitnMOz9r8t3BEf04GRlfzgZraM0gUUwTjAgEF\n"\ +"-----END DH PARAMETERS-----\n"; + +static int test_ncr_dh(int cfd) +{ +struct ncr_key_generate_st kgen; +ncr_key_t private1, public1; +int ret; +gnutls_datum g, p, params; +gnutls_dh_params_t dhp; + + fprintf(stdout, "Tests on DH key exchange:"); + fflush(stdout); + + params.data = (void*)dh_params_txt; + params.size = sizeof(dh_params_txt)-1; + + ret = gnutls_dh_params_init(&dhp); + if (ret < 0) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + fprintf(stderr, "gnutls: %s\n", gnutls_strerror(ret)); + return 1; + } + + ret = gnutls_dh_params_import_pkcs3(dhp, ¶ms, GNUTLS_X509_FMT_PEM); + if (ret < 0) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + fprintf(stderr, "gnutls: %s\n", gnutls_strerror(ret)); + return 1; + } + + ret = gnutls_dh_params_export_raw(dhp, &p, &g, NULL); + if (ret < 0) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + fprintf(stderr, "gnutls: %s\n", gnutls_strerror(ret)); + return 1; + } + + /* generate a DH key */ + if (ioctl(cfd, NCRIO_KEY_INIT, &private1)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_INIT)"); + return 1; + } + + if (ioctl(cfd, NCRIO_KEY_INIT, &public1)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_INIT)"); + return 1; + } + + memset(&kgen, 0, sizeof(kgen)); + kgen.desc = private1; + kgen.desc2 = public1; + kgen.params.algorithm = NCR_ALG_DH; + kgen.params.keyflags = NCR_KEY_FLAG_EXPORTABLE; + kgen.params.params.dh.p = p.data; + kgen.params.params.dh.p_size = p.size; + kgen.params.params.dh.g = g.data; + kgen.params.params.dh.g_size = g.size; + + if (ioctl(cfd, NCRIO_KEY_GENERATE_PAIR, &kgen)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_GENERATE)"); + return 1; + } + + fprintf(stdout, " Success\n"); + + return 0; +} + #define RSA_ENCRYPT_SIZE 32 static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oaep) @@ -726,6 +802,9 @@ main() return 1; } + if (test_ncr_dh(fd)) + return 1; + if (test_ncr_rsa(fd)) return 1; diff --git a/ncr-dh.c b/ncr-dh.c new file mode 100644 index 0000000..4741c2b --- /dev/null +++ b/ncr-dh.c @@ -0,0 +1,145 @@ +/* + * New driver for /dev/crypto device (aka CryptoDev) + + * Copyright (c) 2010 Katholieke Universiteit Leuven + * + * Author: Nikos Mavrogiannopoulos <nmav@gnutls.org> + * + * This file is part of linux cryptodev. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#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> +#include <ncr-dh.h> + +void dh_free(dh_key * key) +{ + mp_clear_multi(&key->p, &key->g, &key->x, NULL); +} + +int dh_import_params(dh_key * key, uint8_t* p, size_t p_size, uint8_t* g, size_t g_size) +{ +int ret; +int err; + + if ((err = mp_init_multi(&key->p, &key->g, &key->x, &key->y, NULL)) != CRYPT_OK) { + err(); + return -ENOMEM; + } + + if ((err = mp_read_unsigned_bin(&key->p, (unsigned char *)p, p_size)) != CRYPT_OK) { + err(); + ret = _ncr_tomerr(err); + goto fail; + } + + if ((err = mp_read_unsigned_bin(&key->g, (unsigned char *)g, g_size)) != CRYPT_OK) { + err(); + ret = _ncr_tomerr(err); + goto fail; + } + + return 0; +fail: + mp_clear_multi(&key->p, &key->g, &key->x, &key->y, NULL); + + return ret; +} + +int dh_generate_key(dh_key * key) +{ +void* buf; +int size; +int err, ret; + + size = mp_unsigned_bin_size(&key->p); + if (size == 0) { + err(); + return -EINVAL; + } + + buf = kmalloc(size, GFP_KERNEL); + if (buf == NULL) { + err(); + return -ENOMEM; + } + + get_random_bytes( buf, size); + + if ((err = mp_read_unsigned_bin(&key->x, buf, size)) != CRYPT_OK) { + err(); + ret = _ncr_tomerr(err); + goto fail; + } + + err = mp_mod( &key->g, &key->p, &key->x); + if (err != CRYPT_OK) { + err(); + ret = _ncr_tomerr(err); + goto fail; + } + + key->type = PK_PRIVATE; + + ret = 0; +fail: + kfree(buf); + + return ret; + +} + +int dh_generate_public(dh_key * public, dh_key* private) +{ +int err, ret; + + err = mp_copy(&private->g, &public->g); + if (err != CRYPT_OK) { + err(); + ret = _ncr_tomerr(err); + goto fail; + } + + err = mp_copy(&private->p, &public->p); + if (err != CRYPT_OK) { + err(); + ret = _ncr_tomerr(err); + goto fail; + } + + err = mp_exptmod(&private->g, &private->x, &private->p, &public->y); + if (err != CRYPT_OK) { + err(); + ret = _ncr_tomerr(err); + goto fail; + } + + public->type = PK_PUBLIC; + + ret = 0; +fail: + + return ret; + +} diff --git a/ncr-dh.h b/ncr-dh.h new file mode 100644 index 0000000..ba7a92b --- /dev/null +++ b/ncr-dh.h @@ -0,0 +1,21 @@ +#ifndef NCR_DH_H +# define NCR_DH_H + +#include <tomcrypt.h> + +typedef struct { + int type; /* PK_PRIVATE or PK_PUBLIC */ + mp_int p; + mp_int g; + mp_int x; /* private */ + mp_int y; /* public: y=g^x */ +} dh_key; + +int dh_generate_key(dh_key * key); +int dh_import_params(dh_key * key, uint8_t* p, size_t p_size, uint8_t* g, size_t g_size); +void dh_free(dh_key * key); +int dh_generate_public(dh_key * public, dh_key* private); + +int dh_export(uint8_t *out, size_t *outlen, int type, dh_key *key); +int dh_import(const uint8_t *in, size_t inlen, dh_key *key); +#endif @@ -5,6 +5,7 @@ #include <asm/atomic.h> #include "cryptodev_int.h" #include <ncr-pk.h> +#include <ncr-dh.h> #define KEY_DATA_MAX_SIZE 3*1024 @@ -18,6 +19,7 @@ struct algo_properties_st { unsigned can_sign:1; unsigned can_digest:1; unsigned can_encrypt:1; + unsigned can_kx:1; /* key exchange */ unsigned is_symmetric:1; unsigned is_pk:1; int digest_size; @@ -73,6 +75,7 @@ struct key_item_st { union { rsa_key rsa; dsa_key dsa; + dh_key dh; } pk; } key; @@ -510,14 +510,23 @@ int ret; err(); return ret; } + + if (item->type == NCR_KEY_TYPE_INVALID) { + err(); + ret = -EINVAL; + goto fail; + } info.flags = item->flags; info.type = item->type; info.algorithm = item->algorithm->algo; + + ret = 0; +fail: _ncr_key_item_put( item); - return 0; + return ret; } int ncr_key_generate_pair(struct list_sem_st* lst, void __user* arg) @@ -34,7 +34,7 @@ static struct workqueue_struct * pk_wq = NULL; -static int tomerr(int err) +int _ncr_tomerr(int err) { switch (err) { case CRYPT_BUFFER_OVERFLOW: @@ -57,6 +57,9 @@ void ncr_pk_clear(struct key_item_st* key) case NCR_ALG_DSA: dsa_free(&key->key.pk.dsa); break; + case NCR_ALG_DH: + dh_free(&key->key.pk.dh); + break; default: return; } @@ -81,14 +84,14 @@ static int ncr_pk_make_public_and_id( struct key_item_st * private, struct key_i cret = rsa_export(tmp, &max_size, PK_PUBLIC, &private->key.pk.rsa); if (cret != CRYPT_OK) { err(); - ret = tomerr(cret); + ret = _ncr_tomerr(cret); goto fail; } cret = rsa_import(tmp, max_size, &public->key.pk.rsa); if (cret != CRYPT_OK) { err(); - ret = tomerr(cret); + ret = _ncr_tomerr(cret); goto fail; } break; @@ -96,14 +99,21 @@ static int ncr_pk_make_public_and_id( struct key_item_st * private, struct key_i cret = dsa_export(tmp, &max_size, PK_PUBLIC, &private->key.pk.dsa); if (cret != CRYPT_OK) { err(); - ret = tomerr(cret); + ret = _ncr_tomerr(cret); goto fail; } cret = dsa_import(tmp, max_size, &public->key.pk.dsa); if (cret != CRYPT_OK) { err(); - ret = tomerr(cret); + ret = _ncr_tomerr(cret); + goto fail; + } + break; + case NCR_ALG_DH: + ret = dh_generate_public(&public->key.pk.dh, &private->key.pk.dh); + if (ret < 0) { + err(); goto fail; } break; @@ -117,7 +127,7 @@ static int ncr_pk_make_public_and_id( struct key_item_st * private, struct key_i cret = hash_memory(_ncr_algo_to_properties(NCR_ALG_SHA1), tmp, max_size, private->key_id, &key_id_size); if (cret != CRYPT_OK) { err(); - ret = tomerr(cret); + ret = _ncr_tomerr(cret); goto fail; } private->key_id_size = public->key_id_size = key_id_size; @@ -146,7 +156,7 @@ int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * pa if (cret != CRYPT_OK) { *packed_size = max_size; err(); - return tomerr(cret); + return _ncr_tomerr(cret); } break; case NCR_ALG_DSA: @@ -154,7 +164,7 @@ int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * pa if (cret != CRYPT_OK) { *packed_size = max_size; err(); - return tomerr(cret); + return _ncr_tomerr(cret); } break; default: @@ -180,14 +190,14 @@ int ncr_pk_unpack( struct key_item_st * key, const void * packed, size_t packed_ cret = rsa_import(packed, packed_size, (void*)&key->key.pk.rsa); if (cret != CRYPT_OK) { err(); - return tomerr(cret); + return _ncr_tomerr(cret); } break; case NCR_ALG_DSA: cret = dsa_import(packed, packed_size, (void*)&key->key.pk.dsa); if (cret != CRYPT_OK) { err(); - return tomerr(cret); + return _ncr_tomerr(cret); } break; default: @@ -211,7 +221,8 @@ struct keygen_st { static void keygen_handler(struct work_struct *instance) { unsigned long e; - int cret; + int cret, ret; + uint8_t * tmp = NULL; struct keygen_st *st = container_of(instance, struct keygen_st, pk_gen); @@ -224,7 +235,7 @@ static void keygen_handler(struct work_struct *instance) cret = rsa_make_key(st->params->params.rsa.bits/8, e, &st->private->key.pk.rsa); if (cret != CRYPT_OK) { err(); - st->ret = tomerr(cret); + st->ret = _ncr_tomerr(cret); } else st->ret = 0; break; @@ -238,15 +249,62 @@ static void keygen_handler(struct work_struct *instance) st->params->params.dsa.p_bits/8, &st->private->key.pk.dsa); if (cret != CRYPT_OK) { err(); - st->ret = tomerr(cret); + st->ret = _ncr_tomerr(cret); } else st->ret = 0; break; + case NCR_ALG_DH: { + uint8_t * p, *g; + size_t p_size, g_size; + + p_size = st->params->params.dh.p_size; + g_size = st->params->params.dh.g_size; + + tmp = kmalloc(g_size+p_size, GFP_KERNEL); + if (tmp == NULL) { + err(); + st->ret = -ENOMEM; + goto fail; + } + + p = tmp; + g = &tmp[p_size]; + + if (unlikely(copy_from_user(p, st->params->params.dh.p, p_size))) { + err(); + st->ret = -EFAULT; + goto fail; + } + + if (unlikely(copy_from_user(g, st->params->params.dh.g, g_size))) { + err(); + st->ret = -EFAULT; + goto fail; + } + + ret = dh_import_params(&st->private->key.pk.dh, p, p_size, g, g_size); + if (ret < 0) { + err(); + st->ret = ret; + goto fail; + } + + ret = dh_generate_key(&st->private->key.pk.dh); + if (ret < 0) { + st->ret = ret; + err(); + goto fail; + } + st->ret = 0; + break; + } default: err(); st->ret = -EINVAL; } +fail: + kfree(tmp); complete(&st->completed); } @@ -416,7 +474,7 @@ void * input, *output; if (cret != CRYPT_OK) { err(); - ret = tomerr(cret); + ret = _ncr_tomerr(cret); goto fail; } *osg_size = osize; @@ -478,7 +536,7 @@ void * input, *output; if (cret != CRYPT_OK) { err(); - ret = tomerr(cret); + ret = _ncr_tomerr(cret); goto fail; } @@ -543,7 +601,7 @@ void * input, *output; ctx->type, ctx->sign_hash, ctx->salt_len, &ctx->key->key.pk.rsa); if (cret != CRYPT_OK) { err(); - return tomerr(cret); + return _ncr_tomerr(cret); } *osg_size = osize; break; @@ -553,7 +611,7 @@ void * input, *output; if (cret != CRYPT_OK) { err(); - return tomerr(cret); + return _ncr_tomerr(cret); } *osg_size = osize; break; @@ -604,7 +662,7 @@ uint8_t* sig; ctx->salt_len, &stat, &ctx->key->key.pk.rsa); if (cret != CRYPT_OK) { err(); - ret = tomerr(cret); + ret = _ncr_tomerr(cret); goto fail; } @@ -619,7 +677,7 @@ uint8_t* sig; hash, hash_size, &stat, &ctx->key->key.pk.dsa); if (cret != CRYPT_OK) { err(); - ret = tomerr(cret); + ret = _ncr_tomerr(cret); goto fail; } @@ -51,4 +51,6 @@ int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, const struct scatterlist* sign_sg, unsigned int sign_sg_cnt, size_t sign_sg_size, const void* hash, size_t hash_size, ncr_error_t* err); +int _ncr_tomerr(int err); + #endif diff --git a/ncr-sessions.c b/ncr-sessions.c index bd68075..c5b31ac 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -201,6 +201,8 @@ static const struct algo_properties_st algo_properties[] = { .can_encrypt=1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC }, { .algo = NCR_ALG_DSA, .kstr = NULL, .is_pk = 1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC }, + { .algo = NCR_ALG_DH, .kstr = NULL, .is_pk = 1, + .can_kx=1, .key_type = NCR_KEY_TYPE_PUBLIC }, { .algo = NCR_ALG_NONE } }; @@ -39,6 +39,7 @@ typedef enum { NCR_ALG_RSA=140, NCR_ALG_DSA, + NCR_ALG_DH, /* DH as in PKCS #3 */ } ncr_algorithm_t; @@ -76,6 +77,7 @@ struct ncr_key_generate_params_st { ncr_algorithm_t algorithm; /* just a cipher algorithm when * generating secret keys */ + unsigned int keyflags; union { struct { @@ -83,14 +85,23 @@ struct ncr_key_generate_params_st { } secret; struct { unsigned int bits; - unsigned long e; + unsigned long e; /* use zero for default */ } rsa; struct { - unsigned int q_bits; + /* For DSS standard allowed values + * are: p:1024 q: 160 + * p:2048 q: 224 + * p:2048 q: 256 + * p:3072 q: 256 + */ unsigned int p_bits; + unsigned int q_bits; } dsa; struct { - unsigned int bits; + uint8_t __user *p; /* prime */ + size_t p_size; + uint8_t __user *g; /* generator */ + size_t g_size; } dh; } params; }; |