Bitcoin Core  31.0.0
P2P Digital Currency
tests_impl.h
Go to the documentation of this file.
1 /***********************************************************************
2  * Copyright (c) 2015 Andrew Poelstra *
3  * Distributed under the MIT software license, see the accompanying *
4  * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
5  ***********************************************************************/
6 
7 #ifndef SECP256K1_MODULE_ECDH_TESTS_H
8 #define SECP256K1_MODULE_ECDH_TESTS_H
9 
10 #include "../../unit_test.h"
11 
12 static int ecdh_hash_function_test_xpassthru(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
13  (void)y;
14  (void)data;
15  memcpy(output, x, 32);
16  return 1;
17 }
18 
19 static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
20  (void)output;
21  (void)x;
22  (void)y;
23  (void)data;
24  return 0;
25 }
26 
27 static int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
28  (void)data;
29  /* Save x and y as uncompressed public key */
30  output[0] = 0x04;
31  memcpy(output + 1, x, 32);
32  memcpy(output + 33, y, 32);
33  return 1;
34 }
35 
36 static void test_ecdh_api(void) {
37  secp256k1_pubkey point;
38  unsigned char res[32];
39  unsigned char s_one[32] = { 0 };
40  s_one[31] = 1;
41 
42  CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_one) == 1);
43 
44  /* Check all NULLs are detected */
45  CHECK(secp256k1_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1);
46  CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, NULL, &point, s_one, NULL, NULL));
47  CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, res, NULL, s_one, NULL, NULL));
48  CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, res, &point, NULL, NULL, NULL));
49  CHECK(secp256k1_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1);
50 }
51 
52 static void test_ecdh_generator_basepoint(void) {
53  unsigned char s_one[32] = { 0 };
54  secp256k1_pubkey point[2];
55  int i;
56 
57  s_one[31] = 1;
58  /* Check against pubkey creation when the basepoint is the generator */
59  for (i = 0; i < 2 * COUNT; ++i) {
60  secp256k1_sha256 sha;
61  unsigned char s_b32[32];
62  unsigned char output_ecdh[65];
63  unsigned char output_ser[32];
64  unsigned char point_ser[65];
65  size_t point_ser_len = sizeof(point_ser);
67 
69  secp256k1_scalar_get_b32(s_b32, &s);
70 
71  CHECK(secp256k1_ec_pubkey_create(CTX, &point[0], s_one) == 1);
72  CHECK(secp256k1_ec_pubkey_create(CTX, &point[1], s_b32) == 1);
73 
74  /* compute using ECDH function with custom hash function */
75  CHECK(secp256k1_ecdh(CTX, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom, NULL) == 1);
76  /* compute "explicitly" */
77  CHECK(secp256k1_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1);
78  /* compare */
79  CHECK(secp256k1_memcmp_var(output_ecdh, point_ser, 65) == 0);
80 
81  /* compute using ECDH function with default hash function */
82  CHECK(secp256k1_ecdh(CTX, output_ecdh, &point[0], s_b32, NULL, NULL) == 1);
83  /* compute "explicitly" */
84  CHECK(secp256k1_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1);
86  secp256k1_sha256_write(&sha, point_ser, point_ser_len);
87  secp256k1_sha256_finalize(&sha, output_ser);
88  /* compare */
89  CHECK(secp256k1_memcmp_var(output_ecdh, output_ser, 32) == 0);
90  }
91 }
92 
93 static void test_bad_scalar(void) {
94  unsigned char s_zero[32] = { 0 };
95  unsigned char s_overflow[32] = { 0 };
96  unsigned char s_rand[32] = { 0 };
97  unsigned char output[32];
98  secp256k1_scalar rand;
99  secp256k1_pubkey point;
100 
101  /* Create random point */
103  secp256k1_scalar_get_b32(s_rand, &rand);
104  CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_rand) == 1);
105 
106  /* Try to multiply it by bad values */
107  memcpy(s_overflow, secp256k1_group_order_bytes, 32);
108  CHECK(secp256k1_ecdh(CTX, output, &point, s_zero, NULL, NULL) == 0);
109  CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 0);
110  /* ...and a good one */
111  s_overflow[31] -= 1;
112  CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 1);
113 
114  /* Hash function failure results in ecdh failure */
115  CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, ecdh_hash_function_test_fail, NULL) == 0);
116 }
117 
119 static void test_result_basepoint(void) {
120  secp256k1_pubkey point;
121  secp256k1_scalar rand;
122  unsigned char s[32];
123  unsigned char s_inv[32];
124  unsigned char out[32];
125  unsigned char out_inv[32];
126  unsigned char out_base[32];
127  int i;
128 
129  unsigned char s_one[32] = { 0 };
130  s_one[31] = 1;
131  CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_one) == 1);
132  CHECK(secp256k1_ecdh(CTX, out_base, &point, s_one, NULL, NULL) == 1);
133 
134  for (i = 0; i < 2 * COUNT; i++) {
136  secp256k1_scalar_get_b32(s, &rand);
137  secp256k1_scalar_inverse(&rand, &rand);
138  secp256k1_scalar_get_b32(s_inv, &rand);
139 
140  CHECK(secp256k1_ec_pubkey_create(CTX, &point, s) == 1);
141  CHECK(secp256k1_ecdh(CTX, out, &point, s_inv, NULL, NULL) == 1);
142  CHECK(secp256k1_memcmp_var(out, out_base, 32) == 0);
143 
144  CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_inv) == 1);
145  CHECK(secp256k1_ecdh(CTX, out_inv, &point, s, NULL, NULL) == 1);
146  CHECK(secp256k1_memcmp_var(out_inv, out_base, 32) == 0);
147  }
148 }
149 
150 static void test_ecdh_wycheproof(void) {
151 #include "../../wycheproof/ecdh_secp256k1_test.h"
152  int t;
154  int parsed_ok;
155  secp256k1_pubkey point;
156  const unsigned char *pk;
157  const unsigned char *sk;
158  const unsigned char *expected_shared_secret;
159  unsigned char output_ecdh[65] = { 0 };
160 
161  int expected_result;
162 
163  memset(&point, 0, sizeof(point));
165  parsed_ok = secp256k1_ec_pubkey_parse(CTX, &point, pk, testvectors[t].pk_len);
166 
168  CHECK(parsed_ok == expected_result);
169  if (!parsed_ok) {
170  continue;
171  }
172 
174  CHECK(testvectors[t].sk_len == 32);
175 
176  CHECK(secp256k1_ecdh(CTX, output_ecdh, &point, sk, ecdh_hash_function_test_xpassthru, NULL) == 1);
177  expected_shared_secret = &wycheproof_ecdh_shared_secrets[testvectors[t].shared_offset];
178 
179  CHECK(secp256k1_memcmp_var(output_ecdh, expected_shared_secret, testvectors[t].shared_len) == 0);
180  }
181 }
182 
183 /* --- Test registry --- */
184 static const struct tf_test_entry tests_ecdh[] = {
190 };
191 
192 #endif /* SECP256K1_MODULE_ECDH_TESTS_H */
#define CASE1(name)
Definition: unit_test.h:25
static int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data)
Definition: tests_impl.h:27
static void test_bad_scalar(void)
Definition: tests_impl.h:93
static const unsigned char wycheproof_ecdh_shared_secrets[]
static const unsigned char secp256k1_group_order_bytes[32]
Definition: testutil.h:15
SECP256K1_API int secp256k1_ec_pubkey_serialize(const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey *pubkey, unsigned int flags) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Serialize a pubkey object into a serialized byte sequence.
Definition: secp256k1.c:268
memcpy(result.begin(), stream.data(), stream.size())
static const struct tf_test_entry tests_ecdh[]
Definition: tests_impl.h:184
#define SECP256K1_ECDH_WYCHEPROOF_NUMBER_TESTVECTORS
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Compute the public key for a secret key.
Definition: secp256k1.c:612
#define SECP256K1_EC_UNCOMPRESSED
Definition: secp256k1.h:225
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize.
Definition: secp256k1.h:224
static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *a)
Compute the inverse of a scalar (modulo the group order).
static void test_ecdh_wycheproof(void)
Definition: tests_impl.h:150
static void test_ecdh_generator_basepoint(void)
Definition: tests_impl.h:52
Definition: unit_test.h:51
static void test_ecdh_api(void)
Definition: tests_impl.h:36
static secp256k1_context * CTX
Definition: tests.c:42
static void testutil_random_scalar_order(secp256k1_scalar *num)
Definition: testutil.h:133
static int ecdh_hash_function_test_xpassthru(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data)
Definition: tests_impl.h:12
#define CHECK(cond)
Unconditional failure on condition failure.
Definition: util.h:35
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *input, size_t inputlen) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse a variable-length public key into the pubkey object.
Definition: secp256k1.c:250
A scalar modulo the group order of the secp256k1 curve.
Definition: scalar_4x64.h:13
static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar *a)
Convert a scalar to a byte array.
static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size)
static void test_result_basepoint(void)
Test that ECDH(sG, 1/s) == ECDH((1/s)G, s) == ECDH(G, 1) for a few random s.
Definition: tests_impl.h:119
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(const secp256k1_context *ctx, unsigned char *output, const secp256k1_pubkey *pubkey, const unsigned char *seckey, secp256k1_ecdh_hash_function hashfp, void *data) 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.
Definition: main_impl.h:30
static const wycheproof_ecdh_testvector testvectors[SECP256K1_ECDH_WYCHEPROOF_NUMBER_TESTVECTORS]
static SECP256K1_INLINE int secp256k1_memcmp_var(const void *s1, const void *s2, size_t n)
Semantics like memcmp.
Definition: util.h:269
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash)
static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data)
Definition: tests_impl.h:19
static const unsigned char wycheproof_ecdh_public_keys[]
#define CHECK_ILLEGAL(ctx, expr)
Definition: tests.c:79
static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32)
static const unsigned char wycheproof_ecdh_private_keys[]
Opaque data structure that holds a parsed and valid public key.
Definition: secp256k1.h:61
int COUNT
Definition: unit_test.c:23