summaryrefslogtreecommitdiff
path: root/lib/nettle
diff options
context:
space:
mode:
Diffstat (limited to 'lib/nettle')
-rw-r--r--lib/nettle/Makefile.am7
-rw-r--r--lib/nettle/ecc.h123
-rw-r--r--lib/nettle/ecc_free.c40
-rw-r--r--lib/nettle/ecc_make_key.c125
-rw-r--r--lib/nettle/ecc_shared_secret.c80
-rw-r--r--lib/nettle/ecc_sign_hash.c103
-rw-r--r--lib/nettle/ecc_test.c125
-rw-r--r--lib/nettle/ecc_verify_hash.c135
-rw-r--r--lib/nettle/gnettle.h2
-rw-r--r--lib/nettle/ltc_ecc_map.c73
-rw-r--r--lib/nettle/ltc_ecc_mulmod.c141
-rw-r--r--lib/nettle/ltc_ecc_points.c60
-rw-r--r--lib/nettle/ltc_ecc_projective_add_point.c195
-rw-r--r--lib/nettle/ltc_ecc_projective_dbl_point.c146
-rw-r--r--lib/nettle/mp_unsigned_bin.c28
-rw-r--r--lib/nettle/mpi.c2
-rw-r--r--lib/nettle/multi.c46
-rw-r--r--lib/nettle/pk.c131
-rw-r--r--lib/nettle/rnd.c10
-rw-r--r--lib/nettle/rnd.h2
20 files changed, 1568 insertions, 6 deletions
diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am
index e902e774d5..0516800762 100644
--- a/lib/nettle/Makefile.am
+++ b/lib/nettle/Makefile.am
@@ -34,4 +34,9 @@ endif
noinst_LTLIBRARIES = libcrypto.la
-libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c init.c egd.c egd.h
+libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c init.c egd.c egd.h \
+ multi.c ecc_free.c ecc.h ecc_make_key.c ecc_shared_secret.c \
+ ecc_test.c ltc_ecc_map.c \
+ ltc_ecc_mulmod.c ltc_ecc_points.c \
+ ltc_ecc_projective_add_point.c ltc_ecc_projective_dbl_point.c \
+ mp_unsigned_bin.c ecc_sign_hash.c ecc_verify_hash.c
diff --git a/lib/nettle/ecc.h b/lib/nettle/ecc.h
new file mode 100644
index 0000000000..0ba3b0b08c
--- /dev/null
+++ b/lib/nettle/ecc.h
@@ -0,0 +1,123 @@
+#include <gmp.h>
+#include <nettle/nettle-types.h>
+#include <nettle/dsa.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#define LTC_MECC
+#define ECC256
+
+#define PK_PRIVATE 1
+#define PK_PUBLIC 2
+
+/* ---- ECC Routines ---- */
+/* size of our temp buffers for exported keys */
+#define ECC_BUF_SIZE 512
+
+/* max private key size */
+#define ECC_MAXSIZE 66
+
+/** Structure defines a NIST GF(p) curve */
+typedef struct {
+ /** The size of the curve in octets */
+ int size;
+
+ /** name of curve */
+ const char *name;
+
+ /** The prime that defines the field the curve is in (encoded in hex) */
+ const char *prime;
+
+ /** The fields B param (hex) */
+ const char *B;
+
+ /** The order of the curve (hex) */
+ const char *order;
+
+ /** The x co-ordinate of the base point on the curve (hex) */
+ const char *Gx;
+
+ /** The y co-ordinate of the base point on the curve (hex) */
+ const char *Gy;
+} ltc_ecc_set_type;
+
+/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */
+typedef struct {
+ /** The x co-ordinate */
+ mpz_t x;
+
+ /** The y co-ordinate */
+ mpz_t y;
+
+ /** The z co-ordinate */
+ mpz_t z;
+} ecc_point;
+
+/** An ECC key */
+typedef struct {
+ /** Type of key, PK_PRIVATE or PK_PUBLIC */
+ int type;
+
+ mpz_t prime;
+ mpz_t order;
+ mpz_t Gx;
+ mpz_t Gy;
+
+ /** The public key */
+ ecc_point pubkey;
+
+ /** The private key */
+ mpz_t k;
+} ecc_key;
+
+/** the ECC params provided */
+extern const ltc_ecc_set_type ltc_ecc_sets[];
+
+int ecc_test(void);
+void ecc_sizes(int *low, int *high);
+int ecc_get_size(ecc_key *key);
+
+int ecc_make_key(void *random_ctx, nettle_random_func random, ecc_key *key, const ltc_ecc_set_type *dp);
+int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, mpz_t prime, mpz_t order, mpz_t Gx, mpz_t Gy);
+void ecc_free(ecc_key *key);
+
+int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
+ unsigned char *out, unsigned long *outlen);
+
+int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
+ struct dsa_signature *signature,
+ void *random_ctx, nettle_random_func random, ecc_key *key);
+
+int ecc_verify_hash(struct dsa_signature * signature,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key);
+
+/* low level functions */
+ecc_point *ltc_ecc_new_point(void);
+void ltc_ecc_del_point(ecc_point *p);
+int ltc_ecc_is_valid_idx(int n);
+
+/* point ops (mp == montgomery digit) */
+/* R = 2P */
+int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mpz_t modulus);
+
+/* R = P + Q */
+int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mpz_t modulus);
+
+/* R = kG */
+int ltc_ecc_mulmod(mpz_t k, ecc_point *G, ecc_point *R, mpz_t modulus, int map);
+
+/* map P to affine from projective */
+int ltc_ecc_map(ecc_point *P, mpz_t modulus);
+
+/* helper functions */
+int mp_init_multi(mpz_t *a, ...);
+void mp_clear_multi(mpz_t *a, ...);
+unsigned long mp_unsigned_bin_size(mpz_t a);
+int mp_to_unsigned_bin(mpz_t a, unsigned char *b);
+int mp_read_unsigned_bin(mpz_t a, unsigned char *b, unsigned long len);
+#define mp_isodd(a) (mpz_size(a) > 0 ? (mpz_getlimbn(a, 0) & 1 ? 1 : 0) : 0)
+
+#define MP_DIGIT_BIT (sizeof(mp_limb_t) * 8 - GMP_NAIL_BITS)
diff --git a/lib/nettle/ecc_free.c b/lib/nettle/ecc_free.c
new file mode 100644
index 0000000000..7cc9774db2
--- /dev/null
+++ b/lib/nettle/ecc_free.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ecc_free.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Free an ECC key from memory
+ @param key The key you wish to free
+*/
+void ecc_free(ecc_key *key)
+{
+ assert(key != NULL);
+ mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &key->prime, &key->order, &key->Gx, &key->Gy, NULL);
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_free.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ecc_make_key.c b/lib/nettle/ecc_make_key.c
new file mode 100644
index 0000000000..3ca757115a
--- /dev/null
+++ b/lib/nettle/ecc_make_key.c
@@ -0,0 +1,125 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ecc_make_key.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Make a new ECC key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param keysize The keysize for the new key (in octets from 20 to 65 bytes)
+ @param key [out] Destination of the newly created key
+ @return 0 if successful, upon error all allocated memory will be freed
+*/
+
+int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, mpz_t prime, mpz_t order, mpz_t Gx, mpz_t Gy)
+{
+ int err;
+ ecc_point *base;
+ unsigned char *buf;
+ int keysize;
+
+ assert(key != NULL);
+ assert(random != NULL);
+
+ keysize = mp_unsigned_bin_size(order);
+
+ /* allocate ram */
+ base = NULL;
+ buf = malloc(keysize);
+ if (buf == NULL) {
+ return -1;
+ }
+
+ /* make up random string */
+ random(random_ctx, keysize, buf);
+
+ /* setup the key variables */
+ if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &key->prime, &key->order, &key->Gx, &key->Gy, NULL)) != 0) {
+ goto ERR_BUF;
+ }
+ base = ltc_ecc_new_point();
+ if (base == NULL) {
+ err = -1;
+ goto errkey;
+ }
+
+ /* read in the specs for this key */
+ mpz_set(key->prime, prime);
+ mpz_set(key->order, order);
+ mpz_set(key->Gx, Gx);
+ mpz_set(key->Gy, Gy);
+
+ mpz_set(base->x, key->Gx);
+ mpz_set(base->y, key->Gy);
+ mpz_set_ui(base->z, 1);
+ if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buf, keysize)) != 0) { goto errkey; }
+
+ /* the key should be smaller than the order of base point */
+ if (mpz_cmp(key->k, key->order) >= 0) {
+ mpz_mod(key->k, key->k, key->order);
+ }
+ /* make the public key */
+ if ((err = ltc_ecc_mulmod(key->k, base, &key->pubkey, key->prime, 1)) != 0) { goto errkey; }
+ key->type = PK_PRIVATE;
+
+ /* free up ram */
+ err = 0;
+ goto cleanup;
+errkey:
+ mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &key->order, &key->prime, &key->Gx, &key->Gy, NULL);
+cleanup:
+ ltc_ecc_del_point(base);
+ERR_BUF:
+ free(buf);
+ return err;
+}
+
+int ecc_make_key(void *random_ctx, nettle_random_func random, ecc_key *key, const ltc_ecc_set_type *dp)
+{
+ mpz_t prime, order, Gx, Gy;
+ int err;
+
+ /* setup the key variables */
+ if ((err = mp_init_multi(&prime, &order, &Gx, &Gy, NULL)) != 0) {
+ goto cleanup;
+ }
+
+ /* read in the specs for this key */
+ mpz_set_str(prime, (char *)dp->prime, 16);
+ mpz_set_str(order, (char *)dp->order, 16);
+ mpz_set_str(Gx, (char *)dp->Gx, 16);
+ mpz_set_str(Gy, (char *)dp->Gy, 16);
+
+ err = ecc_make_key_ex(random_ctx, random, key, prime, order, Gx, Gy);
+
+ mp_clear_multi(&prime, &order, &Gx, &Gy, NULL);
+cleanup:
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_make_key.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ecc_shared_secret.c b/lib/nettle/ecc_shared_secret.c
new file mode 100644
index 0000000000..a3eb46a868
--- /dev/null
+++ b/lib/nettle/ecc_shared_secret.c
@@ -0,0 +1,80 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+#include <string.h>
+
+/**
+ @file ecc_shared_secret.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Create an ECC shared secret between two keys
+ @param private_key The private ECC key
+ @param public_key The public key
+ @param out [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63)
+ @param outlen [in/out] The max size and resulting size of the shared secret
+ @return 0 if successful
+*/
+int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x;
+ ecc_point *result;
+ int err;
+
+ assert(private_key != NULL);
+ assert(public_key != NULL);
+ assert(out != NULL);
+ assert(outlen != NULL);
+
+ /* type valid? */
+ if (private_key->type != PK_PRIVATE) {
+ return -1;
+ }
+
+ /* make new point */
+ result = ltc_ecc_new_point();
+ if (result == NULL) {
+ return -1;
+ }
+
+ if ((err = ltc_ecc_mulmod(private_key->k, &public_key->pubkey, result, private_key->prime, 1)) != 0) { goto done; }
+
+ x = (unsigned long)mp_unsigned_bin_size(private_key->prime);
+ if (*outlen < x) {
+ *outlen = x;
+ err = -1;
+ goto done;
+ }
+ memset(out, 0, x);
+ if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != 0) { goto done; }
+
+ err = 0;
+ *outlen = x;
+done:
+ ltc_ecc_del_point(result);
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_shared_secret.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ecc_sign_hash.c b/lib/nettle/ecc_sign_hash.c
new file mode 100644
index 0000000000..b2da7f22c6
--- /dev/null
+++ b/lib/nettle/ecc_sign_hash.c
@@ -0,0 +1,103 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+#include <nettle/dsa.h>
+
+/**
+ @file ecc_sign_hash.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Sign a message digest
+ @param in The message digest to sign
+ @param inlen The length of the digest
+ @param signature The destination for the signature
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param key A private ECC key
+ @return 0 if successful
+*/
+int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
+ struct dsa_signature *signature,
+ void *random_ctx, nettle_random_func random, ecc_key *key)
+{
+ ecc_key pubkey;
+ mpz_t r, s, e;
+ int err;
+
+ assert(in != NULL);
+ assert(signature != NULL);
+ assert(key != NULL);
+
+ /* is this a private key? */
+ if (key->type != PK_PRIVATE) {
+ return -1;
+ }
+
+ /* get the hash and load it as a bignum into 'e' */
+ /* init the bignums */
+ if ((err = mp_init_multi(&r, &s, &e, NULL)) != 0) {
+ return err;
+ }
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, (int)inlen)) != 0) { goto errnokey; }
+
+ /* make up a key and export the public copy */
+ for (;;) {
+ if ((err = ecc_make_key_ex(random_ctx, random, &pubkey, key->prime, key->order, key->Gx, key->Gy)) != 0) {
+ goto errnokey;
+ }
+
+ /* find r = x1 mod n */
+ mpz_mod(r, pubkey.pubkey.x, pubkey.order);
+
+ if (mpz_cmp_ui(r, 0) == 0) {
+ ecc_free(&pubkey);
+ } else {
+ /* find s = (e + xr)/k */
+ mpz_invert(pubkey.k, pubkey.k, pubkey.order);
+
+ /* mulmod */
+ mpz_mul(s, key->k, r);
+ mpz_mod(s, s, pubkey.order);
+ mpz_add(s, e, s);
+ mpz_mod(s, s, pubkey.order);
+
+ mpz_mul(s, s, pubkey.k);
+ mpz_mod(s, s, pubkey.order);
+ ecc_free(&pubkey);
+ if (mpz_cmp_ui(s,0) != 0) {
+ break;
+ }
+ }
+ }
+
+ memcpy(&signature->r, &r, sizeof(signature->r));
+ memcpy(&signature->s, &s, sizeof(signature->s));
+
+errnokey:
+ mp_clear_multi(&e, NULL);
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sign_hash.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ecc_test.c b/lib/nettle/ecc_test.c
new file mode 100644
index 0000000000..4c74a9f7a6
--- /dev/null
+++ b/lib/nettle/ecc_test.c
@@ -0,0 +1,125 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+#include "gnettle.h"
+#include <gnutls_int.h>
+#include <gnutls_algorithms.h>
+
+/**
+ @file ecc_test.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Perform on the ECC system
+ @return 0 if successful
+*/
+int ecc_test(void)
+{
+ mpz_t modulus, order;
+ ecc_point *G, *GG;
+ int i, err;
+
+ if ((err = mp_init_multi(&modulus, &order, NULL)) != 0) {
+ return err;
+ }
+
+ G = ltc_ecc_new_point();
+ GG = ltc_ecc_new_point();
+ if (G == NULL || GG == NULL) {
+ mp_clear_multi(&modulus,&order, NULL);
+ ltc_ecc_del_point(G);
+ ltc_ecc_del_point(GG);
+ return -1;
+ }
+
+ for (i = 1; i<=2; i++) {
+ const gnutls_ecc_curve_entry_st *st = _gnutls_ecc_curve_get_params (i);
+
+ printf("Testing %s (%d)\n", _gnutls_ecc_curve_get_name(i), i);
+
+ if (mpz_set_str(modulus, (char *)st->prime, 16) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ if (mpz_set_str(order, (char *)st->order, 16) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ /* is prime actually prime? */
+ if ((err = mpz_probab_prime_p(modulus, PRIME_CHECK_PARAM)) <= 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ if ((err = mpz_probab_prime_p(order, PRIME_CHECK_PARAM)) <= 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ if (mpz_set_str(G->x, (char *)st->Gx, 16) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ if (mpz_set_str(G->y, (char *)st->Gy, 16) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+ mpz_set_ui(G->z, 1);
+
+ /* then we should have G == (order + 1)G */
+ mpz_add_ui(order, order, 1);
+ if ((err = ltc_ecc_mulmod(order, G, GG, modulus, 1)) != 0) { goto done; }
+
+ if (mpz_cmp(G->y, GG->y) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ if (mpz_cmp(G->x, GG->x) != 0) {
+fprintf(stderr, "XXX %d\n", __LINE__);
+ err = -1;
+ goto done;
+ }
+
+ }
+ err = 0;
+done:
+ ltc_ecc_del_point(GG);
+ ltc_ecc_del_point(G);
+ mp_clear_multi(&order, &modulus, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_test.c,v $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ecc_verify_hash.c b/lib/nettle/ecc_verify_hash.c
new file mode 100644
index 0000000000..71315f3795
--- /dev/null
+++ b/lib/nettle/ecc_verify_hash.c
@@ -0,0 +1,135 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ecc_verify_hash.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/* verify
+ *
+ * w = s^-1 mod n
+ * u1 = xw
+ * u2 = rw
+ * X = u1*G + u2*Q
+ * v = X_x1 mod n
+ * accept if v == r
+ */
+
+/**
+ Verify an ECC signature
+ @param signature The signature to verify
+ @param hash The hash (message digest) that was signed
+ @param hashlen The length of the hash (octets)
+ @param stat Result of signature, 1==valid, 0==invalid
+ @param key The corresponding public ECC key
+ @return 0 if successful (even if the signature is not valid)
+*/
+int ecc_verify_hash(struct dsa_signature * signature,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key)
+{
+ ecc_point *mG, *mQ;
+ mpz_t v, w, u1, u2, e;
+ int err;
+
+ assert(signature != NULL);
+ assert(hash != NULL);
+ assert(stat != NULL);
+ assert(key != NULL);
+
+ /* default to invalid signature */
+ *stat = 0;
+
+ /* allocate ints */
+ if ((err = mp_init_multi(&v, &w, &u1, &u2, &e, NULL)) != 0) {
+ return -1;
+ }
+
+ /* allocate points */
+ mG = ltc_ecc_new_point();
+ mQ = ltc_ecc_new_point();
+ if (mQ == NULL || mG == NULL) {
+ err = -1;
+ goto error;
+ }
+
+ /* check for zero */
+ if (mpz_cmp_ui(signature->r,0) == 0 || mpz_cmp_ui(signature->s,0) == 0 ||
+ mpz_cmp(signature->r, key->order) >= 0 || mpz_cmp(signature->s, key->order) >= 0) {
+ err = -1;
+ goto error;
+ }
+
+ /* read hash */
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, (int)hashlen)) != 0) { goto error; }
+
+ /* w = s^-1 mod n */
+ mpz_invert(w, signature->s, key->order);
+
+ /* u1 = ew */
+ mpz_mul(u1, e, w);
+ mpz_mod(u1, u1, key->order);
+
+ /* u2 = rw */
+ mpz_mul(u2, signature->r, w);
+ mpz_mod(u2, u2, key->order);
+
+ /* find mG and mQ */
+ mpz_set(mG->x, key->Gx);
+ mpz_set(mG->y, key->Gy);
+ mpz_set_ui(mG->z, 1);
+
+ mpz_set(mQ->x, key->pubkey.x);
+ mpz_set(mQ->y, key->pubkey.y);
+ mpz_set(mQ->z, key->pubkey.z);
+
+ /* compute u1*mG + u2*mQ = mG */
+ if ((err = ltc_ecc_mulmod(u1, mG, mG, key->prime, 0)) != 0) { goto error; }
+ if ((err = ltc_ecc_mulmod(u2, mQ, mQ, key->prime, 0)) != 0) { goto error; }
+
+ /* add them */
+ if ((err = ltc_ecc_projective_add_point(mQ, mG, mG, key->prime)) != 0) { goto error; }
+
+ /* reduce */
+ if ((err = ltc_ecc_map(mG, key->prime)) != 0) { goto error; }
+
+ /* v = X_x1 mod n */
+ mpz_mod(v, mG->x, key->order);
+
+ /* does v == r */
+ if (mpz_cmp(v, signature->r) == 0) {
+ *stat = 1;
+ }
+
+ /* clear up and return */
+ err = 0;
+error:
+ ltc_ecc_del_point(mG);
+ ltc_ecc_del_point(mQ);
+ mp_clear_multi(&v, &w, &u1, &u2, &e, NULL);
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_verify_hash.c,v $ */
+/* $Revision: 1.14 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/gnettle.h b/lib/nettle/gnettle.h
new file mode 100644
index 0000000000..768590c73d
--- /dev/null
+++ b/lib/nettle/gnettle.h
@@ -0,0 +1,2 @@
+#define PRIME_CHECK_PARAM 8
+
diff --git a/lib/nettle/ltc_ecc_map.c b/lib/nettle/ltc_ecc_map.c
new file mode 100644
index 0000000000..f22426009d
--- /dev/null
+++ b/lib/nettle/ltc_ecc_map.c
@@ -0,0 +1,73 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ltc_ecc_map.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Map a projective jacbobian point back to affine space
+ @param P [in/out] The point to map
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return 0 on success
+*/
+int ltc_ecc_map(ecc_point *P, mpz_t modulus)
+{
+ mpz_t t1, t2;
+ int err;
+
+ assert(P != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != 0) {
+ return -1;
+ }
+
+ mpz_mod(P->z, P->z, modulus);
+
+ /* get 1/z */
+ mpz_invert(t1, P->z, modulus);
+
+ /* get 1/z^2 and 1/z^3 */
+ mpz_mul(t2, t1, t1);
+ mpz_mod(t2, t2, modulus);
+ mpz_mul(t1, t1, t2);
+ mpz_mod(t1, t1, modulus);
+
+ /* multiply against x/y */
+ mpz_mul(P->x, P->x, t2);
+ mpz_mod(P->x, P->x, modulus);
+ mpz_mul(P->y, P->y, t1);
+ mpz_mod(P->y, P->y, modulus);
+ mpz_set_ui(P->z, 1);
+
+ err = 0;
+
+ mp_clear_multi(&t1, &t2, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_map.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ltc_ecc_mulmod.c b/lib/nettle/ltc_ecc_mulmod.c
new file mode 100644
index 0000000000..ab845ce014
--- /dev/null
+++ b/lib/nettle/ltc_ecc_mulmod.c
@@ -0,0 +1,141 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ltc_ecc_mulmod_timing.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Perform a point multiplication (timing resistant)
+ @param k The scalar to multiply by
+ @param G The base point
+ @param R [out] Destination for kG
+ @param modulus The modulus of the field the ECC curve is in
+ @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
+ @return 0 on success
+*/
+int ltc_ecc_mulmod(mpz_t k, ecc_point *G, ecc_point *R, mpz_t modulus, int map)
+{
+ ecc_point *tG, *M[3];
+ int i, j, err;
+ unsigned long buf;
+ int first, bitbuf, bitcpy, bitcnt, mode, digidx;
+
+ assert(k != NULL);
+ assert(G != NULL);
+ assert(R != NULL);
+ assert(modulus != NULL);
+
+ /* alloc ram for window temps */
+ for (i = 0; i < 3; i++) {
+ M[i] = ltc_ecc_new_point();
+ if (M[i] == NULL) {
+ for (j = 0; j < i; j++) {
+ ltc_ecc_del_point(M[j]);
+ }
+ return -1;
+ }
+ }
+
+ /* make a copy of G incase R==G */
+ tG = ltc_ecc_new_point();
+ if (tG == NULL) { err = -1; goto done; }
+
+ /* tG = G and convert to montgomery */
+ mpz_set(tG->x, G->x);
+ mpz_set(tG->y, G->y);
+ mpz_set(tG->z, G->z);
+
+ /* calc the M tab */
+ /* M[0] == G */
+ mpz_set(M[0]->x, tG->x);
+ mpz_set(M[0]->y, tG->y);
+ mpz_set(M[0]->z, tG->z);
+ /* M[1] == 2G */
+ if ((err = ltc_ecc_projective_dbl_point(tG, M[1], modulus)) != 0) { goto done; }
+
+ /* setup sliding window */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = mpz_size(k) - 1;
+ bitcpy = bitbuf = 0;
+ first = 1;
+
+ /* perform ops */
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ if (digidx == -1) {
+ break;
+ }
+ buf = mpz_getlimbn(k, digidx);
+ bitcnt = (int) MP_DIGIT_BIT;
+ --digidx;
+ }
+
+ /* grab the next msb from the ltiplicand */
+ i = (buf >> (MP_DIGIT_BIT - 1)) & 1;
+ buf <<= 1;
+
+ if (mode == 0 && i == 0) {
+ /* dummy operations */
+ if ((err = ltc_ecc_projective_add_point(M[0], M[1], M[2], modulus)) != 0) { goto done; }
+ if ((err = ltc_ecc_projective_dbl_point(M[1], M[2], modulus)) != 0) { goto done; }
+ continue;
+ }
+
+ if (mode == 0 && i == 1) {
+ mode = 1;
+ /* dummy operations */
+ if ((err = ltc_ecc_projective_add_point(M[0], M[1], M[2], modulus)) != 0) { goto done; }
+ if ((err = ltc_ecc_projective_dbl_point(M[1], M[2], modulus)) != 0) { goto done; }
+ continue;
+ }
+
+ if ((err = ltc_ecc_projective_add_point(M[0], M[1], M[i^1], modulus)) != 0) { goto done; }
+ if ((err = ltc_ecc_projective_dbl_point(M[i], M[i], modulus)) != 0) { goto done; }
+ }
+
+ /* copy result out */
+ mpz_set(R->x, M[0]->x);
+ mpz_set(R->y, M[0]->y);
+ mpz_set(R->z, M[0]->z);
+
+ /* map R back from projective space */
+ if (map) {
+ err = ltc_ecc_map(R, modulus);
+ } else {
+ err = 0;
+ }
+done:
+ ltc_ecc_del_point(tG);
+ for (i = 0; i < 3; i++) {
+ ltc_ecc_del_point(M[i]);
+ }
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ltc_ecc_points.c b/lib/nettle/ltc_ecc_points.c
new file mode 100644
index 0000000000..93ad85d403
--- /dev/null
+++ b/lib/nettle/ltc_ecc_points.c
@@ -0,0 +1,60 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ltc_ecc_points.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef LTC_MECC
+
+/**
+ Allocate a new ECC point
+ @return A newly allocated point or NULL on error
+*/
+ecc_point *ltc_ecc_new_point(void)
+{
+ ecc_point *p;
+ p = calloc(1, sizeof(*p));
+ if (p == NULL) {
+ return NULL;
+ }
+ if (mp_init_multi(&p->x, &p->y, &p->z, NULL) != 0) {
+ free(p);
+ return NULL;
+ }
+ return p;
+}
+
+/** Free an ECC point from memory
+ @param p The point to free
+*/
+void ltc_ecc_del_point(ecc_point *p)
+{
+ /* prevents free'ing null arguments */
+ if (p != NULL) {
+ mp_clear_multi(&p->x, &p->y, &p->z, NULL); /* note: p->z may be NULL but that's ok with this function anyways */
+ free(p);
+ }
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_points.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ltc_ecc_projective_add_point.c b/lib/nettle/ltc_ecc_projective_add_point.c
new file mode 100644
index 0000000000..2b008367c6
--- /dev/null
+++ b/lib/nettle/ltc_ecc_projective_add_point.c
@@ -0,0 +1,195 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ltc_ecc_projective_add_point.c
+ ECC Crypto, Tom St Denis
+*/
+
+#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC))
+
+/**
+ Add two ECC points
+ @param P The point to add
+ @param Q The point to add
+ @param R [out] The destination of the double
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return 0 on success
+*/
+int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mpz_t modulus)
+{
+ mpz_t t1, t2, x, y, z;
+ int err;
+
+ assert(P != NULL);
+ assert(Q != NULL);
+ assert(R != NULL);
+ assert(modulus != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != 0) {
+ return err;
+ }
+
+ /* should we dbl instead? */
+ mpz_sub(t1, modulus, Q->y);
+
+ if ( (mpz_cmp(P->x, Q->x) == 0) &&
+ (Q->z != NULL && mpz_cmp(P->z, Q->z) == 0) &&
+ (mpz_cmp(P->y, Q->y) == 0 || mpz_cmp(P->y, t1) == 0)) {
+ mp_clear_multi(&t1, &t2, &x, &y, &z, NULL);
+ return ltc_ecc_projective_dbl_point(P, R, modulus);
+ }
+
+ mpz_set(x, P->x);
+ mpz_set(y, P->y);
+ mpz_set(z, P->z);
+
+ /* if Z is one then these are no-operations */
+ if (mpz_cmp_ui(Q->z, 1) != 0) {
+ /* T1 = Z' * Z' */
+ mpz_mul(t1, Q->z, Q->z);
+ mpz_mod(t1, t1, modulus);
+ /* X = X * T1 */
+ mpz_mul(x, x, t1);
+ mpz_mod(x, x, modulus);
+ /* T1 = Z' * T1 */
+ mpz_mul(t1, t1, Q->z);
+ mpz_mod(t1, t1, modulus);
+ /* Y = Y * T1 */
+ mpz_mul(y, y, t1);
+ mpz_mod(y, y, modulus);
+ }
+
+ /* T1 = Z*Z */
+ mpz_mul(t1, z, z);
+ mpz_mod(t1, t1, modulus);
+ /* T2 = X' * T1 */
+ mpz_mul(t2, t1, Q->x);
+ mpz_mod(t2, t2, modulus);
+ /* T1 = Z * T1 */
+ mpz_mul(t1, t1, z);
+ mpz_mod(t1, t1, modulus);
+ /* T1 = Y' * T1 */
+ mpz_mul(t1, t1, Q->y);
+ mpz_mod(t1, t1, modulus);
+
+ /* Y = Y - T1 */
+ mpz_sub(y, y, t1);
+ if (mpz_cmp_ui(y, 0) < 0) {
+ mpz_add(y, y, modulus);
+ }
+ /* T1 = 2T1 */
+ mpz_add(t1, t1, t1);
+ if (mpz_cmp(t1, modulus) >= 0) {
+ mpz_sub(t1, t1, modulus);
+ }
+ /* T1 = Y + T1 */
+ mpz_add(t1, t1, y);
+ if (mpz_cmp(t1, modulus) >= 0) {
+ mpz_sub(t1, t1, modulus);
+ }
+ /* X = X - T2 */
+ mpz_sub(x, x, t2);
+ if (mpz_cmp_ui(x, 0) < 0) {
+ mpz_add(x, x, modulus);
+ }
+ /* T2 = 2T2 */
+ mpz_add(t2, t2, t2);
+ if (mpz_cmp(t2, modulus) >= 0) {
+ mpz_sub(t2, t2, modulus);
+ }
+ /* T2 = X + T2 */
+ mpz_add(t2, t2, x);
+ if (mpz_cmp(t2, modulus) >= 0) {
+ mpz_sub(t2, t2, modulus);
+ }
+
+ /* if Z' != 1 */
+ if (mpz_cmp_ui(Q->z, 1) != 0) {
+ /* Z = Z * Z' */
+ mpz_mul(z, z, Q->z);
+ mpz_mod(z, z, modulus);
+ }
+
+ /* Z = Z * X */
+ mpz_mul(z, z, x);
+ mpz_mod(z, z, modulus);
+
+ /* T1 = T1 * X */
+ mpz_mul(t1, t1, x);
+ mpz_mod(t1, t1, modulus);
+ /* X = X * X */
+ mpz_mul(x, x, x);
+ mpz_mod(x, x, modulus);
+ /* T2 = T2 * x */
+ mpz_mul(t2, t2, x);
+ mpz_mod(t2, t2, modulus);
+ /* T1 = T1 * X */
+ mpz_mul(t1, t1, x);
+ mpz_mod(t1, t1, modulus);
+
+ /* X = Y*Y */
+ mpz_mul(x, y, y);
+ mpz_mod(x, x, modulus);
+ /* X = X - T2 */
+ mpz_sub(x, x, t2);
+ if (mpz_cmp_ui(x, 0) < 0) {
+ mpz_add(x, x, modulus);
+ }
+
+ /* T2 = T2 - X */
+ mpz_sub(t2, t2, x);
+ if (mpz_cmp_ui(t2, 0) < 0) {
+ mpz_add(t2, t2, modulus);
+ }
+ /* T2 = T2 - X */
+ mpz_sub(t2, t2, x);
+ if (mpz_cmp_ui(t2, 0) < 0) {
+ mpz_add(t2, t2, modulus);
+ }
+ /* T2 = T2 * Y */
+ mpz_mul(t2, t2, y);
+ mpz_mod(t2, t2, modulus);
+ /* Y = T2 - T1 */
+ mpz_sub(y, t2, t1);
+ if (mpz_cmp_ui(y, 0) < 0) {
+ mpz_add(y, y, modulus);
+ }
+ /* Y = Y/2 */
+ if (mp_isodd(y)) {
+ mpz_add(y, y, modulus);
+ }
+ mpz_divexact_ui(y, y, 2);
+
+ mpz_set(R->x, x);
+ mpz_set(R->y, y);
+ mpz_set(R->z, z);
+
+ err = 0;
+
+ mp_clear_multi(&t1, &t2, &x, &y, &z, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c,v $ */
+/* $Revision: 1.16 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/ltc_ecc_projective_dbl_point.c b/lib/nettle/ltc_ecc_projective_dbl_point.c
new file mode 100644
index 0000000000..d9b7ec6e6c
--- /dev/null
+++ b/lib/nettle/ltc_ecc_projective_dbl_point.c
@@ -0,0 +1,146 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "ecc.h"
+
+/**
+ @file ltc_ecc_projective_dbl_point.c
+ ECC Crypto, Tom St Denis
+*/
+
+#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_LTC_DESC))
+
+/**
+ Double an ECC point
+ @param P The point to double
+ @param R [out] The destination of the double
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return 0 on success
+*/
+int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mpz_t modulus)
+{
+ mpz_t t1, t2;
+ int err;
+
+ assert(P != NULL);
+ assert(R != NULL);
+ assert(modulus != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != 0) {
+ return err;
+ }
+
+ if (P != R) {
+ mpz_set(R->x, P->x);
+ mpz_set(R->y, P->y);
+ mpz_set(R->z, P->z);
+ }
+
+ /* t1 = Z * Z */
+ mpz_mul(t1, R->z, R->z);
+ mpz_mod(t1, t1, modulus);
+ /* Z = Y * Z */
+ mpz_mul(R->z, R->y, R->z);
+ mpz_mod(R->z, R->z, modulus);
+ /* Z = 2Z */
+ mpz_add(R->z, R->z, R->z);
+ if (mpz_cmp(R->z, modulus) >= 0) {
+ mpz_sub(R->z, R->z, modulus);
+ }
+
+ /* T2 = X - T1 */
+ mpz_sub(t2, R->x, t1);
+ if (mpz_cmp_ui(t2, 0) < 0) {
+ mpz_add(t2, t2, modulus);
+ }
+ /* T1 = X + T1 */
+ mpz_add(t1, t1, R->x);
+ if (mpz_cmp(t1, modulus) >= 0) {
+ mpz_sub(t1, t1, modulus);
+ }
+ /* T2 = T1 * T2 */
+ mpz_mul(t2, t1, t2);
+ mpz_mod(t2, t2, modulus);
+ /* T1 = 2T2 */
+ mpz_add(t1, t2, t2);
+ if (mpz_cmp(t1, modulus) >= 0) {
+ mpz_sub(t1, t1, modulus);
+ }
+ /* T1 = T1 + T2 */
+ mpz_add(t1, t1, t2);
+ if (mpz_cmp(t1, modulus) >= 0) {
+ mpz_sub(t1, t1, modulus);
+ }
+
+ /* Y = 2Y */
+ mpz_add(R->y, R->y, R->y);
+ if (mpz_cmp(R->y, modulus) >= 0) {
+ mpz_sub(R->y, R->y, modulus);
+ }
+ /* Y = Y * Y */
+ mpz_mul(R->y, R->y, R->y);
+ mpz_mod(R->y, R->y, modulus);
+ /* T2 = Y * Y */
+ mpz_mul(t2, R->y, R->y);
+ mpz_mod(t2, t2, modulus);
+ /* T2 = T2/2 */
+ if (mp_isodd(t2)) {
+ mpz_add(t2, t2, modulus);
+ }
+ mpz_divexact_ui(t2, t2, 2);
+ /* Y = Y * X */
+ mpz_mul(R->y, R->y, R->x);
+ mpz_mod(R->y, R->y, modulus);
+
+ /* X = T1 * T1 */
+ mpz_mul(R->x, t1, t1);
+ mpz_mod(R->x, R->x, modulus);
+ /* X = X - Y */
+ mpz_sub(R->x, R->x, R->y);
+ if (mpz_cmp_ui(R->x, 0) < 0) {
+ mpz_add(R->x, R->x, modulus);
+ }
+ /* X = X - Y */
+ mpz_sub(R->x, R->x, R->y);
+ if (mpz_cmp_ui(R->x, 0) < 0) {
+ mpz_add(R->x, R->x, modulus);
+ }
+
+ /* Y = Y - X */
+ mpz_sub(R->y, R->y, R->x);
+ if (mpz_cmp_ui(R->y, 0) < 0) {
+ mpz_add(R->y, R->y, modulus);
+ }
+ /* Y = Y * T1 */
+ mpz_mul(R->y, R->y, t1);
+ mpz_mod(R->y, R->y, modulus);
+ /* Y = Y - T2 */
+ mpz_sub(R->y, R->y, t2);
+ if (mpz_cmp_ui(R->y, 0) < 0) {
+ mpz_add( R->y, R->y, modulus);
+ }
+
+ err = 0;
+
+ mp_clear_multi(&t1, &t2, NULL);
+ return err;
+}
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
+
diff --git a/lib/nettle/mp_unsigned_bin.c b/lib/nettle/mp_unsigned_bin.c
new file mode 100644
index 0000000000..0da8bba32e
--- /dev/null
+++ b/lib/nettle/mp_unsigned_bin.c
@@ -0,0 +1,28 @@
+#include "ecc.h"
+
+unsigned long mp_unsigned_bin_size(mpz_t a)
+{
+ unsigned long t;
+ assert(a != NULL);
+
+ t = mpz_sizeinbase(a, 2);
+ if (mpz_cmp_ui((a), 0) == 0) return 0;
+ return (t>>3) + ((t&7)?1:0);
+}
+
+int mp_to_unsigned_bin(mpz_t a, unsigned char *b)
+{
+ assert(a != NULL);
+ assert(b != NULL);
+ mpz_export(b, NULL, 1, 1, 1, 0, a);
+
+ return 0;
+}
+
+int mp_read_unsigned_bin(mpz_t a, unsigned char *b, unsigned long len)
+{
+ assert(a != NULL);
+ assert(b != NULL);
+ mpz_import(a, len, 1, 1, 1, 0, b);
+ return 0;
+}
diff --git a/lib/nettle/mpi.c b/lib/nettle/mpi.c
index c76705c18f..eef8a2cc36 100644
--- a/lib/nettle/mpi.c
+++ b/lib/nettle/mpi.c
@@ -33,6 +33,7 @@
#include <gnutls_mpi.h>
#include <gmp.h>
#include <nettle/bignum.h>
+#include <gnettle.h>
#include <random.h>
#define TOMPZ(x) (*((mpz_t*)(x)))
@@ -390,7 +391,6 @@ wrap_nettle_mpi_mul_ui (bigint_t w, const bigint_t a, unsigned long b)
}
-#define PRIME_CHECK_PARAM 8
static int
wrap_nettle_prime_check (bigint_t pp)
{
diff --git a/lib/nettle/multi.c b/lib/nettle/multi.c
new file mode 100644
index 0000000000..788c8e9a00
--- /dev/null
+++ b/lib/nettle/multi.c
@@ -0,0 +1,46 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include <gmp.h>
+#include <stdarg.h>
+#include <ecc.h>
+
+int mp_init_multi(mpz_t *a, ...)
+{
+ mpz_t *cur = a;
+ int np = 0;
+ va_list args;
+
+ va_start(args, a);
+ while (cur != NULL) {
+ mpz_init(*cur);
+ ++np;
+ cur = va_arg(args, mpz_t*);
+ }
+ va_end(args);
+ return 0;
+}
+
+void mp_clear_multi(mpz_t *a, ...)
+{
+ mpz_t *cur = a;
+ va_list args;
+
+ va_start(args, a);
+ while (cur != NULL) {
+ mpz_clear(*cur);
+ cur = va_arg(args, mpz_t*);
+ }
+ va_end(args);
+}
+
+/* $Source$ */
+/* $Revision$ */
+/* $Date$ */
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index 5ee9769d0d..f1722bede7 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2010
- * Free Software Foundation, Inc.
+ * Copyright (C) 2010 Free Software Foundation, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -42,9 +41,13 @@
#include <nettle/rsa.h>
#include <random.h>
#include <gnutls/crypto.h>
+#include "rnd.h"
+#include "ecc.h"
#define TOMPZ(x) (*((mpz_t*)(x)))
+static inline int is_supported_curve(int curve);
+
static void
rnd_func (void *_ctx, unsigned length, uint8_t * data)
{
@@ -81,6 +84,69 @@ _rsa_params_to_privkey (const gnutls_pk_params_st * pk_params,
}
+static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo, gnutls_datum_t * out,
+ const gnutls_pk_params_st * priv,
+ const gnutls_pk_params_st * pub)
+{
+ int ret;
+
+ switch (algo)
+ {
+ case GNUTLS_PK_ECDH:
+ {
+ ecc_key ecc_pub, ecc_priv;
+ int curve = priv->flags;
+ unsigned long sz;
+
+ if (is_supported_curve(curve) == 0)
+ return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
+
+ ecc_pub.type = PK_PUBLIC;
+ memcpy(&ecc_pub.prime, pub->params[0], sizeof(mpz_t));
+ memcpy(&ecc_pub.order, pub->params[1], sizeof(mpz_t));
+ memcpy(&ecc_pub.Gx, pub->params[2], sizeof(mpz_t));
+ memcpy(&ecc_pub.Gy, pub->params[3], sizeof(mpz_t));
+ memcpy(&ecc_pub.pubkey.x, pub->params[4], sizeof(mpz_t));
+ memcpy(&ecc_pub.pubkey.y, pub->params[5], sizeof(mpz_t));
+ memcpy(&ecc_pub.pubkey.z, pub->params[6], sizeof(mpz_t));
+
+ ecc_priv.type = PK_PRIVATE;
+ memcpy(&ecc_priv.prime, priv->params[0], sizeof(mpz_t));
+ memcpy(&ecc_priv.order, priv->params[1], sizeof(mpz_t));
+ memcpy(&ecc_priv.Gx, priv->params[2], sizeof(mpz_t));
+ memcpy(&ecc_priv.Gy, priv->params[3], sizeof(mpz_t));
+ memcpy(&ecc_priv.pubkey.x, priv->params[4], sizeof(mpz_t));
+ memcpy(&ecc_priv.pubkey.y, priv->params[5], sizeof(mpz_t));
+ memcpy(&ecc_priv.pubkey.z, priv->params[6], sizeof(mpz_t));
+ memcpy(&ecc_priv.k, priv->params[7], sizeof(mpz_t));
+
+ sz = ECC_BUF_SIZE;
+ out->data = gnutls_malloc(sz);
+ if (out->data == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ ret = ecc_shared_secret(&ecc_priv, &ecc_pub, out->data, &sz);
+ if (ret != 0)
+ {
+ gnutls_free(out->data);
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ }
+ out->size = sz;
+ break;
+ }
+ default:
+ gnutls_assert ();
+ ret = GNUTLS_E_INTERNAL_ERROR;
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+
+ return ret;
+}
+
static int
_wrap_nettle_pk_encrypt (gnutls_pk_algorithm_t algo,
gnutls_datum_t * ciphertext,
@@ -89,7 +155,6 @@ _wrap_nettle_pk_encrypt (gnutls_pk_algorithm_t algo,
{
int ret;
- /* make a sexp from pkey */
switch (algo)
{
case GNUTLS_PK_RSA:
@@ -486,6 +551,15 @@ cleanup:
return ret;
}
+static inline int is_supported_curve(int curve)
+{
+ if (_gnutls_ecc_curve_get_name(curve) != NULL)
+ return 1;
+ else
+ return 0;
+}
+
+
static int
wrap_nettle_pk_generate_params (gnutls_pk_algorithm_t algo,
unsigned int level /*bits */ ,
@@ -605,6 +679,56 @@ rsa_fail:
break;
}
+ case GNUTLS_PK_ECDH:
+ {
+ ecc_key key;
+ ltc_ecc_set_type tls_ecc_set;
+ const gnutls_ecc_curve_entry_st *st;
+
+ st = _gnutls_ecc_curve_get_params(level);
+ if (st == NULL)
+ return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
+
+ tls_ecc_set.size = st->size;
+ tls_ecc_set.prime = st->prime;
+ tls_ecc_set.order = st->order;
+ tls_ecc_set.Gx = st->Gx;
+ tls_ecc_set.Gy = st->Gy;
+
+ ret = ecc_make_key(NULL, _int_random_func, &key, &tls_ecc_set);
+ if (ret != 0)
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ params->params_nr = 0;
+ for (i = 0; i < ECDH_PRIVATE_PARAMS; i++)
+ {
+ params->params[i] = _gnutls_mpi_alloc_like(&key.prime);
+ if (params->params[i] == NULL)
+ {
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto ecc_fail;
+ }
+ params->params_nr++;
+ }
+ params->flags = level;
+
+ mpz_set(TOMPZ(params->params[0]), key.prime);
+ mpz_set(TOMPZ(params->params[1]), key.order);
+ mpz_set(TOMPZ(params->params[2]), key.Gx);
+ mpz_set(TOMPZ(params->params[3]), key.Gy);
+ mpz_set(TOMPZ(params->params[4]), key.pubkey.x);
+ mpz_set(TOMPZ(params->params[5]), key.pubkey.y);
+ mpz_set(TOMPZ(params->params[6]), key.pubkey.z);
+ mpz_set(TOMPZ(params->params[7]), key.k);
+
+ecc_fail:
+ ecc_free(&key);
+
+ if (ret < 0)
+ goto fail;
+
+ break;
+ }
default:
gnutls_assert ();
return GNUTLS_E_INVALID_REQUEST;
@@ -666,4 +790,5 @@ gnutls_crypto_pk_st _gnutls_pk_ops = {
.verify = _wrap_nettle_pk_verify,
.generate = wrap_nettle_pk_generate_params,
.pk_fixup_private_params = wrap_nettle_pk_fixup,
+ .derive = _wrap_nettle_pk_derive,
};
diff --git a/lib/nettle/rnd.c b/lib/nettle/rnd.c
index 8af0adde57..b503e10e1d 100644
--- a/lib/nettle/rnd.c
+++ b/lib/nettle/rnd.c
@@ -33,6 +33,7 @@
#include <gnutls_errors.h>
#include <gnutls_num.h>
#include <nettle/yarrow.h>
+#include "rnd.h"
#define SOURCES 2
@@ -440,7 +441,6 @@ wrap_nettle_rnd_init (void **ctx)
}
-
static int
wrap_nettle_rnd (void *_ctx, int level, void *data, size_t datasize)
{
@@ -467,6 +467,14 @@ wrap_nettle_rnd (void *_ctx, int level, void *data, size_t datasize)
return 0;
}
+/* internal function to provide to nettle functions that
+ * require a nettle_random_func().
+ */
+void _int_random_func(void *ctx, unsigned length, uint8_t *dst)
+{
+ wrap_nettle_rnd(ctx, 0, dst, length);
+}
+
int crypto_rnd_prio = INT_MAX;
gnutls_crypto_rnd_st _gnutls_rnd_ops = {
diff --git a/lib/nettle/rnd.h b/lib/nettle/rnd.h
new file mode 100644
index 0000000000..5deefd392c
--- /dev/null
+++ b/lib/nettle/rnd.h
@@ -0,0 +1,2 @@
+void _int_random_func(void *ctx,
+ unsigned length, uint8_t *dst);