diff options
Diffstat (limited to 'lib/nettle')
-rw-r--r-- | lib/nettle/Makefile.am | 7 | ||||
-rw-r--r-- | lib/nettle/ecc.h | 123 | ||||
-rw-r--r-- | lib/nettle/ecc_free.c | 40 | ||||
-rw-r--r-- | lib/nettle/ecc_make_key.c | 125 | ||||
-rw-r--r-- | lib/nettle/ecc_shared_secret.c | 80 | ||||
-rw-r--r-- | lib/nettle/ecc_sign_hash.c | 103 | ||||
-rw-r--r-- | lib/nettle/ecc_test.c | 125 | ||||
-rw-r--r-- | lib/nettle/ecc_verify_hash.c | 135 | ||||
-rw-r--r-- | lib/nettle/gnettle.h | 2 | ||||
-rw-r--r-- | lib/nettle/ltc_ecc_map.c | 73 | ||||
-rw-r--r-- | lib/nettle/ltc_ecc_mulmod.c | 141 | ||||
-rw-r--r-- | lib/nettle/ltc_ecc_points.c | 60 | ||||
-rw-r--r-- | lib/nettle/ltc_ecc_projective_add_point.c | 195 | ||||
-rw-r--r-- | lib/nettle/ltc_ecc_projective_dbl_point.c | 146 | ||||
-rw-r--r-- | lib/nettle/mp_unsigned_bin.c | 28 | ||||
-rw-r--r-- | lib/nettle/mpi.c | 2 | ||||
-rw-r--r-- | lib/nettle/multi.c | 46 | ||||
-rw-r--r-- | lib/nettle/pk.c | 131 | ||||
-rw-r--r-- | lib/nettle/rnd.c | 10 | ||||
-rw-r--r-- | lib/nettle/rnd.h | 2 |
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); |