Bitcoin Core  24.99.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 int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
11  (void)output;
12  (void)x;
13  (void)y;
14  (void)data;
15  return 0;
16 }
17 
18 int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
19  (void)data;
20  /* Save x and y as uncompressed public key */
21  output[0] = 0x04;
22  memcpy(output + 1, x, 32);
23  memcpy(output + 33, y, 32);
24  return 1;
25 }
26 
27 void test_ecdh_api(void) {
28  /* Setup context that just counts errors */
30  secp256k1_pubkey point;
31  unsigned char res[32];
32  unsigned char s_one[32] = { 0 };
33  int32_t ecount = 0;
34  s_one[31] = 1;
35 
38  CHECK(secp256k1_ec_pubkey_create(tctx, &point, s_one) == 1);
39 
40  /* Check all NULLs are detected */
41  CHECK(secp256k1_ecdh(tctx, res, &point, s_one, NULL, NULL) == 1);
42  CHECK(ecount == 0);
43  CHECK(secp256k1_ecdh(tctx, NULL, &point, s_one, NULL, NULL) == 0);
44  CHECK(ecount == 1);
45  CHECK(secp256k1_ecdh(tctx, res, NULL, s_one, NULL, NULL) == 0);
46  CHECK(ecount == 2);
47  CHECK(secp256k1_ecdh(tctx, res, &point, NULL, NULL, NULL) == 0);
48  CHECK(ecount == 3);
49  CHECK(secp256k1_ecdh(tctx, res, &point, s_one, NULL, NULL) == 1);
50  CHECK(ecount == 3);
51 
52  /* Cleanup */
54 }
55 
57  unsigned char s_one[32] = { 0 };
58  secp256k1_pubkey point[2];
59  int i;
60 
61  s_one[31] = 1;
62  /* Check against pubkey creation when the basepoint is the generator */
63  for (i = 0; i < 2 * count; ++i) {
64  secp256k1_sha256 sha;
65  unsigned char s_b32[32];
66  unsigned char output_ecdh[65];
67  unsigned char output_ser[32];
68  unsigned char point_ser[65];
69  size_t point_ser_len = sizeof(point_ser);
71 
73  secp256k1_scalar_get_b32(s_b32, &s);
74 
75  CHECK(secp256k1_ec_pubkey_create(ctx, &point[0], s_one) == 1);
76  CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1);
77 
78  /* compute using ECDH function with custom hash function */
79  CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom, NULL) == 1);
80  /* compute "explicitly" */
81  CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1);
82  /* compare */
83  CHECK(secp256k1_memcmp_var(output_ecdh, point_ser, 65) == 0);
84 
85  /* compute using ECDH function with default hash function */
86  CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32, NULL, NULL) == 1);
87  /* compute "explicitly" */
88  CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1);
90  secp256k1_sha256_write(&sha, point_ser, point_ser_len);
91  secp256k1_sha256_finalize(&sha, output_ser);
92  /* compare */
93  CHECK(secp256k1_memcmp_var(output_ecdh, output_ser, 32) == 0);
94  }
95 }
96 
97 void test_bad_scalar(void) {
98  unsigned char s_zero[32] = { 0 };
99  unsigned char s_overflow[32] = {
100  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
101  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
102  0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
103  0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41
104  };
105  unsigned char s_rand[32] = { 0 };
106  unsigned char output[32];
107  secp256k1_scalar rand;
108  secp256k1_pubkey point;
109 
110  /* Create random point */
111  random_scalar_order(&rand);
112  secp256k1_scalar_get_b32(s_rand, &rand);
113  CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_rand) == 1);
114 
115  /* Try to multiply it by bad values */
116  CHECK(secp256k1_ecdh(ctx, output, &point, s_zero, NULL, NULL) == 0);
117  CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, NULL, NULL) == 0);
118  /* ...and a good one */
119  s_overflow[31] -= 1;
120  CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, NULL, NULL) == 1);
121 
122  /* Hash function failure results in ecdh failure */
123  CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, ecdh_hash_function_test_fail, NULL) == 0);
124 }
125 
128  secp256k1_pubkey point;
129  secp256k1_scalar rand;
130  unsigned char s[32];
131  unsigned char s_inv[32];
132  unsigned char out[32];
133  unsigned char out_inv[32];
134  unsigned char out_base[32];
135  int i;
136 
137  unsigned char s_one[32] = { 0 };
138  s_one[31] = 1;
139  CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_one) == 1);
140  CHECK(secp256k1_ecdh(ctx, out_base, &point, s_one, NULL, NULL) == 1);
141 
142  for (i = 0; i < 2 * count; i++) {
143  random_scalar_order(&rand);
144  secp256k1_scalar_get_b32(s, &rand);
145  secp256k1_scalar_inverse(&rand, &rand);
146  secp256k1_scalar_get_b32(s_inv, &rand);
147 
148  CHECK(secp256k1_ec_pubkey_create(ctx, &point, s) == 1);
149  CHECK(secp256k1_ecdh(ctx, out, &point, s_inv, NULL, NULL) == 1);
150  CHECK(secp256k1_memcmp_var(out, out_base, 32) == 0);
151 
152  CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_inv) == 1);
153  CHECK(secp256k1_ecdh(ctx, out_inv, &point, s, NULL, NULL) == 1);
154  CHECK(secp256k1_memcmp_var(out_inv, out_base, 32) == 0);
155  }
156 }
157 
158 void run_ecdh_tests(void) {
159  test_ecdh_api();
161  test_bad_scalar();
163 }
164 
165 #endif /* SECP256K1_MODULE_ECDH_TESTS_H */
int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data)
Definition: tests_impl.h:18
void test_bad_scalar(void)
Definition: tests_impl.h:97
int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data)
Definition: tests_impl.h:10
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:127
void test_ecdh_api(void)
Definition: tests_impl.h:27
void run_ecdh_tests(void)
Definition: tests_impl.h:158
void test_ecdh_generator_basepoint(void)
Definition: tests_impl.h:56
#define CHECK(cond)
Unconditional failure on condition failure.
Definition: util.h:35
static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar *a)
Convert a scalar to a byte array.
static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *a)
Compute the inverse of a scalar (modulo the group order).
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash)
static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32)
static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size)
static SECP256K1_INLINE int secp256k1_memcmp_var(const void *s1, const void *s2, size_t n)
Semantics like memcmp.
Definition: util.h:196
SECP256K1_API void secp256k1_context_destroy(secp256k1_context *ctx) SECP256K1_ARG_NONNULL(1)
Destroy a secp256k1 context object (created in dynamically allocated memory).
Definition: secp256k1.c:146
#define SECP256K1_CONTEXT_SIGN
Definition: secp256k1.h:200
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:246
SECP256K1_API void secp256k1_context_set_error_callback(secp256k1_context *ctx, void(*fun)(const char *message, void *data), const void *data) SECP256K1_ARG_NONNULL(1)
Set a callback function to be called when an internal consistency check fails.
Definition: secp256k1.c:162
SECP256K1_API void secp256k1_context_set_illegal_callback(secp256k1_context *ctx, void(*fun)(const char *message, void *data), const void *data) SECP256K1_ARG_NONNULL(1)
Set a callback function to be called when an illegal argument is passed to an API call.
Definition: secp256k1.c:153
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:551
SECP256K1_API secp256k1_context * secp256k1_context_create(unsigned int flags) SECP256K1_WARN_UNUSED_RESULT
Create a secp256k1 context object (in dynamically allocated memory).
Definition: secp256k1.c:107
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize.
Definition: secp256k1.h:205
#define SECP256K1_EC_UNCOMPRESSED
Definition: secp256k1.h:206
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:29
Opaque data structure that holds a parsed and valid public key.
Definition: secp256k1.h:70
A scalar modulo the group order of the secp256k1 curve.
Definition: scalar_4x64.h:13
void random_scalar_order(secp256k1_scalar *num)
Definition: tests.c:124
static secp256k1_context * ctx
Definition: tests.c:34
static void counting_illegal_callback_fn(const char *str, void *data)
Definition: tests.c:36
static int count
Definition: tests.c:33