Bitcoin Core 30.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
12static 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
19static 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
27static 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
36static 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
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) {
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
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
93static 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];
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
119static 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++) {
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
150static 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 --- */
184static const struct tf_test_entry tests_ecdh[] = {
190};
191
192#endif /* SECP256K1_MODULE_ECDH_TESTS_H */
static void test_ecdh_api(void)
Definition: tests_impl.h:36
static const struct tf_test_entry tests_ecdh[]
Definition: tests_impl.h:184
static void test_bad_scalar(void)
Definition: tests_impl.h:93
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 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
static void test_ecdh_generator_basepoint(void)
Definition: tests_impl.h:52
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_ecdh_wycheproof(void)
Definition: tests_impl.h:150
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
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_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:268
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
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
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:604
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize.
Definition: secp256k1.h:224
#define SECP256K1_EC_UNCOMPRESSED
Definition: secp256k1.h:225
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
Opaque data structure that holds a parsed and valid public key.
Definition: secp256k1.h:61
A scalar modulo the group order of the secp256k1 curve.
Definition: scalar_4x64.h:13
Definition: unit_test.h:51
#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:15
static void testutil_random_scalar_order(secp256k1_scalar *num)
Definition: testutil.h:137
int COUNT
Definition: unit_test.c:23
#define CASE1(name)
Definition: unit_test.h:25