Skip to content

Commit

Permalink
[ECDH API change] Allow pass arbitrary data to hash function
Browse files Browse the repository at this point in the history
  • Loading branch information
fanatid committed May 16, 2018
1 parent b00be65 commit c8fbc3c
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 19 deletions.
8 changes: 6 additions & 2 deletions include/secp256k1_ecdh.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ extern "C" {
* Out: output: pointer to an array to be filled by the function
* In: x: pointer to a 32-byte x coordinate
* y: pointer to a 32-byte y coordinate
* data: Arbitrary data pointer that is passed through
*/
typedef int (*secp256k1_ecdh_hash_function)(
unsigned char *output,
const unsigned char *x,
const unsigned char *y
const unsigned char *y,
void *data
);

/** An implementation of SHA256 hash function that applies to compressed public key. */
Expand All @@ -35,13 +37,15 @@ SECP256K1_API extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_func
* initialized public key
* privkey: a 32-byte scalar with which to multiply the point
* hashfp: pointer to a hash function. If NULL, secp256k1_ecdh_hash_function_sha256 is used
* data: Arbitrary data pointer that is passed through
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
const secp256k1_context* ctx,
unsigned char *output,
const secp256k1_pubkey *pubkey,
const unsigned char *privkey,
secp256k1_ecdh_hash_function hashfp
secp256k1_ecdh_hash_function hashfp,
void *data
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

#ifdef __cplusplus
Expand Down
2 changes: 1 addition & 1 deletion src/bench_ecdh.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static void bench_ecdh(void* arg) {
bench_ecdh_data *data = (bench_ecdh_data*)arg;

for (i = 0; i < 20000; i++) {
CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar, NULL) == 1);
CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar, NULL, NULL) == 1);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/java/org_bitcoin_NativeSecp256k1.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1e
nonce_res,
&pubkey,
secdata,
NULL,
NULL
);
}
Expand Down
7 changes: 4 additions & 3 deletions src/modules/ecdh/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
#include "include/secp256k1_ecdh.h"
#include "ecmult_const_impl.h"

static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char *x, const unsigned char *y) {
static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
unsigned char version = (y[31] & 0x01) | 0x02;
secp256k1_sha256 sha;
(void)data;

secp256k1_sha256_initialize(&sha);
secp256k1_sha256_write(&sha, &version, 1);
Expand All @@ -25,7 +26,7 @@ static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char
const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256 = ecdh_hash_function_sha256;
const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default = ecdh_hash_function_sha256;

int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pubkey *point, const unsigned char *scalar, secp256k1_ecdh_hash_function hashfp) {
int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pubkey *point, const unsigned char *scalar, secp256k1_ecdh_hash_function hashfp, void *data) {
int ret = 0;
int overflow = 0;
secp256k1_gej res;
Expand Down Expand Up @@ -56,7 +57,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se
secp256k1_fe_get_b32(x, &pt.x);
secp256k1_fe_get_b32(y, &pt.y);

ret = hashfp(output, x, y);
ret = hashfp(output, x, y, data);
}

secp256k1_scalar_clear(&s);
Expand Down
28 changes: 15 additions & 13 deletions src/modules/ecdh/tests_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@
#ifndef SECP256K1_MODULE_ECDH_TESTS_H
#define SECP256K1_MODULE_ECDH_TESTS_H

int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y) {
int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
(void)output;
(void)x;
(void)y;
(void)data;
return 0;
}

int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y) {
int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
(void)data;
/* Save x and y as uncompressed public key */
output[0] = 0x04;
memcpy(output + 1, x, 32);
Expand All @@ -36,15 +38,15 @@ void test_ecdh_api(void) {
CHECK(secp256k1_ec_pubkey_create(tctx, &point, s_one) == 1);

/* Check all NULLs are detected */
CHECK(secp256k1_ecdh(tctx, res, &point, s_one, NULL) == 1);
CHECK(secp256k1_ecdh(tctx, res, &point, s_one, NULL, NULL) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_ecdh(tctx, NULL, &point, s_one, NULL) == 0);
CHECK(secp256k1_ecdh(tctx, NULL, &point, s_one, NULL, NULL) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_ecdh(tctx, res, NULL, s_one, NULL) == 0);
CHECK(secp256k1_ecdh(tctx, res, NULL, s_one, NULL, NULL) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_ecdh(tctx, res, &point, NULL, NULL) == 0);
CHECK(secp256k1_ecdh(tctx, res, &point, NULL, NULL, NULL) == 0);
CHECK(ecount == 3);
CHECK(secp256k1_ecdh(tctx, res, &point, s_one, NULL) == 1);
CHECK(secp256k1_ecdh(tctx, res, &point, s_one, NULL, NULL) == 1);
CHECK(ecount == 3);

/* Cleanup */
Expand Down Expand Up @@ -74,14 +76,14 @@ void test_ecdh_generator_basepoint(void) {
CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1);

/* compute using ECDH function with custom hash function */
CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom) == 1);
CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom, NULL) == 1);
/* compute "explicitly" */
CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1);
/* compare */
CHECK(memcmp(output_ecdh, point_ser, 65) == 0);

/* compute using ECDH function with default hash function */
CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32, NULL) == 1);
CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32, NULL, NULL) == 1);
/* compute "explicitly" */
CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1);
secp256k1_sha256_initialize(&sha);
Expand Down Expand Up @@ -111,14 +113,14 @@ void test_bad_scalar(void) {
CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_rand) == 1);

/* Try to multiply it by bad values */
CHECK(secp256k1_ecdh(ctx, output, &point, s_zero, NULL) == 0);
CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, NULL) == 0);
CHECK(secp256k1_ecdh(ctx, output, &point, s_zero, NULL, NULL) == 0);
CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, NULL, NULL) == 0);
/* ...and a good one */
s_overflow[31] -= 1;
CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, NULL) == 1);
CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, NULL, NULL) == 1);

/* Hash function failure results in ecdh failure */
CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, ecdh_hash_function_test_fail) == 0);
CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, ecdh_hash_function_test_fail, NULL) == 0);
}

void run_ecdh_tests(void) {
Expand Down

0 comments on commit c8fbc3c

Please sign in to comment.