Typo fix in comment.
[BearSSL] / test / test_speed.c
1 /*
2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include "inner.h"
30
31 #define HASH_SIZE(cname) br_ ## cname ## _SIZE
32
33 #define SPEED_HASH(Name, cname) \
34 static void \
35 test_speed_ ## cname(void) \
36 { \
37 unsigned char buf[8192]; \
38 unsigned char tmp[HASH_SIZE(cname)]; \
39 br_ ## cname ## _context mc; \
40 int i; \
41 long num; \
42 \
43 memset(buf, 'T', sizeof buf); \
44 for (i = 0; i < 10; i ++) { \
45 br_ ## cname ## _init(&mc); \
46 br_ ## cname ## _update(&mc, buf, sizeof buf); \
47 br_ ## cname ## _out(&mc, tmp); \
48 } \
49 num = 10; \
50 for (;;) { \
51 clock_t begin, end; \
52 double tt; \
53 long k; \
54 \
55 br_ ## cname ## _init(&mc); \
56 begin = clock(); \
57 for (k = num; k > 0; k --) { \
58 br_ ## cname ## _update(&mc, buf, sizeof buf); \
59 } \
60 end = clock(); \
61 br_ ## cname ## _out(&mc, tmp); \
62 tt = (double)(end - begin) / CLOCKS_PER_SEC; \
63 if (tt >= 2.0) { \
64 printf("%-30s %8.2f MB/s\n", #Name, \
65 ((double)sizeof buf) * (double)num \
66 / (tt * 1000000.0)); \
67 fflush(stdout); \
68 return; \
69 } \
70 num <<= 1; \
71 } \
72 }
73
74 #define BLOCK_SIZE(cname) br_ ## cname ## _BLOCK_SIZE
75
76 #define SPEED_BLOCKCIPHER_CBC(Name, fname, cname, klen, dir) \
77 static void \
78 test_speed_ ## fname(void) \
79 { \
80 unsigned char key[klen]; \
81 unsigned char buf[8192 - (8192 % BLOCK_SIZE(cname))]; \
82 unsigned char iv[BLOCK_SIZE(cname)]; \
83 const br_block_cbc ## dir ## _class *vt; \
84 br_ ## cname ## _cbc ## dir ## _keys ec; \
85 int i; \
86 long num; \
87 \
88 memset(key, 'T', sizeof key); \
89 memset(buf, 'P', sizeof buf); \
90 memset(iv, 'X', sizeof iv); \
91 vt = br_ ## cname ## _cbc ## dir ## _get_vtable(); \
92 if (vt == NULL) { \
93 printf("%-30s UNAVAILABLE\n", #Name); \
94 fflush(stdout); \
95 return; \
96 } \
97 for (i = 0; i < 10; i ++) { \
98 vt->init(&ec.vtable, key, sizeof key); \
99 vt->run(&ec.vtable, iv, buf, sizeof buf); \
100 } \
101 num = 10; \
102 for (;;) { \
103 clock_t begin, end; \
104 double tt; \
105 long k; \
106 \
107 vt->init(&ec.vtable, key, sizeof key); \
108 begin = clock(); \
109 for (k = num; k > 0; k --) { \
110 vt->run(&ec.vtable, iv, buf, sizeof buf); \
111 } \
112 end = clock(); \
113 tt = (double)(end - begin) / CLOCKS_PER_SEC; \
114 if (tt >= 2.0) { \
115 printf("%-30s %8.2f MB/s\n", #Name, \
116 ((double)sizeof buf) * (double)num \
117 / (tt * 1000000.0)); \
118 fflush(stdout); \
119 return; \
120 } \
121 num <<= 1; \
122 } \
123 }
124
125 #define SPEED_BLOCKCIPHER_CTR(Name, fname, cname, klen) \
126 static void \
127 test_speed_ ## fname(void) \
128 { \
129 unsigned char key[klen]; \
130 unsigned char buf[8192 - (8192 % BLOCK_SIZE(cname))]; \
131 unsigned char iv[BLOCK_SIZE(cname) - 4]; \
132 const br_block_ctr_class *vt; \
133 br_ ## cname ## _ctr_keys ec; \
134 int i; \
135 long num; \
136 \
137 memset(key, 'T', sizeof key); \
138 memset(buf, 'P', sizeof buf); \
139 memset(iv, 'X', sizeof iv); \
140 vt = br_ ## cname ## _ctr_get_vtable(); \
141 if (vt == NULL) { \
142 printf("%-30s UNAVAILABLE\n", #Name); \
143 fflush(stdout); \
144 return; \
145 } \
146 for (i = 0; i < 10; i ++) { \
147 vt->init(&ec.vtable, key, sizeof key); \
148 vt->run(&ec.vtable, iv, 1, buf, sizeof buf); \
149 } \
150 num = 10; \
151 for (;;) { \
152 clock_t begin, end; \
153 double tt; \
154 long k; \
155 \
156 vt->init(&ec.vtable, key, sizeof key); \
157 begin = clock(); \
158 for (k = num; k > 0; k --) { \
159 vt->run(&ec.vtable, iv, 1, buf, sizeof buf); \
160 } \
161 end = clock(); \
162 tt = (double)(end - begin) / CLOCKS_PER_SEC; \
163 if (tt >= 2.0) { \
164 printf("%-30s %8.2f MB/s\n", #Name, \
165 ((double)sizeof buf) * (double)num \
166 / (tt * 1000000.0)); \
167 fflush(stdout); \
168 return; \
169 } \
170 num <<= 1; \
171 } \
172 }
173
174 #define SPEED_CHACHA20(Name, fname) \
175 static void \
176 test_speed_ ## fname(void) \
177 { \
178 br_chacha20_run bc; \
179 unsigned char key[32]; \
180 unsigned char buf[8192]; \
181 unsigned char iv[12]; \
182 int i; \
183 long num; \
184 \
185 bc = br_ ## fname ## _get(); \
186 if (bc == 0) { \
187 printf("%-30s UNAVAILABLE\n", #Name); \
188 fflush(stdout); \
189 return; \
190 } \
191 memset(key, 'T', sizeof key); \
192 memset(buf, 'P', sizeof buf); \
193 memset(iv, 'X', sizeof iv); \
194 for (i = 0; i < 10; i ++) { \
195 bc(key, iv, i, buf, sizeof buf); \
196 } \
197 num = 10; \
198 for (;;) { \
199 clock_t begin, end; \
200 double tt; \
201 long k; \
202 \
203 begin = clock(); \
204 for (k = num; k > 0; k --) { \
205 bc(key, iv, (uint32_t)k, buf, sizeof buf); \
206 } \
207 end = clock(); \
208 tt = (double)(end - begin) / CLOCKS_PER_SEC; \
209 if (tt >= 2.0) { \
210 printf("%-30s %8.2f MB/s\n", #Name, \
211 ((double)sizeof buf) * (double)num \
212 / (tt * 1000000.0)); \
213 fflush(stdout); \
214 return; \
215 } \
216 num <<= 1; \
217 } \
218 }
219
220 SPEED_HASH(MD5, md5)
221 SPEED_HASH(SHA-1, sha1)
222 SPEED_HASH(SHA-256, sha256)
223 SPEED_HASH(SHA-512, sha512)
224
225 /*
226 * There are no vtable selection functions for the portable implementations,
227 * so we define some custom macros.
228 */
229 #define br_aes_big_cbcenc_get_vtable() (&br_aes_big_cbcenc_vtable)
230 #define br_aes_big_cbcdec_get_vtable() (&br_aes_big_cbcdec_vtable)
231 #define br_aes_big_ctr_get_vtable() (&br_aes_big_ctr_vtable)
232 #define br_aes_big_ctrcbc_get_vtable() (&br_aes_big_ctrcbc_vtable)
233 #define br_aes_small_cbcenc_get_vtable() (&br_aes_small_cbcenc_vtable)
234 #define br_aes_small_cbcdec_get_vtable() (&br_aes_small_cbcdec_vtable)
235 #define br_aes_small_ctr_get_vtable() (&br_aes_small_ctr_vtable)
236 #define br_aes_small_ctrcbc_get_vtable() (&br_aes_small_ctrcbc_vtable)
237 #define br_aes_ct_cbcenc_get_vtable() (&br_aes_ct_cbcenc_vtable)
238 #define br_aes_ct_cbcdec_get_vtable() (&br_aes_ct_cbcdec_vtable)
239 #define br_aes_ct_ctr_get_vtable() (&br_aes_ct_ctr_vtable)
240 #define br_aes_ct_ctrcbc_get_vtable() (&br_aes_ct_ctrcbc_vtable)
241 #define br_aes_ct64_cbcenc_get_vtable() (&br_aes_ct64_cbcenc_vtable)
242 #define br_aes_ct64_cbcdec_get_vtable() (&br_aes_ct64_cbcdec_vtable)
243 #define br_aes_ct64_ctr_get_vtable() (&br_aes_ct64_ctr_vtable)
244 #define br_aes_ct64_ctrcbc_get_vtable() (&br_aes_ct64_ctrcbc_vtable)
245 #define br_chacha20_ct_get() (&br_chacha20_ct_run)
246
247 #define SPEED_AES(iname) \
248 SPEED_BLOCKCIPHER_CBC(AES-128 CBC encrypt (iname), aes128_ ## iname ## _cbcenc, aes_ ## iname, 16, enc) \
249 SPEED_BLOCKCIPHER_CBC(AES-128 CBC decrypt (iname), aes128_ ## iname ## _cbcdec, aes_ ## iname, 16, dec) \
250 SPEED_BLOCKCIPHER_CBC(AES-192 CBC encrypt (iname), aes192_ ## iname ## _cbcenc, aes_ ## iname, 24, enc) \
251 SPEED_BLOCKCIPHER_CBC(AES-192 CBC decrypt (iname), aes192_ ## iname ## _cbcdec, aes_ ## iname, 24, dec) \
252 SPEED_BLOCKCIPHER_CBC(AES-256 CBC encrypt (iname), aes256_ ## iname ## _cbcenc, aes_ ## iname, 32, enc) \
253 SPEED_BLOCKCIPHER_CBC(AES-256 CBC decrypt (iname), aes256_ ## iname ## _cbcdec, aes_ ## iname, 32, dec) \
254 SPEED_BLOCKCIPHER_CTR(AES-128 CTR (iname), aes128_ ## iname ## _ctr, aes_ ## iname, 16) \
255 SPEED_BLOCKCIPHER_CTR(AES-192 CTR (iname), aes192_ ## iname ## _ctr, aes_ ## iname, 24) \
256 SPEED_BLOCKCIPHER_CTR(AES-256 CTR (iname), aes256_ ## iname ## _ctr, aes_ ## iname, 32)
257
258 SPEED_AES(big)
259 SPEED_AES(small)
260 SPEED_AES(ct)
261 SPEED_AES(ct64)
262 SPEED_AES(x86ni)
263 SPEED_AES(pwr8)
264
265 #define br_des_tab_cbcenc_get_vtable() (&br_des_tab_cbcenc_vtable)
266 #define br_des_tab_cbcdec_get_vtable() (&br_des_tab_cbcdec_vtable)
267 #define br_des_ct_cbcenc_get_vtable() (&br_des_ct_cbcenc_vtable)
268 #define br_des_ct_cbcdec_get_vtable() (&br_des_ct_cbcdec_vtable)
269
270 #define SPEED_DES(iname) \
271 SPEED_BLOCKCIPHER_CBC(DES CBC encrypt (iname), des_ ## iname ## _cbcenc, des_ ## iname, 8, enc) \
272 SPEED_BLOCKCIPHER_CBC(DES CBC decrypt (iname), des_ ## iname ## _cbcdec, des_ ## iname, 8, dec) \
273 SPEED_BLOCKCIPHER_CBC(3DES CBC encrypt (iname), 3des_ ## iname ## _cbcenc, des_ ## iname, 24, enc) \
274 SPEED_BLOCKCIPHER_CBC(3DES CBC decrypt (iname), 3des_ ## iname ## _cbcdec, des_ ## iname, 24, dec)
275
276 SPEED_DES(tab)
277 SPEED_DES(ct)
278
279 SPEED_CHACHA20(ChaCha20 (ct), chacha20_ct)
280 SPEED_CHACHA20(ChaCha20 (sse2), chacha20_sse2)
281
282 static void
283 test_speed_ghash_inner(char *name, br_ghash gh)
284 {
285 unsigned char buf[8192], h[16], y[16];
286 int i;
287 long num;
288
289 memset(buf, 'T', sizeof buf);
290 memset(h, 'P', sizeof h);
291 memset(y, 0, sizeof y);
292 for (i = 0; i < 10; i ++) {
293 gh(y, h, buf, sizeof buf);
294 }
295 num = 10;
296 for (;;) {
297 clock_t begin, end;
298 double tt;
299 long k;
300
301 begin = clock();
302 for (k = num; k > 0; k --) {
303 gh(y, h, buf, sizeof buf);
304 }
305 end = clock();
306 tt = (double)(end - begin) / CLOCKS_PER_SEC;
307 if (tt >= 2.0) {
308 printf("%-30s %8.2f MB/s\n", name,
309 ((double)sizeof buf) * (double)num
310 / (tt * 1000000.0));
311 fflush(stdout);
312 return;
313 }
314 num <<= 1;
315 }
316 }
317
318 static void
319 test_speed_ghash_ctmul(void)
320 {
321 test_speed_ghash_inner("GHASH (ctmul)", &br_ghash_ctmul);
322 }
323
324 static void
325 test_speed_ghash_ctmul32(void)
326 {
327 test_speed_ghash_inner("GHASH (ctmul32)", &br_ghash_ctmul32);
328 }
329
330 static void
331 test_speed_ghash_ctmul64(void)
332 {
333 test_speed_ghash_inner("GHASH (ctmul64)", &br_ghash_ctmul64);
334 }
335
336 static void
337 test_speed_ghash_pclmul(void)
338 {
339 br_ghash gh;
340
341 gh = br_ghash_pclmul_get();
342 if (gh == 0) {
343 printf("%-30s UNAVAILABLE\n", "GHASH (pclmul)");
344 fflush(stdout);
345 } else {
346 test_speed_ghash_inner("GHASH (pclmul)", gh);
347 }
348 }
349
350 static void
351 test_speed_ghash_pwr8(void)
352 {
353 br_ghash gh;
354
355 gh = br_ghash_pwr8_get();
356 if (gh == 0) {
357 printf("%-30s UNAVAILABLE\n", "GHASH (pwr8)");
358 fflush(stdout);
359 } else {
360 test_speed_ghash_inner("GHASH (pwr8)", gh);
361 }
362 }
363
364 static uint32_t
365 fake_chacha20(const void *key, const void *iv,
366 uint32_t cc, void *data, size_t len)
367 {
368 (void)key;
369 (void)iv;
370 (void)data;
371 (void)len;
372 return cc + (uint32_t)((len + 63) >> 6);
373 }
374
375 /*
376 * To speed-test Poly1305, we run it with a do-nothing stub instead of
377 * ChaCha20.
378 */
379 static void
380 test_speed_poly1305_inner(char *name, br_poly1305_run pl)
381 {
382 unsigned char buf[8192], key[32], iv[12], aad[13], tag[16];
383 int i;
384 long num;
385
386 memset(key, 'K', sizeof key);
387 memset(iv, 'I', sizeof iv);
388 memset(aad, 'A', sizeof aad);
389 memset(buf, 'T', sizeof buf);
390 for (i = 0; i < 10; i ++) {
391 pl(key, iv, buf, sizeof buf,
392 aad, sizeof aad, tag, &fake_chacha20, 0);
393 }
394 num = 10;
395 for (;;) {
396 clock_t begin, end;
397 double tt;
398 long k;
399
400 begin = clock();
401 for (k = num; k > 0; k --) {
402 pl(key, iv, buf, sizeof buf,
403 aad, sizeof aad, tag, &fake_chacha20, 0);
404 }
405 end = clock();
406 tt = (double)(end - begin) / CLOCKS_PER_SEC;
407 if (tt >= 2.0) {
408 printf("%-30s %8.2f MB/s\n", name,
409 ((double)sizeof buf) * (double)num
410 / (tt * 1000000.0));
411 fflush(stdout);
412 return;
413 }
414 num <<= 1;
415 }
416 }
417
418 static void
419 test_speed_poly1305_ctmul(void)
420 {
421 test_speed_poly1305_inner("Poly1305 (ctmul)", &br_poly1305_ctmul_run);
422 }
423
424 static void
425 test_speed_poly1305_ctmul32(void)
426 {
427 test_speed_poly1305_inner("Poly1305 (ctmul32)",
428 &br_poly1305_ctmul32_run);
429 }
430
431 static void
432 test_speed_poly1305_ctmulq(void)
433 {
434 br_poly1305_run bp;
435
436 bp = br_poly1305_ctmulq_get();
437 if (bp == 0) {
438 printf("%-30s UNAVAILABLE\n", "Poly1305 (ctmulq)");
439 } else {
440 test_speed_poly1305_inner("Poly1305 (ctmulq)", bp);
441 }
442 }
443
444 static void
445 test_speed_poly1305_i15(void)
446 {
447 test_speed_poly1305_inner("Poly1305 (i15)", &br_poly1305_i15_run);
448 }
449
450 static void
451 test_speed_eax_inner(char *name,
452 const br_block_ctrcbc_class *vt, size_t key_len)
453 {
454 unsigned char buf[8192], key[32], nonce[16], aad[16], tag[16];
455 int i;
456 long num;
457 br_aes_gen_ctrcbc_keys ac;
458 br_eax_context ec;
459
460 if (vt == NULL) {
461 printf("%-30s UNAVAILABLE\n", name);
462 fflush(stdout);
463 return;
464 }
465 memset(key, 'K', key_len);
466 memset(nonce, 'N', sizeof nonce);
467 memset(aad, 'A', sizeof aad);
468 memset(buf, 'T', sizeof buf);
469 for (i = 0; i < 10; i ++) {
470 vt->init(&ac.vtable, key, key_len);
471 br_eax_init(&ec, &ac.vtable);
472 br_eax_reset(&ec, nonce, sizeof nonce);
473 br_eax_aad_inject(&ec, aad, sizeof aad);
474 br_eax_flip(&ec);
475 br_eax_run(&ec, 1, buf, sizeof buf);
476 br_eax_get_tag(&ec, tag);
477 }
478 num = 10;
479 for (;;) {
480 clock_t begin, end;
481 double tt;
482 long k;
483
484 begin = clock();
485 for (k = num; k > 0; k --) {
486 vt->init(&ac.vtable, key, key_len);
487 br_eax_init(&ec, &ac.vtable);
488 br_eax_reset(&ec, nonce, sizeof nonce);
489 br_eax_aad_inject(&ec, aad, sizeof aad);
490 br_eax_flip(&ec);
491 br_eax_run(&ec, 1, buf, sizeof buf);
492 br_eax_get_tag(&ec, tag);
493 }
494 end = clock();
495 tt = (double)(end - begin) / CLOCKS_PER_SEC;
496 if (tt >= 2.0) {
497 printf("%-30s %8.2f MB/s\n", name,
498 ((double)sizeof buf) * (double)num
499 / (tt * 1000000.0));
500 fflush(stdout);
501 return;
502 }
503 num <<= 1;
504 }
505 }
506
507 #define SPEED_EAX(Algo, algo, keysize, impl) \
508 static void \
509 test_speed_eax_ ## algo ## keysize ## _ ## impl(void) \
510 { \
511 test_speed_eax_inner("EAX " #Algo "-" #keysize "(" #impl ")", \
512 br_ ## algo ## _ ## impl ## _ctrcbc_get_vtable() \
513 , (keysize) >> 3); \
514 }
515
516 SPEED_EAX(AES, aes, 128, big)
517 SPEED_EAX(AES, aes, 128, small)
518 SPEED_EAX(AES, aes, 128, ct)
519 SPEED_EAX(AES, aes, 128, ct64)
520 SPEED_EAX(AES, aes, 128, x86ni)
521 SPEED_EAX(AES, aes, 128, pwr8)
522 SPEED_EAX(AES, aes, 192, big)
523 SPEED_EAX(AES, aes, 192, small)
524 SPEED_EAX(AES, aes, 192, ct)
525 SPEED_EAX(AES, aes, 192, ct64)
526 SPEED_EAX(AES, aes, 192, x86ni)
527 SPEED_EAX(AES, aes, 192, pwr8)
528 SPEED_EAX(AES, aes, 256, big)
529 SPEED_EAX(AES, aes, 256, small)
530 SPEED_EAX(AES, aes, 256, ct)
531 SPEED_EAX(AES, aes, 256, ct64)
532 SPEED_EAX(AES, aes, 256, x86ni)
533 SPEED_EAX(AES, aes, 256, pwr8)
534
535 static void
536 test_speed_shake_inner(int security_level)
537 {
538 unsigned char buf[8192];
539 br_shake_context sc;
540 int i;
541 long num;
542
543 memset(buf, 'D', sizeof buf);
544 br_shake_init(&sc, security_level);
545 for (i = 0; i < 10; i ++) {
546 br_shake_inject(&sc, buf, sizeof buf);
547 }
548 num = 10;
549 for (;;) {
550 clock_t begin, end;
551 double tt;
552 long k;
553
554 begin = clock();
555 for (k = num; k > 0; k --) {
556 br_shake_inject(&sc, buf, sizeof buf);
557 }
558 end = clock();
559 tt = (double)(end - begin) / CLOCKS_PER_SEC;
560 if (tt >= 2.0) {
561 printf("SHAKE%-3d (inject) %8.2f MB/s\n",
562 security_level,
563 ((double)sizeof buf) * (double)num
564 / (tt * 1000000.0));
565 fflush(stdout);
566 break;
567 }
568 num <<= 1;
569 }
570
571 br_shake_flip(&sc);
572 for (i = 0; i < 10; i ++) {
573 br_shake_produce(&sc, buf, sizeof buf);
574 }
575
576 num = 10;
577 for (;;) {
578 clock_t begin, end;
579 double tt;
580 long k;
581
582 begin = clock();
583 for (k = num; k > 0; k --) {
584 br_shake_produce(&sc, buf, sizeof buf);
585 }
586 end = clock();
587 tt = (double)(end - begin) / CLOCKS_PER_SEC;
588 if (tt >= 2.0) {
589 printf("SHAKE%-3d (produce) %8.2f MB/s\n",
590 security_level,
591 ((double)sizeof buf) * (double)num
592 / (tt * 1000000.0));
593 fflush(stdout);
594 break;
595 }
596 num <<= 1;
597 }
598 }
599
600 static void
601 test_speed_shake128(void)
602 {
603 test_speed_shake_inner(128);
604 }
605
606 static void
607 test_speed_shake256(void)
608 {
609 test_speed_shake_inner(256);
610 }
611
612 static const unsigned char RSA_N[] = {
613 0xE9, 0xF2, 0x4A, 0x2F, 0x96, 0xDF, 0x0A, 0x23,
614 0x01, 0x85, 0xF1, 0x2C, 0xB2, 0xA8, 0xEF, 0x23,
615 0xCE, 0x2E, 0xB0, 0x4E, 0x18, 0x31, 0x95, 0x5B,
616 0x98, 0x2D, 0x9B, 0x8C, 0xE3, 0x1A, 0x2B, 0x96,
617 0xB5, 0xC7, 0xEE, 0xED, 0x72, 0x43, 0x2D, 0xFE,
618 0x7F, 0x61, 0x33, 0xEA, 0x14, 0xFC, 0xDE, 0x80,
619 0x17, 0x42, 0xF0, 0xF3, 0xC3, 0xC7, 0x89, 0x47,
620 0x76, 0x5B, 0xFA, 0x33, 0xC4, 0x8C, 0x94, 0xDE,
621 0x6A, 0x75, 0xD8, 0x1A, 0xF4, 0x49, 0xBC, 0xF3,
622 0xB7, 0x9E, 0x2C, 0x8D, 0xEC, 0x5A, 0xEE, 0xBF,
623 0x4B, 0x5A, 0x7F, 0xEF, 0x21, 0x39, 0xDB, 0x1D,
624 0x83, 0x5E, 0x7E, 0x2F, 0xAA, 0x5E, 0xBA, 0x28,
625 0xC3, 0xA2, 0x53, 0x19, 0xFB, 0x2F, 0x78, 0x6B,
626 0x14, 0x60, 0x49, 0x3C, 0xCC, 0x1B, 0xE9, 0x1E,
627 0x3D, 0x10, 0xA4, 0xEB, 0x7F, 0x66, 0x98, 0xF6,
628 0xC3, 0xAC, 0x35, 0xF5, 0x01, 0x84, 0xFF, 0x7D,
629 0x1F, 0x72, 0xBE, 0xB4, 0xD1, 0x89, 0xC8, 0xDD,
630 0x44, 0xE7, 0xB5, 0x2E, 0x2C, 0xE1, 0x85, 0xF5,
631 0x15, 0x50, 0xA9, 0x08, 0xC7, 0x67, 0xD9, 0x2B,
632 0x6C, 0x11, 0xB3, 0xEB, 0x28, 0x8D, 0xF4, 0xCC,
633 0xE3, 0xC3, 0xC5, 0x04, 0x0E, 0x7C, 0x8D, 0xDB,
634 0x39, 0x06, 0x6A, 0x74, 0x75, 0xDF, 0xA8, 0x0F,
635 0xDA, 0x67, 0x5A, 0x73, 0x1E, 0xFD, 0x8E, 0x4C,
636 0xEE, 0x17, 0xEE, 0x1E, 0x67, 0xDB, 0x98, 0x70,
637 0x60, 0xF7, 0xB9, 0xB5, 0x1F, 0x19, 0x93, 0xD6,
638 0x3F, 0x2F, 0x1F, 0xB6, 0x5B, 0x59, 0xAA, 0x85,
639 0xBB, 0x25, 0xE4, 0x13, 0xEF, 0xE7, 0xB9, 0x87,
640 0x9C, 0x3F, 0x5E, 0xE4, 0x08, 0xA3, 0x51, 0xCF,
641 0x8B, 0xAD, 0xF4, 0xE6, 0x1A, 0x5F, 0x51, 0xDD,
642 0xA8, 0xBE, 0xE8, 0xD1, 0x20, 0x19, 0x61, 0x6C,
643 0x18, 0xAB, 0xCA, 0x0A, 0xD9, 0x82, 0xA6, 0x94,
644 0xD5, 0x69, 0x2A, 0xF6, 0x43, 0x66, 0x31, 0x09
645 };
646
647 static const unsigned char RSA_E[] = {
648 0x01, 0x00, 0x01
649 };
650
651 static const unsigned char RSA_P[] = {
652 0xFD, 0x39, 0x40, 0x56, 0x20, 0x80, 0xC5, 0x81,
653 0x4C, 0x5F, 0x0C, 0x1A, 0x52, 0x84, 0x03, 0x2F,
654 0xCE, 0x82, 0xB0, 0xD8, 0x30, 0x23, 0x7F, 0x77,
655 0x45, 0xC2, 0x01, 0xC4, 0x68, 0x96, 0x0D, 0xA7,
656 0x22, 0xA9, 0x6C, 0xA9, 0x1A, 0x33, 0xE5, 0x2F,
657 0xB5, 0x07, 0x9A, 0xF9, 0xEA, 0x33, 0xA5, 0xC8,
658 0x96, 0x60, 0x6A, 0xCA, 0xEB, 0xE5, 0x6E, 0x09,
659 0x46, 0x7E, 0x2D, 0xEF, 0x93, 0x7D, 0x56, 0xED,
660 0x75, 0x70, 0x3B, 0x96, 0xC4, 0xD5, 0xDB, 0x0B,
661 0x3F, 0x69, 0xDF, 0x06, 0x18, 0x76, 0xF4, 0xCF,
662 0xF8, 0x84, 0x22, 0xDF, 0xBD, 0x71, 0x62, 0x7B,
663 0x67, 0x99, 0xBC, 0x09, 0x95, 0x54, 0xA4, 0x98,
664 0x83, 0xF5, 0xA9, 0xCF, 0x09, 0xA5, 0x1F, 0x61,
665 0x25, 0xB4, 0x70, 0x6C, 0x91, 0xB8, 0xB3, 0xD0,
666 0xCE, 0x9C, 0x45, 0x65, 0x9B, 0xEF, 0xD4, 0x70,
667 0xBE, 0x86, 0xD2, 0x98, 0x5D, 0xEB, 0xE3, 0xFF
668 };
669
670 static const unsigned char RSA_Q[] = {
671 0xEC, 0x82, 0xEE, 0x63, 0x5F, 0x40, 0x52, 0xDB,
672 0x38, 0x7A, 0x37, 0x6A, 0x54, 0x5B, 0xD9, 0xA0,
673 0x73, 0xB4, 0xBB, 0x52, 0xB2, 0x84, 0x07, 0xD0,
674 0xCC, 0x82, 0x0D, 0x20, 0xB3, 0xFA, 0xD5, 0xB6,
675 0x25, 0x92, 0x35, 0x4D, 0xB4, 0xC7, 0x36, 0x48,
676 0xCE, 0x5E, 0x21, 0x4A, 0xA6, 0x74, 0x65, 0xF4,
677 0x7D, 0x1D, 0xBC, 0x3B, 0xE2, 0xF4, 0x3E, 0x11,
678 0x58, 0x10, 0x6C, 0x04, 0x46, 0x9E, 0x8D, 0x57,
679 0xE0, 0x04, 0xE2, 0xEC, 0x47, 0xCF, 0xB3, 0x2A,
680 0xFD, 0x4C, 0x55, 0x18, 0xDB, 0xDE, 0x3B, 0xDC,
681 0xF4, 0x5B, 0xDA, 0xF3, 0x1A, 0xC8, 0x41, 0x6F,
682 0x73, 0x3B, 0xFE, 0x3C, 0xA0, 0xDB, 0xBA, 0x6E,
683 0x65, 0xA5, 0xE8, 0x02, 0xA5, 0x6C, 0xEA, 0x03,
684 0xF6, 0x99, 0xF7, 0xCB, 0x4B, 0xB7, 0x11, 0x51,
685 0x93, 0x88, 0x3F, 0xF9, 0x06, 0x85, 0xA9, 0x1E,
686 0xCA, 0x64, 0xF8, 0x11, 0xA5, 0x1A, 0xCA, 0xF7
687 };
688
689 static const unsigned char RSA_DP[] = {
690 0x77, 0x95, 0xE0, 0x02, 0x4C, 0x9B, 0x43, 0xAA,
691 0xCA, 0x4C, 0x60, 0xC4, 0xD5, 0x8F, 0x2E, 0x8A,
692 0x17, 0x36, 0xB5, 0x19, 0x83, 0xB2, 0x5F, 0xF2,
693 0x0D, 0xE9, 0x8F, 0x38, 0x18, 0x44, 0x34, 0xF2,
694 0x67, 0x76, 0x27, 0xB0, 0xBC, 0x85, 0x21, 0x89,
695 0x24, 0x2F, 0x11, 0x4B, 0x51, 0x05, 0x4F, 0x17,
696 0xA9, 0x9C, 0xA3, 0x12, 0x6D, 0xD1, 0x0D, 0xE4,
697 0x27, 0x7C, 0x53, 0x69, 0x3E, 0xF8, 0x04, 0x63,
698 0x64, 0x00, 0xBA, 0xC3, 0x7A, 0xF5, 0x9B, 0xDA,
699 0x75, 0xFA, 0x23, 0xAF, 0x17, 0x42, 0xA6, 0x5E,
700 0xC8, 0xF8, 0x6E, 0x17, 0xC7, 0xB9, 0x92, 0x4E,
701 0xC1, 0x20, 0x63, 0x23, 0x0B, 0x78, 0xCB, 0xBA,
702 0x93, 0x27, 0x23, 0x28, 0x79, 0x5F, 0x97, 0xB0,
703 0x23, 0x44, 0x51, 0x8B, 0x94, 0x4D, 0xEB, 0xED,
704 0x82, 0x85, 0x5E, 0x68, 0x9B, 0xF9, 0xE9, 0x13,
705 0xCD, 0x86, 0x92, 0x52, 0x0E, 0x98, 0xE6, 0x35
706 };
707
708 static const unsigned char RSA_DQ[] = {
709 0xD8, 0xDD, 0x71, 0xB3, 0x62, 0xBA, 0xBB, 0x7E,
710 0xD1, 0xF9, 0x96, 0xE8, 0x83, 0xB3, 0xB9, 0x08,
711 0x9C, 0x30, 0x03, 0x77, 0xDF, 0xC2, 0x9A, 0xDC,
712 0x05, 0x39, 0xD6, 0xC9, 0xBE, 0xDE, 0x68, 0xA9,
713 0xDD, 0x27, 0x84, 0x82, 0xDD, 0x19, 0xB1, 0x97,
714 0xEE, 0xCA, 0x77, 0x22, 0x59, 0x20, 0xEF, 0xFF,
715 0xCF, 0xDD, 0xBD, 0x24, 0xF8, 0x84, 0xD6, 0x88,
716 0xD6, 0xC4, 0x30, 0x17, 0x77, 0x9D, 0x98, 0xA3,
717 0x14, 0x01, 0xC7, 0x05, 0xBB, 0x0F, 0x23, 0x0D,
718 0x6F, 0x37, 0x57, 0xEC, 0x34, 0x67, 0x41, 0x62,
719 0xE8, 0x19, 0x75, 0xD9, 0x66, 0x1C, 0x6B, 0x8B,
720 0xC3, 0x11, 0x26, 0x9C, 0xF7, 0x2E, 0xA3, 0x72,
721 0xE8, 0xF7, 0xC8, 0x96, 0xEC, 0x92, 0xC2, 0xBD,
722 0xA1, 0x98, 0x2A, 0x93, 0x99, 0xB8, 0xA2, 0x43,
723 0xB7, 0xD0, 0xBE, 0x40, 0x1C, 0x8F, 0xE0, 0xB4,
724 0x20, 0x07, 0x97, 0x43, 0xAE, 0xAD, 0xB3, 0x9F
725 };
726
727 static const unsigned char RSA_IQ[] = {
728 0xB7, 0xE2, 0x60, 0xA9, 0x62, 0xEC, 0xEC, 0x0B,
729 0x57, 0x02, 0x96, 0xF9, 0x36, 0x35, 0x2C, 0x37,
730 0xAF, 0xC2, 0xEE, 0x71, 0x49, 0x26, 0x8E, 0x0F,
731 0x27, 0xB1, 0xFA, 0x0F, 0xEA, 0xDC, 0xF0, 0x8B,
732 0x53, 0x6C, 0xB2, 0x46, 0x27, 0xCD, 0x29, 0xA2,
733 0x35, 0x0F, 0x5D, 0x8A, 0x3F, 0x20, 0x8C, 0x13,
734 0x3D, 0xA1, 0xFF, 0x85, 0x91, 0x99, 0xE8, 0x50,
735 0xED, 0xF1, 0x29, 0x00, 0xEE, 0x24, 0x90, 0xB5,
736 0x5F, 0x3A, 0x74, 0x26, 0xD7, 0xA2, 0x24, 0x8D,
737 0x89, 0x88, 0xD8, 0x35, 0x22, 0x22, 0x8A, 0x66,
738 0x5D, 0x5C, 0xDE, 0x83, 0x8C, 0xFA, 0x27, 0xE6,
739 0xB9, 0xEB, 0x72, 0x08, 0xCD, 0x53, 0x4B, 0x93,
740 0x0F, 0xAD, 0xC3, 0xF8, 0x7C, 0xFE, 0x84, 0xD7,
741 0x08, 0xF3, 0xBE, 0x3D, 0x60, 0x1E, 0x95, 0x8D,
742 0x44, 0x5B, 0x65, 0x7E, 0xC1, 0x30, 0xC3, 0x84,
743 0xC0, 0xB0, 0xFE, 0xBF, 0x28, 0x54, 0x1E, 0xC4
744 };
745
746 static const br_rsa_public_key RSA_PK = {
747 (void *)RSA_N, sizeof RSA_N,
748 (void *)RSA_E, sizeof RSA_E
749 };
750
751 static const br_rsa_private_key RSA_SK = {
752 2048,
753 (void *)RSA_P, sizeof RSA_P,
754 (void *)RSA_Q, sizeof RSA_Q,
755 (void *)RSA_DP, sizeof RSA_DP,
756 (void *)RSA_DQ, sizeof RSA_DQ,
757 (void *)RSA_IQ, sizeof RSA_IQ
758 };
759
760 static void
761 test_speed_rsa_inner(char *name,
762 br_rsa_public fpub, br_rsa_private fpriv, br_rsa_keygen kgen)
763 {
764 unsigned char tmp[sizeof RSA_N];
765 int i;
766 long num;
767 /*
768 br_hmac_drbg_context rng;
769 */
770 br_aesctr_drbg_context rng;
771 const br_block_ctr_class *ictr;
772
773 memset(tmp, 'R', sizeof tmp);
774 tmp[0] = 0;
775 for (i = 0; i < 10; i ++) {
776 if (!fpriv(tmp, &RSA_SK)) {
777 abort();
778 }
779 }
780 num = 10;
781 for (;;) {
782 clock_t begin, end;
783 double tt;
784 long k;
785
786 begin = clock();
787 for (k = num; k > 0; k --) {
788 fpriv(tmp, &RSA_SK);
789 }
790 end = clock();
791 tt = (double)(end - begin) / CLOCKS_PER_SEC;
792 if (tt >= 2.0) {
793 printf("%-30s %8.2f priv/s\n", name,
794 (double)num / tt);
795 fflush(stdout);
796 break;
797 }
798 num <<= 1;
799 }
800 for (i = 0; i < 10; i ++) {
801 if (!fpub(tmp, sizeof tmp, &RSA_PK)) {
802 abort();
803 }
804 }
805 num = 10;
806 for (;;) {
807 clock_t begin, end;
808 double tt;
809 long k;
810
811 begin = clock();
812 for (k = num; k > 0; k --) {
813 fpub(tmp, sizeof tmp, &RSA_PK);
814 }
815 end = clock();
816 tt = (double)(end - begin) / CLOCKS_PER_SEC;
817 if (tt >= 2.0) {
818 printf("%-30s %8.2f pub/s\n", name,
819 (double)num / tt);
820 fflush(stdout);
821 break;
822 }
823 num <<= 1;
824 }
825
826 if (kgen == 0) {
827 printf("%-30s KEYGEN UNAVAILABLE\n", name);
828 fflush(stdout);
829 return;
830 }
831 /*
832 br_hmac_drbg_init(&rng, &br_sha256_vtable, "RSA keygen seed", 15);
833 */
834 ictr = br_aes_x86ni_ctr_get_vtable();
835 if (ictr == NULL) {
836 ictr = br_aes_pwr8_ctr_get_vtable();
837 if (ictr == NULL) {
838 #if BR_64
839 ictr = &br_aes_ct64_ctr_vtable;
840 #else
841 ictr = &br_aes_ct_ctr_vtable;
842 #endif
843 }
844 }
845 br_aesctr_drbg_init(&rng, ictr, "RSA keygen seed", 15);
846
847 num = 10;
848 for (;;) {
849 clock_t begin, end;
850 double tt;
851 long k;
852
853 begin = clock();
854 for (k = num; k > 0; k --) {
855 br_rsa_private_key sk;
856 unsigned char kbuf[BR_RSA_KBUF_PRIV_SIZE(1024)];
857
858 kgen(&rng.vtable, &sk, kbuf, NULL, NULL, 1024, 0);
859 }
860 end = clock();
861 tt = (double)(end - begin) / CLOCKS_PER_SEC;
862 if (tt >= 10.0) {
863 printf("%-30s %8.2f kgen[1024]/s\n", name,
864 (double)num / tt);
865 fflush(stdout);
866 break;
867 }
868 num <<= 1;
869 }
870
871 num = 10;
872 for (;;) {
873 clock_t begin, end;
874 double tt;
875 long k;
876
877 begin = clock();
878 for (k = num; k > 0; k --) {
879 br_rsa_private_key sk;
880 unsigned char kbuf[BR_RSA_KBUF_PRIV_SIZE(2048)];
881
882 kgen(&rng.vtable, &sk, kbuf, NULL, NULL, 2048, 0);
883 }
884 end = clock();
885 tt = (double)(end - begin) / CLOCKS_PER_SEC;
886 if (tt >= 10.0) {
887 printf("%-30s %8.2f kgen[2048]/s\n", name,
888 (double)num / tt);
889 fflush(stdout);
890 break;
891 }
892 num <<= 1;
893 }
894 }
895
896 static void
897 test_speed_rsa_i15(void)
898 {
899 test_speed_rsa_inner("RSA i15",
900 &br_rsa_i15_public, &br_rsa_i15_private, &br_rsa_i15_keygen);
901 }
902
903 static void
904 test_speed_rsa_i31(void)
905 {
906 test_speed_rsa_inner("RSA i31",
907 &br_rsa_i31_public, &br_rsa_i31_private, &br_rsa_i31_keygen);
908 }
909
910 static void
911 test_speed_rsa_i32(void)
912 {
913 test_speed_rsa_inner("RSA i32",
914 &br_rsa_i32_public, &br_rsa_i32_private, 0);
915 }
916
917 static void
918 test_speed_rsa_i62(void)
919 {
920 br_rsa_public pub;
921 br_rsa_private priv;
922 br_rsa_keygen kgen;
923
924 pub = br_rsa_i62_public_get();
925 priv = br_rsa_i62_private_get();
926 kgen = br_rsa_i62_keygen_get();
927 if (pub) {
928 test_speed_rsa_inner("RSA i62", pub, priv, kgen);
929 } else {
930 printf("%-30s UNAVAILABLE\n", "RSA i62");
931 }
932 }
933
934 static void
935 test_speed_ec_inner_1(const char *name,
936 const br_ec_impl *impl, const br_ec_curve_def *cd)
937 {
938 unsigned char bx[80], U[160];
939 uint32_t x[22], n[22];
940 size_t nlen, ulen;
941 int i;
942 long num;
943
944 nlen = cd->order_len;
945 br_i31_decode(n, cd->order, nlen);
946 memset(bx, 'T', sizeof bx);
947 br_i31_decode_reduce(x, bx, sizeof bx, n);
948 br_i31_encode(bx, nlen, x);
949 ulen = cd->generator_len;
950 memcpy(U, cd->generator, ulen);
951 for (i = 0; i < 10; i ++) {
952 impl->mul(U, ulen, bx, nlen, cd->curve);
953 }
954 num = 10;
955 for (;;) {
956 clock_t begin, end;
957 double tt;
958 long k;
959
960 begin = clock();
961 for (k = num; k > 0; k --) {
962 impl->mul(U, ulen, bx, nlen, cd->curve);
963 }
964 end = clock();
965 tt = (double)(end - begin) / CLOCKS_PER_SEC;
966 if (tt >= 2.0) {
967 printf("%-30s %8.2f mul/s\n", name,
968 (double)num / tt);
969 fflush(stdout);
970 break;
971 }
972 num <<= 1;
973 }
974 }
975
976 static void
977 test_speed_ec_inner_2(const char *name,
978 const br_ec_impl *impl, const br_ec_curve_def *cd)
979 {
980 unsigned char bx[80], U[160];
981 uint32_t x[22], n[22];
982 size_t nlen;
983 int i;
984 long num;
985
986 nlen = cd->order_len;
987 br_i31_decode(n, cd->order, nlen);
988 memset(bx, 'T', sizeof bx);
989 br_i31_decode_reduce(x, bx, sizeof bx, n);
990 br_i31_encode(bx, nlen, x);
991 for (i = 0; i < 10; i ++) {
992 impl->mulgen(U, bx, nlen, cd->curve);
993 }
994 num = 10;
995 for (;;) {
996 clock_t begin, end;
997 double tt;
998 long k;
999
1000 begin = clock();
1001 for (k = num; k > 0; k --) {
1002 impl->mulgen(U, bx, nlen, cd->curve);
1003 }
1004 end = clock();
1005 tt = (double)(end - begin) / CLOCKS_PER_SEC;
1006 if (tt >= 2.0) {
1007 printf("%-30s %8.2f mul/s\n", name,
1008 (double)num / tt);
1009 fflush(stdout);
1010 break;
1011 }
1012 num <<= 1;
1013 }
1014 }
1015
1016 static void
1017 test_speed_ec_inner(const char *name,
1018 const br_ec_impl *impl, const br_ec_curve_def *cd)
1019 {
1020 char tmp[50];
1021
1022 test_speed_ec_inner_1(name, impl, cd);
1023 sprintf(tmp, "%s (FP)", name);
1024 test_speed_ec_inner_2(tmp, impl, cd);
1025 }
1026
1027 static void
1028 test_speed_ec_p256_m15(void)
1029 {
1030 test_speed_ec_inner("EC p256_m15",
1031 &br_ec_p256_m15, &br_secp256r1);
1032 }
1033
1034 static void
1035 test_speed_ec_p256_m31(void)
1036 {
1037 test_speed_ec_inner("EC p256_m31",
1038 &br_ec_p256_m31, &br_secp256r1);
1039 }
1040
1041 static void
1042 test_speed_ec_p256_m62(void)
1043 {
1044 const br_ec_impl *ec;
1045
1046 ec = br_ec_p256_m62_get();
1047 if (ec != NULL) {
1048 test_speed_ec_inner("EC p256_m62", ec, &br_secp256r1);
1049 } else {
1050 printf("%-30s UNAVAILABLE\n", "EC p256_m62");
1051 }
1052 }
1053
1054 static void
1055 test_speed_ec_p256_m64(void)
1056 {
1057 const br_ec_impl *ec;
1058
1059 ec = br_ec_p256_m64_get();
1060 if (ec != NULL) {
1061 test_speed_ec_inner("EC p256_m64", ec, &br_secp256r1);
1062 } else {
1063 printf("%-30s UNAVAILABLE\n", "EC p256_m64");
1064 }
1065 }
1066
1067 static void
1068 test_speed_ec_prime_i15(void)
1069 {
1070 test_speed_ec_inner("EC prime_i15 P-256",
1071 &br_ec_prime_i15, &br_secp256r1);
1072 test_speed_ec_inner("EC prime_i15 P-384",
1073 &br_ec_prime_i15, &br_secp384r1);
1074 test_speed_ec_inner("EC prime_i15 P-521",
1075 &br_ec_prime_i15, &br_secp521r1);
1076 }
1077
1078 static void
1079 test_speed_ec_prime_i31(void)
1080 {
1081 test_speed_ec_inner("EC prime_i31 P-256",
1082 &br_ec_prime_i31, &br_secp256r1);
1083 test_speed_ec_inner("EC prime_i31 P-384",
1084 &br_ec_prime_i31, &br_secp384r1);
1085 test_speed_ec_inner("EC prime_i31 P-521",
1086 &br_ec_prime_i31, &br_secp521r1);
1087 }
1088
1089 static void
1090 test_speed_ec_c25519_i15(void)
1091 {
1092 test_speed_ec_inner("EC c25519_i15",
1093 &br_ec_c25519_i15, &br_curve25519);
1094 }
1095
1096 static void
1097 test_speed_ec_c25519_i31(void)
1098 {
1099 test_speed_ec_inner("EC c25519_i31",
1100 &br_ec_c25519_i31, &br_curve25519);
1101 }
1102
1103 static void
1104 test_speed_ec_c25519_m15(void)
1105 {
1106 test_speed_ec_inner("EC c25519_m15",
1107 &br_ec_c25519_m15, &br_curve25519);
1108 }
1109
1110 static void
1111 test_speed_ec_c25519_m31(void)
1112 {
1113 test_speed_ec_inner("EC c25519_m31",
1114 &br_ec_c25519_m31, &br_curve25519);
1115 }
1116
1117 static void
1118 test_speed_ec_c25519_m62(void)
1119 {
1120 const br_ec_impl *ec;
1121
1122 ec = br_ec_c25519_m62_get();
1123 if (ec != NULL) {
1124 test_speed_ec_inner("EC c25519_m62", ec, &br_curve25519);
1125 } else {
1126 printf("%-30s UNAVAILABLE\n", "EC c25519_m62");
1127 }
1128 }
1129
1130 static void
1131 test_speed_ec_c25519_m64(void)
1132 {
1133 const br_ec_impl *ec;
1134
1135 ec = br_ec_c25519_m64_get();
1136 if (ec != NULL) {
1137 test_speed_ec_inner("EC c25519_m64", ec, &br_curve25519);
1138 } else {
1139 printf("%-30s UNAVAILABLE\n", "EC c25519_m64");
1140 }
1141 }
1142
1143 static void
1144 test_speed_ecdsa_inner(const char *name,
1145 const br_ec_impl *impl, const br_ec_curve_def *cd,
1146 br_ecdsa_sign sign, br_ecdsa_vrfy vrfy)
1147 {
1148 unsigned char bx[80], U[160], hv[32], sig[160];
1149 uint32_t x[22], n[22];
1150 size_t nlen, ulen, sig_len;
1151 int i;
1152 long num;
1153 br_ec_private_key sk;
1154 br_ec_public_key pk;
1155
1156 nlen = cd->order_len;
1157 br_i31_decode(n, cd->order, nlen);
1158 memset(bx, 'T', sizeof bx);
1159 br_i31_decode_reduce(x, bx, sizeof bx, n);
1160 br_i31_encode(bx, nlen, x);
1161 ulen = cd->generator_len;
1162 memcpy(U, cd->generator, ulen);
1163 impl->mul(U, ulen, bx, nlen, cd->curve);
1164 sk.curve = cd->curve;
1165 sk.x = bx;
1166 sk.xlen = nlen;
1167 pk.curve = cd->curve;
1168 pk.q = U;
1169 pk.qlen = ulen;
1170
1171 memset(hv, 'H', sizeof hv);
1172 sig_len = sign(impl, &br_sha256_vtable, hv, &sk, sig);
1173 if (vrfy(impl, hv, sizeof hv, &pk, sig, sig_len) != 1) {
1174 fprintf(stderr, "self-test sign/verify failed\n");
1175 exit(EXIT_FAILURE);
1176 }
1177
1178 for (i = 0; i < 10; i ++) {
1179 hv[1] ++;
1180 sign(impl, &br_sha256_vtable, hv, &sk, sig);
1181 vrfy(impl, hv, sizeof hv, &pk, sig, sig_len);
1182 }
1183
1184 num = 10;
1185 for (;;) {
1186 clock_t begin, end;
1187 double tt;
1188 long k;
1189
1190 begin = clock();
1191 for (k = num; k > 0; k --) {
1192 hv[1] ++;
1193 sig_len = sign(impl, &br_sha256_vtable, hv, &sk, sig);
1194 }
1195 end = clock();
1196 tt = (double)(end - begin) / CLOCKS_PER_SEC;
1197 if (tt >= 2.0) {
1198 printf("%-30s %8.2f sign/s\n", name,
1199 (double)num / tt);
1200 fflush(stdout);
1201 break;
1202 }
1203 num <<= 1;
1204 }
1205
1206 num = 10;
1207 for (;;) {
1208 clock_t begin, end;
1209 double tt;
1210 long k;
1211
1212 begin = clock();
1213 for (k = num; k > 0; k --) {
1214 vrfy(impl, hv, sizeof hv, &pk, sig, sig_len);
1215 }
1216 end = clock();
1217 tt = (double)(end - begin) / CLOCKS_PER_SEC;
1218 if (tt >= 2.0) {
1219 printf("%-30s %8.2f verify/s\n", name,
1220 (double)num / tt);
1221 fflush(stdout);
1222 break;
1223 }
1224 num <<= 1;
1225 }
1226 }
1227
1228 static void
1229 test_speed_ecdsa_p256_m15(void)
1230 {
1231 test_speed_ecdsa_inner("ECDSA m15 P-256",
1232 &br_ec_p256_m15, &br_secp256r1,
1233 &br_ecdsa_i15_sign_asn1,
1234 &br_ecdsa_i15_vrfy_asn1);
1235 }
1236
1237 static void
1238 test_speed_ecdsa_p256_m31(void)
1239 {
1240 test_speed_ecdsa_inner("ECDSA m31 P-256",
1241 &br_ec_p256_m31, &br_secp256r1,
1242 &br_ecdsa_i31_sign_asn1,
1243 &br_ecdsa_i31_vrfy_asn1);
1244 }
1245
1246 static void
1247 test_speed_ecdsa_p256_m62(void)
1248 {
1249 const br_ec_impl *ec;
1250
1251 ec = br_ec_p256_m62_get();
1252 if (ec != NULL) {
1253 test_speed_ecdsa_inner("ECDSA m62 P-256",
1254 ec, &br_secp256r1,
1255 &br_ecdsa_i31_sign_asn1,
1256 &br_ecdsa_i31_vrfy_asn1);
1257 } else {
1258 printf("%-30s UNAVAILABLE\n", "ECDSA m62 P-256");
1259 }
1260 }
1261
1262 static void
1263 test_speed_ecdsa_p256_m64(void)
1264 {
1265 const br_ec_impl *ec;
1266
1267 ec = br_ec_p256_m64_get();
1268 if (ec != NULL) {
1269 test_speed_ecdsa_inner("ECDSA m64 P-256",
1270 ec, &br_secp256r1,
1271 &br_ecdsa_i31_sign_asn1,
1272 &br_ecdsa_i31_vrfy_asn1);
1273 } else {
1274 printf("%-30s UNAVAILABLE\n", "ECDSA m64 P-256");
1275 }
1276 }
1277
1278 static void
1279 test_speed_ecdsa_i15(void)
1280 {
1281 test_speed_ecdsa_inner("ECDSA i15 P-256",
1282 &br_ec_prime_i15, &br_secp256r1,
1283 &br_ecdsa_i15_sign_asn1,
1284 &br_ecdsa_i15_vrfy_asn1);
1285 test_speed_ecdsa_inner("ECDSA i15 P-384",
1286 &br_ec_prime_i15, &br_secp384r1,
1287 &br_ecdsa_i15_sign_asn1,
1288 &br_ecdsa_i15_vrfy_asn1);
1289 test_speed_ecdsa_inner("ECDSA i15 P-521",
1290 &br_ec_prime_i15, &br_secp521r1,
1291 &br_ecdsa_i15_sign_asn1,
1292 &br_ecdsa_i15_vrfy_asn1);
1293 }
1294
1295 static void
1296 test_speed_ecdsa_i31(void)
1297 {
1298 test_speed_ecdsa_inner("ECDSA i31 P-256",
1299 &br_ec_prime_i31, &br_secp256r1,
1300 &br_ecdsa_i31_sign_asn1,
1301 &br_ecdsa_i31_vrfy_asn1);
1302 test_speed_ecdsa_inner("ECDSA i31 P-384",
1303 &br_ec_prime_i31, &br_secp384r1,
1304 &br_ecdsa_i31_sign_asn1,
1305 &br_ecdsa_i31_vrfy_asn1);
1306 test_speed_ecdsa_inner("ECDSA i31 P-521",
1307 &br_ec_prime_i31, &br_secp521r1,
1308 &br_ecdsa_i31_sign_asn1,
1309 &br_ecdsa_i31_vrfy_asn1);
1310 }
1311
1312 static void
1313 test_speed_i31(void)
1314 {
1315 static const unsigned char bp[] = {
1316 /* A 521-bit prime integer (order of the P-521 curve). */
1317 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1318 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1319 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1320 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1321 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F,
1322 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
1323 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C,
1324 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38,
1325 0x64, 0x09
1326 };
1327
1328 unsigned char tmp[60 + sizeof bp];
1329 uint32_t p[20], x[20], y[20], z[20], uu[60], p0i;
1330 int i;
1331 long num;
1332
1333 br_i31_decode(p, bp, sizeof bp);
1334 p0i = br_i31_ninv31(p[1]);
1335 memset(tmp, 'T', sizeof tmp);
1336 br_i31_decode_reduce(x, tmp, sizeof tmp, p);
1337 memset(tmp, 'U', sizeof tmp);
1338 br_i31_decode_reduce(y, tmp, sizeof tmp, p);
1339
1340 for (i = 0; i < 10; i ++) {
1341 br_i31_to_monty(x, p);
1342 }
1343 num = 10;
1344 for (;;) {
1345 clock_t begin, end;
1346 double tt;
1347 long k;
1348
1349 begin = clock();
1350 for (k = num; k > 0; k --) {
1351 br_i31_to_monty(x, p);
1352 }
1353 end = clock();
1354 tt = (double)(end - begin) / CLOCKS_PER_SEC;
1355 if (tt >= 2.0) {
1356 printf("%-30s %8.2f ops/s\n", "i31 to_monty",
1357 (double)num / tt);
1358 fflush(stdout);
1359 break;
1360 }
1361 num <<= 1;
1362 }
1363
1364 for (i = 0; i < 10; i ++) {
1365 br_i31_from_monty(x, p, p0i);
1366 }
1367 num = 10;
1368 for (;;) {
1369 clock_t begin, end;
1370 double tt;
1371 long k;
1372
1373 begin = clock();
1374 for (k = num; k > 0; k --) {
1375 br_i31_from_monty(x, p, p0i);
1376 }
1377 end = clock();
1378 tt = (double)(end - begin) / CLOCKS_PER_SEC;
1379 if (tt >= 2.0) {
1380 printf("%-30s %8.2f ops/s\n", "i31 from_monty",
1381 (double)num / tt);
1382 fflush(stdout);
1383 break;
1384 }
1385 num <<= 1;
1386 }
1387
1388 for (i = 0; i < 10; i ++) {
1389 br_i31_montymul(z, x, y, p, p0i);
1390 }
1391 num = 10;
1392 for (;;) {
1393 clock_t begin, end;
1394 double tt;
1395 long k;
1396
1397 begin = clock();
1398 for (k = num; k > 0; k --) {
1399 br_i31_montymul(z, x, y, p, p0i);
1400 }
1401 end = clock();
1402 tt = (double)(end - begin) / CLOCKS_PER_SEC;
1403 if (tt >= 2.0) {
1404 printf("%-30s %8.2f ops/s\n", "i31 montymul",
1405 (double)num / tt);
1406 fflush(stdout);
1407 break;
1408 }
1409 num <<= 1;
1410 }
1411
1412 for (i = 0; i < 10; i ++) {
1413 br_i31_moddiv(x, y, p, p0i, uu);
1414 }
1415 num = 10;
1416 for (;;) {
1417 clock_t begin, end;
1418 double tt;
1419 long k;
1420
1421 begin = clock();
1422 for (k = num; k > 0; k --) {
1423 br_i31_moddiv(x, y, p, p0i, uu);
1424 }
1425 end = clock();
1426 tt = (double)(end - begin) / CLOCKS_PER_SEC;
1427 if (tt >= 2.0) {
1428 printf("%-30s %8.2f ops/s\n", "i31 moddiv",
1429 (double)num / tt);
1430 fflush(stdout);
1431 break;
1432 }
1433 num <<= 1;
1434 }
1435 }
1436
1437 #if 0
1438
1439 static unsigned char P2048[] = {
1440 0xFD, 0xB6, 0xE0, 0x3E, 0x00, 0x49, 0x4C, 0xF0, 0x69, 0x3A, 0xDD, 0x7D,
1441 0xF8, 0xA2, 0x41, 0xB0, 0x6C, 0x67, 0xC5, 0xBA, 0xB8, 0x46, 0x80, 0xF5,
1442 0xBF, 0xAB, 0x98, 0xFC, 0x84, 0x73, 0xA5, 0x63, 0xC9, 0x52, 0x12, 0xDA,
1443 0x4C, 0xC1, 0x5B, 0x9D, 0x8D, 0xDF, 0xCD, 0xFE, 0xC5, 0xAD, 0x5A, 0x6F,
1444 0xDD, 0x02, 0xD9, 0xEC, 0x71, 0xEF, 0xEB, 0xB6, 0x95, 0xED, 0x94, 0x25,
1445 0x0E, 0x63, 0xDD, 0x6A, 0x52, 0xC7, 0x93, 0xAF, 0x85, 0x9D, 0x2C, 0xBE,
1446 0x5C, 0xBE, 0x35, 0xD8, 0xDD, 0x39, 0xEF, 0x1B, 0xB1, 0x49, 0x67, 0xB2,
1447 0x33, 0xC9, 0x7C, 0xE1, 0x51, 0x79, 0x51, 0x59, 0xCA, 0x6E, 0x2A, 0xDF,
1448 0x0D, 0x76, 0x1C, 0xE7, 0xA5, 0xC0, 0x1E, 0x6C, 0x56, 0x3A, 0x32, 0xE5,
1449 0xB5, 0xC5, 0xD4, 0xDB, 0xFE, 0xFF, 0xF8, 0xF2, 0x96, 0xA9, 0xC9, 0x65,
1450 0x59, 0x9E, 0x01, 0x79, 0x9D, 0x38, 0x68, 0x0F, 0xAD, 0x43, 0x3A, 0xD6,
1451 0x84, 0x0A, 0xE2, 0xEF, 0x96, 0xC1, 0x6D, 0x89, 0x74, 0x19, 0x63, 0x82,
1452 0x3B, 0xA0, 0x9C, 0xBA, 0x78, 0xDE, 0xDC, 0xC2, 0xE7, 0xD4, 0xFA, 0xD6,
1453 0x19, 0x21, 0x29, 0xAE, 0x5E, 0xF4, 0x38, 0x81, 0xC6, 0x9E, 0x0E, 0x3C,
1454 0xCD, 0xC0, 0xDC, 0x93, 0x5D, 0xFD, 0x9A, 0x5C, 0xAB, 0x54, 0x1F, 0xFF,
1455 0x9C, 0x12, 0x1B, 0x4C, 0xDF, 0x2D, 0x9C, 0x85, 0xF9, 0x68, 0x15, 0x89,
1456 0x42, 0x9B, 0x6C, 0x45, 0x89, 0x3A, 0xBC, 0xE9, 0x19, 0x91, 0xBE, 0x0C,
1457 0xEF, 0x90, 0xCC, 0xF6, 0xD6, 0xF0, 0x3D, 0x5C, 0xF5, 0xE5, 0x0F, 0x2F,
1458 0x02, 0x8A, 0x83, 0x4B, 0x93, 0x2F, 0x14, 0x12, 0x1F, 0x56, 0x9A, 0x12,
1459 0x58, 0x88, 0xAE, 0x60, 0xB8, 0x5A, 0xE4, 0xA1, 0xBF, 0x4A, 0x81, 0x84,
1460 0xAB, 0xBB, 0xE4, 0xD0, 0x1D, 0x41, 0xD9, 0x0A, 0xAB, 0x1E, 0x47, 0x5B,
1461 0x31, 0xAC, 0x2B, 0x73
1462 };
1463
1464 static unsigned char G2048[] = {
1465 0x02
1466 };
1467
1468 static void
1469 test_speed_modpow(void)
1470 {
1471 uint32_t mx[65], mp[65], me[65], t1[65], t2[65], len;
1472 unsigned char e[64];
1473 int i;
1474 long num;
1475
1476 len = br_int_decode(mp, sizeof mp / sizeof mp[0],
1477 P2048, sizeof P2048);
1478 if (len != 65) {
1479 abort();
1480 }
1481 memset(e, 'P', sizeof e);
1482 if (!br_int_decode(me, sizeof me / sizeof me[0], e, sizeof e)) {
1483 abort();
1484 }
1485 if (!br_modint_decode(mx, mp, G2048, sizeof G2048)) {
1486 abort();
1487 }
1488 for (i = 0; i < 10; i ++) {
1489 br_modint_to_monty(mx, mp);
1490 br_modint_montypow(mx, me, mp, t1, t2);
1491 br_modint_from_monty(mx, mp);
1492 }
1493 num = 10;
1494 for (;;) {
1495 clock_t begin, end;
1496 double tt;
1497 long k;
1498
1499 begin = clock();
1500 for (k = num; k > 0; k --) {
1501 br_modint_to_monty(mx, mp);
1502 br_modint_montypow(mx, me, mp, t1, t2);
1503 br_modint_from_monty(mx, mp);
1504 }
1505 end = clock();
1506 tt = (double)(end - begin) / CLOCKS_PER_SEC;
1507 if (tt >= 2.0) {
1508 printf("%-30s %8.2f exp/s\n", "pow[2048:256]",
1509 (double)num / tt);
1510 fflush(stdout);
1511 return;
1512 }
1513 num <<= 1;
1514 }
1515 }
1516
1517 static void
1518 test_speed_moddiv(void)
1519 {
1520 uint32_t mx[65], my[65], mp[65], t1[65], t2[65], t3[65], len;
1521 unsigned char x[255], y[255];
1522 int i;
1523 long num;
1524
1525 len = br_int_decode(mp, sizeof mp / sizeof mp[0],
1526 P2048, sizeof P2048);
1527 if (len != 65) {
1528 abort();
1529 }
1530 memset(x, 'T', sizeof x);
1531 memset(y, 'P', sizeof y);
1532 if (!br_modint_decode(mx, mp, x, sizeof x)) {
1533 abort();
1534 }
1535 if (!br_modint_decode(my, mp, y, sizeof y)) {
1536 abort();
1537 }
1538 for (i = 0; i < 10; i ++) {
1539 br_modint_div(mx, my, mp, t1, t2, t3);
1540 }
1541 num = 10;
1542 for (;;) {
1543 clock_t begin, end;
1544 double tt;
1545 long k;
1546
1547 begin = clock();
1548 for (k = num; k > 0; k --) {
1549 br_modint_div(mx, my, mp, t1, t2, t3);
1550 }
1551 end = clock();
1552 tt = (double)(end - begin) / CLOCKS_PER_SEC;
1553 if (tt >= 2.0) {
1554 printf("%-30s %8.2f div/s\n", "div[2048]",
1555 (double)num / tt);
1556 fflush(stdout);
1557 return;
1558 }
1559 num <<= 1;
1560 }
1561 }
1562 #endif
1563
1564 #define STU(x) { test_speed_ ## x, #x }
1565
1566 static const struct {
1567 void (*fn)(void);
1568 char *name;
1569 } tfns[] = {
1570 STU(md5),
1571 STU(sha1),
1572 STU(sha256),
1573 STU(sha512),
1574
1575 STU(aes128_big_cbcenc),
1576 STU(aes128_big_cbcdec),
1577 STU(aes192_big_cbcenc),
1578 STU(aes192_big_cbcdec),
1579 STU(aes256_big_cbcenc),
1580 STU(aes256_big_cbcdec),
1581 STU(aes128_big_ctr),
1582 STU(aes192_big_ctr),
1583 STU(aes256_big_ctr),
1584
1585 STU(aes128_small_cbcenc),
1586 STU(aes128_small_cbcdec),
1587 STU(aes192_small_cbcenc),
1588 STU(aes192_small_cbcdec),
1589 STU(aes256_small_cbcenc),
1590 STU(aes256_small_cbcdec),
1591 STU(aes128_small_ctr),
1592 STU(aes192_small_ctr),
1593 STU(aes256_small_ctr),
1594
1595 STU(aes128_ct_cbcenc),
1596 STU(aes128_ct_cbcdec),
1597 STU(aes192_ct_cbcenc),
1598 STU(aes192_ct_cbcdec),
1599 STU(aes256_ct_cbcenc),
1600 STU(aes256_ct_cbcdec),
1601 STU(aes128_ct_ctr),
1602 STU(aes192_ct_ctr),
1603 STU(aes256_ct_ctr),
1604
1605 STU(aes128_ct64_cbcenc),
1606 STU(aes128_ct64_cbcdec),
1607 STU(aes192_ct64_cbcenc),
1608 STU(aes192_ct64_cbcdec),
1609 STU(aes256_ct64_cbcenc),
1610 STU(aes256_ct64_cbcdec),
1611 STU(aes128_ct64_ctr),
1612 STU(aes192_ct64_ctr),
1613 STU(aes256_ct64_ctr),
1614
1615 STU(aes128_x86ni_cbcenc),
1616 STU(aes128_x86ni_cbcdec),
1617 STU(aes192_x86ni_cbcenc),
1618 STU(aes192_x86ni_cbcdec),
1619 STU(aes256_x86ni_cbcenc),
1620 STU(aes256_x86ni_cbcdec),
1621 STU(aes128_x86ni_ctr),
1622 STU(aes192_x86ni_ctr),
1623 STU(aes256_x86ni_ctr),
1624
1625 STU(aes128_pwr8_cbcenc),
1626 STU(aes128_pwr8_cbcdec),
1627 STU(aes192_pwr8_cbcenc),
1628 STU(aes192_pwr8_cbcdec),
1629 STU(aes256_pwr8_cbcenc),
1630 STU(aes256_pwr8_cbcdec),
1631 STU(aes128_pwr8_ctr),
1632 STU(aes192_pwr8_ctr),
1633 STU(aes256_pwr8_ctr),
1634
1635 STU(des_tab_cbcenc),
1636 STU(des_tab_cbcdec),
1637 STU(3des_tab_cbcenc),
1638 STU(3des_tab_cbcdec),
1639
1640 STU(des_ct_cbcenc),
1641 STU(des_ct_cbcdec),
1642 STU(3des_ct_cbcenc),
1643 STU(3des_ct_cbcdec),
1644
1645 STU(chacha20_ct),
1646 STU(chacha20_sse2),
1647
1648 STU(ghash_ctmul),
1649 STU(ghash_ctmul32),
1650 STU(ghash_ctmul64),
1651 STU(ghash_pclmul),
1652 STU(ghash_pwr8),
1653
1654 STU(poly1305_ctmul),
1655 STU(poly1305_ctmul32),
1656 STU(poly1305_ctmulq),
1657 STU(poly1305_i15),
1658
1659 STU(eax_aes128_big),
1660 STU(eax_aes192_big),
1661 STU(eax_aes256_big),
1662 STU(eax_aes128_small),
1663 STU(eax_aes192_small),
1664 STU(eax_aes256_small),
1665 STU(eax_aes128_ct),
1666 STU(eax_aes192_ct),
1667 STU(eax_aes256_ct),
1668 STU(eax_aes128_ct64),
1669 STU(eax_aes192_ct64),
1670 STU(eax_aes256_ct64),
1671 STU(eax_aes128_x86ni),
1672 STU(eax_aes192_x86ni),
1673 STU(eax_aes256_x86ni),
1674 STU(eax_aes128_pwr8),
1675 STU(eax_aes192_pwr8),
1676 STU(eax_aes256_pwr8),
1677
1678 STU(shake128),
1679 STU(shake256),
1680
1681 STU(rsa_i15),
1682 STU(rsa_i31),
1683 STU(rsa_i32),
1684 STU(rsa_i62),
1685 STU(ec_prime_i15),
1686 STU(ec_prime_i31),
1687 STU(ec_p256_m15),
1688 STU(ec_p256_m31),
1689 STU(ec_p256_m62),
1690 STU(ec_p256_m64),
1691 STU(ec_c25519_i15),
1692 STU(ec_c25519_i31),
1693 STU(ec_c25519_m15),
1694 STU(ec_c25519_m31),
1695 STU(ec_c25519_m62),
1696 STU(ec_c25519_m64),
1697 STU(ecdsa_p256_m15),
1698 STU(ecdsa_p256_m31),
1699 STU(ecdsa_p256_m62),
1700 STU(ecdsa_p256_m64),
1701 STU(ecdsa_i15),
1702 STU(ecdsa_i31),
1703
1704 STU(i31)
1705 };
1706
1707 static int
1708 eq_name(const char *s1, const char *s2)
1709 {
1710 for (;;) {
1711 int c1, c2;
1712
1713 for (;;) {
1714 c1 = *s1 ++;
1715 if (c1 >= 'A' && c1 <= 'Z') {
1716 c1 += 'a' - 'A';
1717 } else {
1718 switch (c1) {
1719 case '-': case '_': case '.': case ' ':
1720 continue;
1721 }
1722 }
1723 break;
1724 }
1725 for (;;) {
1726 c2 = *s2 ++;
1727 if (c2 >= 'A' && c2 <= 'Z') {
1728 c2 += 'a' - 'A';
1729 } else {
1730 switch (c2) {
1731 case '-': case '_': case '.': case ' ':
1732 continue;
1733 }
1734 }
1735 break;
1736 }
1737 if (c1 != c2) {
1738 return 0;
1739 }
1740 if (c1 == 0) {
1741 return 1;
1742 }
1743 }
1744 }
1745
1746 int
1747 main(int argc, char *argv[])
1748 {
1749 size_t u;
1750
1751 if (argc <= 1) {
1752 printf("usage: testspeed all | name...\n");
1753 printf("individual test names:\n");
1754 for (u = 0; u < (sizeof tfns) / (sizeof tfns[0]); u ++) {
1755 printf(" %s\n", tfns[u].name);
1756 }
1757 } else {
1758 for (u = 0; u < (sizeof tfns) / (sizeof tfns[0]); u ++) {
1759 int i;
1760
1761 for (i = 1; i < argc; i ++) {
1762 if (eq_name(argv[i], tfns[u].name)
1763 || eq_name(argv[i], "all"))
1764 {
1765 tfns[u].fn();
1766 break;
1767 }
1768 }
1769 }
1770 }
1771 return 0;
1772 }