Added API to save and restore session parameters (for controllable session resumption...
[BearSSL] / test / test_speed.c
1 /*
2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include "inner.h"
30
31 #define HASH_SIZE(cname) br_ ## cname ## _SIZE
32
33 #define SPEED_HASH(Name, cname) \
34 static void \
35 test_speed_ ## cname(void) \
36 { \
37 unsigned char buf[8192]; \
38 unsigned char tmp[HASH_SIZE(cname)]; \
39 br_ ## cname ## _context mc; \
40 int i; \
41 long num; \
42 \
43 memset(buf, 'T', sizeof buf); \
44 for (i = 0; i < 10; i ++) { \
45 br_ ## cname ## _init(&mc); \
46 br_ ## cname ## _update(&mc, buf, sizeof buf); \
47 br_ ## cname ## _out(&mc, tmp); \
48 } \
49 num = 10; \
50 for (;;) { \
51 clock_t begin, end; \
52 double tt; \
53 long k; \
54 \
55 br_ ## cname ## _init(&mc); \
56 begin = clock(); \
57 for (k = num; k > 0; k --) { \
58 br_ ## cname ## _update(&mc, buf, sizeof buf); \
59 } \
60 end = clock(); \
61 br_ ## cname ## _out(&mc, tmp); \
62 tt = (double)(end - begin) / CLOCKS_PER_SEC; \
63 if (tt >= 2.0) { \
64 printf("%-30s %8.2f MB/s\n", #Name, \
65 ((double)sizeof buf) * (double)num \
66 / (tt * 1000000.0)); \
67 fflush(stdout); \
68 return; \
69 } \
70 num <<= 1; \
71 } \
72 }
73
74 #define BLOCK_SIZE(cname) br_ ## cname ## _BLOCK_SIZE
75
76 #define SPEED_BLOCKCIPHER_CBC(Name, fname, cname, klen, dir) \
77 static void \
78 test_speed_ ## fname(void) \
79 { \
80 unsigned char key[klen]; \
81 unsigned char buf[8192 - (8192 % BLOCK_SIZE(cname))]; \
82 unsigned char iv[BLOCK_SIZE(cname)]; \
83 const br_block_cbc ## dir ## _class *vt; \
84 br_ ## cname ## _cbc ## dir ## _keys ec; \
85 int i; \
86 long num; \
87 \
88 memset(key, 'T', sizeof key); \
89 memset(buf, 'P', sizeof buf); \
90 memset(iv, 'X', sizeof iv); \
91 vt = &br_ ## cname ## _cbc ## dir ## _vtable; \
92 for (i = 0; i < 10; i ++) { \
93 vt->init(&ec.vtable, key, sizeof key); \
94 vt->run(&ec.vtable, iv, buf, sizeof buf); \
95 } \
96 num = 10; \
97 for (;;) { \
98 clock_t begin, end; \
99 double tt; \
100 long k; \
101 \
102 vt->init(&ec.vtable, key, sizeof key); \
103 begin = clock(); \
104 for (k = num; k > 0; k --) { \
105 vt->run(&ec.vtable, iv, buf, sizeof buf); \
106 } \
107 end = clock(); \
108 tt = (double)(end - begin) / CLOCKS_PER_SEC; \
109 if (tt >= 2.0) { \
110 printf("%-30s %8.2f MB/s\n", #Name, \
111 ((double)sizeof buf) * (double)num \
112 / (tt * 1000000.0)); \
113 fflush(stdout); \
114 return; \
115 } \
116 num <<= 1; \
117 } \
118 }
119
120 #define SPEED_BLOCKCIPHER_CTR(Name, fname, cname, klen) \
121 static void \
122 test_speed_ ## fname(void) \
123 { \
124 unsigned char key[klen]; \
125 unsigned char buf[8192 - (8192 % BLOCK_SIZE(cname))]; \
126 unsigned char iv[BLOCK_SIZE(cname) - 4]; \
127 const br_block_ctr_class *vt; \
128 br_ ## cname ## _ctr_keys ec; \
129 int i; \
130 long num; \
131 \
132 memset(key, 'T', sizeof key); \
133 memset(buf, 'P', sizeof buf); \
134 memset(iv, 'X', sizeof iv); \
135 vt = &br_ ## cname ## _ctr_vtable; \
136 for (i = 0; i < 10; i ++) { \
137 vt->init(&ec.vtable, key, sizeof key); \
138 vt->run(&ec.vtable, iv, 1, buf, sizeof buf); \
139 } \
140 num = 10; \
141 for (;;) { \
142 clock_t begin, end; \
143 double tt; \
144 long k; \
145 \
146 vt->init(&ec.vtable, key, sizeof key); \
147 begin = clock(); \
148 for (k = num; k > 0; k --) { \
149 vt->run(&ec.vtable, iv, 1, buf, sizeof buf); \
150 } \
151 end = clock(); \
152 tt = (double)(end - begin) / CLOCKS_PER_SEC; \
153 if (tt >= 2.0) { \
154 printf("%-30s %8.2f MB/s\n", #Name, \
155 ((double)sizeof buf) * (double)num \
156 / (tt * 1000000.0)); \
157 fflush(stdout); \
158 return; \
159 } \
160 num <<= 1; \
161 } \
162 }
163
164 SPEED_HASH(MD5, md5)
165 SPEED_HASH(SHA-1, sha1)
166 SPEED_HASH(SHA-256, sha256)
167 SPEED_HASH(SHA-512, sha512)
168
169 #define SPEED_AES(iname) \
170 SPEED_BLOCKCIPHER_CBC(AES-128 CBC encrypt (iname), aes128_ ## iname ## _cbcenc, aes_ ## iname, 16, enc) \
171 SPEED_BLOCKCIPHER_CBC(AES-128 CBC decrypt (iname), aes128_ ## iname ## _cbcdec, aes_ ## iname, 16, dec) \
172 SPEED_BLOCKCIPHER_CBC(AES-192 CBC encrypt (iname), aes192_ ## iname ## _cbcenc, aes_ ## iname, 24, enc) \
173 SPEED_BLOCKCIPHER_CBC(AES-192 CBC decrypt (iname), aes192_ ## iname ## _cbcdec, aes_ ## iname, 24, dec) \
174 SPEED_BLOCKCIPHER_CBC(AES-256 CBC encrypt (iname), aes256_ ## iname ## _cbcenc, aes_ ## iname, 32, enc) \
175 SPEED_BLOCKCIPHER_CBC(AES-256 CBC decrypt (iname), aes256_ ## iname ## _cbcdec, aes_ ## iname, 32, dec) \
176 SPEED_BLOCKCIPHER_CTR(AES-128 CTR (iname), aes128_ ## iname ## _ctr, aes_ ## iname, 16) \
177 SPEED_BLOCKCIPHER_CTR(AES-192 CTR (iname), aes192_ ## iname ## _ctr, aes_ ## iname, 24) \
178 SPEED_BLOCKCIPHER_CTR(AES-256 CTR (iname), aes256_ ## iname ## _ctr, aes_ ## iname, 32)
179
180 SPEED_AES(big)
181 SPEED_AES(small)
182 SPEED_AES(ct)
183 SPEED_AES(ct64)
184
185 #define SPEED_DES(iname) \
186 SPEED_BLOCKCIPHER_CBC(DES CBC encrypt (iname), des_ ## iname ## _cbcenc, des_ ## iname, 8, enc) \
187 SPEED_BLOCKCIPHER_CBC(DES CBC decrypt (iname), des_ ## iname ## _cbcdec, des_ ## iname, 8, dec) \
188 SPEED_BLOCKCIPHER_CBC(3DES CBC encrypt (iname), 3des_ ## iname ## _cbcenc, des_ ## iname, 24, enc) \
189 SPEED_BLOCKCIPHER_CBC(3DES CBC decrypt (iname), 3des_ ## iname ## _cbcdec, des_ ## iname, 24, dec)
190
191 SPEED_DES(tab)
192 SPEED_DES(ct)
193
194 static void
195 test_speed_ghash_inner(char *name, br_ghash gh)
196 {
197 unsigned char buf[8192], h[16], y[16];
198 int i;
199 long num;
200
201 memset(buf, 'T', sizeof buf);
202 memset(h, 'P', sizeof h);
203 memset(y, 0, sizeof y);
204 for (i = 0; i < 10; i ++) {
205 gh(y, h, buf, sizeof buf);
206 }
207 num = 10;
208 for (;;) {
209 clock_t begin, end;
210 double tt;
211 long k;
212
213 begin = clock();
214 for (k = num; k > 0; k --) {
215 gh(y, h, buf, sizeof buf);
216 }
217 end = clock();
218 tt = (double)(end - begin) / CLOCKS_PER_SEC;
219 if (tt >= 2.0) {
220 printf("%-30s %8.2f MB/s\n", name,
221 ((double)sizeof buf) * (double)num
222 / (tt * 1000000.0));
223 fflush(stdout);
224 return;
225 }
226 num <<= 1;
227 }
228 }
229
230 static void
231 test_speed_ghash_ctmul(void)
232 {
233 test_speed_ghash_inner("GHASH (ctmul)", &br_ghash_ctmul);
234 }
235
236 static void
237 test_speed_ghash_ctmul32(void)
238 {
239 test_speed_ghash_inner("GHASH (ctmul32)", &br_ghash_ctmul32);
240 }
241
242 static void
243 test_speed_ghash_ctmul64(void)
244 {
245 test_speed_ghash_inner("GHASH (ctmul64)", &br_ghash_ctmul64);
246 }
247
248 static const unsigned char RSA_N[] = {
249 0xE9, 0xF2, 0x4A, 0x2F, 0x96, 0xDF, 0x0A, 0x23,
250 0x01, 0x85, 0xF1, 0x2C, 0xB2, 0xA8, 0xEF, 0x23,
251 0xCE, 0x2E, 0xB0, 0x4E, 0x18, 0x31, 0x95, 0x5B,
252 0x98, 0x2D, 0x9B, 0x8C, 0xE3, 0x1A, 0x2B, 0x96,
253 0xB5, 0xC7, 0xEE, 0xED, 0x72, 0x43, 0x2D, 0xFE,
254 0x7F, 0x61, 0x33, 0xEA, 0x14, 0xFC, 0xDE, 0x80,
255 0x17, 0x42, 0xF0, 0xF3, 0xC3, 0xC7, 0x89, 0x47,
256 0x76, 0x5B, 0xFA, 0x33, 0xC4, 0x8C, 0x94, 0xDE,
257 0x6A, 0x75, 0xD8, 0x1A, 0xF4, 0x49, 0xBC, 0xF3,
258 0xB7, 0x9E, 0x2C, 0x8D, 0xEC, 0x5A, 0xEE, 0xBF,
259 0x4B, 0x5A, 0x7F, 0xEF, 0x21, 0x39, 0xDB, 0x1D,
260 0x83, 0x5E, 0x7E, 0x2F, 0xAA, 0x5E, 0xBA, 0x28,
261 0xC3, 0xA2, 0x53, 0x19, 0xFB, 0x2F, 0x78, 0x6B,
262 0x14, 0x60, 0x49, 0x3C, 0xCC, 0x1B, 0xE9, 0x1E,
263 0x3D, 0x10, 0xA4, 0xEB, 0x7F, 0x66, 0x98, 0xF6,
264 0xC3, 0xAC, 0x35, 0xF5, 0x01, 0x84, 0xFF, 0x7D,
265 0x1F, 0x72, 0xBE, 0xB4, 0xD1, 0x89, 0xC8, 0xDD,
266 0x44, 0xE7, 0xB5, 0x2E, 0x2C, 0xE1, 0x85, 0xF5,
267 0x15, 0x50, 0xA9, 0x08, 0xC7, 0x67, 0xD9, 0x2B,
268 0x6C, 0x11, 0xB3, 0xEB, 0x28, 0x8D, 0xF4, 0xCC,
269 0xE3, 0xC3, 0xC5, 0x04, 0x0E, 0x7C, 0x8D, 0xDB,
270 0x39, 0x06, 0x6A, 0x74, 0x75, 0xDF, 0xA8, 0x0F,
271 0xDA, 0x67, 0x5A, 0x73, 0x1E, 0xFD, 0x8E, 0x4C,
272 0xEE, 0x17, 0xEE, 0x1E, 0x67, 0xDB, 0x98, 0x70,
273 0x60, 0xF7, 0xB9, 0xB5, 0x1F, 0x19, 0x93, 0xD6,
274 0x3F, 0x2F, 0x1F, 0xB6, 0x5B, 0x59, 0xAA, 0x85,
275 0xBB, 0x25, 0xE4, 0x13, 0xEF, 0xE7, 0xB9, 0x87,
276 0x9C, 0x3F, 0x5E, 0xE4, 0x08, 0xA3, 0x51, 0xCF,
277 0x8B, 0xAD, 0xF4, 0xE6, 0x1A, 0x5F, 0x51, 0xDD,
278 0xA8, 0xBE, 0xE8, 0xD1, 0x20, 0x19, 0x61, 0x6C,
279 0x18, 0xAB, 0xCA, 0x0A, 0xD9, 0x82, 0xA6, 0x94,
280 0xD5, 0x69, 0x2A, 0xF6, 0x43, 0x66, 0x31, 0x09
281 };
282
283 static const unsigned char RSA_E[] = {
284 0x01, 0x00, 0x01
285 };
286
287 static const unsigned char RSA_P[] = {
288 0xFD, 0x39, 0x40, 0x56, 0x20, 0x80, 0xC5, 0x81,
289 0x4C, 0x5F, 0x0C, 0x1A, 0x52, 0x84, 0x03, 0x2F,
290 0xCE, 0x82, 0xB0, 0xD8, 0x30, 0x23, 0x7F, 0x77,
291 0x45, 0xC2, 0x01, 0xC4, 0x68, 0x96, 0x0D, 0xA7,
292 0x22, 0xA9, 0x6C, 0xA9, 0x1A, 0x33, 0xE5, 0x2F,
293 0xB5, 0x07, 0x9A, 0xF9, 0xEA, 0x33, 0xA5, 0xC8,
294 0x96, 0x60, 0x6A, 0xCA, 0xEB, 0xE5, 0x6E, 0x09,
295 0x46, 0x7E, 0x2D, 0xEF, 0x93, 0x7D, 0x56, 0xED,
296 0x75, 0x70, 0x3B, 0x96, 0xC4, 0xD5, 0xDB, 0x0B,
297 0x3F, 0x69, 0xDF, 0x06, 0x18, 0x76, 0xF4, 0xCF,
298 0xF8, 0x84, 0x22, 0xDF, 0xBD, 0x71, 0x62, 0x7B,
299 0x67, 0x99, 0xBC, 0x09, 0x95, 0x54, 0xA4, 0x98,
300 0x83, 0xF5, 0xA9, 0xCF, 0x09, 0xA5, 0x1F, 0x61,
301 0x25, 0xB4, 0x70, 0x6C, 0x91, 0xB8, 0xB3, 0xD0,
302 0xCE, 0x9C, 0x45, 0x65, 0x9B, 0xEF, 0xD4, 0x70,
303 0xBE, 0x86, 0xD2, 0x98, 0x5D, 0xEB, 0xE3, 0xFF
304 };
305
306 static const unsigned char RSA_Q[] = {
307 0xEC, 0x82, 0xEE, 0x63, 0x5F, 0x40, 0x52, 0xDB,
308 0x38, 0x7A, 0x37, 0x6A, 0x54, 0x5B, 0xD9, 0xA0,
309 0x73, 0xB4, 0xBB, 0x52, 0xB2, 0x84, 0x07, 0xD0,
310 0xCC, 0x82, 0x0D, 0x20, 0xB3, 0xFA, 0xD5, 0xB6,
311 0x25, 0x92, 0x35, 0x4D, 0xB4, 0xC7, 0x36, 0x48,
312 0xCE, 0x5E, 0x21, 0x4A, 0xA6, 0x74, 0x65, 0xF4,
313 0x7D, 0x1D, 0xBC, 0x3B, 0xE2, 0xF4, 0x3E, 0x11,
314 0x58, 0x10, 0x6C, 0x04, 0x46, 0x9E, 0x8D, 0x57,
315 0xE0, 0x04, 0xE2, 0xEC, 0x47, 0xCF, 0xB3, 0x2A,
316 0xFD, 0x4C, 0x55, 0x18, 0xDB, 0xDE, 0x3B, 0xDC,
317 0xF4, 0x5B, 0xDA, 0xF3, 0x1A, 0xC8, 0x41, 0x6F,
318 0x73, 0x3B, 0xFE, 0x3C, 0xA0, 0xDB, 0xBA, 0x6E,
319 0x65, 0xA5, 0xE8, 0x02, 0xA5, 0x6C, 0xEA, 0x03,
320 0xF6, 0x99, 0xF7, 0xCB, 0x4B, 0xB7, 0x11, 0x51,
321 0x93, 0x88, 0x3F, 0xF9, 0x06, 0x85, 0xA9, 0x1E,
322 0xCA, 0x64, 0xF8, 0x11, 0xA5, 0x1A, 0xCA, 0xF7
323 };
324
325 static const unsigned char RSA_DP[] = {
326 0x77, 0x95, 0xE0, 0x02, 0x4C, 0x9B, 0x43, 0xAA,
327 0xCA, 0x4C, 0x60, 0xC4, 0xD5, 0x8F, 0x2E, 0x8A,
328 0x17, 0x36, 0xB5, 0x19, 0x83, 0xB2, 0x5F, 0xF2,
329 0x0D, 0xE9, 0x8F, 0x38, 0x18, 0x44, 0x34, 0xF2,
330 0x67, 0x76, 0x27, 0xB0, 0xBC, 0x85, 0x21, 0x89,
331 0x24, 0x2F, 0x11, 0x4B, 0x51, 0x05, 0x4F, 0x17,
332 0xA9, 0x9C, 0xA3, 0x12, 0x6D, 0xD1, 0x0D, 0xE4,
333 0x27, 0x7C, 0x53, 0x69, 0x3E, 0xF8, 0x04, 0x63,
334 0x64, 0x00, 0xBA, 0xC3, 0x7A, 0xF5, 0x9B, 0xDA,
335 0x75, 0xFA, 0x23, 0xAF, 0x17, 0x42, 0xA6, 0x5E,
336 0xC8, 0xF8, 0x6E, 0x17, 0xC7, 0xB9, 0x92, 0x4E,
337 0xC1, 0x20, 0x63, 0x23, 0x0B, 0x78, 0xCB, 0xBA,
338 0x93, 0x27, 0x23, 0x28, 0x79, 0x5F, 0x97, 0xB0,
339 0x23, 0x44, 0x51, 0x8B, 0x94, 0x4D, 0xEB, 0xED,
340 0x82, 0x85, 0x5E, 0x68, 0x9B, 0xF9, 0xE9, 0x13,
341 0xCD, 0x86, 0x92, 0x52, 0x0E, 0x98, 0xE6, 0x35
342 };
343
344 static const unsigned char RSA_DQ[] = {
345 0xD8, 0xDD, 0x71, 0xB3, 0x62, 0xBA, 0xBB, 0x7E,
346 0xD1, 0xF9, 0x96, 0xE8, 0x83, 0xB3, 0xB9, 0x08,
347 0x9C, 0x30, 0x03, 0x77, 0xDF, 0xC2, 0x9A, 0xDC,
348 0x05, 0x39, 0xD6, 0xC9, 0xBE, 0xDE, 0x68, 0xA9,
349 0xDD, 0x27, 0x84, 0x82, 0xDD, 0x19, 0xB1, 0x97,
350 0xEE, 0xCA, 0x77, 0x22, 0x59, 0x20, 0xEF, 0xFF,
351 0xCF, 0xDD, 0xBD, 0x24, 0xF8, 0x84, 0xD6, 0x88,
352 0xD6, 0xC4, 0x30, 0x17, 0x77, 0x9D, 0x98, 0xA3,
353 0x14, 0x01, 0xC7, 0x05, 0xBB, 0x0F, 0x23, 0x0D,
354 0x6F, 0x37, 0x57, 0xEC, 0x34, 0x67, 0x41, 0x62,
355 0xE8, 0x19, 0x75, 0xD9, 0x66, 0x1C, 0x6B, 0x8B,
356 0xC3, 0x11, 0x26, 0x9C, 0xF7, 0x2E, 0xA3, 0x72,
357 0xE8, 0xF7, 0xC8, 0x96, 0xEC, 0x92, 0xC2, 0xBD,
358 0xA1, 0x98, 0x2A, 0x93, 0x99, 0xB8, 0xA2, 0x43,
359 0xB7, 0xD0, 0xBE, 0x40, 0x1C, 0x8F, 0xE0, 0xB4,
360 0x20, 0x07, 0x97, 0x43, 0xAE, 0xAD, 0xB3, 0x9F
361 };
362
363 static const unsigned char RSA_IQ[] = {
364 0xB7, 0xE2, 0x60, 0xA9, 0x62, 0xEC, 0xEC, 0x0B,
365 0x57, 0x02, 0x96, 0xF9, 0x36, 0x35, 0x2C, 0x37,
366 0xAF, 0xC2, 0xEE, 0x71, 0x49, 0x26, 0x8E, 0x0F,
367 0x27, 0xB1, 0xFA, 0x0F, 0xEA, 0xDC, 0xF0, 0x8B,
368 0x53, 0x6C, 0xB2, 0x46, 0x27, 0xCD, 0x29, 0xA2,
369 0x35, 0x0F, 0x5D, 0x8A, 0x3F, 0x20, 0x8C, 0x13,
370 0x3D, 0xA1, 0xFF, 0x85, 0x91, 0x99, 0xE8, 0x50,
371 0xED, 0xF1, 0x29, 0x00, 0xEE, 0x24, 0x90, 0xB5,
372 0x5F, 0x3A, 0x74, 0x26, 0xD7, 0xA2, 0x24, 0x8D,
373 0x89, 0x88, 0xD8, 0x35, 0x22, 0x22, 0x8A, 0x66,
374 0x5D, 0x5C, 0xDE, 0x83, 0x8C, 0xFA, 0x27, 0xE6,
375 0xB9, 0xEB, 0x72, 0x08, 0xCD, 0x53, 0x4B, 0x93,
376 0x0F, 0xAD, 0xC3, 0xF8, 0x7C, 0xFE, 0x84, 0xD7,
377 0x08, 0xF3, 0xBE, 0x3D, 0x60, 0x1E, 0x95, 0x8D,
378 0x44, 0x5B, 0x65, 0x7E, 0xC1, 0x30, 0xC3, 0x84,
379 0xC0, 0xB0, 0xFE, 0xBF, 0x28, 0x54, 0x1E, 0xC4
380 };
381
382 static const br_rsa_public_key RSA_PK = {
383 (void *)RSA_N, sizeof RSA_N,
384 (void *)RSA_E, sizeof RSA_E
385 };
386
387 static const br_rsa_private_key RSA_SK = {
388 2048,
389 (void *)RSA_P, sizeof RSA_P,
390 (void *)RSA_Q, sizeof RSA_Q,
391 (void *)RSA_DP, sizeof RSA_DP,
392 (void *)RSA_DQ, sizeof RSA_DQ,
393 (void *)RSA_IQ, sizeof RSA_IQ
394 };
395
396 static void
397 test_speed_rsa_inner(char *name,
398 br_rsa_public fpub, br_rsa_private fpriv)
399 {
400 unsigned char tmp[sizeof RSA_N];
401 int i;
402 long num;
403
404 memset(tmp, 'R', sizeof tmp);
405 tmp[0] = 0;
406 for (i = 0; i < 10; i ++) {
407 if (!fpriv(tmp, &RSA_SK)) {
408 abort();
409 }
410 }
411 num = 10;
412 for (;;) {
413 clock_t begin, end;
414 double tt;
415 long k;
416
417 begin = clock();
418 for (k = num; k > 0; k --) {
419 fpriv(tmp, &RSA_SK);
420 }
421 end = clock();
422 tt = (double)(end - begin) / CLOCKS_PER_SEC;
423 if (tt >= 2.0) {
424 printf("%-30s %8.2f priv/s\n", name,
425 (double)num / tt);
426 fflush(stdout);
427 break;
428 }
429 num <<= 1;
430 }
431 for (i = 0; i < 10; i ++) {
432 if (!fpub(tmp, sizeof tmp, &RSA_PK)) {
433 abort();
434 }
435 }
436 num = 10;
437 for (;;) {
438 clock_t begin, end;
439 double tt;
440 long k;
441
442 begin = clock();
443 for (k = num; k > 0; k --) {
444 fpub(tmp, sizeof tmp, &RSA_PK);
445 }
446 end = clock();
447 tt = (double)(end - begin) / CLOCKS_PER_SEC;
448 if (tt >= 2.0) {
449 printf("%-30s %8.2f pub/s\n", name,
450 (double)num / tt);
451 fflush(stdout);
452 break;
453 }
454 num <<= 1;
455 }
456 }
457
458 static void
459 test_speed_rsa_i31(void)
460 {
461 test_speed_rsa_inner("RSA i31",
462 &br_rsa_i31_public, &br_rsa_i31_private);
463 }
464
465 static void
466 test_speed_rsa_i32(void)
467 {
468 test_speed_rsa_inner("RSA i32",
469 &br_rsa_i32_public, &br_rsa_i32_private);
470 }
471
472 static void
473 test_speed_ec_inner(const char *name,
474 const br_ec_impl *impl, const br_ec_curve_def *cd)
475 {
476 unsigned char bx[80], U[160];
477 uint32_t x[22], n[22];
478 size_t nlen, ulen;
479 int i;
480 long num;
481
482 nlen = cd->order_len;
483 br_i31_decode(n, cd->order, nlen);
484 memset(bx, 'T', sizeof bx);
485 br_i31_decode_reduce(x, bx, sizeof bx, n);
486 br_i31_encode(bx, nlen, x);
487 ulen = cd->generator_len;
488 memcpy(U, cd->generator, ulen);
489 for (i = 0; i < 10; i ++) {
490 impl->mul(U, ulen, bx, nlen, cd->curve);
491 }
492 num = 10;
493 for (;;) {
494 clock_t begin, end;
495 double tt;
496 long k;
497
498 begin = clock();
499 for (k = num; k > 0; k --) {
500 impl->mul(U, ulen, bx, nlen, cd->curve);
501 }
502 end = clock();
503 tt = (double)(end - begin) / CLOCKS_PER_SEC;
504 if (tt >= 2.0) {
505 printf("%-30s %8.2f mul/s\n", name,
506 (double)num / tt);
507 fflush(stdout);
508 break;
509 }
510 num <<= 1;
511 }
512 }
513
514 static void
515 test_speed_ec_prime_i31(void)
516 {
517 test_speed_ec_inner("EC i31 P-256", &br_ec_prime_i31, &br_secp256r1);
518 test_speed_ec_inner("EC i31 P-384", &br_ec_prime_i31, &br_secp384r1);
519 test_speed_ec_inner("EC i31 P-521", &br_ec_prime_i31, &br_secp521r1);
520 }
521
522 static void
523 test_speed_ecdsa_inner(const char *name,
524 const br_ec_impl *impl, const br_ec_curve_def *cd,
525 br_ecdsa_sign sign, br_ecdsa_vrfy vrfy)
526 {
527 unsigned char bx[80], U[160], hv[32], sig[160];
528 uint32_t x[22], n[22];
529 size_t nlen, ulen, sig_len;
530 int i;
531 long num;
532 br_ec_private_key sk;
533 br_ec_public_key pk;
534
535 nlen = cd->order_len;
536 br_i31_decode(n, cd->order, nlen);
537 memset(bx, 'T', sizeof bx);
538 br_i31_decode_reduce(x, bx, sizeof bx, n);
539 br_i31_encode(bx, nlen, x);
540 ulen = cd->generator_len;
541 memcpy(U, cd->generator, ulen);
542 impl->mul(U, ulen, bx, nlen, cd->curve);
543 sk.curve = cd->curve;
544 sk.x = bx;
545 sk.xlen = nlen;
546 pk.curve = cd->curve;
547 pk.q = U;
548 pk.qlen = ulen;
549
550 memset(hv, 'H', sizeof hv);
551 sig_len = sign(impl, &br_sha256_vtable, hv, &sk, sig);
552 if (vrfy(impl, hv, sizeof hv, &pk, sig, sig_len) != 1) {
553 fprintf(stderr, "self-test sign/verify failed\n");
554 exit(EXIT_FAILURE);
555 }
556
557 for (i = 0; i < 10; i ++) {
558 hv[1] ++;
559 sign(impl, &br_sha256_vtable, hv, &sk, sig);
560 vrfy(impl, hv, sizeof hv, &pk, sig, sig_len);
561 }
562
563 num = 10;
564 for (;;) {
565 clock_t begin, end;
566 double tt;
567 long k;
568
569 begin = clock();
570 for (k = num; k > 0; k --) {
571 hv[1] ++;
572 sig_len = sign(impl, &br_sha256_vtable, hv, &sk, sig);
573 }
574 end = clock();
575 tt = (double)(end - begin) / CLOCKS_PER_SEC;
576 if (tt >= 2.0) {
577 printf("%-30s %8.2f sign/s\n", name,
578 (double)num / tt);
579 fflush(stdout);
580 break;
581 }
582 num <<= 1;
583 }
584
585 num = 10;
586 for (;;) {
587 clock_t begin, end;
588 double tt;
589 long k;
590
591 begin = clock();
592 for (k = num; k > 0; k --) {
593 vrfy(impl, hv, sizeof hv, &pk, sig, sig_len);
594 }
595 end = clock();
596 tt = (double)(end - begin) / CLOCKS_PER_SEC;
597 if (tt >= 2.0) {
598 printf("%-30s %8.2f verify/s\n", name,
599 (double)num / tt);
600 fflush(stdout);
601 break;
602 }
603 num <<= 1;
604 }
605 }
606
607 static void
608 test_speed_ecdsa_i31(void)
609 {
610 test_speed_ecdsa_inner("ECDSA i31 P-256",
611 &br_ec_prime_i31, &br_secp256r1,
612 &br_ecdsa_i31_sign_asn1,
613 &br_ecdsa_i31_vrfy_asn1);
614 test_speed_ecdsa_inner("ECDSA i31 P-384",
615 &br_ec_prime_i31, &br_secp384r1,
616 &br_ecdsa_i31_sign_asn1,
617 &br_ecdsa_i31_vrfy_asn1);
618 test_speed_ecdsa_inner("ECDSA i31 P-521",
619 &br_ec_prime_i31, &br_secp521r1,
620 &br_ecdsa_i31_sign_asn1,
621 &br_ecdsa_i31_vrfy_asn1);
622 }
623
624 #if 0
625 /* obsolete */
626 static void
627 test_speed_ec_prime_i31_inner(const char *name,
628 const unsigned char *bg, const br_ec_prime_i31_curve *cc)
629 {
630 unsigned char bx[80], point[160];
631 uint32_t x[BR_EC_I31_LEN];
632 br_ec_prime_i31_jacobian P;
633 uint32_t xbl;
634 size_t plen;
635 int i;
636 long num;
637
638 xbl = cc->p[0];
639 xbl -= (xbl >> 5);
640 plen = (xbl + 7) >> 3;
641 memset(bx, 'T', sizeof bx);
642 br_i31_decode_reduce(x, bx, sizeof bx, cc->p);
643 br_i31_encode(bx, plen, x);
644 br_ec_prime_i31_decode(&P, bg, 1 + (plen << 1), cc);
645 for (i = 0; i < 10; i ++) {
646 br_ec_prime_i31_mul(&P, bx, plen, cc);
647 br_ec_prime_i31_encode(point, &P, cc);
648 }
649 num = 10;
650 for (;;) {
651 clock_t begin, end;
652 double tt;
653 long k;
654
655 begin = clock();
656 for (k = num; k > 0; k --) {
657 br_ec_prime_i31_mul(&P, bx, plen, cc);
658 br_ec_prime_i31_encode(point, &P, cc);
659 }
660 end = clock();
661 tt = (double)(end - begin) / CLOCKS_PER_SEC;
662 if (tt >= 2.0) {
663 printf("%-30s %8.2f mul/s\n", name,
664 (double)num / tt);
665 fflush(stdout);
666 break;
667 }
668 num <<= 1;
669 }
670 }
671
672 static void
673 test_speed_ec_prime_i31(void)
674 {
675 test_speed_ec_prime_i31_inner("EC i31 P-256",
676 br_g_secp256r1, &br_ec_prime_i31_secp256r1);
677 test_speed_ec_prime_i31_inner("EC i31 P-384",
678 br_g_secp384r1, &br_ec_prime_i31_secp384r1);
679 test_speed_ec_prime_i31_inner("EC i31 P-521",
680 br_g_secp521r1, &br_ec_prime_i31_secp521r1);
681 }
682
683 static void
684 test_speed_ec_prime_i32_inner(const char *name,
685 const unsigned char *bg, const br_ec_prime_i32_curve *cc)
686 {
687 unsigned char bx[80], point[160];
688 uint32_t x[BR_EC_I32_LEN];
689 br_ec_prime_i32_jacobian P;
690 size_t plen;
691 int i;
692 long num;
693
694 plen = (cc->p[0] + 7) >> 3;
695 memset(bx, 'T', sizeof bx);
696 br_i32_decode_reduce(x, bx, sizeof bx, cc->p);
697 br_i32_encode(bx, plen, x);
698 br_ec_prime_i32_decode(&P, bg, 1 + (plen << 1), cc);
699 for (i = 0; i < 10; i ++) {
700 br_ec_prime_i32_mul(&P, bx, plen, cc);
701 br_ec_prime_i32_encode(point, &P, cc);
702 }
703 num = 10;
704 for (;;) {
705 clock_t begin, end;
706 double tt;
707 long k;
708
709 begin = clock();
710 for (k = num; k > 0; k --) {
711 br_ec_prime_i32_mul(&P, bx, plen, cc);
712 br_ec_prime_i32_encode(point, &P, cc);
713 }
714 end = clock();
715 tt = (double)(end - begin) / CLOCKS_PER_SEC;
716 if (tt >= 2.0) {
717 printf("%-30s %8.2f mul/s\n", name,
718 (double)num / tt);
719 fflush(stdout);
720 break;
721 }
722 num <<= 1;
723 }
724 }
725
726 static void
727 test_speed_ec_prime_i32(void)
728 {
729 test_speed_ec_prime_i32_inner("EC i32 P-256",
730 br_g_secp256r1, &br_ec_prime_i32_secp256r1);
731 test_speed_ec_prime_i32_inner("EC i32 P-384",
732 br_g_secp384r1, &br_ec_prime_i32_secp384r1);
733 test_speed_ec_prime_i32_inner("EC i32 P-521",
734 br_g_secp521r1, &br_ec_prime_i32_secp521r1);
735 }
736 #endif
737
738 static void
739 test_speed_i31(void)
740 {
741 static const unsigned char bp[] = {
742 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
743 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
744 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
745 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
746 };
747
748 unsigned char tmp[60 + sizeof bp];
749 uint32_t p[10], x[10], y[10], z[10], p0i;
750 int i;
751 long num;
752
753 br_i31_decode(p, bp, sizeof bp);
754 p0i = br_i31_ninv31(p[1]);
755 memset(tmp, 'T', sizeof tmp);
756 br_i31_decode_reduce(x, tmp, sizeof tmp, p);
757 memset(tmp, 'U', sizeof tmp);
758 br_i31_decode_reduce(y, tmp, sizeof tmp, p);
759
760 for (i = 0; i < 10; i ++) {
761 br_i31_to_monty(x, p);
762 }
763 num = 10;
764 for (;;) {
765 clock_t begin, end;
766 double tt;
767 long k;
768
769 begin = clock();
770 for (k = num; k > 0; k --) {
771 br_i31_to_monty(x, p);
772 }
773 end = clock();
774 tt = (double)(end - begin) / CLOCKS_PER_SEC;
775 if (tt >= 2.0) {
776 printf("%-30s %8.2f ops/s\n", "i31 to_monty",
777 (double)num / tt);
778 fflush(stdout);
779 break;
780 }
781 num <<= 1;
782 }
783
784 for (i = 0; i < 10; i ++) {
785 br_i31_from_monty(x, p, p0i);
786 }
787 num = 10;
788 for (;;) {
789 clock_t begin, end;
790 double tt;
791 long k;
792
793 begin = clock();
794 for (k = num; k > 0; k --) {
795 br_i31_from_monty(x, p, p0i);
796 }
797 end = clock();
798 tt = (double)(end - begin) / CLOCKS_PER_SEC;
799 if (tt >= 2.0) {
800 printf("%-30s %8.2f ops/s\n", "i31 from_monty",
801 (double)num / tt);
802 fflush(stdout);
803 break;
804 }
805 num <<= 1;
806 }
807
808 for (i = 0; i < 10; i ++) {
809 br_i31_montymul(z, x, y, p, p0i);
810 }
811 num = 10;
812 for (;;) {
813 clock_t begin, end;
814 double tt;
815 long k;
816
817 begin = clock();
818 for (k = num; k > 0; k --) {
819 br_i31_montymul(z, x, y, p, p0i);
820 }
821 end = clock();
822 tt = (double)(end - begin) / CLOCKS_PER_SEC;
823 if (tt >= 2.0) {
824 printf("%-30s %8.2f ops/s\n", "i31 montymul",
825 (double)num / tt);
826 fflush(stdout);
827 break;
828 }
829 num <<= 1;
830 }
831 }
832
833 #if 0
834
835 static unsigned char P2048[] = {
836 0xFD, 0xB6, 0xE0, 0x3E, 0x00, 0x49, 0x4C, 0xF0, 0x69, 0x3A, 0xDD, 0x7D,
837 0xF8, 0xA2, 0x41, 0xB0, 0x6C, 0x67, 0xC5, 0xBA, 0xB8, 0x46, 0x80, 0xF5,
838 0xBF, 0xAB, 0x98, 0xFC, 0x84, 0x73, 0xA5, 0x63, 0xC9, 0x52, 0x12, 0xDA,
839 0x4C, 0xC1, 0x5B, 0x9D, 0x8D, 0xDF, 0xCD, 0xFE, 0xC5, 0xAD, 0x5A, 0x6F,
840 0xDD, 0x02, 0xD9, 0xEC, 0x71, 0xEF, 0xEB, 0xB6, 0x95, 0xED, 0x94, 0x25,
841 0x0E, 0x63, 0xDD, 0x6A, 0x52, 0xC7, 0x93, 0xAF, 0x85, 0x9D, 0x2C, 0xBE,
842 0x5C, 0xBE, 0x35, 0xD8, 0xDD, 0x39, 0xEF, 0x1B, 0xB1, 0x49, 0x67, 0xB2,
843 0x33, 0xC9, 0x7C, 0xE1, 0x51, 0x79, 0x51, 0x59, 0xCA, 0x6E, 0x2A, 0xDF,
844 0x0D, 0x76, 0x1C, 0xE7, 0xA5, 0xC0, 0x1E, 0x6C, 0x56, 0x3A, 0x32, 0xE5,
845 0xB5, 0xC5, 0xD4, 0xDB, 0xFE, 0xFF, 0xF8, 0xF2, 0x96, 0xA9, 0xC9, 0x65,
846 0x59, 0x9E, 0x01, 0x79, 0x9D, 0x38, 0x68, 0x0F, 0xAD, 0x43, 0x3A, 0xD6,
847 0x84, 0x0A, 0xE2, 0xEF, 0x96, 0xC1, 0x6D, 0x89, 0x74, 0x19, 0x63, 0x82,
848 0x3B, 0xA0, 0x9C, 0xBA, 0x78, 0xDE, 0xDC, 0xC2, 0xE7, 0xD4, 0xFA, 0xD6,
849 0x19, 0x21, 0x29, 0xAE, 0x5E, 0xF4, 0x38, 0x81, 0xC6, 0x9E, 0x0E, 0x3C,
850 0xCD, 0xC0, 0xDC, 0x93, 0x5D, 0xFD, 0x9A, 0x5C, 0xAB, 0x54, 0x1F, 0xFF,
851 0x9C, 0x12, 0x1B, 0x4C, 0xDF, 0x2D, 0x9C, 0x85, 0xF9, 0x68, 0x15, 0x89,
852 0x42, 0x9B, 0x6C, 0x45, 0x89, 0x3A, 0xBC, 0xE9, 0x19, 0x91, 0xBE, 0x0C,
853 0xEF, 0x90, 0xCC, 0xF6, 0xD6, 0xF0, 0x3D, 0x5C, 0xF5, 0xE5, 0x0F, 0x2F,
854 0x02, 0x8A, 0x83, 0x4B, 0x93, 0x2F, 0x14, 0x12, 0x1F, 0x56, 0x9A, 0x12,
855 0x58, 0x88, 0xAE, 0x60, 0xB8, 0x5A, 0xE4, 0xA1, 0xBF, 0x4A, 0x81, 0x84,
856 0xAB, 0xBB, 0xE4, 0xD0, 0x1D, 0x41, 0xD9, 0x0A, 0xAB, 0x1E, 0x47, 0x5B,
857 0x31, 0xAC, 0x2B, 0x73
858 };
859
860 static unsigned char G2048[] = {
861 0x02
862 };
863
864 static void
865 test_speed_modpow(void)
866 {
867 uint32_t mx[65], mp[65], me[65], t1[65], t2[65], len;
868 unsigned char e[64];
869 int i;
870 long num;
871
872 len = br_int_decode(mp, sizeof mp / sizeof mp[0],
873 P2048, sizeof P2048);
874 if (len != 65) {
875 abort();
876 }
877 memset(e, 'P', sizeof e);
878 if (!br_int_decode(me, sizeof me / sizeof me[0], e, sizeof e)) {
879 abort();
880 }
881 if (!br_modint_decode(mx, mp, G2048, sizeof G2048)) {
882 abort();
883 }
884 for (i = 0; i < 10; i ++) {
885 br_modint_to_monty(mx, mp);
886 br_modint_montypow(mx, me, mp, t1, t2);
887 br_modint_from_monty(mx, mp);
888 }
889 num = 10;
890 for (;;) {
891 clock_t begin, end;
892 double tt;
893 long k;
894
895 begin = clock();
896 for (k = num; k > 0; k --) {
897 br_modint_to_monty(mx, mp);
898 br_modint_montypow(mx, me, mp, t1, t2);
899 br_modint_from_monty(mx, mp);
900 }
901 end = clock();
902 tt = (double)(end - begin) / CLOCKS_PER_SEC;
903 if (tt >= 2.0) {
904 printf("%-30s %8.2f exp/s\n", "pow[2048:256]",
905 (double)num / tt);
906 fflush(stdout);
907 return;
908 }
909 num <<= 1;
910 }
911 }
912
913 static void
914 test_speed_moddiv(void)
915 {
916 uint32_t mx[65], my[65], mp[65], t1[65], t2[65], t3[65], len;
917 unsigned char x[255], y[255];
918 int i;
919 long num;
920
921 len = br_int_decode(mp, sizeof mp / sizeof mp[0],
922 P2048, sizeof P2048);
923 if (len != 65) {
924 abort();
925 }
926 memset(x, 'T', sizeof x);
927 memset(y, 'P', sizeof y);
928 if (!br_modint_decode(mx, mp, x, sizeof x)) {
929 abort();
930 }
931 if (!br_modint_decode(my, mp, y, sizeof y)) {
932 abort();
933 }
934 for (i = 0; i < 10; i ++) {
935 br_modint_div(mx, my, mp, t1, t2, t3);
936 }
937 num = 10;
938 for (;;) {
939 clock_t begin, end;
940 double tt;
941 long k;
942
943 begin = clock();
944 for (k = num; k > 0; k --) {
945 br_modint_div(mx, my, mp, t1, t2, t3);
946 }
947 end = clock();
948 tt = (double)(end - begin) / CLOCKS_PER_SEC;
949 if (tt >= 2.0) {
950 printf("%-30s %8.2f div/s\n", "div[2048]",
951 (double)num / tt);
952 fflush(stdout);
953 return;
954 }
955 num <<= 1;
956 }
957 }
958 #endif
959
960 #define STU(x) { test_speed_ ## x, #x }
961
962 static const struct {
963 void (*fn)(void);
964 char *name;
965 } tfns[] = {
966 STU(md5),
967 STU(sha1),
968 STU(sha256),
969 STU(sha512),
970
971 STU(aes128_big_cbcenc),
972 STU(aes128_big_cbcdec),
973 STU(aes192_big_cbcenc),
974 STU(aes192_big_cbcdec),
975 STU(aes256_big_cbcenc),
976 STU(aes256_big_cbcdec),
977 STU(aes128_big_ctr),
978 STU(aes192_big_ctr),
979 STU(aes256_big_ctr),
980
981 STU(aes128_small_cbcenc),
982 STU(aes128_small_cbcdec),
983 STU(aes192_small_cbcenc),
984 STU(aes192_small_cbcdec),
985 STU(aes256_small_cbcenc),
986 STU(aes256_small_cbcdec),
987 STU(aes128_small_ctr),
988 STU(aes192_small_ctr),
989 STU(aes256_small_ctr),
990
991 STU(aes128_ct_cbcenc),
992 STU(aes128_ct_cbcdec),
993 STU(aes192_ct_cbcenc),
994 STU(aes192_ct_cbcdec),
995 STU(aes256_ct_cbcenc),
996 STU(aes256_ct_cbcdec),
997 STU(aes128_ct_ctr),
998 STU(aes192_ct_ctr),
999 STU(aes256_ct_ctr),
1000
1001 STU(aes128_ct64_cbcenc),
1002 STU(aes128_ct64_cbcdec),
1003 STU(aes192_ct64_cbcenc),
1004 STU(aes192_ct64_cbcdec),
1005 STU(aes256_ct64_cbcenc),
1006 STU(aes256_ct64_cbcdec),
1007 STU(aes128_ct64_ctr),
1008 STU(aes192_ct64_ctr),
1009 STU(aes256_ct64_ctr),
1010
1011 STU(des_tab_cbcenc),
1012 STU(des_tab_cbcdec),
1013 STU(3des_tab_cbcenc),
1014 STU(3des_tab_cbcdec),
1015
1016 STU(des_ct_cbcenc),
1017 STU(des_ct_cbcdec),
1018 STU(3des_ct_cbcenc),
1019 STU(3des_ct_cbcdec),
1020
1021 STU(ghash_ctmul),
1022 STU(ghash_ctmul32),
1023 STU(ghash_ctmul64),
1024
1025 STU(rsa_i31),
1026 STU(rsa_i32),
1027 STU(ec_prime_i31),
1028 STU(ecdsa_i31),
1029
1030 STU(i31)
1031 };
1032
1033 static int
1034 eq_name(const char *s1, const char *s2)
1035 {
1036 for (;;) {
1037 int c1, c2;
1038
1039 for (;;) {
1040 c1 = *s1 ++;
1041 if (c1 >= 'A' && c1 <= 'Z') {
1042 c1 += 'a' - 'A';
1043 } else {
1044 switch (c1) {
1045 case '-': case '_': case '.': case ' ':
1046 continue;
1047 }
1048 }
1049 break;
1050 }
1051 for (;;) {
1052 c2 = *s2 ++;
1053 if (c2 >= 'A' && c2 <= 'Z') {
1054 c2 += 'a' - 'A';
1055 } else {
1056 switch (c2) {
1057 case '-': case '_': case '.': case ' ':
1058 continue;
1059 }
1060 }
1061 break;
1062 }
1063 if (c1 != c2) {
1064 return 0;
1065 }
1066 if (c1 == 0) {
1067 return 1;
1068 }
1069 }
1070 }
1071
1072 int
1073 main(int argc, char *argv[])
1074 {
1075 size_t u;
1076
1077 if (argc <= 1) {
1078 printf("usage: testspeed all | name...\n");
1079 printf("individual test names:\n");
1080 for (u = 0; u < (sizeof tfns) / (sizeof tfns[0]); u ++) {
1081 printf(" %s\n", tfns[u].name);
1082 }
1083 } else {
1084 for (u = 0; u < (sizeof tfns) / (sizeof tfns[0]); u ++) {
1085 int i;
1086
1087 for (i = 1; i < argc; i ++) {
1088 if (eq_name(argv[i], tfns[u].name)
1089 || eq_name(argv[i], "all"))
1090 {
1091 tfns[u].fn();
1092 break;
1093 }
1094 }
1095 }
1096 }
1097 return 0;
1098 }