]> Git Repo - secp256k1.git/blob - src/modules/ecdh/tests_impl.h
Merge #710: Eliminate harmless non-constant time operations on secret data.
[secp256k1.git] / src / modules / ecdh / tests_impl.h
1 /**********************************************************************
2  * Copyright (c) 2015 Andrew Poelstra                                 *
3  * Distributed under the MIT software license, see the accompanying   *
4  * file COPYING or http://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 */
29     secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
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
36     secp256k1_context_set_error_callback(tctx, counting_illegal_callback_fn, &ecount);
37     secp256k1_context_set_illegal_callback(tctx, counting_illegal_callback_fn, &ecount);
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 */
53     secp256k1_context_destroy(tctx);
54 }
55
56 void test_ecdh_generator_basepoint(void) {
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 < 100; ++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);
70         secp256k1_scalar s;
71
72         random_scalar_order(&s);
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(memcmp(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);
89         secp256k1_sha256_initialize(&sha);
90         secp256k1_sha256_write(&sha, point_ser, point_ser_len);
91         secp256k1_sha256_finalize(&sha, output_ser);
92         /* compare */
93         CHECK(memcmp(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
126 void run_ecdh_tests(void) {
127     test_ecdh_api();
128     test_ecdh_generator_basepoint();
129     test_bad_scalar();
130 }
131
132 #endif /* SECP256K1_MODULE_ECDH_TESTS_H */
This page took 0.02937 seconds and 4 git commands to generate.