]>
Commit | Line | Data |
---|---|---|
71712b27 GM |
1 | /********************************************************************** |
2 | * Copyright (c) 2013, 2014 Pieter Wuille * | |
3 | * Distributed under the MIT software license, see the accompanying * | |
4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* | |
5 | **********************************************************************/ | |
0a433ea2 | 6 | |
78cd96b1 CF |
7 | #if defined HAVE_CONFIG_H |
8 | #include "libsecp256k1-config.h" | |
9 | #endif | |
10 | ||
5a9989c5 | 11 | #include <stdio.h> |
0592d117 | 12 | #include <stdlib.h> |
a41f32e6 | 13 | |
25f4aec0 | 14 | #include "secp256k1.c" |
f0709ac5 | 15 | #include "testrand_impl.h" |
a41f32e6 | 16 | |
dd08f037 PW |
17 | #ifdef ENABLE_OPENSSL_TESTS |
18 | #include "openssl/bn.h" | |
19 | #include "openssl/ec.h" | |
20 | #include "openssl/ecdsa.h" | |
21 | #include "openssl/obj_mac.h" | |
22 | #endif | |
23 | ||
79f599d3 | 24 | static int count = 64; |
4adf6b2a | 25 | |
404c30a8 PW |
26 | /***** NUM TESTS *****/ |
27 | ||
3f44e1ad PW |
28 | void random_num_negate(secp256k1_num_t *num) { |
29 | if (secp256k1_rand32() & 1) | |
30 | secp256k1_num_negate(num); | |
31 | } | |
32 | ||
9338dbf7 PW |
33 | void random_field_element_test(secp256k1_fe_t *fe) { |
34 | do { | |
35 | unsigned char b32[32]; | |
36 | secp256k1_rand256_test(b32); | |
37 | secp256k1_num_t num; | |
38 | secp256k1_num_set_bin(&num, b32, 32); | |
39 | if (secp256k1_num_cmp(&num, &secp256k1_fe_consts->p) >= 0) | |
40 | continue; | |
d907ebc0 | 41 | VERIFY_CHECK(secp256k1_fe_set_b32(fe, b32)); |
9338dbf7 PW |
42 | break; |
43 | } while(1); | |
44 | } | |
45 | ||
46 | void random_field_element_magnitude(secp256k1_fe_t *fe) { | |
47 | secp256k1_fe_normalize(fe); | |
48 | int n = secp256k1_rand32() % 4; | |
49 | for (int i = 0; i < n; i++) { | |
50 | secp256k1_fe_negate(fe, fe, 1 + 2*i); | |
51 | secp256k1_fe_negate(fe, fe, 2 + 2*i); | |
52 | } | |
53 | } | |
54 | ||
55 | void random_group_element_test(secp256k1_ge_t *ge) { | |
56 | secp256k1_fe_t fe; | |
57 | do { | |
58 | random_field_element_test(&fe); | |
59 | if (secp256k1_ge_set_xo(ge, &fe, secp256k1_rand32() & 1)) | |
60 | break; | |
61 | } while(1); | |
62 | } | |
63 | ||
64 | void random_group_element_jacobian_test(secp256k1_gej_t *gej, const secp256k1_ge_t *ge) { | |
65 | do { | |
66 | random_field_element_test(&gej->z); | |
67 | if (!secp256k1_fe_is_zero(&gej->z)) { | |
68 | break; | |
69 | } | |
70 | } while(1); | |
71 | secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &gej->z); | |
72 | secp256k1_fe_t z3; secp256k1_fe_mul(&z3, &z2, &gej->z); | |
73 | secp256k1_fe_mul(&gej->x, &ge->x, &z2); | |
74 | secp256k1_fe_mul(&gej->y, &ge->y, &z3); | |
75 | gej->infinity = ge->infinity; | |
76 | } | |
77 | ||
404c30a8 | 78 | void random_num_order_test(secp256k1_num_t *num) { |
d06e61cb PW |
79 | do { |
80 | unsigned char b32[32]; | |
81 | secp256k1_rand256_test(b32); | |
82 | secp256k1_num_set_bin(num, b32, 32); | |
83 | if (secp256k1_num_is_zero(num)) | |
84 | continue; | |
85 | if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0) | |
86 | continue; | |
87 | break; | |
88 | } while(1); | |
89 | } | |
90 | ||
a9f5c8b8 PW |
91 | void random_scalar_order_test(secp256k1_scalar_t *num) { |
92 | do { | |
93 | unsigned char b32[32]; | |
94 | secp256k1_rand256_test(b32); | |
95 | int overflow = 0; | |
eca6cdb1 | 96 | secp256k1_scalar_set_b32(num, b32, &overflow); |
a9f5c8b8 PW |
97 | if (overflow || secp256k1_scalar_is_zero(num)) |
98 | continue; | |
99 | break; | |
100 | } while(1); | |
101 | } | |
102 | ||
404c30a8 PW |
103 | void random_num_order(secp256k1_num_t *num) { |
104 | do { | |
105 | unsigned char b32[32]; | |
106 | secp256k1_rand256(b32); | |
107 | secp256k1_num_set_bin(num, b32, 32); | |
108 | if (secp256k1_num_is_zero(num)) | |
109 | continue; | |
110 | if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0) | |
111 | continue; | |
112 | break; | |
113 | } while(1); | |
114 | } | |
115 | ||
2cad067a | 116 | void test_num_copy_inc_cmp(void) { |
404c30a8 | 117 | secp256k1_num_t n1,n2; |
404c30a8 PW |
118 | random_num_order(&n1); |
119 | secp256k1_num_copy(&n2, &n1); | |
1a749b4a PW |
120 | CHECK(secp256k1_num_eq(&n1, &n2)); |
121 | CHECK(secp256k1_num_eq(&n2, &n1)); | |
404c30a8 | 122 | secp256k1_num_inc(&n2); |
1a749b4a PW |
123 | CHECK(!secp256k1_num_eq(&n1, &n2)); |
124 | CHECK(!secp256k1_num_eq(&n2, &n1)); | |
404c30a8 PW |
125 | } |
126 | ||
404c30a8 | 127 | |
2cad067a | 128 | void test_num_get_set_hex(void) { |
404c30a8 | 129 | secp256k1_num_t n1,n2; |
404c30a8 PW |
130 | random_num_order_test(&n1); |
131 | char c[64]; | |
132 | secp256k1_num_get_hex(c, 64, &n1); | |
133 | secp256k1_num_set_hex(&n2, c, 64); | |
1a749b4a | 134 | CHECK(secp256k1_num_eq(&n1, &n2)); |
404c30a8 | 135 | for (int i=0; i<64; i++) { |
71712b27 | 136 | /* check whether the lower 4 bits correspond to the last hex character */ |
404c30a8 PW |
137 | int low1 = secp256k1_num_shift(&n1, 4); |
138 | int lowh = c[63]; | |
f0709ac5 | 139 | int low2 = ((lowh>>6)*9+(lowh-'0'))&15; |
0592d117 | 140 | CHECK(low1 == low2); |
71712b27 | 141 | /* shift bits off the hex representation, and compare */ |
404c30a8 PW |
142 | memmove(c+1, c, 63); |
143 | c[0] = '0'; | |
144 | secp256k1_num_set_hex(&n2, c, 64); | |
1a749b4a | 145 | CHECK(secp256k1_num_eq(&n1, &n2)); |
404c30a8 | 146 | } |
404c30a8 PW |
147 | } |
148 | ||
2cad067a | 149 | void test_num_get_set_bin(void) { |
404c30a8 | 150 | secp256k1_num_t n1,n2; |
404c30a8 PW |
151 | random_num_order_test(&n1); |
152 | unsigned char c[32]; | |
153 | secp256k1_num_get_bin(c, 32, &n1); | |
154 | secp256k1_num_set_bin(&n2, c, 32); | |
1a749b4a | 155 | CHECK(secp256k1_num_eq(&n1, &n2)); |
404c30a8 | 156 | for (int i=0; i<32; i++) { |
71712b27 | 157 | /* check whether the lower 8 bits correspond to the last byte */ |
404c30a8 PW |
158 | int low1 = secp256k1_num_shift(&n1, 8); |
159 | int low2 = c[31]; | |
0592d117 | 160 | CHECK(low1 == low2); |
71712b27 | 161 | /* shift bits off the byte representation, and compare */ |
404c30a8 PW |
162 | memmove(c+1, c, 31); |
163 | c[0] = 0; | |
164 | secp256k1_num_set_bin(&n2, c, 32); | |
1a749b4a | 165 | CHECK(secp256k1_num_eq(&n1, &n2)); |
404c30a8 | 166 | } |
404c30a8 PW |
167 | } |
168 | ||
2cad067a | 169 | void run_num_int(void) { |
404c30a8 | 170 | secp256k1_num_t n1; |
404c30a8 PW |
171 | for (int i=-255; i<256; i++) { |
172 | unsigned char c1[3] = {}; | |
173 | c1[2] = abs(i); | |
174 | unsigned char c2[3] = {0x11,0x22,0x33}; | |
175 | secp256k1_num_set_int(&n1, i); | |
176 | secp256k1_num_get_bin(c2, 3, &n1); | |
0592d117 | 177 | CHECK(memcmp(c1, c2, 3) == 0); |
404c30a8 | 178 | } |
404c30a8 PW |
179 | } |
180 | ||
2cad067a | 181 | void test_num_negate(void) { |
3f44e1ad PW |
182 | secp256k1_num_t n1; |
183 | secp256k1_num_t n2; | |
71712b27 | 184 | random_num_order_test(&n1); /* n1 = R */ |
3f44e1ad | 185 | random_num_negate(&n1); |
71712b27 GM |
186 | secp256k1_num_copy(&n2, &n1); /* n2 = R */ |
187 | secp256k1_num_sub(&n1, &n2, &n1); /* n1 = n2-n1 = 0 */ | |
0592d117 | 188 | CHECK(secp256k1_num_is_zero(&n1)); |
71712b27 GM |
189 | secp256k1_num_copy(&n1, &n2); /* n1 = R */ |
190 | secp256k1_num_negate(&n1); /* n1 = -R */ | |
0592d117 | 191 | CHECK(!secp256k1_num_is_zero(&n1)); |
71712b27 | 192 | secp256k1_num_add(&n1, &n2, &n1); /* n1 = n2+n1 = 0 */ |
0592d117 | 193 | CHECK(secp256k1_num_is_zero(&n1)); |
71712b27 GM |
194 | secp256k1_num_copy(&n1, &n2); /* n1 = R */ |
195 | secp256k1_num_negate(&n1); /* n1 = -R */ | |
0592d117 | 196 | CHECK(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2)); |
71712b27 | 197 | secp256k1_num_negate(&n1); /* n1 = R */ |
1a749b4a | 198 | CHECK(secp256k1_num_eq(&n1, &n2)); |
3f44e1ad PW |
199 | } |
200 | ||
2cad067a | 201 | void test_num_add_sub(void) { |
1a749b4a | 202 | int r = secp256k1_rand32(); |
3f44e1ad PW |
203 | secp256k1_num_t n1; |
204 | secp256k1_num_t n2; | |
71712b27 | 205 | random_num_order_test(&n1); /* n1 = R1 */ |
1a749b4a PW |
206 | if (r & 1) { |
207 | random_num_negate(&n1); | |
208 | } | |
71712b27 | 209 | random_num_order_test(&n2); /* n2 = R2 */ |
1a749b4a PW |
210 | if (r & 2) { |
211 | random_num_negate(&n2); | |
212 | } | |
3f44e1ad | 213 | secp256k1_num_t n1p2, n2p1, n1m2, n2m1; |
71712b27 GM |
214 | secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */ |
215 | secp256k1_num_add(&n2p1, &n2, &n1); /* n2p1 = R2 + R1 */ | |
216 | secp256k1_num_sub(&n1m2, &n1, &n2); /* n1m2 = R1 - R2 */ | |
217 | secp256k1_num_sub(&n2m1, &n2, &n1); /* n2m1 = R2 - R1 */ | |
1a749b4a PW |
218 | CHECK(secp256k1_num_eq(&n1p2, &n2p1)); |
219 | CHECK(!secp256k1_num_eq(&n1p2, &n1m2)); | |
71712b27 | 220 | secp256k1_num_negate(&n2m1); /* n2m1 = -R2 + R1 */ |
1a749b4a PW |
221 | CHECK(secp256k1_num_eq(&n2m1, &n1m2)); |
222 | CHECK(!secp256k1_num_eq(&n2m1, &n1)); | |
71712b27 | 223 | secp256k1_num_add(&n2m1, &n2m1, &n2); /* n2m1 = -R2 + R1 + R2 = R1 */ |
1a749b4a PW |
224 | CHECK(secp256k1_num_eq(&n2m1, &n1)); |
225 | CHECK(!secp256k1_num_eq(&n2p1, &n1)); | |
71712b27 | 226 | secp256k1_num_sub(&n2p1, &n2p1, &n2); /* n2p1 = R2 + R1 - R2 = R1 */ |
1a749b4a | 227 | CHECK(secp256k1_num_eq(&n2p1, &n1)); |
3f44e1ad PW |
228 | } |
229 | ||
2cad067a | 230 | void run_num_smalltests(void) { |
3f44e1ad PW |
231 | for (int i=0; i<100*count; i++) { |
232 | test_num_copy_inc_cmp(); | |
233 | test_num_get_set_hex(); | |
234 | test_num_get_set_bin(); | |
235 | test_num_negate(); | |
236 | test_num_add_sub(); | |
237 | } | |
238 | run_num_int(); | |
239 | } | |
240 | ||
79359302 PW |
241 | /***** SCALAR TESTS *****/ |
242 | ||
243 | int secp256k1_scalar_eq(const secp256k1_scalar_t *s1, const secp256k1_scalar_t *s2) { | |
244 | secp256k1_scalar_t t; | |
79359302 PW |
245 | secp256k1_scalar_negate(&t, s2); |
246 | secp256k1_scalar_add(&t, &t, s1); | |
247 | int ret = secp256k1_scalar_is_zero(&t); | |
79359302 PW |
248 | return ret; |
249 | } | |
250 | ||
251 | void scalar_test(void) { | |
252 | unsigned char c[32]; | |
253 | ||
71712b27 | 254 | /* Set 's' to a random scalar, with value 'snum'. */ |
79359302 PW |
255 | secp256k1_rand256_test(c); |
256 | secp256k1_scalar_t s; | |
79359302 PW |
257 | secp256k1_scalar_set_b32(&s, c, NULL); |
258 | secp256k1_num_t snum; | |
79359302 PW |
259 | secp256k1_num_set_bin(&snum, c, 32); |
260 | secp256k1_num_mod(&snum, &secp256k1_ge_consts->order); | |
261 | ||
71712b27 | 262 | /* Set 's1' to a random scalar, with value 's1num'. */ |
79359302 PW |
263 | secp256k1_rand256_test(c); |
264 | secp256k1_scalar_t s1; | |
79359302 PW |
265 | secp256k1_scalar_set_b32(&s1, c, NULL); |
266 | secp256k1_num_t s1num; | |
79359302 PW |
267 | secp256k1_num_set_bin(&s1num, c, 32); |
268 | secp256k1_num_mod(&s1num, &secp256k1_ge_consts->order); | |
269 | ||
71712b27 | 270 | /* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */ |
79359302 PW |
271 | secp256k1_rand256_test(c); |
272 | secp256k1_scalar_t s2; | |
79359302 PW |
273 | int overflow = 0; |
274 | secp256k1_scalar_set_b32(&s2, c, &overflow); | |
275 | secp256k1_num_t s2num; | |
79359302 PW |
276 | secp256k1_num_set_bin(&s2num, c, 32); |
277 | secp256k1_num_mod(&s2num, &secp256k1_ge_consts->order); | |
278 | ||
279 | { | |
71712b27 | 280 | /* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */ |
1e6c77c3 PW |
281 | secp256k1_scalar_t n; |
282 | secp256k1_scalar_set_int(&n, 0); | |
79359302 | 283 | for (int i = 0; i < 256; i += 4) { |
1e6c77c3 PW |
284 | secp256k1_scalar_t t; |
285 | secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); | |
286 | for (int j = 0; j < 4; j++) { | |
287 | secp256k1_scalar_add(&n, &n, &n); | |
288 | } | |
289 | secp256k1_scalar_add(&n, &n, &t); | |
79359302 | 290 | } |
1e6c77c3 PW |
291 | CHECK(secp256k1_scalar_eq(&n, &s)); |
292 | } | |
293 | ||
294 | { | |
295 | /* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */ | |
296 | secp256k1_scalar_t n; | |
297 | secp256k1_scalar_set_int(&n, 0); | |
298 | int i = 0; | |
299 | while (i < 256) { | |
300 | int now = (secp256k1_rand32() % 15) + 1; | |
301 | if (now + i > 256) { | |
302 | now = 256 - i; | |
303 | } | |
304 | secp256k1_scalar_t t; | |
305 | secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now)); | |
306 | for (int j = 0; j < now; j++) { | |
307 | secp256k1_scalar_add(&n, &n, &n); | |
308 | } | |
309 | secp256k1_scalar_add(&n, &n, &t); | |
310 | i += now; | |
311 | } | |
312 | CHECK(secp256k1_scalar_eq(&n, &s)); | |
79359302 PW |
313 | } |
314 | ||
315 | { | |
71712b27 | 316 | /* Test that get_b32 returns the same as get_bin on the number. */ |
79359302 PW |
317 | unsigned char r1[32]; |
318 | secp256k1_scalar_get_b32(r1, &s2); | |
319 | unsigned char r2[32]; | |
320 | secp256k1_num_get_bin(r2, 32, &s2num); | |
321 | CHECK(memcmp(r1, r2, 32) == 0); | |
71712b27 | 322 | /* If no overflow occurred when assigning, it should also be equal to the original byte array. */ |
79359302 PW |
323 | CHECK((memcmp(r1, c, 32) == 0) == (overflow == 0)); |
324 | } | |
325 | ||
326 | { | |
71712b27 | 327 | /* Test that adding the scalars together is equal to adding their numbers together modulo the order. */ |
79359302 | 328 | secp256k1_num_t rnum; |
79359302 PW |
329 | secp256k1_num_add(&rnum, &snum, &s2num); |
330 | secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order); | |
331 | secp256k1_scalar_t r; | |
79359302 PW |
332 | secp256k1_scalar_add(&r, &s, &s2); |
333 | secp256k1_num_t r2num; | |
79359302 PW |
334 | secp256k1_scalar_get_num(&r2num, &r); |
335 | CHECK(secp256k1_num_eq(&rnum, &r2num)); | |
79359302 PW |
336 | } |
337 | ||
338 | { | |
71712b27 | 339 | /* Test that multipying the scalars is equal to multiplying their numbers modulo the order. */ |
79359302 | 340 | secp256k1_num_t rnum; |
79359302 PW |
341 | secp256k1_num_mul(&rnum, &snum, &s2num); |
342 | secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order); | |
343 | secp256k1_scalar_t r; | |
79359302 PW |
344 | secp256k1_scalar_mul(&r, &s, &s2); |
345 | secp256k1_num_t r2num; | |
79359302 PW |
346 | secp256k1_scalar_get_num(&r2num, &r); |
347 | CHECK(secp256k1_num_eq(&rnum, &r2num)); | |
71712b27 | 348 | /* The result can only be zero if at least one of the factors was zero. */ |
79359302 | 349 | CHECK(secp256k1_scalar_is_zero(&r) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_zero(&s2))); |
71712b27 | 350 | /* The results can only be equal to one of the factors if that factor was zero, or the other factor was one. */ |
79359302 PW |
351 | CHECK(secp256k1_num_eq(&rnum, &snum) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_one(&s2))); |
352 | CHECK(secp256k1_num_eq(&rnum, &s2num) == (secp256k1_scalar_is_zero(&s2) || secp256k1_scalar_is_one(&s))); | |
79359302 PW |
353 | } |
354 | ||
355 | { | |
71712b27 | 356 | /* Check that comparison with zero matches comparison with zero on the number. */ |
79359302 | 357 | CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s)); |
71712b27 | 358 | /* Check that comparison with the half order is equal to testing for high scalar. */ |
79359302 PW |
359 | CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &secp256k1_ge_consts->half_order) > 0)); |
360 | secp256k1_scalar_t neg; | |
79359302 PW |
361 | secp256k1_scalar_negate(&neg, &s); |
362 | secp256k1_num_t negnum; | |
79359302 PW |
363 | secp256k1_num_sub(&negnum, &secp256k1_ge_consts->order, &snum); |
364 | secp256k1_num_mod(&negnum, &secp256k1_ge_consts->order); | |
71712b27 | 365 | /* Check that comparison with the half order is equal to testing for high scalar after negation. */ |
79359302 | 366 | CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &secp256k1_ge_consts->half_order) > 0)); |
71712b27 | 367 | /* Negating should change the high property, unless the value was already zero. */ |
79359302 PW |
368 | CHECK((secp256k1_scalar_is_high(&s) == secp256k1_scalar_is_high(&neg)) == secp256k1_scalar_is_zero(&s)); |
369 | secp256k1_num_t negnum2; | |
79359302 | 370 | secp256k1_scalar_get_num(&negnum2, &neg); |
71712b27 | 371 | /* Negating a scalar should be equal to (order - n) mod order on the number. */ |
79359302 PW |
372 | CHECK(secp256k1_num_eq(&negnum, &negnum2)); |
373 | secp256k1_scalar_add(&neg, &neg, &s); | |
71712b27 | 374 | /* Adding a number to its negation should result in zero. */ |
79359302 PW |
375 | CHECK(secp256k1_scalar_is_zero(&neg)); |
376 | secp256k1_scalar_negate(&neg, &neg); | |
71712b27 | 377 | /* Negating zero should still result in zero. */ |
79359302 | 378 | CHECK(secp256k1_scalar_is_zero(&neg)); |
79359302 PW |
379 | } |
380 | ||
381 | { | |
71712b27 | 382 | /* Test that scalar inverses are equal to the inverse of their number modulo the order. */ |
79359302 PW |
383 | if (!secp256k1_scalar_is_zero(&s)) { |
384 | secp256k1_scalar_t inv; | |
79359302 PW |
385 | secp256k1_scalar_inverse(&inv, &s); |
386 | secp256k1_num_t invnum; | |
79359302 PW |
387 | secp256k1_num_mod_inverse(&invnum, &snum, &secp256k1_ge_consts->order); |
388 | secp256k1_num_t invnum2; | |
79359302 PW |
389 | secp256k1_scalar_get_num(&invnum2, &inv); |
390 | CHECK(secp256k1_num_eq(&invnum, &invnum2)); | |
391 | secp256k1_scalar_mul(&inv, &inv, &s); | |
71712b27 | 392 | /* Multiplying a scalar with its inverse must result in one. */ |
79359302 PW |
393 | CHECK(secp256k1_scalar_is_one(&inv)); |
394 | secp256k1_scalar_inverse(&inv, &inv); | |
71712b27 | 395 | /* Inverting one must result in one. */ |
79359302 | 396 | CHECK(secp256k1_scalar_is_one(&inv)); |
79359302 PW |
397 | } |
398 | } | |
399 | ||
400 | { | |
71712b27 | 401 | /* Test commutativity of add. */ |
79359302 | 402 | secp256k1_scalar_t r1, r2; |
79359302 PW |
403 | secp256k1_scalar_add(&r1, &s1, &s2); |
404 | secp256k1_scalar_add(&r2, &s2, &s1); | |
405 | CHECK(secp256k1_scalar_eq(&r1, &r2)); | |
79359302 PW |
406 | } |
407 | ||
52132078 PW |
408 | { |
409 | /* Test add_bit. */ | |
410 | int bit = secp256k1_rand32() % 256; | |
411 | secp256k1_scalar_t b; | |
1e6c77c3 | 412 | secp256k1_scalar_set_int(&b, 1); |
52132078 PW |
413 | CHECK(secp256k1_scalar_is_one(&b)); |
414 | for (int i = 0; i < bit; i++) { | |
415 | secp256k1_scalar_add(&b, &b, &b); | |
416 | } | |
417 | secp256k1_scalar_t r1 = s1, r2 = s1; | |
418 | secp256k1_scalar_add(&r1, &r1, &b); | |
419 | if (!(secp256k1_scalar_get_bits(&s1, 255, 1) == 1 && secp256k1_scalar_get_bits(&r1, 255, 1) == 0)) { | |
420 | /* No overflow happened. */ | |
421 | secp256k1_scalar_add_bit(&r2, bit); | |
422 | CHECK(secp256k1_scalar_eq(&r1, &r2)); | |
423 | } | |
424 | } | |
425 | ||
79359302 | 426 | { |
71712b27 | 427 | /* Test commutativity of mul. */ |
79359302 | 428 | secp256k1_scalar_t r1, r2; |
79359302 PW |
429 | secp256k1_scalar_mul(&r1, &s1, &s2); |
430 | secp256k1_scalar_mul(&r2, &s2, &s1); | |
431 | CHECK(secp256k1_scalar_eq(&r1, &r2)); | |
79359302 PW |
432 | } |
433 | ||
434 | { | |
71712b27 | 435 | /* Test associativity of add. */ |
79359302 | 436 | secp256k1_scalar_t r1, r2; |
79359302 PW |
437 | secp256k1_scalar_add(&r1, &s1, &s2); |
438 | secp256k1_scalar_add(&r1, &r1, &s); | |
439 | secp256k1_scalar_add(&r2, &s2, &s); | |
440 | secp256k1_scalar_add(&r2, &s1, &r2); | |
441 | CHECK(secp256k1_scalar_eq(&r1, &r2)); | |
79359302 PW |
442 | } |
443 | ||
444 | { | |
71712b27 | 445 | /* Test associativity of mul. */ |
79359302 | 446 | secp256k1_scalar_t r1, r2; |
79359302 PW |
447 | secp256k1_scalar_mul(&r1, &s1, &s2); |
448 | secp256k1_scalar_mul(&r1, &r1, &s); | |
449 | secp256k1_scalar_mul(&r2, &s2, &s); | |
450 | secp256k1_scalar_mul(&r2, &s1, &r2); | |
451 | CHECK(secp256k1_scalar_eq(&r1, &r2)); | |
79359302 PW |
452 | } |
453 | ||
454 | { | |
71712b27 | 455 | /* Test distributitivity of mul over add. */ |
79359302 | 456 | secp256k1_scalar_t r1, r2, t; |
79359302 PW |
457 | secp256k1_scalar_add(&r1, &s1, &s2); |
458 | secp256k1_scalar_mul(&r1, &r1, &s); | |
459 | secp256k1_scalar_mul(&r2, &s1, &s); | |
460 | secp256k1_scalar_mul(&t, &s2, &s); | |
461 | secp256k1_scalar_add(&r2, &r2, &t); | |
462 | CHECK(secp256k1_scalar_eq(&r1, &r2)); | |
79359302 | 463 | } |
1d52a8b1 PW |
464 | |
465 | { | |
71712b27 | 466 | /* Test square. */ |
1d52a8b1 PW |
467 | secp256k1_scalar_t r1, r2; |
468 | secp256k1_scalar_sqr(&r1, &s1); | |
469 | secp256k1_scalar_mul(&r2, &s1, &s1); | |
470 | CHECK(secp256k1_scalar_eq(&r1, &r2)); | |
471 | } | |
79359302 PW |
472 | } |
473 | ||
474 | void run_scalar_tests(void) { | |
475 | for (int i = 0; i < 128 * count; i++) { | |
476 | scalar_test(); | |
477 | } | |
478 | } | |
479 | ||
09ca4f32 PD |
480 | /***** FIELD TESTS *****/ |
481 | ||
482 | void random_fe(secp256k1_fe_t *x) { | |
483 | unsigned char bin[32]; | |
d907ebc0 PW |
484 | do { |
485 | secp256k1_rand256(bin); | |
486 | if (secp256k1_fe_set_b32(x, bin)) { | |
487 | return; | |
488 | } | |
489 | } while(1); | |
09ca4f32 PD |
490 | } |
491 | ||
6d6102fe PD |
492 | void random_fe_non_zero(secp256k1_fe_t *nz) { |
493 | int tries = 10; | |
09ca4f32 | 494 | while (--tries >= 0) { |
6d6102fe PD |
495 | random_fe(nz); |
496 | secp256k1_fe_normalize(nz); | |
497 | if (!secp256k1_fe_is_zero(nz)) | |
09ca4f32 PD |
498 | break; |
499 | } | |
71712b27 | 500 | /* Infinitesimal probability of spurious failure here */ |
0592d117 | 501 | CHECK(tries >= 0); |
09ca4f32 PD |
502 | } |
503 | ||
6d6102fe PD |
504 | void random_fe_non_square(secp256k1_fe_t *ns) { |
505 | random_fe_non_zero(ns); | |
506 | secp256k1_fe_t r; | |
507 | if (secp256k1_fe_sqrt(&r, ns)) { | |
508 | secp256k1_fe_negate(ns, ns, 1); | |
509 | } | |
510 | } | |
511 | ||
f16be77f PD |
512 | int check_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) { |
513 | secp256k1_fe_t an = *a; secp256k1_fe_normalize(&an); | |
514 | secp256k1_fe_t bn = *b; secp256k1_fe_normalize(&bn); | |
515 | return secp256k1_fe_equal(&an, &bn); | |
516 | } | |
517 | ||
518 | int check_fe_inverse(const secp256k1_fe_t *a, const secp256k1_fe_t *ai) { | |
519 | secp256k1_fe_t x; secp256k1_fe_mul(&x, a, ai); | |
520 | secp256k1_fe_t one; secp256k1_fe_set_int(&one, 1); | |
521 | return check_fe_equal(&x, &one); | |
522 | } | |
523 | ||
2cad067a | 524 | void run_field_inv(void) { |
f16be77f PD |
525 | secp256k1_fe_t x, xi, xii; |
526 | for (int i=0; i<10*count; i++) { | |
527 | random_fe_non_zero(&x); | |
528 | secp256k1_fe_inv(&xi, &x); | |
529 | CHECK(check_fe_inverse(&x, &xi)); | |
530 | secp256k1_fe_inv(&xii, &xi); | |
531 | CHECK(check_fe_equal(&x, &xii)); | |
532 | } | |
533 | } | |
534 | ||
2cad067a | 535 | void run_field_inv_var(void) { |
f16be77f PD |
536 | secp256k1_fe_t x, xi, xii; |
537 | for (int i=0; i<10*count; i++) { | |
538 | random_fe_non_zero(&x); | |
539 | secp256k1_fe_inv_var(&xi, &x); | |
540 | CHECK(check_fe_inverse(&x, &xi)); | |
541 | secp256k1_fe_inv_var(&xii, &xi); | |
542 | CHECK(check_fe_equal(&x, &xii)); | |
543 | } | |
544 | } | |
545 | ||
2cad067a | 546 | void run_field_inv_all(void) { |
f16be77f | 547 | secp256k1_fe_t x[16], xi[16], xii[16]; |
71712b27 | 548 | /* Check it's safe to call for 0 elements */ |
f16be77f PD |
549 | secp256k1_fe_inv_all(0, xi, x); |
550 | for (int i=0; i<count; i++) { | |
551 | size_t len = (secp256k1_rand32() & 15) + 1; | |
3276e7d4 | 552 | for (size_t j=0; j<len; j++) |
f16be77f PD |
553 | random_fe_non_zero(&x[j]); |
554 | secp256k1_fe_inv_all(len, xi, x); | |
3276e7d4 | 555 | for (size_t j=0; j<len; j++) |
f16be77f PD |
556 | CHECK(check_fe_inverse(&x[j], &xi[j])); |
557 | secp256k1_fe_inv_all(len, xii, xi); | |
3276e7d4 | 558 | for (size_t j=0; j<len; j++) |
f16be77f PD |
559 | CHECK(check_fe_equal(&x[j], &xii[j])); |
560 | } | |
561 | } | |
562 | ||
2cad067a | 563 | void run_field_inv_all_var(void) { |
f16be77f | 564 | secp256k1_fe_t x[16], xi[16], xii[16]; |
71712b27 | 565 | /* Check it's safe to call for 0 elements */ |
f16be77f PD |
566 | secp256k1_fe_inv_all_var(0, xi, x); |
567 | for (int i=0; i<count; i++) { | |
568 | size_t len = (secp256k1_rand32() & 15) + 1; | |
3276e7d4 | 569 | for (size_t j=0; j<len; j++) |
f16be77f PD |
570 | random_fe_non_zero(&x[j]); |
571 | secp256k1_fe_inv_all_var(len, xi, x); | |
3276e7d4 | 572 | for (size_t j=0; j<len; j++) |
f16be77f PD |
573 | CHECK(check_fe_inverse(&x[j], &xi[j])); |
574 | secp256k1_fe_inv_all_var(len, xii, xi); | |
3276e7d4 | 575 | for (size_t j=0; j<len; j++) |
f16be77f PD |
576 | CHECK(check_fe_equal(&x[j], &xii[j])); |
577 | } | |
578 | } | |
579 | ||
2cad067a | 580 | void run_sqr(void) { |
59447da3 PD |
581 | secp256k1_fe_t x, s; |
582 | ||
59447da3 PD |
583 | { |
584 | secp256k1_fe_set_int(&x, 1); | |
585 | secp256k1_fe_negate(&x, &x, 1); | |
586 | ||
587 | for (int i=1; i<=512; ++i) { | |
588 | secp256k1_fe_mul_int(&x, 2); | |
589 | secp256k1_fe_normalize(&x); | |
590 | secp256k1_fe_sqr(&s, &x); | |
59447da3 PD |
591 | } |
592 | } | |
59447da3 PD |
593 | } |
594 | ||
09ca4f32 PD |
595 | void test_sqrt(const secp256k1_fe_t *a, const secp256k1_fe_t *k) { |
596 | secp256k1_fe_t r1, r2; | |
597 | int v = secp256k1_fe_sqrt(&r1, a); | |
0592d117 | 598 | CHECK((v == 0) == (k == NULL)); |
09ca4f32 PD |
599 | |
600 | if (k != NULL) { | |
71712b27 | 601 | /* Check that the returned root is +/- the given known answer */ |
09ca4f32 PD |
602 | secp256k1_fe_negate(&r2, &r1, 1); |
603 | secp256k1_fe_add(&r1, k); secp256k1_fe_add(&r2, k); | |
604 | secp256k1_fe_normalize(&r1); secp256k1_fe_normalize(&r2); | |
0592d117 | 605 | CHECK(secp256k1_fe_is_zero(&r1) || secp256k1_fe_is_zero(&r2)); |
09ca4f32 PD |
606 | } |
607 | } | |
608 | ||
2cad067a | 609 | void run_sqrt(void) { |
09ca4f32 | 610 | secp256k1_fe_t ns, x, s, t; |
6d6102fe | 611 | |
71712b27 | 612 | /* Check sqrt(0) is 0 */ |
6d6102fe PD |
613 | secp256k1_fe_set_int(&x, 0); |
614 | secp256k1_fe_sqr(&s, &x); | |
615 | test_sqrt(&s, &x); | |
616 | ||
71712b27 | 617 | /* Check sqrt of small squares (and their negatives) */ |
6d6102fe PD |
618 | for (int i=1; i<=100; i++) { |
619 | secp256k1_fe_set_int(&x, i); | |
09ca4f32 PD |
620 | secp256k1_fe_sqr(&s, &x); |
621 | test_sqrt(&s, &x); | |
6d6102fe | 622 | secp256k1_fe_negate(&t, &s, 1); |
09ca4f32 PD |
623 | test_sqrt(&t, NULL); |
624 | } | |
6d6102fe | 625 | |
71712b27 | 626 | /* Consistency checks for large random values */ |
6d6102fe PD |
627 | for (int i=0; i<10; i++) { |
628 | random_fe_non_square(&ns); | |
629 | for (int j=0; j<count; j++) { | |
630 | random_fe(&x); | |
631 | secp256k1_fe_sqr(&s, &x); | |
632 | test_sqrt(&s, &x); | |
633 | secp256k1_fe_negate(&t, &s, 1); | |
634 | test_sqrt(&t, NULL); | |
635 | secp256k1_fe_mul(&t, &s, &ns); | |
636 | test_sqrt(&t, NULL); | |
637 | } | |
638 | } | |
09ca4f32 PD |
639 | } |
640 | ||
9338dbf7 PW |
641 | /***** GROUP TESTS *****/ |
642 | ||
643 | int ge_equals_ge(const secp256k1_ge_t *a, const secp256k1_ge_t *b) { | |
644 | if (a->infinity && b->infinity) | |
645 | return 1; | |
646 | return check_fe_equal(&a->x, &b->x) && check_fe_equal(&a->y, &b->y); | |
647 | } | |
648 | ||
649 | void ge_equals_gej(const secp256k1_ge_t *a, const secp256k1_gej_t *b) { | |
650 | secp256k1_ge_t bb; | |
651 | secp256k1_gej_t bj = *b; | |
652 | secp256k1_ge_set_gej_var(&bb, &bj); | |
653 | CHECK(ge_equals_ge(a, &bb)); | |
654 | } | |
655 | ||
656 | void gej_equals_gej(const secp256k1_gej_t *a, const secp256k1_gej_t *b) { | |
657 | secp256k1_ge_t aa, bb; | |
658 | secp256k1_gej_t aj = *a, bj = *b; | |
659 | secp256k1_ge_set_gej_var(&aa, &aj); | |
660 | secp256k1_ge_set_gej_var(&bb, &bj); | |
661 | CHECK(ge_equals_ge(&aa, &bb)); | |
662 | } | |
663 | ||
2cad067a | 664 | void test_ge(void) { |
9338dbf7 PW |
665 | secp256k1_ge_t a, b, i, n; |
666 | random_group_element_test(&a); | |
667 | random_group_element_test(&b); | |
668 | n = a; | |
669 | secp256k1_fe_normalize(&a.y); | |
670 | secp256k1_fe_negate(&n.y, &a.y, 1); | |
671 | secp256k1_ge_set_infinity(&i); | |
672 | random_field_element_magnitude(&a.x); | |
673 | random_field_element_magnitude(&a.y); | |
674 | random_field_element_magnitude(&b.x); | |
675 | random_field_element_magnitude(&b.y); | |
676 | random_field_element_magnitude(&n.x); | |
677 | random_field_element_magnitude(&n.y); | |
678 | ||
679 | secp256k1_gej_t aj, bj, ij, nj; | |
680 | random_group_element_jacobian_test(&aj, &a); | |
681 | random_group_element_jacobian_test(&bj, &b); | |
682 | secp256k1_gej_set_infinity(&ij); | |
683 | random_group_element_jacobian_test(&nj, &n); | |
684 | random_field_element_magnitude(&aj.x); | |
685 | random_field_element_magnitude(&aj.y); | |
686 | random_field_element_magnitude(&aj.z); | |
687 | random_field_element_magnitude(&bj.x); | |
688 | random_field_element_magnitude(&bj.y); | |
689 | random_field_element_magnitude(&bj.z); | |
690 | random_field_element_magnitude(&nj.x); | |
691 | random_field_element_magnitude(&nj.y); | |
692 | random_field_element_magnitude(&nj.z); | |
693 | ||
71712b27 | 694 | /* gej + gej adds */ |
9338dbf7 PW |
695 | secp256k1_gej_t aaj; secp256k1_gej_add_var(&aaj, &aj, &aj); |
696 | secp256k1_gej_t abj; secp256k1_gej_add_var(&abj, &aj, &bj); | |
697 | secp256k1_gej_t aij; secp256k1_gej_add_var(&aij, &aj, &ij); | |
698 | secp256k1_gej_t anj; secp256k1_gej_add_var(&anj, &aj, &nj); | |
699 | secp256k1_gej_t iaj; secp256k1_gej_add_var(&iaj, &ij, &aj); | |
700 | secp256k1_gej_t iij; secp256k1_gej_add_var(&iij, &ij, &ij); | |
701 | ||
71712b27 | 702 | /* gej + ge adds */ |
9338dbf7 PW |
703 | secp256k1_gej_t aa; secp256k1_gej_add_ge_var(&aa, &aj, &a); |
704 | secp256k1_gej_t ab; secp256k1_gej_add_ge_var(&ab, &aj, &b); | |
705 | secp256k1_gej_t ai; secp256k1_gej_add_ge_var(&ai, &aj, &i); | |
706 | secp256k1_gej_t an; secp256k1_gej_add_ge_var(&an, &aj, &n); | |
707 | secp256k1_gej_t ia; secp256k1_gej_add_ge_var(&ia, &ij, &a); | |
708 | secp256k1_gej_t ii; secp256k1_gej_add_ge_var(&ii, &ij, &i); | |
709 | ||
71712b27 | 710 | /* const gej + ge adds */ |
9338dbf7 PW |
711 | secp256k1_gej_t aac; secp256k1_gej_add_ge(&aac, &aj, &a); |
712 | secp256k1_gej_t abc; secp256k1_gej_add_ge(&abc, &aj, &b); | |
713 | secp256k1_gej_t anc; secp256k1_gej_add_ge(&anc, &aj, &n); | |
714 | secp256k1_gej_t iac; secp256k1_gej_add_ge(&iac, &ij, &a); | |
715 | ||
716 | CHECK(secp256k1_gej_is_infinity(&an)); | |
717 | CHECK(secp256k1_gej_is_infinity(&anj)); | |
718 | CHECK(secp256k1_gej_is_infinity(&anc)); | |
719 | gej_equals_gej(&aa, &aaj); | |
720 | gej_equals_gej(&aa, &aac); | |
721 | gej_equals_gej(&ab, &abj); | |
722 | gej_equals_gej(&ab, &abc); | |
723 | gej_equals_gej(&an, &anj); | |
724 | gej_equals_gej(&an, &anc); | |
725 | gej_equals_gej(&ia, &iaj); | |
726 | gej_equals_gej(&ai, &aij); | |
727 | gej_equals_gej(&ii, &iij); | |
728 | ge_equals_gej(&a, &ai); | |
729 | ge_equals_gej(&a, &ai); | |
730 | ge_equals_gej(&a, &iaj); | |
731 | ge_equals_gej(&a, &iaj); | |
732 | ge_equals_gej(&a, &iac); | |
733 | } | |
734 | ||
2cad067a | 735 | void run_ge(void) { |
9338dbf7 PW |
736 | for (int i = 0; i < 2000*count; i++) { |
737 | test_ge(); | |
738 | } | |
739 | } | |
740 | ||
09ca4f32 PD |
741 | /***** ECMULT TESTS *****/ |
742 | ||
2cad067a | 743 | void run_ecmult_chain(void) { |
71712b27 | 744 | /* random starting point A (on the curve) */ |
d907ebc0 PW |
745 | secp256k1_fe_t ax; VERIFY_CHECK(secp256k1_fe_set_hex(&ax, "8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004", 64)); |
746 | secp256k1_fe_t ay; VERIFY_CHECK(secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64)); | |
f11ff5be | 747 | secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay); |
71712b27 | 748 | /* two random initial factors xn and gn */ |
4adf6b2a | 749 | secp256k1_num_t xn; |
4adf6b2a PW |
750 | secp256k1_num_set_hex(&xn, "84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407", 64); |
751 | secp256k1_num_t gn; | |
4adf6b2a | 752 | secp256k1_num_set_hex(&gn, "a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de", 64); |
71712b27 | 753 | /* two small multipliers to be applied to xn and gn in every iteration: */ |
4adf6b2a | 754 | secp256k1_num_t xf; |
4adf6b2a PW |
755 | secp256k1_num_set_hex(&xf, "1337", 4); |
756 | secp256k1_num_t gf; | |
4adf6b2a | 757 | secp256k1_num_set_hex(&gf, "7113", 4); |
71712b27 | 758 | /* accumulators with the resulting coefficients to A and G */ |
4adf6b2a | 759 | secp256k1_num_t ae; |
4adf6b2a PW |
760 | secp256k1_num_set_int(&ae, 1); |
761 | secp256k1_num_t ge; | |
4adf6b2a | 762 | secp256k1_num_set_int(&ge, 0); |
71712b27 | 763 | /* the point being computed */ |
f11ff5be PW |
764 | secp256k1_gej_t x = a; |
765 | const secp256k1_num_t *order = &secp256k1_ge_consts->order; | |
404c30a8 | 766 | for (int i=0; i<200*count; i++) { |
71712b27 | 767 | /* in each iteration, compute X = xn*X + gn*G; */ |
b1483f87 | 768 | secp256k1_ecmult(&x, &x, &xn, &gn); |
71712b27 GM |
769 | /* also compute ae and ge: the actual accumulated factors for A and G */ |
770 | /* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */ | |
f11ff5be PW |
771 | secp256k1_num_mod_mul(&ae, &ae, &xn, order); |
772 | secp256k1_num_mod_mul(&ge, &ge, &xn, order); | |
4adf6b2a | 773 | secp256k1_num_add(&ge, &ge, &gn); |
2f9e831d | 774 | secp256k1_num_mod(&ge, order); |
71712b27 | 775 | /* modify xn and gn */ |
f11ff5be PW |
776 | secp256k1_num_mod_mul(&xn, &xn, &xf, order); |
777 | secp256k1_num_mod_mul(&gn, &gn, &gf, order); | |
404c30a8 | 778 | |
71712b27 | 779 | /* verify */ |
404c30a8 PW |
780 | if (i == 19999) { |
781 | char res[132]; int resl = 132; | |
782 | secp256k1_gej_get_hex(res, &resl, &x); | |
0592d117 | 783 | CHECK(strcmp(res, "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)") == 0); |
404c30a8 | 784 | } |
4adf6b2a | 785 | } |
71712b27 | 786 | /* redo the computation, but directly with the resulting ae and ge coefficients: */ |
b1483f87 | 787 | secp256k1_gej_t x2; secp256k1_ecmult(&x2, &a, &ae, &ge); |
404c30a8 | 788 | char res[132]; int resl = 132; |
f11ff5be | 789 | char res2[132]; int resl2 = 132; |
404c30a8 | 790 | secp256k1_gej_get_hex(res, &resl, &x); |
f11ff5be | 791 | secp256k1_gej_get_hex(res2, &resl2, &x2); |
0592d117 PW |
792 | CHECK(strcmp(res, res2) == 0); |
793 | CHECK(strlen(res) == 131); | |
a41f32e6 PW |
794 | } |
795 | ||
eb0be8ee | 796 | void test_point_times_order(const secp256k1_gej_t *point) { |
b5c9ee75 PW |
797 | /* X * (point + G) + (order-X) * (pointer + G) = 0 */ |
798 | secp256k1_num_t x; | |
799 | random_num_order_test(&x); | |
800 | secp256k1_num_t nx; | |
801 | secp256k1_num_sub(&nx, &secp256k1_ge_consts->order, &x); | |
802 | secp256k1_gej_t res1, res2; | |
803 | secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */ | |
804 | secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ | |
805 | secp256k1_gej_add_var(&res1, &res1, &res2); | |
806 | CHECK(secp256k1_gej_is_infinity(&res1)); | |
4e0ed539 PW |
807 | } |
808 | ||
2cad067a | 809 | void run_point_times_order(void) { |
d907ebc0 | 810 | secp256k1_fe_t x; VERIFY_CHECK(secp256k1_fe_set_hex(&x, "02", 2)); |
4e0ed539 | 811 | for (int i=0; i<500; i++) { |
09ca4f32 PD |
812 | secp256k1_ge_t p; |
813 | if (secp256k1_ge_set_xo(&p, &x, 1)) { | |
0592d117 | 814 | CHECK(secp256k1_ge_is_valid(&p)); |
09ca4f32 PD |
815 | secp256k1_gej_t j; |
816 | secp256k1_gej_set_ge(&j, &p); | |
0592d117 | 817 | CHECK(secp256k1_gej_is_valid(&j)); |
09ca4f32 PD |
818 | test_point_times_order(&j); |
819 | } | |
910d0de4 | 820 | secp256k1_fe_sqr(&x, &x); |
4e0ed539 | 821 | } |
910d0de4 PW |
822 | char c[65]; int cl=65; |
823 | secp256k1_fe_get_hex(c, &cl, &x); | |
0592d117 | 824 | CHECK(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0); |
4e0ed539 PW |
825 | } |
826 | ||
eb0be8ee | 827 | void test_wnaf(const secp256k1_num_t *number, int w) { |
4adf6b2a | 828 | secp256k1_num_t x, two, t; |
4adf6b2a PW |
829 | secp256k1_num_set_int(&x, 0); |
830 | secp256k1_num_set_int(&two, 2); | |
0b730597 | 831 | int wnaf[256]; |
eb0be8ee | 832 | int bits = secp256k1_ecmult_wnaf(wnaf, number, w); |
0b730597 | 833 | CHECK(bits <= 256); |
4e0ed539 | 834 | int zeroes = -1; |
b1483f87 | 835 | for (int i=bits-1; i>=0; i--) { |
4adf6b2a | 836 | secp256k1_num_mul(&x, &x, &two); |
b1483f87 | 837 | int v = wnaf[i]; |
4e0ed539 | 838 | if (v) { |
71712b27 | 839 | CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */ |
4e0ed539 | 840 | zeroes=0; |
71712b27 GM |
841 | CHECK((v & 1) == 1); /* check non-zero elements are odd */ |
842 | CHECK(v <= (1 << (w-1)) - 1); /* check range below */ | |
843 | CHECK(v >= -(1 << (w-1)) - 1); /* check range above */ | |
4e0ed539 | 844 | } else { |
71712b27 | 845 | CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */ |
4e0ed539 PW |
846 | zeroes++; |
847 | } | |
4adf6b2a PW |
848 | secp256k1_num_set_int(&t, v); |
849 | secp256k1_num_add(&x, &x, &t); | |
4e0ed539 | 850 | } |
0b730597 PW |
851 | secp256k1_num_t xcopy = x, ncopy = *number; |
852 | secp256k1_num_mod(&xcopy, &secp256k1_ge_consts->order); | |
853 | secp256k1_num_mod(&ncopy, &secp256k1_ge_consts->order); | |
854 | CHECK(secp256k1_num_eq(&xcopy, &ncopy)); /* check that wnaf represents number */ | |
4e0ed539 PW |
855 | } |
856 | ||
2cad067a | 857 | void run_wnaf(void) { |
d06e61cb | 858 | secp256k1_num_t n; |
404c30a8 | 859 | for (int i=0; i<count; i++) { |
d06e61cb PW |
860 | random_num_order(&n); |
861 | if (i % 1) | |
862 | secp256k1_num_negate(&n); | |
eb0be8ee | 863 | test_wnaf(&n, 4+(i%10)); |
4e0ed539 PW |
864 | } |
865 | } | |
a41f32e6 | 866 | |
a9f5c8b8 PW |
867 | void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *key, const secp256k1_scalar_t *msg, int *recid) { |
868 | secp256k1_scalar_t nonce; | |
dd08f037 | 869 | do { |
a9f5c8b8 | 870 | random_scalar_order_test(&nonce); |
dd08f037 | 871 | } while(!secp256k1_ecdsa_sig_sign(sig, key, msg, &nonce, recid)); |
dd08f037 PW |
872 | } |
873 | ||
2cad067a | 874 | void test_ecdsa_sign_verify(void) { |
a9f5c8b8 | 875 | secp256k1_scalar_t msg, key; |
a9f5c8b8 | 876 | random_scalar_order_test(&msg); |
a9f5c8b8 | 877 | random_scalar_order_test(&key); |
764332d0 PW |
878 | secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key); |
879 | secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj); | |
d41e93a5 | 880 | secp256k1_ecdsa_sig_t sig; |
dd08f037 | 881 | random_sign(&sig, &key, &msg, NULL); |
a9f5c8b8 | 882 | secp256k1_num_t msg_num; |
a9f5c8b8 PW |
883 | secp256k1_scalar_get_num(&msg_num, &msg); |
884 | CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num)); | |
885 | secp256k1_num_inc(&msg_num); | |
886 | CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num)); | |
0a07e62f PW |
887 | } |
888 | ||
2cad067a | 889 | void run_ecdsa_sign_verify(void) { |
404c30a8 | 890 | for (int i=0; i<10*count; i++) { |
0a07e62f PW |
891 | test_ecdsa_sign_verify(); |
892 | } | |
893 | } | |
894 | ||
2cad067a | 895 | void test_ecdsa_end_to_end(void) { |
25f4aec0 PW |
896 | unsigned char privkey[32]; |
897 | unsigned char message[32]; | |
898 | ||
71712b27 | 899 | /* Generate a random key and message. */ |
25f4aec0 PW |
900 | { |
901 | secp256k1_num_t msg, key; | |
25f4aec0 | 902 | random_num_order_test(&msg); |
25f4aec0 PW |
903 | random_num_order_test(&key); |
904 | secp256k1_num_get_bin(privkey, 32, &key); | |
905 | secp256k1_num_get_bin(message, 32, &msg); | |
25f4aec0 PW |
906 | } |
907 | ||
71712b27 | 908 | /* Construct and verify corresponding public key. */ |
ae6bc76e | 909 | CHECK(secp256k1_ec_seckey_verify(privkey) == 1); |
9974d869 | 910 | unsigned char pubkey[65]; int pubkeylen = 65; |
ae6bc76e PW |
911 | CHECK(secp256k1_ec_pubkey_create(pubkey, &pubkeylen, privkey, secp256k1_rand32() % 2) == 1); |
912 | CHECK(secp256k1_ec_pubkey_verify(pubkey, pubkeylen)); | |
25f4aec0 | 913 | |
71712b27 | 914 | /* Verify private key import and export. */ |
25f4aec0 | 915 | unsigned char seckey[300]; int seckeylen = 300; |
ae6bc76e | 916 | CHECK(secp256k1_ec_privkey_export(privkey, seckey, &seckeylen, secp256k1_rand32() % 2) == 1); |
25f4aec0 | 917 | unsigned char privkey2[32]; |
ae6bc76e | 918 | CHECK(secp256k1_ec_privkey_import(privkey2, seckey, seckeylen) == 1); |
25f4aec0 PW |
919 | CHECK(memcmp(privkey, privkey2, 32) == 0); |
920 | ||
71712b27 | 921 | /* Optionally tweak the keys using addition. */ |
25f4aec0 PW |
922 | if (secp256k1_rand32() % 3 == 0) { |
923 | unsigned char rnd[32]; | |
924 | secp256k1_rand256_test(rnd); | |
ae6bc76e PW |
925 | int ret1 = secp256k1_ec_privkey_tweak_add(privkey, rnd); |
926 | int ret2 = secp256k1_ec_pubkey_tweak_add(pubkey, pubkeylen, rnd); | |
25f4aec0 PW |
927 | CHECK(ret1 == ret2); |
928 | if (ret1 == 0) return; | |
9974d869 | 929 | unsigned char pubkey2[65]; int pubkeylen2 = 65; |
ae6bc76e | 930 | CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); |
25f4aec0 PW |
931 | CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); |
932 | } | |
933 | ||
71712b27 | 934 | /* Optionally tweak the keys using multiplication. */ |
25f4aec0 PW |
935 | if (secp256k1_rand32() % 3 == 0) { |
936 | unsigned char rnd[32]; | |
937 | secp256k1_rand256_test(rnd); | |
ae6bc76e PW |
938 | int ret1 = secp256k1_ec_privkey_tweak_mul(privkey, rnd); |
939 | int ret2 = secp256k1_ec_pubkey_tweak_mul(pubkey, pubkeylen, rnd); | |
25f4aec0 PW |
940 | CHECK(ret1 == ret2); |
941 | if (ret1 == 0) return; | |
9974d869 | 942 | unsigned char pubkey2[65]; int pubkeylen2 = 65; |
ae6bc76e | 943 | CHECK(secp256k1_ec_pubkey_create(pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); |
25f4aec0 PW |
944 | CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); |
945 | } | |
946 | ||
71712b27 | 947 | /* Sign. */ |
9974d869 | 948 | unsigned char signature[72]; int signaturelen = 72; |
25f4aec0 PW |
949 | while(1) { |
950 | unsigned char rnd[32]; | |
951 | secp256k1_rand256_test(rnd); | |
952 | if (secp256k1_ecdsa_sign(message, 32, signature, &signaturelen, privkey, rnd) == 1) { | |
953 | break; | |
954 | } | |
955 | } | |
71712b27 | 956 | /* Verify. */ |
25f4aec0 | 957 | CHECK(secp256k1_ecdsa_verify(message, 32, signature, signaturelen, pubkey, pubkeylen) == 1); |
71712b27 | 958 | /* Destroy signature and verify again. */ |
25f4aec0 PW |
959 | signature[signaturelen - 1 - secp256k1_rand32() % 20] += 1 + (secp256k1_rand32() % 255); |
960 | CHECK(secp256k1_ecdsa_verify(message, 32, signature, signaturelen, pubkey, pubkeylen) != 1); | |
961 | ||
71712b27 | 962 | /* Compact sign. */ |
9974d869 | 963 | unsigned char csignature[64]; int recid = 0; |
25f4aec0 PW |
964 | while(1) { |
965 | unsigned char rnd[32]; | |
966 | secp256k1_rand256_test(rnd); | |
967 | if (secp256k1_ecdsa_sign_compact(message, 32, csignature, privkey, rnd, &recid) == 1) { | |
968 | break; | |
969 | } | |
970 | } | |
71712b27 | 971 | /* Recover. */ |
9974d869 | 972 | unsigned char recpubkey[65]; int recpubkeylen = 0; |
25f4aec0 PW |
973 | CHECK(secp256k1_ecdsa_recover_compact(message, 32, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) == 1); |
974 | CHECK(recpubkeylen == pubkeylen); | |
975 | CHECK(memcmp(pubkey, recpubkey, pubkeylen) == 0); | |
71712b27 | 976 | /* Destroy signature and verify again. */ |
25f4aec0 PW |
977 | csignature[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255); |
978 | CHECK(secp256k1_ecdsa_recover_compact(message, 32, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) != 1 || | |
979 | memcmp(pubkey, recpubkey, pubkeylen) != 0); | |
980 | CHECK(recpubkeylen == pubkeylen); | |
3fd6253e | 981 | |
25f4aec0 PW |
982 | } |
983 | ||
2cad067a | 984 | void run_ecdsa_end_to_end(void) { |
25f4aec0 PW |
985 | for (int i=0; i<64*count; i++) { |
986 | test_ecdsa_end_to_end(); | |
987 | } | |
988 | } | |
989 | ||
6e052878 PW |
990 | /* Tests several edge cases. */ |
991 | void test_ecdsa_edge_cases(void) { | |
3bf029d6 PW |
992 | const unsigned char msg32[32] = { |
993 | 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', | |
994 | 'a', ' ', 'v', 'e', 'r', 'y', ' ', 's', | |
995 | 'e', 'c', 'r', 'e', 't', ' ', 'm', 'e', | |
996 | 's', 's', 'a', 'g', 'e', '.', '.', '.' | |
997 | }; | |
998 | const unsigned char sig64[64] = { | |
6e052878 PW |
999 | /* Generated by signing the above message with nonce 'This is the nonce we will use...' |
1000 | * and secret key 0 (which is not valid), resulting in recid 0. */ | |
3bf029d6 PW |
1001 | 0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8, |
1002 | 0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96, | |
1003 | 0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63, | |
1004 | 0x17, 0x9A, 0x7D, 0xD1, 0x7B, 0xD2, 0x35, 0x32, | |
1005 | 0x4B, 0x1B, 0x7D, 0xF3, 0x4C, 0xE1, 0xF6, 0x8E, | |
1006 | 0x69, 0x4F, 0xF6, 0xF1, 0x1A, 0xC7, 0x51, 0xDD, | |
1007 | 0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, | |
1008 | 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 | |
1009 | }; | |
1010 | unsigned char pubkey[65]; | |
1011 | int pubkeylen = 65; | |
1012 | CHECK(!secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 0)); | |
1013 | CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 1)); | |
1014 | CHECK(!secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 2)); | |
1015 | CHECK(!secp256k1_ecdsa_recover_compact(msg32, 32, sig64, pubkey, &pubkeylen, 0, 3)); | |
6e052878 PW |
1016 | |
1017 | /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ | |
1018 | const unsigned char sigb64[64] = { | |
1019 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1020 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1021 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1022 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, | |
1023 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1024 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1025 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
1026 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, | |
1027 | }; | |
1028 | unsigned char pubkeyb[33]; | |
1029 | int pubkeyblen = 33; | |
1030 | for (int recid = 0; recid < 4; recid++) { | |
1031 | unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04}; | |
1032 | CHECK(secp256k1_ecdsa_recover_compact(msg32, 32, sigb64, pubkeyb, &pubkeyblen, 1, recid)); | |
1033 | CHECK(secp256k1_ecdsa_verify(msg32, 32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 1); | |
1034 | /* Damage signature. */ | |
1035 | sigbder[7]++; | |
1036 | CHECK(secp256k1_ecdsa_verify(msg32, 32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 0); | |
1037 | } | |
3bf029d6 PW |
1038 | } |
1039 | ||
6e052878 PW |
1040 | void run_ecdsa_edge_cases(void) { |
1041 | test_ecdsa_edge_cases(); | |
3bf029d6 | 1042 | } |
25f4aec0 | 1043 | |
dd08f037 | 1044 | #ifdef ENABLE_OPENSSL_TESTS |
a9f5c8b8 | 1045 | EC_KEY *get_openssl_key(const secp256k1_scalar_t *key) { |
12e29b32 PW |
1046 | unsigned char privkey[300]; |
1047 | int privkeylen; | |
1048 | int compr = secp256k1_rand32() & 1; | |
1049 | const unsigned char* pbegin = privkey; | |
dd08f037 | 1050 | EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); |
ffffc878 | 1051 | CHECK(secp256k1_eckey_privkey_serialize(privkey, &privkeylen, key, compr)); |
0592d117 PW |
1052 | CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); |
1053 | CHECK(EC_KEY_check_key(ec_key)); | |
dd08f037 PW |
1054 | return ec_key; |
1055 | } | |
1056 | ||
2cad067a | 1057 | void test_ecdsa_openssl(void) { |
a9f5c8b8 | 1058 | secp256k1_scalar_t key, msg; |
dd08f037 PW |
1059 | unsigned char message[32]; |
1060 | secp256k1_rand256_test(message); | |
eca6cdb1 | 1061 | secp256k1_scalar_set_b32(&msg, message, NULL); |
a9f5c8b8 | 1062 | random_scalar_order_test(&key); |
dd08f037 PW |
1063 | secp256k1_gej_t qj; |
1064 | secp256k1_ecmult_gen(&qj, &key); | |
1065 | secp256k1_ge_t q; | |
1066 | secp256k1_ge_set_gej(&q, &qj); | |
1067 | EC_KEY *ec_key = get_openssl_key(&key); | |
0592d117 | 1068 | CHECK(ec_key); |
dd08f037 | 1069 | unsigned char signature[80]; |
9974d869 | 1070 | unsigned int sigsize = 80; |
0592d117 | 1071 | CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); |
dd08f037 | 1072 | secp256k1_ecdsa_sig_t sig; |
0592d117 | 1073 | CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize)); |
a9f5c8b8 | 1074 | secp256k1_num_t msg_num; |
a9f5c8b8 PW |
1075 | secp256k1_scalar_get_num(&msg_num, &msg); |
1076 | CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num)); | |
dd08f037 | 1077 | secp256k1_num_inc(&sig.r); |
a9f5c8b8 | 1078 | CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num)); |
dd08f037 PW |
1079 | |
1080 | random_sign(&sig, &key, &msg, NULL); | |
9974d869 GM |
1081 | int secp_sigsize = 80; |
1082 | CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sig)); | |
1083 | CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1); | |
dd08f037 | 1084 | |
dd08f037 | 1085 | EC_KEY_free(ec_key); |
dd08f037 PW |
1086 | } |
1087 | ||
2cad067a | 1088 | void run_ecdsa_openssl(void) { |
dd08f037 PW |
1089 | for (int i=0; i<10*count; i++) { |
1090 | test_ecdsa_openssl(); | |
1091 | } | |
1092 | } | |
1093 | #endif | |
1094 | ||
404c30a8 | 1095 | int main(int argc, char **argv) { |
71712b27 | 1096 | /* find iteration count */ |
3fd6253e PW |
1097 | if (argc > 1) { |
1098 | count = strtol(argv[1], NULL, 0); | |
1099 | } | |
1100 | ||
71712b27 | 1101 | /* find random seed */ |
3fd6253e PW |
1102 | uint64_t seed; |
1103 | if (argc > 2) { | |
1104 | seed = strtoull(argv[2], NULL, 0); | |
1105 | } else { | |
1106 | FILE *frand = fopen("/dev/urandom", "r"); | |
1107 | if (!frand || !fread(&seed, sizeof(seed), 1, frand)) { | |
1108 | seed = time(NULL) * 1337; | |
1109 | } | |
1110 | fclose(frand); | |
1111 | } | |
1112 | secp256k1_rand_seed(seed); | |
404c30a8 | 1113 | |
dd08f037 | 1114 | printf("test count = %i\n", count); |
3fd6253e | 1115 | printf("random seed = %llu\n", (unsigned long long)seed); |
dd08f037 | 1116 | |
71712b27 | 1117 | /* initialize */ |
04e34d18 | 1118 | secp256k1_start(SECP256K1_START_SIGN | SECP256K1_START_VERIFY); |
4adf6b2a | 1119 | |
71712b27 | 1120 | /* num tests */ |
3f44e1ad | 1121 | run_num_smalltests(); |
404c30a8 | 1122 | |
71712b27 | 1123 | /* scalar tests */ |
79359302 PW |
1124 | run_scalar_tests(); |
1125 | ||
71712b27 | 1126 | /* field tests */ |
f16be77f PD |
1127 | run_field_inv(); |
1128 | run_field_inv_var(); | |
1129 | run_field_inv_all(); | |
1130 | run_field_inv_all_var(); | |
59447da3 | 1131 | run_sqr(); |
09ca4f32 PD |
1132 | run_sqrt(); |
1133 | ||
71712b27 | 1134 | /* group tests */ |
9338dbf7 PW |
1135 | run_ge(); |
1136 | ||
71712b27 | 1137 | /* ecmult tests */ |
404c30a8 PW |
1138 | run_wnaf(); |
1139 | run_point_times_order(); | |
1140 | run_ecmult_chain(); | |
1141 | ||
71712b27 | 1142 | /* ecdsa tests */ |
404c30a8 | 1143 | run_ecdsa_sign_verify(); |
25f4aec0 | 1144 | run_ecdsa_end_to_end(); |
6e052878 | 1145 | run_ecdsa_edge_cases(); |
dd08f037 PW |
1146 | #ifdef ENABLE_OPENSSL_TESTS |
1147 | run_ecdsa_openssl(); | |
1148 | #endif | |
910d0de4 | 1149 | |
9974d869 | 1150 | printf("random run = %llu\n", (unsigned long long)secp256k1_rand32() + ((unsigned long long)secp256k1_rand32() << 32)); |
bff11e91 | 1151 | |
71712b27 | 1152 | /* shutdown */ |
25f4aec0 | 1153 | secp256k1_stop(); |
a41f32e6 PW |
1154 | return 0; |
1155 | } |