xref: /freebsd/contrib/bearssl/test/test_speed.c (revision b3512b30dbec579da28028e29d8b33ec7242af68)
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 }
1773