Bitcoin Core  27.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 static 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 static 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 static void test_ecdh_api(void) {
28  secp256k1_pubkey point;
29  unsigned char res[32];
30  unsigned char s_one[32] = { 0 };
31  s_one[31] = 1;
32 
33  CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_one) == 1);
34 
35  /* Check all NULLs are detected */
36  CHECK(secp256k1_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1);
37  CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, NULL, &point, s_one, NULL, NULL));
38  CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, res, NULL, s_one, NULL, NULL));
39  CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, res, &point, NULL, NULL, NULL));
40  CHECK(secp256k1_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1);
41 }
42 
43 static void test_ecdh_generator_basepoint(void) {
44  unsigned char s_one[32] = { 0 };
45  secp256k1_pubkey point[2];
46  int i;
47 
48  s_one[31] = 1;
49  /* Check against pubkey creation when the basepoint is the generator */
50  for (i = 0; i < 2 * COUNT; ++i) {
51  secp256k1_sha256 sha;
52  unsigned char s_b32[32];
53  unsigned char output_ecdh[65];
54  unsigned char output_ser[32];
55  unsigned char point_ser[65];
56  size_t point_ser_len = sizeof(point_ser);
58 
60  secp256k1_scalar_get_b32(s_b32, &s);
61 
62  CHECK(secp256k1_ec_pubkey_create(CTX, &point[0], s_one) == 1);
63  CHECK(secp256k1_ec_pubkey_create(CTX, &point[1], s_b32) == 1);
64 
65  /* compute using ECDH function with custom hash function */
66  CHECK(secp256k1_ecdh(CTX, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom, NULL) == 1);
67  /* compute "explicitly" */
68  CHECK(secp256k1_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1);
69  /* compare */
70  CHECK(secp256k1_memcmp_var(output_ecdh, point_ser, 65) == 0);
71 
72  /* compute using ECDH function with default hash function */
73  CHECK(secp256k1_ecdh(CTX, output_ecdh, &point[0], s_b32, NULL, NULL) == 1);
74  /* compute "explicitly" */
75  CHECK(secp256k1_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1);
77  secp256k1_sha256_write(&sha, point_ser, point_ser_len);
78  secp256k1_sha256_finalize(&sha, output_ser);
79  /* compare */
80  CHECK(secp256k1_memcmp_var(output_ecdh, output_ser, 32) == 0);
81  }
82 }
83 
84 static void test_bad_scalar(void) {
85  unsigned char s_zero[32] = { 0 };
86  unsigned char s_overflow[32] = {
87  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
88  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
89  0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
90  0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41
91  };
92  unsigned char s_rand[32] = { 0 };
93  unsigned char output[32];
94  secp256k1_scalar rand;
95  secp256k1_pubkey point;
96 
97  /* Create random point */
98  random_scalar_order(&rand);
99  secp256k1_scalar_get_b32(s_rand, &rand);
100  CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_rand) == 1);
101 
102  /* Try to multiply it by bad values */
103  CHECK(secp256k1_ecdh(CTX, output, &point, s_zero, NULL, NULL) == 0);
104  CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 0);
105  /* ...and a good one */
106  s_overflow[31] -= 1;
107  CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 1);
108 
109  /* Hash function failure results in ecdh failure */
110  CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, ecdh_hash_function_test_fail, NULL) == 0);
111 }
112 
114 static void test_result_basepoint(void) {
115  secp256k1_pubkey point;
116  secp256k1_scalar rand;
117  unsigned char s[32];
118  unsigned char s_inv[32];
119  unsigned char out[32];
120  unsigned char out_inv[32];
121  unsigned char out_base[32];
122  int i;
123 
124  unsigned char s_one[32] = { 0 };
125  s_one[31] = 1;
126  CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_one) == 1);
127  CHECK(secp256k1_ecdh(CTX, out_base, &point, s_one, NULL, NULL) == 1);
128 
129  for (i = 0; i < 2 * COUNT; i++) {
130  random_scalar_order(&rand);
131  secp256k1_scalar_get_b32(s, &rand);
132  secp256k1_scalar_inverse(&rand, &rand);
133  secp256k1_scalar_get_b32(s_inv, &rand);
134 
135  CHECK(secp256k1_ec_pubkey_create(CTX, &point, s) == 1);
136  CHECK(secp256k1_ecdh(CTX, out, &point, s_inv, NULL, NULL) == 1);
137  CHECK(secp256k1_memcmp_var(out, out_base, 32) == 0);
138 
139  CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_inv) == 1);
140  CHECK(secp256k1_ecdh(CTX, out_inv, &point, s, NULL, NULL) == 1);
141  CHECK(secp256k1_memcmp_var(out_inv, out_base, 32) == 0);
142  }
143 }
144 
145 static void run_ecdh_tests(void) {
146  test_ecdh_api();
148  test_bad_scalar();
150 }
151 
152 #endif /* SECP256K1_MODULE_ECDH_TESTS_H */
static void test_ecdh_api(void)
Definition: tests_impl.h:27
static void test_bad_scalar(void)
Definition: tests_impl.h:84
static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data)
Definition: tests_impl.h:10
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:114
static void run_ecdh_tests(void)
Definition: tests_impl.h:145
static void test_ecdh_generator_basepoint(void)
Definition: tests_impl.h:43
static int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data)
Definition: tests_impl.h:18
#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:226
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:279
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:584
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize.
Definition: secp256k1.h:215
#define SECP256K1_EC_UNCOMPRESSED
Definition: secp256k1.h:216
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:74
A scalar modulo the group order of the secp256k1 curve.
Definition: scalar_4x64.h:13
static int COUNT
Definition: tests.c:40
#define CHECK_ILLEGAL(ctx, expr)
Definition: tests.c:78
static secp256k1_context * CTX
Definition: tests.c:41
static void random_scalar_order(secp256k1_scalar *num)
Definition: tests.c:196