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) \
34static void \
35test_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) \
77static void \
78test_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) \
126static void \
127test_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) \
175static void \
176test_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
220SPEED_HASH(MD5, md5)
221SPEED_HASH(SHA-1, sha1)
222SPEED_HASH(SHA-256, sha256)
223SPEED_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) \
248SPEED_BLOCKCIPHER_CBC(AES-128 CBC encrypt (iname), aes128_ ## iname ## _cbcenc, aes_ ## iname, 16, enc) \
249SPEED_BLOCKCIPHER_CBC(AES-128 CBC decrypt (iname), aes128_ ## iname ## _cbcdec, aes_ ## iname, 16, dec) \
250SPEED_BLOCKCIPHER_CBC(AES-192 CBC encrypt (iname), aes192_ ## iname ## _cbcenc, aes_ ## iname, 24, enc) \
251SPEED_BLOCKCIPHER_CBC(AES-192 CBC decrypt (iname), aes192_ ## iname ## _cbcdec, aes_ ## iname, 24, dec) \
252SPEED_BLOCKCIPHER_CBC(AES-256 CBC encrypt (iname), aes256_ ## iname ## _cbcenc, aes_ ## iname, 32, enc) \
253SPEED_BLOCKCIPHER_CBC(AES-256 CBC decrypt (iname), aes256_ ## iname ## _cbcdec, aes_ ## iname, 32, dec) \
254SPEED_BLOCKCIPHER_CTR(AES-128 CTR (iname), aes128_ ## iname ## _ctr, aes_ ## iname, 16) \
255SPEED_BLOCKCIPHER_CTR(AES-192 CTR (iname), aes192_ ## iname ## _ctr, aes_ ## iname, 24) \
256SPEED_BLOCKCIPHER_CTR(AES-256 CTR (iname), aes256_ ## iname ## _ctr, aes_ ## iname, 32)
257
258SPEED_AES(big)
259SPEED_AES(small)
260SPEED_AES(ct)
261SPEED_AES(ct64)
262SPEED_AES(x86ni)
263SPEED_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) \
271SPEED_BLOCKCIPHER_CBC(DES CBC encrypt (iname), des_ ## iname ## _cbcenc, des_ ## iname, 8, enc) \
272SPEED_BLOCKCIPHER_CBC(DES CBC decrypt (iname), des_ ## iname ## _cbcdec, des_ ## iname, 8, dec) \
273SPEED_BLOCKCIPHER_CBC(3DES CBC encrypt (iname), 3des_ ## iname ## _cbcenc, des_ ## iname, 24, enc) \
274SPEED_BLOCKCIPHER_CBC(3DES CBC decrypt (iname), 3des_ ## iname ## _cbcdec, des_ ## iname, 24, dec)
275
276SPEED_DES(tab)
277SPEED_DES(ct)
278
279SPEED_CHACHA20(ChaCha20 (ct), chacha20_ct)
280SPEED_CHACHA20(ChaCha20 (sse2), chacha20_sse2)
281
282static void
283test_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
318static void
319test_speed_ghash_ctmul(void)
320{
321	test_speed_ghash_inner("GHASH (ctmul)", &br_ghash_ctmul);
322}
323
324static void
325test_speed_ghash_ctmul32(void)
326{
327	test_speed_ghash_inner("GHASH (ctmul32)", &br_ghash_ctmul32);
328}
329
330static void
331test_speed_ghash_ctmul64(void)
332{
333	test_speed_ghash_inner("GHASH (ctmul64)", &br_ghash_ctmul64);
334}
335
336static void
337test_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
350static void
351test_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
364static uint32_t
365fake_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 */
379static void
380test_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
418static void
419test_speed_poly1305_ctmul(void)
420{
421	test_speed_poly1305_inner("Poly1305 (ctmul)", &br_poly1305_ctmul_run);
422}
423
424static void
425test_speed_poly1305_ctmul32(void)
426{
427	test_speed_poly1305_inner("Poly1305 (ctmul32)",
428		&br_poly1305_ctmul32_run);
429}
430
431static void
432test_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
444static void
445test_speed_poly1305_i15(void)
446{
447	test_speed_poly1305_inner("Poly1305 (i15)", &br_poly1305_i15_run);
448}
449
450static void
451test_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) \
508static void \
509test_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
516SPEED_EAX(AES, aes, 128, big)
517SPEED_EAX(AES, aes, 128, small)
518SPEED_EAX(AES, aes, 128, ct)
519SPEED_EAX(AES, aes, 128, ct64)
520SPEED_EAX(AES, aes, 128, x86ni)
521SPEED_EAX(AES, aes, 128, pwr8)
522SPEED_EAX(AES, aes, 192, big)
523SPEED_EAX(AES, aes, 192, small)
524SPEED_EAX(AES, aes, 192, ct)
525SPEED_EAX(AES, aes, 192, ct64)
526SPEED_EAX(AES, aes, 192, x86ni)
527SPEED_EAX(AES, aes, 192, pwr8)
528SPEED_EAX(AES, aes, 256, big)
529SPEED_EAX(AES, aes, 256, small)
530SPEED_EAX(AES, aes, 256, ct)
531SPEED_EAX(AES, aes, 256, ct64)
532SPEED_EAX(AES, aes, 256, x86ni)
533SPEED_EAX(AES, aes, 256, pwr8)
534
535static void
536test_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
600static void
601test_speed_shake128(void)
602{
603	test_speed_shake_inner(128);
604}
605
606static void
607test_speed_shake256(void)
608{
609	test_speed_shake_inner(256);
610}
611
612static 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
647static const unsigned char RSA_E[] = {
648	0x01, 0x00, 0x01
649};
650
651static 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
670static 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
689static 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
708static 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
727static 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
746static const br_rsa_public_key RSA_PK = {
747	(void *)RSA_N, sizeof RSA_N,
748	(void *)RSA_E, sizeof RSA_E
749};
750
751static 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
760static void
761test_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
896static void
897test_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
903static void
904test_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
910static void
911test_speed_rsa_i32(void)
912{
913	test_speed_rsa_inner("RSA i32",
914		&br_rsa_i32_public, &br_rsa_i32_private, 0);
915}
916
917static void
918test_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
934static void
935test_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
976static void
977test_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
1016static void
1017test_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
1027static void
1028test_speed_ec_p256_m15(void)
1029{
1030	test_speed_ec_inner("EC p256_m15",
1031		&br_ec_p256_m15, &br_secp256r1);
1032}
1033
1034static void
1035test_speed_ec_p256_m31(void)
1036{
1037	test_speed_ec_inner("EC p256_m31",
1038		&br_ec_p256_m31, &br_secp256r1);
1039}
1040
1041static void
1042test_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
1054static void
1055test_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
1067static void
1068test_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
1078static void
1079test_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
1089static void
1090test_speed_ec_c25519_i15(void)
1091{
1092	test_speed_ec_inner("EC c25519_i15",
1093		&br_ec_c25519_i15, &br_curve25519);
1094}
1095
1096static void
1097test_speed_ec_c25519_i31(void)
1098{
1099	test_speed_ec_inner("EC c25519_i31",
1100		&br_ec_c25519_i31, &br_curve25519);
1101}
1102
1103static void
1104test_speed_ec_c25519_m15(void)
1105{
1106	test_speed_ec_inner("EC c25519_m15",
1107		&br_ec_c25519_m15, &br_curve25519);
1108}
1109
1110static void
1111test_speed_ec_c25519_m31(void)
1112{
1113	test_speed_ec_inner("EC c25519_m31",
1114		&br_ec_c25519_m31, &br_curve25519);
1115}
1116
1117static void
1118test_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
1130static void
1131test_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
1143static void
1144test_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
1228static void
1229test_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
1237static void
1238test_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
1246static void
1247test_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
1262static void
1263test_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
1278static void
1279test_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
1295static void
1296test_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
1312static void
1313test_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
1439static 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
1464static unsigned char G2048[] = {
1465	0x02
1466};
1467
1468static void
1469test_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
1517static void
1518test_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
1566static 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
1707static int
1708eq_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
1746int
1747main(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