add tests for key generation

This commit is contained in:
Markus Teich 2016-06-12 20:52:22 +02:00
parent 5957a77707
commit 62b87e57a7
7 changed files with 274 additions and 63 deletions

View File

@ -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)

27
brandt.c Normal file
View File

@ -0,0 +1,27 @@
#include <gcrypt.h>
#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();
}

View File

@ -22,6 +22,9 @@
#ifndef _BRANDT_BRANDT_H
#define _BRANDT_BRANDT_H
#include <unistd.h>
#include <stdint.h>
/**
* FIXME.
*/
@ -86,6 +89,9 @@ typedef void
uint16_t price);
void
BRANDT_init ();
/**
* Join an auction described by the @a auction_data parameter.
*

190
crypto.c
View File

@ -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;
//}

View File

@ -25,13 +25,18 @@
#include <gcrypt.h>
#include <stdint.h>
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 */

12
test.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef _BRANDT_TEST_H
#define _BRANDT_TEST_H
#include <stdio.h>
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

59
test_crypto.c Normal file
View File

@ -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;
}