Skip to content

Commit

Permalink
Move ECDH into its own module
Browse files Browse the repository at this point in the history
  • Loading branch information
apoelstra committed Jul 29, 2015
1 parent d51027a commit e0e7987
Show file tree
Hide file tree
Showing 13 changed files with 292 additions and 227 deletions.
14 changes: 7 additions & 7 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ noinst_HEADERS += src/group.h
noinst_HEADERS += src/group_impl.h
noinst_HEADERS += src/num_gmp.h
noinst_HEADERS += src/num_gmp_impl.h
noinst_HEADERS += src/ecdh.h
noinst_HEADERS += src/ecdh_impl.h
noinst_HEADERS += src/ecdsa.h
noinst_HEADERS += src/ecdsa_impl.h
noinst_HEADERS += src/eckey.h
noinst_HEADERS += src/eckey_impl.h
noinst_HEADERS += src/ecmult.h
noinst_HEADERS += src/ecmult_impl.h
noinst_HEADERS += src/ecmult_const.h
noinst_HEADERS += src/ecmult_const_impl.h
noinst_HEADERS += src/ecmult_gen.h
noinst_HEADERS += src/ecmult_gen_impl.h
noinst_HEADERS += src/num.h
Expand Down Expand Up @@ -51,7 +51,7 @@ libsecp256k1_la_LIBADD = $(SECP_LIBS)

noinst_PROGRAMS =
if USE_BENCHMARK
noinst_PROGRAMS += bench_verify bench_recover bench_sign bench_internal bench_ecdh
noinst_PROGRAMS += bench_verify bench_recover bench_sign bench_internal
bench_verify_SOURCES = src/bench_verify.c
bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS)
bench_verify_LDFLAGS = -static
Expand All @@ -65,10 +65,6 @@ bench_internal_SOURCES = src/bench_internal.c
bench_internal_LDADD = $(SECP_LIBS)
bench_internal_LDFLAGS = -static
bench_internal_CPPFLAGS = $(SECP_INCLUDES)
bench_ecdh_SOURCES = src/bench_ecdh.c
bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS)
bench_ecdh_LDFLAGS = -static
bench_ecdh_CPPFLAGS = $(SECP_INCLUDES)
endif

if USE_TESTS
Expand Down Expand Up @@ -101,3 +97,7 @@ CLEANFILES = gen_context src/ecmult_static_context.h
endif

EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h

if ENABLE_MODULE_ECDH
include src/modules/ecdh/Makefile.am.include
endif
11 changes: 11 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ AC_ARG_ENABLE(ecmult_static_precomputation,
[use_ecmult_static_precomputation=$enableval],
[use_ecmult_static_precomputation=yes])

AC_ARG_ENABLE(module_ecdh,
AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation (default is no)]),
[enable_module_ecdh=$enableval],
[enable_module_ecdh=no])

AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto],
[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto])

Expand Down Expand Up @@ -315,13 +320,18 @@ if test x"$use_ecmult_static_precomputation" = x"yes"; then
AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table])
fi

if test x"$enable_module_ecdh" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_ECDH, 1, [Define this symbol to enable the ECDH module])
fi

AC_C_BIGENDIAN()

AC_MSG_NOTICE([Using assembly optimizations: $set_asm])
AC_MSG_NOTICE([Using field implementation: $set_field])
AC_MSG_NOTICE([Using bignum implementation: $set_bignum])
AC_MSG_NOTICE([Using scalar implementation: $set_scalar])
AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism])
AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh])

AC_CONFIG_HEADERS([src/libsecp256k1-config.h])
AC_CONFIG_FILES([Makefile libsecp256k1.pc])
Expand All @@ -332,6 +342,7 @@ AC_SUBST(SECP_TEST_INCLUDES)
AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"])
AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"])
AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$use_ecmult_static_precomputation" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"])

