Bitcoin Core 31.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#include "../../unit_test.h"
11#include "../../testutil.h"
12
13static int ecdh_hash_function_test_xpassthru(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
14 (void)y;
15 (void)data;
16 memcpy(output, x, 32);
17 return 1;
18}
19
20static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
21 (void)output;
22 (void)x;
23 (void)y;
24 (void)data;
25 return 0;
26}
27
28static int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) {
29 (void)data;
30 /* Save x and y as uncompressed public key */
31 output[0] = 0x04;
32 memcpy(output + 1, x, 32);
33 memcpy(output + 33, y, 32);
34 return 1;
35}
36
37static void test_ecdh_api(void) {
38 secp256k1_pubkey point;
39 unsigned char res[32];
40 unsigned char s_one[32] = { 0 };
41 s_one[31] = 1;
42
43 CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_one) == 1);
44
45 /* Check all NULLs are detected */
46 CHECK(secp256k1_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1);
47 CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, NULL, &point, s_one, NULL, NULL));
48 CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, res, NULL, s_one, NULL, NULL));
49 CHECK_ILLEGAL(CTX, secp256k1_ecdh(CTX, res, &point, NULL, NULL, NULL));
50 CHECK(secp256k1_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1);
51}
52
54 unsigned char s_one[32] = { 0 };
55 secp256k1_pubkey point[2];
56 int i;
57
58 s_one[31] = 1;
59 /* Check against pubkey creation when the basepoint is the generator */
60 for (i = 0; i < 2 * COUNT; ++i) {
62 unsigned char s_b32[32];
63 unsigned char output_ecdh[65];
64 unsigned char output_ser[32];
65 unsigned char point_ser[65];
66 size_t point_ser_len = sizeof(point_ser);
68
71
72 CHECK(secp256k1_ec_pubkey_create(CTX, &point[0], s_one) == 1);
73 CHECK(secp256k1_ec_pubkey_create(CTX, &point[1], s_b32) == 1);
74
75 /* compute using ECDH function with custom hash function */
76 CHECK(secp256k1_ecdh(CTX, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom, NULL) == 1);
77 /* compute "explicitly" */
78 CHECK(secp256k1_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1);
79 /* compare */
80 CHECK(secp256k1_memcmp_var(output_ecdh, point_ser, 65) == 0);
81
82 /* compute using ECDH function with default hash function */
83 CHECK(secp256k1_ecdh(CTX, output_ecdh, &point[0], s_b32, NULL, NULL) == 1);
84 /* compute "explicitly" */
85 CHECK(secp256k1_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1);
87 secp256k1_sha256_write(secp256k1_get_hash_context(CTX), &sha, point_ser, point_ser_len);
89 /* compare */
90 CHECK(secp256k1_memcmp_var(output_ecdh, output_ser, 32) == 0);
91 }
92}
93
95static void test_ecdh_ctx_sha256(void) {
96 /* Check ctx-provided SHA256 compression override takes effect */
98 unsigned char out_default[65], out_custom[65];
99 const unsigned char sk[32] = {1};
100 secp256k1_pubkey pubkey;
101 CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, sk) == 1);
102
103 /* Default behavior */
104 CHECK(secp256k1_ecdh(ctx, out_default, &pubkey, sk, NULL, NULL) == 1);
105 CHECK(!sha256_ecdh_called);
106
107 /* Override SHA256 compression directly, bypassing the ctx setter sanity checks */
108 ctx->hash_ctx.fn_sha256_compression = sha256_ecdh;
109 CHECK(secp256k1_ecdh(ctx, out_custom, &pubkey, sk, NULL, NULL) == 1);
110
111 /* Outputs must differ if custom compression was used */
112 CHECK(secp256k1_memcmp_var(out_default, out_custom, 32) != 0);
113 CHECK(sha256_ecdh_called);
114
116}
117
118static void test_bad_scalar(void) {
119 unsigned char s_zero[32] = { 0 };
120 unsigned char s_overflow[32] = { 0 };
121 unsigned char s_rand[32] = { 0 };
122 unsigned char output[32];
123 secp256k1_scalar rand;
124 secp256k1_pubkey point;
125
126 /* Create random point */
128 secp256k1_scalar_get_b32(s_rand, &rand);
129 CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_rand) == 1);
130
131 /* Try to multiply it by bad values */
132 memcpy(s_overflow, secp256k1_group_order_bytes, 32);
133 CHECK(secp256k1_ecdh(CTX, output, &point, s_zero, NULL, NULL) == 0);
134 CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 0);
135 /* ...and a good one */
136 s_overflow[31] -= 1;
137 CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 1);
138
139 /* Hash function failure results in ecdh failure */
140 CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, ecdh_hash_function_test_fail, NULL) == 0);
141}
142
144static void test_result_basepoint(void) {
145 secp256k1_pubkey point;
146 secp256k1_scalar rand;
147 unsigned char s[32];
148 unsigned char s_inv[32];
149 unsigned char out[32];
150 unsigned char out_inv[32];
151 unsigned char out_base[32];
152 int i;
153
154 unsigned char s_one[32] = { 0 };
155 s_one[31] = 1;
156 CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_one) == 1);
157 CHECK(secp256k1_ecdh(CTX, out_base, &point, s_one, NULL, NULL) == 1);
158
159 for (i = 0; i < 2 * COUNT; i++) {
162 secp256k1_scalar_inverse(&rand, &rand);
163 secp256k1_scalar_get_b32(s_inv, &rand);
164
165 CHECK(secp256k1_ec_pubkey_create(CTX, &point, s) == 1);
166 CHECK(secp256k1_ecdh(CTX, out, &point, s_inv, NULL, NULL) == 1);
167 CHECK(secp256k1_memcmp_var(out, out_base, 32) == 0);
168
169 CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_inv) == 1);
170 CHECK(secp256k1_ecdh(CTX, out_inv, &point, s, NULL, NULL) == 1);
171 CHECK(secp256k1_memcmp_var(out_inv, out_base, 32) == 0);
172 }
173}
174
175static void test_ecdh_wycheproof(void) {
176#include "../../wycheproof/ecdh_secp256k1_test.h"
177 int t;
179 int parsed_ok;
180 secp256k1_pubkey point;
181 const unsigned char *pk;
182 const unsigned char *sk;
183 const unsigned char *expected_shared_secret;
184 unsigned char output_ecdh[65] = { 0 };
185
186 int expected_result;
187
188 memset(&point, 0, sizeof(point));
190 parsed_ok = secp256k1_ec_pubkey_parse(CTX, &point, pk, testvectors[t].pk_len);
191
193 CHECK(parsed_ok == expected_result);
194 if (!parsed_ok) {
195 continue;
196 }
197
199 CHECK(testvectors[t].sk_len == 32);
200
201 CHECK(secp256k1_ecdh(CTX, output_ecdh, &point, sk, ecdh_hash_function_test_xpassthru, NULL) == 1);
202 expected_shared_secret = &wycheproof_ecdh_shared_secrets[testvectors[t].shared_offset];
203
204 CHECK(secp256k1_memcmp_var(output_ecdh, expected_shared_secret, testvectors[t].shared_len) == 0);
205 }
206}
207
208/* --- Test registry --- */
209static const struct tf_test_entry tests_ecdh[] = {
216};
217
218#endif /* SECP256K1_MODULE_ECDH_TESTS_H */
static void test_ecdh_api(void)
Definition: tests_impl.h:37
static const struct tf_test_entry tests_ecdh[]
Definition: tests_impl.h:209
static void test_bad_scalar(void)
Definition: tests_impl.h:118
static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data)
Definition: tests_impl.h:20
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:144
static void test_ecdh_ctx_sha256(void)
Definition: tests_impl.h:95
static void test_ecdh_generator_basepoint(void)
Definition: tests_impl.h:53
static int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data)
Definition: tests_impl.h:28
static void test_ecdh_wycheproof(void)
Definition: tests_impl.h:175
static int ecdh_hash_function_test_xpassthru(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data)
Definition: tests_impl.h:13
static const unsigned char wycheproof_ecdh_public_keys[]
#define SECP256K1_ECDH_WYCHEPROOF_NUMBER_TESTVECTORS
static const wycheproof_ecdh_testvector testvectors[SECP256K1_ECDH_WYCHEPROOF_NUMBER_TESTVECTORS]
static const unsigned char wycheproof_ecdh_private_keys[]
static const unsigned char wycheproof_ecdh_shared_secrets[]
#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_finalize(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *hash, unsigned char *out32)
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash)
static void secp256k1_sha256_write(const secp256k1_hash_ctx *hash_ctx, 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:271
static SECP256K1_INLINE const secp256k1_hash_ctx * secp256k1_get_hash_context(const secp256k1_context *ctx)
Definition: secp256k1.c:238
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:190
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:287
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:269
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:639
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize.
Definition: secp256k1.h:225
SECP256K1_API secp256k1_context * secp256k1_context_clone(const secp256k1_context *ctx) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT
Copy a secp256k1 context object (into dynamically allocated memory).
Definition: secp256k1.c:166
#define SECP256K1_EC_UNCOMPRESSED
Definition: secp256k1.h:226
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:34
secp256k1_hash_ctx hash_ctx
Definition: secp256k1.c:63
secp256k1_sha256_compression_function fn_sha256_compression
Definition: hash.h:14
Opaque data structure that holds a parsed and valid public key.
Definition: secp256k1.h:62
A scalar modulo the group order of the secp256k1 curve.
Definition: scalar_4x64.h:13
Definition: unit_test.h:53
#define CHECK_ILLEGAL(ctx, expr)
Definition: tests.c:79
static secp256k1_context * CTX
Definition: tests.c:42
static const unsigned char secp256k1_group_order_bytes[32]
Definition: testutil.h:24
static void testutil_random_scalar_order(secp256k1_scalar *num)
Definition: testutil.h:142
#define DEFINE_SHA256_TRANSFORM_PROBE(name)
Definition: testutil.h:15
int COUNT
Definition: unit_test.c:23
#define CASE1(name)
Definition: unit_test.h:27