Skip to content

Commit

Permalink
tests: Add Wycheproof ECDH vectors
Browse files Browse the repository at this point in the history
Adds a test for the ECDH module using the Wycheproof vectors.
We use a python script to convert the JSON-formatted vectors
into C code, in the same spirit as #1245

Co-authored-by: Sean Andersen <6730974+andozw@users.noreply.github.com>
  • Loading branch information
RandomLattice and andozw committed Feb 4, 2024
1 parent 0653a25 commit f26c323
Show file tree
Hide file tree
Showing 10 changed files with 10,615 additions and 11 deletions.
14 changes: 12 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,17 @@ maintainer-clean-local: clean-precomp
### (see the comments in the previous section for detailed rationale)
TESTVECTORS = src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h

if ENABLE_MODULE_ECDH
TESTVECTORS += src/wycheproof/ecdh_secp256k1_test.h
endif

src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h:
mkdir -p $(@D)
python3 $(top_srcdir)/tools/tests_wycheproof_generate.py $(top_srcdir)/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json > $@
python3 $(top_srcdir)/tools/tests_wycheproof_generate_ecdsa.py $(top_srcdir)/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json > $@

src/wycheproof/ecdh_secp256k1_test.h:
mkdir -p $(@D)
python3 $(top_srcdir)/tools/tests_wycheproof_generate_ecdh.py $(top_srcdir)/src/wycheproof/ecdh_secp256k1_test.json > $@

testvectors: $(TESTVECTORS)

Expand All @@ -250,7 +258,9 @@ EXTRA_DIST += sage/secp256k1_params.sage
EXTRA_DIST += sage/weierstrass_prover.sage
EXTRA_DIST += src/wycheproof/WYCHEPROOF_COPYING
EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json
EXTRA_DIST += tools/tests_wycheproof_generate.py
EXTRA_DIST += src/wycheproof/ecdh_secp256k1_test.json
EXTRA_DIST += tools/tests_wycheproof_generate_ecdsa.py
EXTRA_DIST += tools/tests_wycheproof_generate_ecdh.py

if ENABLE_MODULE_ECDH
include src/modules/ecdh/Makefile.am.include
Expand Down
1 change: 1 addition & 0 deletions src/modules/ecdh/Makefile.am.include
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ include_HEADERS += include/secp256k1_ecdh.h
noinst_HEADERS += src/modules/ecdh/main_impl.h
noinst_HEADERS += src/modules/ecdh/tests_impl.h
noinst_HEADERS += src/modules/ecdh/bench_impl.h
noinst_HEADERS += src/wycheproof/ecdh_secp256k1_test.h
50 changes: 50 additions & 0 deletions src/modules/ecdh/tests_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
#ifndef SECP256K1_MODULE_ECDH_TESTS_H
#define SECP256K1_MODULE_ECDH_TESTS_H

static int ecdh_hash_function_test_xpassthru(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
(void)x;
(void)y;
(void)data;
memcpy(output, x, 32);
return 1;
}

static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
(void)output;
(void)x;
Expand Down Expand Up @@ -142,11 +150,53 @@ static void test_result_basepoint(void) {
}
}

static void test_ecdh_wycheproof(void) {
#include "../../wycheproof/ecdh_secp256k1_test.h"
int t;
for (t = 0; t < SECP256K1_ECDH_WYCHEPROOF_NUMBER_TESTVECTORS; t++) {
int parsed_ok;
secp256k1_pubkey point;
const unsigned char *pk;
const unsigned char *sk;
const unsigned char *expected_shared_secret;
unsigned char output_ecdh[65] = { 0 };

int expected_result;
int actual;

memset(&point, 0, sizeof(point));
pk = &wycheproof_ecdh_public_keys[testvectors[t].pk_offset];
parsed_ok = secp256k1_ec_pubkey_parse(CTX, &point, pk, testvectors[t].pk_len);

expected_result = testvectors[t].expected_result;

/* fail if public key is valid, but doesn't parse */
CHECK(parsed_ok || expected_result == 0);

if (!parsed_ok && expected_result == 0) {
continue;
}

sk = &wycheproof_ecdh_private_keys[testvectors[t].sk_offset];
CHECK(testvectors[t].sk_len == 32);

actual = secp256k1_ecdh(CTX, output_ecdh, &point, sk, ecdh_hash_function_test_xpassthru, NULL);
expected_shared_secret = &wycheproof_ecdh_shared_secrets[testvectors[t].shared_offset];

CHECK(actual == expected_result);
if (expected_result == 0) {
CHECK(testvectors[t].shared_len == 0);
}
CHECK(secp256k1_memcmp_var(output_ecdh, expected_shared_secret, testvectors[t].shared_len) == 0);
}
}

static void run_ecdh_tests(void) {
test_ecdh_api();
test_ecdh_generator_basepoint();
test_bad_scalar();
test_result_basepoint();
test_ecdh_wycheproof();
}

#endif /* SECP256K1_MODULE_ECDH_TESTS_H */
11 changes: 10 additions & 1 deletion src/wycheproof/WYCHEPROOF_COPYING
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@
`b063b4aedae951c69df014cd25fa6d69ae9e8cb9`, see
https://github.com/google/wycheproof/blob/b063b4aedae951c69df014cd25fa6d69ae9e8cb9/testvectors_v1/ecdsa_secp256k1_sha256_bitcoin_test.json

* The file `ecdh_secp256k1_test.json` in this directory
comes from Google's project Wycheproof with git commit
`d9f6ec7d8bd8c96da05368999094e4a75ba5cb3d`, see
https://github.com/google/wycheproof/blob/d9f6ec7d8bd8c96da05368999094e4a75ba5cb3d/testvectors_v1/ecdh_secp256k1_test.json

* The file `ecdsa_secp256k1_sha256_bitcoin_test.h` is generated from
`ecdsa_secp256k1_sha256_bitcoin_test.json` using the script
`tests_wycheproof_generate.py`.
`tests_wycheproof_generate_ecdsa.py`.

* The file `ecdh_secp256k1_test.h` is generated from
`ecdh_secp256k1_test.json` using the script
`tests_wycheproof_generate_ecdh.py`.

-------------------------------------------------------------------------------

Expand Down
Loading

0 comments on commit f26c323

Please sign in to comment.