dnl make sure nothing new is exported so that we don't break the cache
PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH"
Expand Down
16 changes: 0 additions & 16 deletions include/secp256k1.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,22 +339,6 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(
secp256k1_pubkey_t *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

/** Compute an EC Diffie-Hellman secret in constant time
* Returns: 1: exponentiation was successful
* 0: scalar was invalid (zero or overflow)
* In: ctx: pointer to a context object (cannot be NULL)
* point: pointer to a public point
* scalar: a 32-byte scalar with which to multiply the point
* Out: result: a 32-byte array which will be populated by an ECDH
* secret computed from the point and scalar
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
const secp256k1_context_t* ctx,
unsigned char *result,
const secp256k1_pubkey_t *point,
const unsigned char *scalar
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

/** Verify an ECDSA secret key.
* Returns: 1: secret key is valid
* 0: secret key is invalid
Expand Down
30 changes: 30 additions & 0 deletions include/secp256k1_ecdh.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef _SECP256K1_ECDH_
# define _SECP256K1_ECDH_

# include "secp256k1.h"

# ifdef __cplusplus
extern "C" {
# endif

/** Compute an EC Diffie-Hellman secret in constant time
* Returns: 1: exponentiation was successful
* 0: scalar was invalid (zero or overflow)
* In: ctx: pointer to a context object (cannot be NULL)
* point: pointer to a public point
* scalar: a 32-byte scalar with which to multiply the point
* Out: result: a 32-byte array which will be populated by an ECDH
* secret computed from the point and scalar
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
const secp256k1_context_t* ctx,
unsigned char *result,
const secp256k1_pubkey_t *point,
const unsigned char *scalar
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

# ifdef __cplusplus
}
# endif

#endif
1 change: 1 addition & 0 deletions src/bench_ecdh.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <string.h>

#include "include/secp256k1.h"
#include "include/secp256k1_ecdh.h"
#include "util.h"
#include "bench.h"

Expand Down
7 changes: 3 additions & 4 deletions src/bench_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "field_impl.h"
#include "group_impl.h"
#include "scalar_impl.h"
#include "ecdh_impl.h"
#include "ecmult_const_impl.h"
#include "ecmult_impl.h"
#include "bench.h"

Expand Down Expand Up @@ -241,12 +241,11 @@ void bench_ecdh_wnaf(void* arg) {
bench_inv_t *data = (bench_inv_t*)arg;

for (i = 0; i < 20000; i++) {
secp256k1_ecdh_wnaf(data->wnaf, data->scalar_x, WINDOW_A);
secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A);
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
}
}


void bench_sha256(void* arg) {
int i;
bench_inv_t *data = (bench_inv_t*)arg;
Expand Down Expand Up @@ -321,7 +320,7 @@ int main(int argc, char **argv) {
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, 200000);
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, 200000);

if (have_flag(argc, argv, "ecdh") || have_flag(argc, argv, "wnaf")) run_benchmark("ecdh_wnaf", bench_ecdh_wnaf, bench_setup, NULL, &data, 10, 20000);
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_const_wnaf", bench_ecdh_wnaf, bench_setup, NULL, &data, 10, 20000);
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000);

if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, 20000);
Expand Down
8 changes: 4 additions & 4 deletions src/ecdh.h → src/ecmult_const.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/**********************************************************************
* Copyright (c) 2015 Pieter Wuille, Andrew Poelstra *
* Copyright (c) 2015 Andrew Poelstra *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#ifndef _SECP256K1_ECDH_
#define _SECP256K1_ECDH_
#ifndef _SECP256K1_ECMULT_CONST_
#define _SECP256K1_ECMULT_CONST_

#include "scalar.h"
#include "group.h"

static void secp256k1_point_multiply(secp256k1_gej_t *r, const secp256k1_ge_t *a, const secp256k1_scalar_t *q);
static void secp256k1_ecmult_const(secp256k1_gej_t *r, const secp256k1_ge_t *a, const secp256k1_scalar_t *q);

#endif
16 changes: 8 additions & 8 deletions src/ecdh_impl.h → src/ecmult_const_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#ifndef _SECP256K1_ECDH_IMPL_
#define _SECP256K1_ECDH_IMPL_
#ifndef _SECP256K1_ECMULT_CONST_IMPL_
#define _SECP256K1_ECMULT_CONST_IMPL_

#include "scalar.h"
#include "group.h"
#include "ecdh.h"
#include "ecmult_const.h"
#include "ecmult_impl.h"

#ifdef USE_ENDOMORPHISM
Expand Down Expand Up @@ -53,7 +53,7 @@
*
* Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335
*/
static int secp256k1_ecdh_wnaf(int *wnaf, secp256k1_scalar_t s, int w) {
static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar_t s, int w) {
int global_sign = 1;
int skew = 0;
int word = 0;
Expand Down Expand Up @@ -119,7 +119,7 @@ static int secp256k1_ecdh_wnaf(int *wnaf, secp256k1_scalar_t s, int w) {
}


static void secp256k1_point_multiply(secp256k1_gej_t *r, const secp256k1_ge_t *a, const secp256k1_scalar_t *scalar) {
static void secp256k1_ecmult_const(secp256k1_gej_t *r, const secp256k1_ge_t *a, const secp256k1_scalar_t *scalar) {
secp256k1_ge_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ge_t tmpa;
secp256k1_fe_t Z;
Expand All @@ -144,16 +144,16 @@ static void secp256k1_point_multiply(secp256k1_gej_t *r, const secp256k1_ge_t *a
secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc);
/* no need for zero correction when using endomorphism since even
* numbers have one added to them anyway */
skew_1 = secp256k1_ecdh_wnaf(wnaf_1, q_1, WINDOW_A - 1);
skew_lam = secp256k1_ecdh_wnaf(wnaf_lam, q_lam, WINDOW_A - 1);
skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1);
skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1);
#else
int is_zero = secp256k1_scalar_is_zero(scalar);
/* the wNAF ladder cannot handle zero, so bump this to one .. we will
* correct the result after the fact */
sc.d[0] += is_zero;
VERIFY_CHECK(!secp256k1_scalar_is_zero(&sc));

secp256k1_ecdh_wnaf(wnaf, sc, WINDOW_A - 1);
secp256k1_wnaf_const(wnaf, sc, WINDOW_A - 1);
#endif

/* Calculate odd multiples of a.
Expand Down
9 changes: 9 additions & 0 deletions src/modules/ecdh/Makefile.am.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
include_HEADERS += include/secp256k1_ecdh.h
noinst_HEADERS += src/modules/ecdh/main_impl.h
noinst_HEADERS += src/modules/ecdh/tests_impl.h
if USE_BENCHMARK
noinst_PROGRAMS += bench_ecdh
bench_ecdh_SOURCES = src/bench_ecdh.c
bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS)
bench_ecdh_LDFLAGS = -static
endif
53 changes: 53 additions & 0 deletions src/modules/ecdh/main_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**********************************************************************
* Copyright (c) 2015 Andrew Poelstra *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#ifndef _SECP256K1_MODULE_ECDH_MAIN_
#define _SECP256K1_MODULE_ECDH_MAIN_

#include "ecmult_const_impl.h"

int secp256k1_ecdh(const secp256k1_context_t* ctx, unsigned char *result, const secp256k1_pubkey_t *point, const unsigned char *scalar) {
int ret = 0;
int overflow = 0;
secp256k1_gej_t res;
secp256k1_ge_t pt;
secp256k1_scalar_t s;
ARG_CHECK(result != NULL);
ARG_CHECK(point != NULL);
ARG_CHECK(scalar != NULL);
(void)ctx;

secp256k1_pubkey_load(ctx, &pt, point);
secp256k1_scalar_set_b32(&s, scalar, &overflow);
if (overflow || secp256k1_scalar_is_zero(&s)) {
ret = 0;
} else {
unsigned char x[32];
unsigned char y[1];
secp256k1_sha256_t sha;

secp256k1_ecmult_const(&res, &pt, &s);
secp256k1_ge_set_gej(&pt, &res);
/* Compute a hash of the point in compressed form
* Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not
* expect its output to be secret and has a timing sidechannel. */
secp256k1_fe_normalize(&pt.x);
secp256k1_fe_normalize(&pt.y);
secp256k1_fe_get_b32(x, &pt.x);
y[0] = 0x02 | secp256k1_fe_is_odd(&pt.y);

secp256k1_sha256_initialize(&sha);
secp256k1_sha256_write(&sha, y, sizeof(y));
secp256k1_sha256_write(&sha, x, sizeof(x));
secp256k1_sha256_finalize(&sha, result);
ret = 1;
}

secp256k1_scalar_clear(&s);
return ret;
}

