]>
Commit | Line | Data |
---|---|---|
1 | /*********************************************************************** | |
2 | * Copyright (c) 2014-2015 Pieter Wuille * | |
3 | * Distributed under the MIT software license, see the accompanying * | |
4 | * file COPYING or https://www.opensource.org/licenses/mit-license.php.* | |
5 | ***********************************************************************/ | |
6 | #include <stdio.h> | |
7 | ||
8 | #include "secp256k1.c" | |
9 | #include "../include/secp256k1.h" | |
10 | ||
11 | #include "assumptions.h" | |
12 | #include "util.h" | |
13 | #include "hash_impl.h" | |
14 | #include "field_impl.h" | |
15 | #include "group_impl.h" | |
16 | #include "scalar_impl.h" | |
17 | #include "ecmult_const_impl.h" | |
18 | #include "ecmult_impl.h" | |
19 | #include "bench.h" | |
20 | ||
21 | typedef struct { | |
22 | secp256k1_scalar scalar[2]; | |
23 | secp256k1_fe fe[4]; | |
24 | secp256k1_ge ge[2]; | |
25 | secp256k1_gej gej[2]; | |
26 | unsigned char data[64]; | |
27 | int wnaf[256]; | |
28 | } bench_inv; | |
29 | ||
30 | void bench_setup(void* arg) { | |
31 | bench_inv *data = (bench_inv*)arg; | |
32 | ||
33 | static const unsigned char init[4][32] = { | |
34 | /* Initializer for scalar[0], fe[0], first half of data, the X coordinate of ge[0], | |
35 | and the (implied affine) X coordinate of gej[0]. */ | |
36 | { | |
37 | 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, | |
38 | 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35, | |
39 | 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59, | |
40 | 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83 | |
41 | }, | |
42 | /* Initializer for scalar[1], fe[1], first half of data, the X coordinate of ge[1], | |
43 | and the (implied affine) X coordinate of gej[1]. */ | |
44 | { | |
45 | 0x82, 0x83, 0x85, 0x87, 0x8b, 0x8d, 0x81, 0x83, | |
46 | 0x97, 0xad, 0xaf, 0xb5, 0xb9, 0xbb, 0xbf, 0xc5, | |
47 | 0xdb, 0xdd, 0xe3, 0xe7, 0xe9, 0xef, 0xf3, 0xf9, | |
48 | 0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3 | |
49 | }, | |
50 | /* Initializer for fe[2] and the Z coordinate of gej[0]. */ | |
51 | { | |
52 | 0x3d, 0x2d, 0xef, 0xf4, 0x25, 0x98, 0x4f, 0x5d, | |
53 | 0xe2, 0xca, 0x5f, 0x41, 0x3f, 0x3f, 0xce, 0x44, | |
54 | 0xaa, 0x2c, 0x53, 0x8a, 0xc6, 0x59, 0x1f, 0x38, | |
55 | 0x38, 0x23, 0xe4, 0x11, 0x27, 0xc6, 0xa0, 0xe7 | |
56 | }, | |
57 | /* Initializer for fe[3] and the Z coordinate of gej[1]. */ | |
58 | { | |
59 | 0xbd, 0x21, 0xa5, 0xe1, 0x13, 0x50, 0x73, 0x2e, | |
60 | 0x52, 0x98, 0xc8, 0x9e, 0xab, 0x00, 0xa2, 0x68, | |
61 | 0x43, 0xf5, 0xd7, 0x49, 0x80, 0x72, 0xa7, 0xf3, | |
62 | 0xd7, 0x60, 0xe6, 0xab, 0x90, 0x92, 0xdf, 0xc5 | |
63 | } | |
64 | }; | |
65 | ||
66 | secp256k1_scalar_set_b32(&data->scalar[0], init[0], NULL); | |
67 | secp256k1_scalar_set_b32(&data->scalar[1], init[1], NULL); | |
68 | secp256k1_fe_set_b32(&data->fe[0], init[0]); | |
69 | secp256k1_fe_set_b32(&data->fe[1], init[1]); | |
70 | secp256k1_fe_set_b32(&data->fe[2], init[2]); | |
71 | secp256k1_fe_set_b32(&data->fe[3], init[3]); | |
72 | CHECK(secp256k1_ge_set_xo_var(&data->ge[0], &data->fe[0], 0)); | |
73 | CHECK(secp256k1_ge_set_xo_var(&data->ge[1], &data->fe[1], 1)); | |
74 | secp256k1_gej_set_ge(&data->gej[0], &data->ge[0]); | |
75 | secp256k1_gej_rescale(&data->gej[0], &data->fe[2]); | |
76 | secp256k1_gej_set_ge(&data->gej[1], &data->ge[1]); | |
77 | secp256k1_gej_rescale(&data->gej[1], &data->fe[3]); | |
78 | memcpy(data->data, init[0], 32); | |
79 | memcpy(data->data + 32, init[1], 32); | |
80 | } | |
81 | ||
82 | void bench_scalar_add(void* arg, int iters) { | |
83 | int i, j = 0; | |
84 | bench_inv *data = (bench_inv*)arg; | |
85 | ||
86 | for (i = 0; i < iters; i++) { | |
87 | j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); | |
88 | } | |
89 | CHECK(j <= iters); | |
90 | } | |
91 | ||
92 | void bench_scalar_negate(void* arg, int iters) { | |
93 | int i; | |
94 | bench_inv *data = (bench_inv*)arg; | |
95 | ||
96 | for (i = 0; i < iters; i++) { | |
97 | secp256k1_scalar_negate(&data->scalar[0], &data->scalar[0]); | |
98 | } | |
99 | } | |
100 | ||
101 | void bench_scalar_mul(void* arg, int iters) { | |
102 | int i; | |
103 | bench_inv *data = (bench_inv*)arg; | |
104 | ||
105 | for (i = 0; i < iters; i++) { | |
106 | secp256k1_scalar_mul(&data->scalar[0], &data->scalar[0], &data->scalar[1]); | |
107 | } | |
108 | } | |
109 | ||
110 | void bench_scalar_split(void* arg, int iters) { | |
111 | int i, j = 0; | |
112 | bench_inv *data = (bench_inv*)arg; | |
113 | ||
114 | for (i = 0; i < iters; i++) { | |
115 | secp256k1_scalar_split_lambda(&data->scalar[0], &data->scalar[1], &data->scalar[0]); | |
116 | j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); | |
117 | } | |
118 | CHECK(j <= iters); | |
119 | } | |
120 | ||
121 | void bench_scalar_inverse(void* arg, int iters) { | |
122 | int i, j = 0; | |
123 | bench_inv *data = (bench_inv*)arg; | |
124 | ||
125 | for (i = 0; i < iters; i++) { | |
126 | secp256k1_scalar_inverse(&data->scalar[0], &data->scalar[0]); | |
127 | j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); | |
128 | } | |
129 | CHECK(j <= iters); | |
130 | } | |
131 | ||
132 | void bench_scalar_inverse_var(void* arg, int iters) { | |
133 | int i, j = 0; | |
134 | bench_inv *data = (bench_inv*)arg; | |
135 | ||
136 | for (i = 0; i < iters; i++) { | |
137 | secp256k1_scalar_inverse_var(&data->scalar[0], &data->scalar[0]); | |
138 | j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); | |
139 | } | |
140 | CHECK(j <= iters); | |
141 | } | |
142 | ||
143 | void bench_field_normalize(void* arg, int iters) { | |
144 | int i; | |
145 | bench_inv *data = (bench_inv*)arg; | |
146 | ||
147 | for (i = 0; i < iters; i++) { | |
148 | secp256k1_fe_normalize(&data->fe[0]); | |
149 | } | |
150 | } | |
151 | ||
152 | void bench_field_normalize_weak(void* arg, int iters) { | |
153 | int i; | |
154 | bench_inv *data = (bench_inv*)arg; | |
155 | ||
156 | for (i = 0; i < iters; i++) { | |
157 | secp256k1_fe_normalize_weak(&data->fe[0]); | |
158 | } | |
159 | } | |
160 | ||
161 | void bench_field_mul(void* arg, int iters) { | |
162 | int i; | |
163 | bench_inv *data = (bench_inv*)arg; | |
164 | ||
165 | for (i = 0; i < iters; i++) { | |
166 | secp256k1_fe_mul(&data->fe[0], &data->fe[0], &data->fe[1]); | |
167 | } | |
168 | } | |
169 | ||
170 | void bench_field_sqr(void* arg, int iters) { | |
171 | int i; | |
172 | bench_inv *data = (bench_inv*)arg; | |
173 | ||
174 | for (i = 0; i < iters; i++) { | |
175 | secp256k1_fe_sqr(&data->fe[0], &data->fe[0]); | |
176 | } | |
177 | } | |
178 | ||
179 | void bench_field_inverse(void* arg, int iters) { | |
180 | int i; | |
181 | bench_inv *data = (bench_inv*)arg; | |
182 | ||
183 | for (i = 0; i < iters; i++) { | |
184 | secp256k1_fe_inv(&data->fe[0], &data->fe[0]); | |
185 | secp256k1_fe_add(&data->fe[0], &data->fe[1]); | |
186 | } | |
187 | } | |
188 | ||
189 | void bench_field_inverse_var(void* arg, int iters) { | |
190 | int i; | |
191 | bench_inv *data = (bench_inv*)arg; | |
192 | ||
193 | for (i = 0; i < iters; i++) { | |
194 | secp256k1_fe_inv_var(&data->fe[0], &data->fe[0]); | |
195 | secp256k1_fe_add(&data->fe[0], &data->fe[1]); | |
196 | } | |
197 | } | |
198 | ||
199 | void bench_field_sqrt(void* arg, int iters) { | |
200 | int i, j = 0; | |
201 | bench_inv *data = (bench_inv*)arg; | |
202 | secp256k1_fe t; | |
203 | ||
204 | for (i = 0; i < iters; i++) { | |
205 | t = data->fe[0]; | |
206 | j += secp256k1_fe_sqrt(&data->fe[0], &t); | |
207 | secp256k1_fe_add(&data->fe[0], &data->fe[1]); | |
208 | } | |
209 | CHECK(j <= iters); | |
210 | } | |
211 | ||
212 | void bench_group_double_var(void* arg, int iters) { | |
213 | int i; | |
214 | bench_inv *data = (bench_inv*)arg; | |
215 | ||
216 | for (i = 0; i < iters; i++) { | |
217 | secp256k1_gej_double_var(&data->gej[0], &data->gej[0], NULL); | |
218 | } | |
219 | } | |
220 | ||
221 | void bench_group_add_var(void* arg, int iters) { | |
222 | int i; | |
223 | bench_inv *data = (bench_inv*)arg; | |
224 | ||
225 | for (i = 0; i < iters; i++) { | |
226 | secp256k1_gej_add_var(&data->gej[0], &data->gej[0], &data->gej[1], NULL); | |
227 | } | |
228 | } | |
229 | ||
230 | void bench_group_add_affine(void* arg, int iters) { | |
231 | int i; | |
232 | bench_inv *data = (bench_inv*)arg; | |
233 | ||
234 | for (i = 0; i < iters; i++) { | |
235 | secp256k1_gej_add_ge(&data->gej[0], &data->gej[0], &data->ge[1]); | |
236 | } | |
237 | } | |
238 | ||
239 | void bench_group_add_affine_var(void* arg, int iters) { | |
240 | int i; | |
241 | bench_inv *data = (bench_inv*)arg; | |
242 | ||
243 | for (i = 0; i < iters; i++) { | |
244 | secp256k1_gej_add_ge_var(&data->gej[0], &data->gej[0], &data->ge[1], NULL); | |
245 | } | |
246 | } | |
247 | ||
248 | void bench_group_to_affine_var(void* arg, int iters) { | |
249 | int i; | |
250 | bench_inv *data = (bench_inv*)arg; | |
251 | ||
252 | for (i = 0; i < iters; ++i) { | |
253 | secp256k1_ge_set_gej_var(&data->ge[1], &data->gej[0]); | |
254 | /* Use the output affine X/Y coordinates to vary the input X/Y/Z coordinates. | |
255 | Note that the resulting coordinates will generally not correspond to a point | |
256 | on the curve, but this is not a problem for the code being benchmarked here. | |
257 | Adding and normalizing have less overhead than EC operations (which could | |
258 | guarantee the point remains on the curve). */ | |
259 | secp256k1_fe_add(&data->gej[0].x, &data->ge[1].y); | |
260 | secp256k1_fe_add(&data->gej[0].y, &data->fe[2]); | |
261 | secp256k1_fe_add(&data->gej[0].z, &data->ge[1].x); | |
262 | secp256k1_fe_normalize_var(&data->gej[0].x); | |
263 | secp256k1_fe_normalize_var(&data->gej[0].y); | |
264 | secp256k1_fe_normalize_var(&data->gej[0].z); | |
265 | } | |
266 | } | |
267 | ||
268 | void bench_ecmult_wnaf(void* arg, int iters) { | |
269 | int i, bits = 0, overflow = 0; | |
270 | bench_inv *data = (bench_inv*)arg; | |
271 | ||
272 | for (i = 0; i < iters; i++) { | |
273 | bits += secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar[0], WINDOW_A); | |
274 | overflow += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); | |
275 | } | |
276 | CHECK(overflow >= 0); | |
277 | CHECK(bits <= 256*iters); | |
278 | } | |
279 | ||
280 | void bench_wnaf_const(void* arg, int iters) { | |
281 | int i, bits = 0, overflow = 0; | |
282 | bench_inv *data = (bench_inv*)arg; | |
283 | ||
284 | for (i = 0; i < iters; i++) { | |
285 | bits += secp256k1_wnaf_const(data->wnaf, &data->scalar[0], WINDOW_A, 256); | |
286 | overflow += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); | |
287 | } | |
288 | CHECK(overflow >= 0); | |
289 | CHECK(bits <= 256*iters); | |
290 | } | |
291 | ||
292 | ||
293 | void bench_sha256(void* arg, int iters) { | |
294 | int i; | |
295 | bench_inv *data = (bench_inv*)arg; | |
296 | secp256k1_sha256 sha; | |
297 | ||
298 | for (i = 0; i < iters; i++) { | |
299 | secp256k1_sha256_initialize(&sha); | |
300 | secp256k1_sha256_write(&sha, data->data, 32); | |
301 | secp256k1_sha256_finalize(&sha, data->data); | |
302 | } | |
303 | } | |
304 | ||
305 | void bench_hmac_sha256(void* arg, int iters) { | |
306 | int i; | |
307 | bench_inv *data = (bench_inv*)arg; | |
308 | secp256k1_hmac_sha256 hmac; | |
309 | ||
310 | for (i = 0; i < iters; i++) { | |
311 | secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); | |
312 | secp256k1_hmac_sha256_write(&hmac, data->data, 32); | |
313 | secp256k1_hmac_sha256_finalize(&hmac, data->data); | |
314 | } | |
315 | } | |
316 | ||
317 | void bench_rfc6979_hmac_sha256(void* arg, int iters) { | |
318 | int i; | |
319 | bench_inv *data = (bench_inv*)arg; | |
320 | secp256k1_rfc6979_hmac_sha256 rng; | |
321 | ||
322 | for (i = 0; i < iters; i++) { | |
323 | secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); | |
324 | secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); | |
325 | } | |
326 | } | |
327 | ||
328 | void bench_context_verify(void* arg, int iters) { | |
329 | int i; | |
330 | (void)arg; | |
331 | for (i = 0; i < iters; i++) { | |
332 | secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY)); | |
333 | } | |
334 | } | |
335 | ||
336 | void bench_context_sign(void* arg, int iters) { | |
337 | int i; | |
338 | (void)arg; | |
339 | for (i = 0; i < iters; i++) { | |
340 | secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_SIGN)); | |
341 | } | |
342 | } | |
343 | ||
344 | int main(int argc, char **argv) { | |
345 | bench_inv data; | |
346 | int iters = get_iters(20000); | |
347 | ||
348 | if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, iters*100); | |
349 | if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, iters*100); | |
350 | if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, iters*10); | |
351 | if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, iters); | |
352 | if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, iters); | |
353 | if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, iters); | |
354 | ||
355 | if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, iters*100); | |
356 | if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, iters*100); | |
357 | if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, iters*10); | |
358 | if (have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, iters*10); | |
359 | if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, iters); | |
360 | if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, iters); | |
361 | if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, iters); | |
362 | ||
363 | if (have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, iters*10); | |
364 | if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, iters*10); | |
365 | if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, iters*10); | |
366 | if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, iters*10); | |
367 | if (have_flag(argc, argv, "group") || have_flag(argc, argv, "to_affine")) run_benchmark("group_to_affine_var", bench_group_to_affine_var, bench_setup, NULL, &data, 10, iters); | |
368 | ||
369 | if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, iters); | |
370 | if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, iters); | |
371 | ||
372 | if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, iters); | |
373 | if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, iters); | |
374 | if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, iters); | |
375 | ||
376 | if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 1 + iters/1000); | |
377 | if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 1 + iters/100); | |
378 | ||
379 | return 0; | |
380 | } |