diff --git a/Makefile.am b/Makefile.am index d13e662..8264db3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,6 +5,7 @@ lib_LTLIBRARIES = \ libbrandt.la libbrandt_la_SOURCES = \ + brandt.c \ crypto.c \ util.c @@ -13,3 +14,11 @@ libbrandt_la_LIBADD = \ libbrandt_la_LDFLAGS = \ -version-info 0:0:0 + +check_PROGRAMS = \ + test_crypto + +test_crypto_SOURCES = test_crypto.c +test_crypto_LDADD = libbrandt.la -lgcrypt -lgpg-error + +TESTS = $(check_PROGRAMS) diff --git a/brandt.c b/brandt.c new file mode 100644 index 0000000..dd88643 --- /dev/null +++ b/brandt.c @@ -0,0 +1,27 @@ + +#include + +#include "crypto.h" +#include "util.h" + +void BRANDT_init () +{ + gcry_error_t err = 0; + if (!gcry_check_version("1.6.0")) { + eprintf("libgcrypt version mismatch"); + } + + /* SECMEM cannot be resized dynamically. We do not know how much we need */ + if ((err = gcry_control(GCRYCTL_DISABLE_SECMEM, 0))) + weprintf("failed to set libgcrypt option DISABLE_SECMEM: %s", + gcry_strerror(err)); + + /* ecc is slow otherwise. */ + if ((err = gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0))) + weprintf("failed to set libgcrypt option ENABLE_QUICK_RANDOM: %s", + gcry_strerror(err)); + + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + brandt_rand_poll(); + brandt_crypto_init(); +} diff --git a/brandt.h b/brandt.h index 1f95d40..b7ebf5b 100644 --- a/brandt.h +++ b/brandt.h @@ -22,6 +22,9 @@ #ifndef _BRANDT_BRANDT_H #define _BRANDT_BRANDT_H +#include +#include + /** * FIXME. */ @@ -86,6 +89,9 @@ typedef void uint16_t price); +void +BRANDT_init (); + /** * Join an auction described by the @a auction_data parameter. * diff --git a/crypto.c b/crypto.c index 399cd21..e78032e 100644 --- a/crypto.c +++ b/crypto.c @@ -26,6 +26,28 @@ #define CURVE "Ed25519" +struct brandt_ec_skey { + unsigned char d[256 / 8]; +}; + +struct brandt_ec_pkey { + unsigned char q_y[256 / 8]; +}; + +gcry_mpi_point_t ec_gen; +gcry_ctx_t ec_ctx; + +void +brandt_crypto_init () +{ + gcry_error_t rc; + + rc = gcry_mpi_ec_new (&ec_ctx, NULL, CURVE); + brandt_assert_gpgerr (rc); + ec_gen = gcry_mpi_ec_get_point ("g", ec_ctx, 0); + brandt_assert (NULL != ec_gen); +} + /* --- RANDOM --- */ void @@ -132,28 +154,31 @@ brandt_mpi_scan_unsigned (gcry_mpi_t *result, const void *data, size_t size) brandt_assert_gpgerr (rc); } -/* --- ECDHE --- */ - -/** - * Convert the given private key from the network format to the - * S-expression that can be used by libgcrypt. - * - * @param priv private key to decode - * @return NULL on error - */ -static gcry_sexp_t -decode_private_ecdhe_key (const struct brandt_dhe_skey *priv) +/* +gcry_mpi_point_t +deserialize_point(const struct brandt_point* data, const int len) { - gcry_sexp_t result; + gcry_sexp_t s; + gcry_ctx_t ctx; + gcry_mpi_point_t ret; gcry_error_t rc; - rc = gcry_sexp_build (&result, NULL, - "(private-key(ecc(curve \"" CURVE "\")" - "(d %b)))", - (int)sizeof (priv->d), priv->d); - brandt_assert_gpgerr (rc); - return result; + rc = gcry_sexp_build(&s, NULL, "(public-key(ecc(curve " CURVE ")(q %b)))", + len, data); + brandt_assert_gpgerr(rc); + + rc = gcry_mpi_ec_new(&ctx, s, NULL); + brandt_assert_gpgerr(rc); + gcry_sexp_release(s); + + ret = gcry_mpi_ec_get_point("q", ctx, 0); + brandt_assert(ret); + gcry_ctx_release(ctx); + return ret; } +*/ + +/* --- EC --- */ /** * Extract values from an S-expression. @@ -213,30 +238,81 @@ key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, const char *topname, return 0; } -/** - * Create a new private key. - * - * @param priv where to write the private key - */ void -brandt_ecdhe_key_create (struct brandt_dhe_skey *priv) +brandt_ec_skey_create (gcry_mpi_t* skey) { - gcry_sexp_t priv_sexp; gcry_sexp_t s_keyparam; + gcry_sexp_t priv_sexp; gcry_mpi_t d; gcry_error_t rc; rc = gcry_sexp_build (&s_keyparam, NULL, "(genkey(ecc(curve \"" CURVE "\")" - "(flags)))") - brandt_assert_gpgerr (rc); - rc = gcry_pk_genkey (&priv_sexp, s_keyparam) - brandt_assert_gpgerr (rc); + "(flags)))"); + brandt_assert_gpgerr (rc); + rc = gcry_pk_genkey (&priv_sexp, s_keyparam); + brandt_assert_gpgerr (rc); gcry_sexp_release (s_keyparam); - rc = key_from_sexp (&d, priv_sexp, "private-key", "d") - brandt_assert_gpgerr (rc); + rc = key_from_sexp (skey, priv_sexp, "private-key", "d"); + brandt_assert_gpgerr (rc); gcry_sexp_release (priv_sexp); - brandt_mpi_print_unsigned (priv->d, sizeof (priv->d), d); - gcry_mpi_release (d); +} + + +void +brandt_ec_pkey_compute (gcry_mpi_point_t* pkey, const gcry_mpi_t skey) +{ + +} + + +void +brandt_ec_keypair_create (gcry_mpi_point_t* pkey, gcry_mpi_t* skey) +{ + gcry_error_t rc; + gcry_sexp_t s_keyparam; + gcry_sexp_t priv_sexp; + gcry_ctx_t ctx; + + rc = gcry_sexp_build (&s_keyparam, NULL, "(genkey(ecc(curve \"" CURVE "\")" + "(flags)))"); + brandt_assert_gpgerr (rc); + + rc = gcry_pk_genkey (&priv_sexp, s_keyparam); + brandt_assert_gpgerr (rc); + gcry_sexp_release (s_keyparam); + + rc = key_from_sexp (skey, priv_sexp, "private-key", "d"); + brandt_assert_gpgerr (rc); + + rc = gcry_mpi_ec_new (&ctx, priv_sexp, NULL); + brandt_assert_gpgerr (rc); + gcry_sexp_release (priv_sexp); + + *pkey = gcry_mpi_ec_get_point("q", ctx, 0); + brandt_assert (NULL != *pkey); + gcry_ctx_release (ctx); +} + + +/** + * Convert the given private key from the network format to the + * S-expression that can be used by libgcrypt. + * + * @param priv private key to decode + * @return NULL on error + */ +static gcry_sexp_t +decode_private_ecdhe_key (const struct brandt_ec_skey *priv) +{ + gcry_sexp_t result; + gcry_error_t rc; + + rc = gcry_sexp_build (&result, NULL, + "(private-key(ecc(curve \"" CURVE "\")" + "(d %b)))", + (int)sizeof (priv->d), priv->d); + brandt_assert_gpgerr (rc); + return result; } /** @@ -246,8 +322,8 @@ brandt_ecdhe_key_create (struct brandt_dhe_skey *priv) * @param pub where to write the public key */ void -brandt_ecdhe_key_get_public (const struct brandt_dhe_skey *priv, - struct brandt_dhe_pkey *pub) +brandt_ecdhe_key_get_public (const struct brandt_ec_skey *priv, + struct brandt_ec_pkey *pub) { gcry_sexp_t sexp; gcry_ctx_t ctx; @@ -275,8 +351,8 @@ brandt_ecdhe_key_get_public (const struct brandt_dhe_skey *priv, * @return 0 on error, 1 on success */ int -brandt_ecdhe (const struct brandt_dhe_skey *priv, - const struct brandt_dhe_pkey *pub, +brandt_ecdhe (const struct brandt_ec_skey *priv, + const struct brandt_ec_pkey *pub, struct brandt_hash_code *key_material) { gcry_error_t rc; @@ -331,13 +407,45 @@ brandt_ecdhe (const struct brandt_dhe_skey *priv, } /** - * @ingroup crypto * Clear memory that was used to store a private key. * - * @param pk location of the key + * @param skey location of the key */ void -brandt_ecdhe_key_clear (struct brandt_dhe_skey *pk) +brandt_ec_key_clear (struct brandt_ec_skey *skey) { - memset (pk, 0, sizeof (struct brandt_dhe_skey)); + memset (skey, 0, sizeof (struct brandt_ec_skey)); } + +/** + * Generate a random value mod n. + * + * @param edc ECC context + * @return random value mod n. + */ +//gcry_mpi_t +//GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccDlogContext *edc) +//{ +// gcry_mpi_t n; +// unsigned int highbit; +// gcry_mpi_t r; +// +// n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); +// +// /* check public key for number of bits, bail out if key is all zeros */ +// highbit = 256; /* Curve25519 */ +// while ( (! gcry_mpi_test_bit (n, highbit)) && +// (0 != highbit) ) +// highbit--; +// GNUNET_assert (0 != highbit); +// /* generate fact < n (without bias) */ +// GNUNET_assert (NULL != (r = gcry_mpi_new (0))); +// do { +// gcry_mpi_randomize (r, +// highbit + 1, +// GCRY_STRONG_RANDOM); +// } +// while (gcry_mpi_cmp (r, n) >= 0); +// gcry_mpi_release (n); +// return r; +//} diff --git a/crypto.h b/crypto.h index c7ba816..28bf4eb 100644 --- a/crypto.h +++ b/crypto.h @@ -25,13 +25,18 @@ #include #include +extern gcry_mpi_point_t ec_gen; +extern gcry_ctx_t ec_ctx; + + +void brandt_crypto_init (); + + /* --- RANDOM --- */ - void brandt_rand_poll (); - /* --- HASHING --- */ struct brandt_hash_code { @@ -41,31 +46,16 @@ struct brandt_hash_code { void brandt_hash (const void *block, size_t size, struct brandt_hash_code *ret); - /* --- MPI --- */ void brandt_mpi_print_unsigned (void *buf, size_t size, gcry_mpi_t val); -void brandt_mpi_scan_unsigned (gcry_mpi_t *result, const void *data, - size_t size); +void brandt_mpi_scan_unsigned (gcry_mpi_t *result, const void *data, size_t size); +/* --- EC --- */ -/* --- ECDHE --- */ - -struct brandt_dhe_skey { - unsigned char d[256 / 8]; -}; - -struct brandt_dhe_pkey { - unsigned char q_y[256 / 8]; -}; - -void brandt_ecdhe_key_create (struct brandt_dhe_skey *priv); -void brandt_ecdhe_key_get_public (const struct brandt_dhe_skey *priv, - struct brandt_dhe_pkey *pub); -int brandt_ecdhe (const struct brandt_dhe_skey *priv, - const struct brandt_dhe_pkey *pub, - struct brandt_hash_code *key_material); -void brandt_ecdhe_key_clear (struct brandt_dhe_skey *priv); +void brandt_ec_skey_create (gcry_mpi_t* skey); +void brandt_ec_pkey_compute (gcry_mpi_point_t* pkey, const gcry_mpi_t skey); +void brandt_ec_keypair_create (gcry_mpi_point_t* pkey, gcry_mpi_t* skey); #endif /* ifndef _BRANDT_CRYPTO_H */ diff --git a/test.h b/test.h new file mode 100644 index 0000000..db63350 --- /dev/null +++ b/test.h @@ -0,0 +1,12 @@ +#ifndef _BRANDT_TEST_H +#define _BRANDT_TEST_H + +#include + +int tests_run = 0; +int ret = 0; + +#define check(cond, message) do { if (!(cond)) { fputs(message, stderr); return 0; } } while (0) +#define run(test) do { tests_run++; if (!test()) ret = 1; } while (0) + +#endif diff --git a/test_crypto.c b/test_crypto.c new file mode 100644 index 0000000..67894eb --- /dev/null +++ b/test_crypto.c @@ -0,0 +1,59 @@ + +#include "brandt.h" +#include "crypto.h" +#include "test.h" + +int +test_brandt_ec_keypair_create () +{ + gcry_mpi_t skey; + gcry_mpi_t x1 = gcry_mpi_new(0); + gcry_mpi_t x2 = gcry_mpi_new(0); + gcry_mpi_t y1 = gcry_mpi_new(0); + gcry_mpi_t y2 = gcry_mpi_new(0); + gcry_mpi_point_t pkey1; + gcry_mpi_point_t pkey2 = gcry_mpi_point_new(0); + + brandt_ec_keypair_create (&pkey1, &skey); + check(skey, "no sec key created"); + check(pkey1, "no pub key created"); + check(pkey2, "could not init pkey2"); + check(x1, "could not init x1"); + check(x2, "could not init x2"); + check(y1, "could not init y1"); + check(y2, "could not init y2"); + + gcry_mpi_ec_mul(pkey2, skey, ec_gen, ec_ctx); + check(!gcry_mpi_ec_get_affine(x1, y1, pkey1, ec_ctx), "could not get affine coords for pkey1"); + check(!gcry_mpi_ec_get_affine(x2, y2, pkey2, ec_ctx), "could not get affine coords for pkey1"); + check(!gcry_mpi_cmp(x1, x2), "x component does not match"); + check(!gcry_mpi_cmp(y1, y2), "y component does not match"); + + gcry_mpi_release(skey); + gcry_mpi_release(x1); + gcry_mpi_release(x2); + gcry_mpi_release(y1); + gcry_mpi_release(y2); + gcry_mpi_point_release(pkey1); + gcry_mpi_point_release(pkey2); +} + +int +main (int argc, char *argv[]) +{ + int repeat = 100; + int i; + + BRANDT_init(); + + for (i = 0; i < repeat; i++) + { + run(test_brandt_ec_keypair_create); + } + + if (!ret) + { + fputs("All tests passed", stderr); + } + return ret; +}