#endif
48 changes: 48 additions & 0 deletions src/modules/ecdh/tests_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**********************************************************************
* Copyright (c) 2015 Andrew Poelstra *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#ifndef _SECP256K1_MODULE_ECDH_TESTS_
#define _SECP256K1_MODULE_ECDH_TESTS_

void test_ecdh_generator_basepoint(void) {
unsigned char s_one[32] = { 0 };
secp256k1_pubkey_t point[2];
int i;

s_one[31] = 1;
/* Check against pubkey creation when the basepoint is the generator */
for (i = 0; i < 100; ++i) {
secp256k1_sha256_t sha;
unsigned char s_b32[32];
unsigned char output_ecdh[32];
unsigned char output_ser[32];
unsigned char point_ser[33];
int point_ser_len = sizeof(point_ser);
secp256k1_scalar_t s;

random_scalar_order(&s);
secp256k1_scalar_get_b32(s_b32, &s);

/* compute using ECDH function */
CHECK(secp256k1_ec_pubkey_create(ctx, &point[0], s_one) == 1);
CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32) == 1);
/* compute "explicitly" */
CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1);
CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], 1) == 1);
CHECK(point_ser_len == sizeof(point_ser));
secp256k1_sha256_initialize(&sha);
secp256k1_sha256_write(&sha, point_ser, point_ser_len);
secp256k1_sha256_finalize(&sha, output_ser);
/* compare */
CHECK(memcmp(output_ecdh, output_ser, sizeof(output_ser)) == 0);
}
}

void run_ecdh_tests(void) {
test_ecdh_generator_basepoint();
}

#endif
Loading

0 comments on commit e0e7987

Please sign in to comment.