progs/rspit.c: Higher resolution timing.
[catacomb] / progs / rspit.c
1 /* -*-c-*-
2 *
3 * Spit out random numbers
4 *
5 * (c) 1999 Straylight/Edgeware
6 */
7
8 /*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <errno.h>
34 #include <math.h>
35 #include <signal.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <time.h>
40
41 #ifndef PORTABLE
42 # include <unistd.h>
43 # include <sys/time.h>
44 #endif
45
46 #include <mLib/darray.h>
47 #include <mLib/dstr.h>
48 #include <mLib/mdwopt.h>
49 #include <mLib/quis.h>
50 #include <mLib/report.h>
51 #include <mLib/sub.h>
52
53 #include "mp.h"
54 #include "mpint.h"
55 #include "mplimits.h"
56 #include "mptext.h"
57
58 #include "fipstest.h"
59 #include "grand.h"
60 #include "maurer.h"
61 #include "key.h"
62
63 #include "lcrand.h"
64 #include "fibrand.h"
65 #include "rand.h"
66 #include "noise.h"
67
68 #include "bbs.h"
69 #include "mprand.h"
70
71 #include "rc4.h"
72 #include "seal.h"
73
74 #include "des-ofb.h"
75 #include "des3-ofb.h"
76 #include "rc2-ofb.h"
77 #include "rc5-ofb.h"
78 #include "mars-ofb.h"
79 #include "skipjack-ofb.h"
80 #include "tea-ofb.h"
81 #include "xtea-ofb.h"
82 #include "blowfish-ofb.h"
83 #include "twofish-ofb.h"
84 #include "idea-ofb.h"
85 #include "cast128-ofb.h"
86 #include "cast256-ofb.h"
87 #include "noekeon-ofb.h"
88 #include "rijndael-ofb.h"
89 #include "rijndael192-ofb.h"
90 #include "rijndael256-ofb.h"
91 #include "safer-ofb.h"
92 #include "safersk-ofb.h"
93 #include "square-ofb.h"
94 #include "serpent-ofb.h"
95
96 #include "des-counter.h"
97 #include "des3-counter.h"
98 #include "rc2-counter.h"
99 #include "rc5-counter.h"
100 #include "mars-counter.h"
101 #include "skipjack-counter.h"
102 #include "tea-counter.h"
103 #include "xtea-counter.h"
104 #include "blowfish-counter.h"
105 #include "twofish-counter.h"
106 #include "idea-counter.h"
107 #include "cast128-counter.h"
108 #include "cast256-counter.h"
109 #include "noekeon-counter.h"
110 #include "rijndael-counter.h"
111 #include "rijndael192-counter.h"
112 #include "rijndael256-counter.h"
113 #include "safer-counter.h"
114 #include "safersk-counter.h"
115 #include "square-counter.h"
116 #include "serpent-counter.h"
117
118 #include "md2-mgf.h"
119 #include "md4-mgf.h"
120 #include "md5-mgf.h"
121 #include "sha-mgf.h"
122 #include "tiger-mgf.h"
123 #include "rmd128-mgf.h"
124 #include "rmd160-mgf.h"
125 #include "rmd256-mgf.h"
126 #include "rmd320-mgf.h"
127
128 #include "rmd160.h"
129
130 /*----- Data structures ---------------------------------------------------*/
131
132 typedef struct gen {
133 const char *name;
134 grand *(*seed)(unsigned /*i*/);
135 unsigned i;
136 const char *help;
137 } gen;
138
139 extern gen generators[];
140
141 #define CIPHERS \
142 E(DES, des) \
143 E(DES3, des3) \
144 E(RC2, rc2) \
145 E(RC5, rc5) \
146 E(MARS, mars) \
147 E(SKIPJACK, skipjack) \
148 E(TEA, tea) \
149 E(XTEA, xtea) \
150 E(BLOWFISH, blowfish) \
151 E(TWOFISH, twofish) \
152 E(IDEA, idea) \
153 E(CAST128, cast128) \
154 E(CAST256, cast256) \
155 E(SQUARE, square) \
156 E(SAFER, safer) \
157 E(SAFERSK, safersk) \
158 E(NOEKEON, noekeon) \
159 E(RIJNDAEL, rijndael) \
160 E(RIJNDAEL192, rijndael192) \
161 E(RIJNDAEL256, rijndael256) \
162 E(SERPENT, serpent)
163
164 #define HASHES \
165 E(MD2, md2) \
166 E(MD4, md4) \
167 E(MD5, md5) \
168 E(SHA, sha) \
169 E(TIGER, tiger) \
170 E(RMD128, rmd128) \
171 E(RMD160, rmd160) \
172 E(RMD256, rmd256) \
173 E(RMD320, rmd320)
174
175 #define E(PRE, pre) CIPHER_##PRE,
176 enum { CIPHERS CIPHER__bogus };
177 #undef E
178
179 #define E(PRE, pre) HASH_##PRE,
180 enum { HASHES HASH__bogus };
181 #undef E
182
183 static const struct {
184 const octet *keysz;
185 size_t blksz;
186 grand *(*ofb)(const void */*k*/, size_t /*sz*/);
187 grand *(*counter)(const void */*k*/, size_t /*sz*/);
188 } ciphertab[] = {
189 #define E(PRE, pre) \
190 { pre##_keysz, PRE##_BLKSZ, pre##_ofbrand, pre##_counterrand },
191 CIPHERS
192 #undef E
193 };
194
195 static const struct {
196 const gchash *h;
197 const octet *keysz;
198 grand *(*mgf)(const void */*k*/, size_t /*sz*/);
199 } hashtab[] = {
200 #define E(PRE, pre) \
201 { &pre, pre##_mgfkeysz, pre##_mgfrand },
202 HASHES
203 #undef E
204 };
205
206 /*----- Miscellaneous static data -----------------------------------------*/
207
208 static FILE *outfp;
209 static mp *outsz = 0;
210 static unsigned maurer_lo = 5, maurer_hi = 8;
211
212 static int argc;
213 static char **argv;
214
215 static unsigned flags = 0;
216
217 #define f_progress 1u
218 #define f_file 2u
219 #define f_fips 4u
220 #define f_maurer 8u
221 #define f_timer 16u
222 #define f_discard 32u
223
224 /*----- Help options ------------------------------------------------------*/
225
226 static void usage(FILE *fp)
227 {
228 pquis(fp, "Usage: $ generator [options]\n");
229 }
230
231 static void version(FILE *fp)
232 {
233 pquis(fp, "$, Catacomb version " VERSION "\n");
234 }
235
236 static void help(FILE *fp)
237 {
238 version(fp);
239 fputc('\n', fp);
240 usage(fp);
241 pquis(fp, "\n\
242 Emits a stream of random bytes suitable for, well, all sorts of things.\n\
243 The primary objective is to be able to generate streams of input for\n\
244 statistical tests, such as Diehard.\n\
245 \n\
246 Options are specific to the particular generator, although there's a\n\
247 common core set:\n\
248 \n\
249 -h, --help Display this help message.\n\
250 -v, --version Display the program's version number.\n\
251 -u, --usage Display a useless usage message.\n\
252 \n\
253 -l, --list Show a list of the supported generators, with\n\
254 their options.\n\
255 -f, --fipstest Run the FIPS 140-1 randomness test.\n\
256 -m, --maurer[=LO-HI] Run Maurer's universal statistical test.\n\
257 -o, --output FILE Write output to FILE, not stdout.\n\
258 -z, --size SIZE Emit SIZE bytes, not an unlimited number.\n\
259 -p, --progress Show a little progress meter (on stderr).\n\
260 -T, --timer Keep track of the CPU time used by the generator.\n\
261 -d, --discard Discard the generated output.\n\
262 \n\
263 (A SIZE may be followed by `g' for gigabytes, `m' for megabytes, or\n\
264 `k' for kilobytes. If unqualified, an amount in bytes is assumed.)\n\
265 ");
266 }
267
268 /*----- Main options parser -----------------------------------------------*/
269
270 static struct option opts[] = {
271
272 /* --- Standard GNU help options --- */
273
274 { "help", 0, 0, 'h' },
275 { "version", 0, 0, 'v' },
276 { "usage", 0, 0, 'u' },
277
278 /* --- Other useful things --- */
279
280 { "list", 0, 0, 'l' },
281 { "fipstest", 0, 0, 'f' },
282 { "maurer", OPTF_ARGOPT, 0, 'm' },
283 { "output", OPTF_ARGREQ, 0, 'o' },
284 { "size", OPTF_ARGREQ, 0, 'z' },
285 { "progress", 0, 0, 'p' },
286 { "timer", 0, 0, 'T' },
287 { "discard", 0, 0, 'd' },
288
289 /* --- End of main table --- */
290
291 { 0, 0, 0, 0 }
292 };
293
294 static const char *sopts = "hvu lfm::o:z:pTd";
295
296 #ifndef OPTION_V
297 DA_DECL(option_v, struct option);
298 # define OPTION_V
299 #endif
300
301 static option_v optv = DA_INIT;
302 static dstr optd = DSTR_INIT;
303
304 /* --- @addopts@ --- *
305 *
306 * Arguments: @const char *s@ = pointer to short options
307 * @struct option *l@ = pointer to long options
308 *
309 * Returns: ---
310 *
311 * Use: Adds a collection of options to the table.
312 */
313
314 static void addopts(const char *s, struct option *l)
315 {
316 dstr_puts(&optd, s);
317 if (DA_LEN(&optv))
318 DA_SHRINK(&optv, 1);
319 while (l->name)
320 DA_PUSH(&optv, *l++);
321 DA_PUSH(&optv, *l);
322 }
323
324 /* --- @opt@ --- *
325 *
326 * Arguments: ---
327 *
328 * Returns: Next option from argument array.
329 *
330 * Use: Fetches options, handling the standard ones.
331 */
332
333 static int opt(void)
334 {
335 for (;;) {
336 int i = mdwopt(argc, argv, optd.buf, DA(&optv), 0, 0, 0);
337 switch (i) {
338 case 'h':
339 help(stdout);
340 exit(0);
341 case 'v':
342 version(stdout);
343 exit(0);
344 case 'u':
345 usage(stdout);
346 exit(0);
347 case 'l': {
348 gen *g;
349 puts("Generators supported:");
350 for (g = generators; g->name; g++)
351 printf(" %s %s\n", g->name, g->help);
352 exit(0);
353 } break;
354 case 'f':
355 flags |= f_fips;
356 break;
357 case 'm':
358 flags |= f_maurer;
359 if (optarg) {
360 char *p;
361 unsigned long lo, hi;
362 lo = strtoul(optarg, &p, 0);
363 if (*p == '-' || *p == ',')
364 hi = strtoul(p + 1, &p, 0);
365 else
366 hi = lo;
367 if (*p != 0 || hi < lo || lo == 0)
368 die(EXIT_FAILURE, "bad bit range `%s'", optarg);
369 maurer_lo = lo;
370 maurer_hi = hi;
371 }
372 break;
373 case 'o':
374 if (flags & f_file)
375 die(EXIT_FAILURE, "already set an output file");
376 if (strcmp(optarg, "-") == 0)
377 outfp = stdout;
378 else {
379 outfp = fopen(optarg, "w");
380 if (!outfp) {
381 die(EXIT_FAILURE, "couldn't open output file `%s': %s",
382 optarg, strerror(errno));
383 }
384 }
385 flags |= f_file;
386 break;
387 case 'z': {
388 char *p;
389 outsz = mp_readstring(outsz, optarg, &p, 0);
390 if (!outsz || MP_NEGP(outsz))
391 die(EXIT_FAILURE, "bad number `%s'", optarg);
392 switch (*p) {
393 case 'G': case 'g': outsz = mp_lsl(outsz, outsz, 10);
394 case 'M': case 'm': outsz = mp_lsl(outsz, outsz, 10);
395 case 'K': case 'k': outsz = mp_lsl(outsz, outsz, 10);
396 case 0:
397 break;
398 default:
399 die(EXIT_FAILURE, "bad suffix `%s'", p);
400 break;
401 }
402 if (*p && p[1] != 0)
403 die(EXIT_FAILURE, "bad suffix `%s'", p);
404 } break;
405 case 'p':
406 flags |= f_progress;
407 break;
408 case 'T':
409 flags |= f_timer;
410 break;
411 case 'd':
412 flags |= f_discard;
413 break;
414 default:
415 return (i);
416 }
417 }
418 }
419
420 /*----- Manglers for seed strings -----------------------------------------*/
421
422 /* --- @unhex@ --- *
423 *
424 * Arguments: @const char *p@ = pointer to input string
425 * @char **end@ = where the end goes
426 * @dstr *d@ = output buffer
427 *
428 * Returns: ---
429 *
430 * Use: Transforms a hex string into a chunk of binary data.
431 */
432
433 static void unhex(const char *p, char **end, dstr *d)
434 {
435 while (p[0] && p[1]) {
436 int x = p[0], y = p[1];
437 if ('0' <= x && x <= '9') x -= '0';
438 else if ('A' <= x && x <= 'F') x -= 'A' - 10;
439 else if ('a' <= x && x <= 'f') x -= 'a' - 10;
440 else x = 0;
441 if ('0' <= y && y <= '9') y -= '0';
442 else if ('A' <= y && y <= 'F') y -= 'A' - 10;
443 else if ('a' <= y && y <= 'f') y -= 'a' - 10;
444 else y = 0;
445 DPUTC(d, (x << 4) + y);
446 p += 2;
447 }
448 *end = (char *)p;
449 }
450
451 /* --- Generate a key --- */
452
453 static void textkey(dstr *d, const char *p, const octet *ksz)
454 {
455 size_t sz = strlen(p);
456
457 if (!sz)
458 die(EXIT_FAILURE, "zero-length key string");
459 if (keysz(sz, ksz) != sz)
460 DPUTM(d, p, sz);
461 else {
462 rmd160_mgfctx g;
463 rmd160_mgfinit(&g, p, sz);
464 sz = keysz(0, ksz);
465 dstr_ensure(d, sz);
466 rmd160_mgfencrypt(&g, 0, d->buf, sz);
467 d->len += sz;
468 }
469 assert(((void)"I can't seem to choose a good key size",
470 keysz(d->len, ksz) == d->len));
471 }
472
473 static void hexkey(dstr *d, const char *p, const octet *ksz)
474 {
475 char *q;
476 unhex(optarg, &q, d);
477 if (*q)
478 die(EXIT_FAILURE, "bad hex key `%s'", p);
479 if (keysz(d->len, ksz) != d->len)
480 die(EXIT_FAILURE, "bad key length");
481 }
482
483 static void randkey(dstr *d, const octet *ksz)
484 {
485 size_t sz = keysz(0, ksz);
486 dstr_ensure(d, sz);
487 rand_get(RAND_GLOBAL, d->buf, sz);
488 d->len += sz;
489 }
490
491 /*----- Generators --------------------------------------------------------*/
492
493 /* --- Blum-Blum-Shub strong generator --- */
494
495 static grand *gen_bbs(unsigned i)
496 {
497 /* --- Default modulus --- *
498 *
499 * The factors of this number are
500 *
501 * @p = 1229936431484295969649886203367009966370895964206162032259292413@
502 * @7754313537966036459299022912838407755462506416274551744201653277@
503 * @313130311731673973886822067@
504 *
505 * @q = 9798171783943489959487301695884963889684294764514008432498259742@
506 * @5374320073594018817245784145742769603334292182227671519041431067@
507 * @61344781426317516045890159@
508 *
509 * Both %$p$% and %$q$% are prime; %$(p - 1)/2$% and %$(q - 1)/2$% have no
510 * common factors. They were found using this program, with random
511 * starting points.
512 *
513 * I hope that, by publishing these factors, I'll dissuade people from
514 * actually using this modulus in an attempt to attain real security. The
515 * program is quite quick at finding Blum numbers, so there's no excuse for
516 * not generating your own.
517 */
518
519 const char *mt =
520 "12051128439013574251357214209433471144307319411973256935382082"
521 "84356405274180923922403660880355098909699130818163691602989614"
522 "90135716255689660470370755013177656905237112577648090277537209"
523 "93607817155427455344810369808478266925293635284364998010510985"
524 "0503830397166360721262431179505917248447259735253684659338653";
525
526 /* --- Other things --- */
527
528 grand *r;
529 const char *xt = 0;
530 unsigned bits = 1024;
531 mp *m, *x;
532 unsigned show = 0;
533 const char *kfile = 0, *id = 0, *ktype = 0;
534
535 /* --- Parse options --- */
536
537 static struct option opts[] = {
538 { "modulus", OPTF_ARGREQ, 0, 'M' },
539 { "generate", 0, 0, 'g' },
540 { "seed", OPTF_ARGREQ, 0, 's' },
541 { "bits", OPTF_ARGREQ, 0, 'b' },
542 { "show", 0, 0, 'S' },
543 { "keyring", OPTF_ARGREQ, 0, 'k' },
544 { "id", OPTF_ARGREQ, 0, 'i' },
545 { "type", OPTF_ARGREQ, 0, 't' },
546 { 0, 0, 0, 0 }
547 };
548
549 addopts("M:gs:b:Sk:i:t:", opts);
550
551 for (;;) {
552 int o = opt();
553 if (o < 0)
554 break;
555 switch (o) {
556 case 'M':
557 mt = optarg;
558 break;
559 case 'g':
560 mt = 0;
561 break;
562 case 's':
563 xt = optarg;
564 break;
565 case 'b':
566 bits = strtoul(optarg, 0, 0);
567 if (bits == 0)
568 die(EXIT_FAILURE, "bad number of bits `%s'", optarg);
569 break;
570 case 'S':
571 show = 1;
572 break;
573 case 'k':
574 kfile = optarg;
575 mt = 0;
576 break;
577 case 'i':
578 id = optarg;
579 mt = 0;
580 break;
581 case 't':
582 ktype = optarg;
583 mt = 0;
584 break;
585 default:
586 return (0);
587 }
588 }
589
590 /* --- Generate a modulus if one is requested --- */
591
592 if (mt) {
593 char *p;
594 m = mp_readstring(MP_NEW, mt, &p, 0);
595 if (!m || *p || (m->v[0] & 3) != 1)
596 die(EXIT_FAILURE, "bad modulus `%s'", mt);
597 /* Unfortunately I don't know how to test for a Blum integer */
598 } else if (kfile || id || ktype) {
599 key_file kf;
600 key *kk;
601 key_data *kd;
602
603 /* --- Open the key file --- */
604
605 if (!kfile)
606 kfile = "keyring";
607 if (key_open(&kf, kfile, KOPEN_READ, key_moan, 0)) {
608 die(EXIT_FAILURE, "error opening key file `%s': %s",
609 kfile, strerror(errno));
610 }
611
612 /* --- Find the key --- */
613
614 if (id) {
615 if ((kk = key_bytag(&kf, id)) == 0)
616 die(EXIT_FAILURE, "key `%s' not found", id);
617 } else {
618 if (!ktype)
619 ktype = "bbs";
620 if ((kk = key_bytype(&kf, ktype)) == 0)
621 die(EXIT_FAILURE, "no suitable key with type `%s' found", ktype);
622 }
623
624 /* --- Read the key data --- */
625
626 if ((kk->k->e & KF_ENCMASK) != KENC_STRUCT)
627 die(EXIT_FAILURE, "key is not structured");
628 if ((kd = key_structfind(kk->k, "n")) == 0)
629 die(EXIT_FAILURE, "key has no subkey `n'");
630 if ((kd->e & KF_ENCMASK) != KENC_MP)
631 die(EXIT_FAILURE, "incompatible subkey encoding");
632 m = MP_COPY(kd->u.m);
633 key_close(&kf);
634 } else {
635 bbs_priv bp;
636
637 if (bbs_gen(&bp, bits, &rand_global, 0,
638 (flags & f_progress) ? pgen_ev : 0, 0))
639 die(EXIT_FAILURE, "modulus generation failed");
640 m = bp.n;
641
642 if (show) {
643 fputs("p = ", stderr);
644 mp_writefile(bp.p, stderr, 10);
645 fputs("\nq = ", stderr);
646 mp_writefile(bp.q, stderr, 10);
647 fputs("\nn = ", stderr);
648 mp_writefile(bp.n, stderr, 10);
649 fputc('\n', stderr);
650 }
651
652 mp_drop(bp.p);
653 mp_drop(bp.q);
654 }
655
656 /* --- Set up a seed --- */
657
658 if (!xt)
659 x = mprand(MP_NEW, mp_bits(m) - 1, &rand_global, 1);
660 else {
661 char *p;
662 x = mp_readstring(MP_NEW, xt, &p, 0);
663 if (*p)
664 die(EXIT_FAILURE, "bad modulus `%s'", xt);
665 }
666
667 /* --- Right --- */
668
669 r = bbs_rand(m, x);
670
671 mp_drop(m);
672 mp_drop(x);
673 return (r);
674 }
675
676 /* --- Catacomb's random number generator --- */
677
678 static grand *gen_rand(unsigned i)
679 {
680 grand *r = rand_create();
681 dstr d = DSTR_INIT;
682
683 static struct option opts[] = {
684 { "key", OPTF_ARGREQ, 0, 'k' },
685 { "text", OPTF_ARGREQ, 0, 't' },
686 { "hex", OPTF_ARGREQ, 0, 'H' },
687 { 0, 0, 0, 0 }
688 };
689
690 addopts("k:t:H:n", opts);
691
692 r->ops->misc(r, RAND_NOISESRC, &noise_source);
693 r->ops->misc(r, RAND_SEED, 160);
694
695 for (;;) {
696 int o = opt();
697 if (o < 0)
698 break;
699 switch (o) {
700 case 'k':
701 DRESET(&d);
702 textkey(&d, optarg, rmd160_hmackeysz);
703 r->ops->misc(r, RAND_KEY, d.buf, d.len);
704 break;
705 case 't':
706 r->ops->misc(r, GRAND_SEEDBLOCK, optarg, strlen(optarg));
707 break;
708 case 'H':
709 DRESET(&d);
710 hexkey(&d, optarg, rmd160_hmackeysz);
711 r->ops->misc(r, GRAND_SEEDBLOCK, d.buf, d.len);
712 break;
713 }
714 }
715
716 dstr_destroy(&d);
717 return (r);
718 }
719
720 /* --- RC4 output --- */
721
722 static grand *gen_rc4(unsigned i)
723 {
724 grand *r;
725 dstr d = DSTR_INIT;
726
727 static struct option opts[] = {
728 { "key", OPTF_ARGREQ, 0, 'k' },
729 { "hex", OPTF_ARGREQ, 0, 'H' },
730 { 0, 0, 0, 0 }
731 };
732
733 addopts("k:H:", opts);
734
735 for (;;) {
736 int o = opt();
737 if (o < 0)
738 break;
739 switch (o) {
740 case 'k':
741 DRESET(&d);
742 textkey(&d, optarg, rc4_keysz);
743 break;
744 case 'H':
745 DRESET(&d);
746 hexkey(&d, optarg, rc4_keysz);
747 break;
748 default:
749 return (0);
750 }
751 }
752
753 if (!d.len)
754 randkey(&d, rc4_keysz);
755 r = rc4_rand(d.buf, d.len);
756 dstr_destroy(&d);
757 return (r);
758 }
759
760 /* --- SEAL output --- */
761
762 static grand *gen_seal(unsigned i)
763 {
764 grand *r;
765 dstr d = DSTR_INIT;
766 uint32 n = 0;
767
768 static struct option opts[] = {
769 { "key", OPTF_ARGREQ, 0, 'k' },
770 { "hex", OPTF_ARGREQ, 0, 'H' },
771 { "sequence", OPTF_ARGREQ, 0, 'n' },
772 { 0, 0, 0, 0 }
773 };
774
775 addopts("k:H:n:", opts);
776
777 for (;;) {
778 int o = opt();
779 if (o < 0)
780 break;
781 switch (o) {
782 case 'k':
783 DRESET(&d);
784 textkey(&d, optarg, seal_keysz);
785 break;
786 case 'H':
787 DRESET(&d);
788 hexkey(&d, optarg, seal_keysz);
789 break;
790 case 'n': {
791 char *p;
792 n = strtoul(optarg, &p, 0);
793 if (*p)
794 die(EXIT_FAILURE, "bad number `%s'", optarg);
795 } break;
796 default:
797 return (0);
798 }
799 }
800
801 if (!d.len)
802 randkey(&d, seal_keysz);
803 r = seal_rand(d.buf, d.len, n);
804 dstr_destroy(&d);
805 return (r);
806 }
807
808 /* --- Output feedback generators --- */
809
810 static grand *gen_ofb(unsigned i)
811 {
812 grand *r;
813 dstr d = DSTR_INIT;
814 dstr iv = DSTR_INIT;
815
816 static struct option opts[] = {
817 { "key", OPTF_ARGREQ, 0, 'k' },
818 { "hex", OPTF_ARGREQ, 0, 'H' },
819 { "iv", OPTF_ARGREQ, 0, 'i' },
820 { 0, 0, 0, 0 }
821 };
822
823 addopts("k:H:i:", opts);
824
825 for (;;) {
826 int o = opt();
827 if (o < 0)
828 break;
829 switch (o) {
830 case 'k':
831 DRESET(&d);
832 textkey(&d, optarg, ciphertab[i].keysz);
833 break;
834 case 'H':
835 DRESET(&d);
836 hexkey(&d, optarg, ciphertab[i].keysz);
837 break;
838 case 'i': {
839 char *p;
840 DRESET(&iv);
841 unhex(optarg, &p, &iv);
842 if (*p)
843 die(EXIT_FAILURE, "bad hex IV `%s'", optarg);
844 if (iv.len != ciphertab[i].blksz) {
845 die(EXIT_FAILURE, "bad IV length %lu (must be %lu)",
846 (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz);
847 }
848 } break;
849 default:
850 return (0);
851 }
852 }
853
854 if (!d.len)
855 randkey(&d, ciphertab[i].keysz);
856 r = ciphertab[i].ofb(d.buf, d.len);
857 if (iv.len)
858 r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf);
859
860 dstr_destroy(&d);
861 dstr_destroy(&iv);
862 return (r);
863 }
864
865 /* --- Counter generators --- */
866
867 static grand *gen_counter(unsigned i)
868 {
869 grand *r;
870 dstr d = DSTR_INIT;
871 dstr iv = DSTR_INIT;
872
873 static struct option opts[] = {
874 { "key", OPTF_ARGREQ, 0, 'k' },
875 { "hex", OPTF_ARGREQ, 0, 'H' },
876 { "iv", OPTF_ARGREQ, 0, 'i' },
877 { 0, 0, 0, 0 }
878 };
879
880 addopts("k:H:i:", opts);
881
882 for (;;) {
883 int o = opt();
884 if (o < 0)
885 break;
886 switch (o) {
887 case 'k':
888 DRESET(&d);
889 textkey(&d, optarg, ciphertab[i].keysz);
890 break;
891 case 'H':
892 DRESET(&d);
893 hexkey(&d, optarg, ciphertab[i].keysz);
894 break;
895 case 'i': {
896 char *p;
897 DRESET(&iv);
898 unhex(optarg, &p, &iv);
899 if (*p)
900 die(EXIT_FAILURE, "bad hex IV `%s'", optarg);
901 if (iv.len != ciphertab[i].blksz) {
902 die(EXIT_FAILURE, "bad IV length %lu (must be %lu)",
903 (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz);
904 }
905 } break;
906 default:
907 return (0);
908 }
909 }
910
911 if (!d.len)
912 randkey(&d, ciphertab[i].keysz);
913 r = ciphertab[i].counter(d.buf, d.len);
914 if (iv.len)
915 r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf);
916
917 dstr_destroy(&d);
918 dstr_destroy(&iv);
919 return (r);
920 }
921
922 /* --- Mask generators --- */
923
924 static grand *gen_mgf(unsigned i)
925 {
926 grand *r;
927 dstr d = DSTR_INIT;
928 uint32 c = 0;
929
930 static struct option opts[] = {
931 { "key", OPTF_ARGREQ, 0, 'k' },
932 { "hex", OPTF_ARGREQ, 0, 'H' },
933 { "index", OPTF_ARGREQ, 0, 'i' },
934 { 0, 0, 0, 0 }
935 };
936
937 addopts("k:H:i:", opts);
938
939 for (;;) {
940 int o = opt();
941 if (o < 0)
942 break;
943 switch (o) {
944 case 'k':
945 DRESET(&d);
946 textkey(&d, optarg, hashtab[i].keysz);
947 break;
948 case 'H':
949 DRESET(&d);
950 hexkey(&d, optarg, hashtab[i].keysz);
951 break;
952 case 'i': {
953 char *p;
954 c = strtoul(optarg, &p, 0);
955 if (*p)
956 die(EXIT_FAILURE, "bad index `%s'", optarg);
957 } break;
958 default:
959 return (0);
960 }
961 }
962
963 if (!d.len)
964 randkey(&d, hashtab[i].keysz);
965
966 r = hashtab[i].mgf(d.buf, d.len);
967 if (c)
968 r->ops->misc(r, GRAND_SEEDUINT32, c);
969
970 dstr_destroy(&d);
971 return (r);
972 }
973
974 /* --- Fibonacci generator --- */
975
976 static grand *gen_fib(unsigned i)
977 {
978 grand *r;
979 uint32 s = 0;
980 char *p;
981 unsigned set = 0;
982
983 static struct option opts[] = {
984 { "seed", OPTF_ARGREQ, 0, 's' },
985 { 0, 0, 0, 0 }
986 };
987
988 addopts("s:", opts);
989
990 for (;;) {
991 int o = opt();
992 if (o < 0)
993 break;
994 switch (o) {
995 case 's':
996 s = strtoul(optarg, &p, 0);
997 if (*p)
998 die(EXIT_FAILURE, "bad integer `%s'", optarg);
999 set = 1;
1000 break;
1001 default:
1002 return (0);
1003 }
1004 }
1005 r = fibrand_create(s);
1006 if (!set)
1007 r->ops->misc(r, GRAND_SEEDRAND, &rand_global);
1008 return (r);
1009 }
1010
1011 /* --- LC generator --- */
1012
1013 static grand *gen_lc(unsigned i)
1014 {
1015 uint32 s = 0;
1016 char *p;
1017 unsigned set = 0;
1018
1019 static struct option opts[] = {
1020 { "seed", OPTF_ARGREQ, 0, 's' },
1021 { 0, 0, 0, 0 }
1022 };
1023
1024 addopts("s:", opts);
1025
1026 for (;;) {
1027 int o = opt();
1028 if (o < 0)
1029 break;
1030 switch (o) {
1031 case 's':
1032 s = strtoul(optarg, &p, 0);
1033 if (*p)
1034 die(EXIT_FAILURE, "bad integer `%s'", optarg);
1035 set = 1;
1036 break;
1037 default:
1038 return (0);
1039 }
1040 }
1041 if (!set) {
1042 do
1043 s = rand_global.ops->range(&rand_global, LCRAND_P);
1044 while (s == LCRAND_FIXEDPT);
1045 }
1046 return (lcrand_create(s));
1047 }
1048
1049 /* --- Basic options parser -- can't generate output --- */
1050
1051 static grand *gen_opts(unsigned i)
1052 {
1053 while (opt() >= 0)
1054 ;
1055 return (0);
1056 }
1057
1058 /*----- Generators table --------------------------------------------------*/
1059
1060 gen generators[] = {
1061 { "fibonacci", gen_fib, 0,
1062 "[-s SEED]" },
1063 { "lc", gen_lc, 0,
1064 "[-s SEED]" },
1065 #define E(PRE, pre) \
1066 { #pre "-ofb", gen_ofb, CIPHER_##PRE, \
1067 "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" },
1068 CIPHERS
1069 #undef E
1070 #define E(PRE, pre) \
1071 { #pre "-counter", gen_counter, CIPHER_##PRE, \
1072 "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" },
1073 CIPHERS
1074 #undef E
1075 #define E(PRE, pre) \
1076 { #pre "-mgf", gen_mgf, HASH_##PRE, \
1077 "[-k KEY-PHRASE] [-H HEX-KEY] [-i INDEX]" },
1078 HASHES
1079 #undef E
1080 { "rc4", gen_rc4, 0,
1081 "[-k KEY-PHRASE] [-H HEX-KEY]" },
1082 { "seal", gen_seal, 0,
1083 "[-k KEY-PHRASE] [-H HEX-KEY] [-n SEQ]" },
1084 { "rand", gen_rand, 0,
1085 "[-n] [-k KEY-PHRASE] [-t TEXT-BLOCK] [-H HEX-BLOCK]" },
1086 { "bbs", gen_bbs, 0,
1087 "[-gS] [-s SEED] [-M MODULUS] [-b BITS] [-k KEYRING] [-i TAG] [-t TYPE]"
1088 },
1089 { 0, 0, 0, 0 },
1090 };
1091
1092 static gen optsg = { "options", gen_opts, 0,
1093 "This message shouldn't be printed." };
1094
1095 /*----- Random number generation ------------------------------------------*/
1096
1097 static int genfile(const void *buf, size_t sz, void *p)
1098 {
1099 FILE *fp = p;
1100 if (fwrite(buf, 1, sz, fp) != sz)
1101 die(EXIT_FAILURE, "error writing to file: %s", strerror(errno));
1102 return (0);
1103 }
1104
1105 static int genbuf(const void *buf, size_t sz, void *p)
1106 {
1107 octet **pp = p;
1108 memcpy(*pp, buf, sz);
1109 *pp += sz;
1110 return (0);
1111 }
1112
1113 typedef struct genmaurer_ctx {
1114 size_t n;
1115 maurer_ctx *m;
1116 } genmaurer_ctx;
1117
1118 static int genmaurer(const void *buf, size_t sz, void *p)
1119 {
1120 genmaurer_ctx *g = p;
1121 size_t i;
1122
1123 for (i = 0; i < g->n; i++)
1124 maurer_test(&g->m[i], buf, sz);
1125 return (0);
1126 }
1127
1128 static double doubletime(void)
1129 {
1130 #ifdef PORTABLE
1131 static time_t start = (time_t)-1;
1132 time_t now = time(0);
1133
1134 if (start == (time_t)-1) start = now;
1135 return difftime(now, start);
1136 #else
1137 struct timeval tv;
1138
1139 gettimeofday(&tv, 0);
1140 return (tv.tv_sec + tv.tv_usec/1000000.0);
1141 #endif
1142 }
1143
1144 static int generate(grand *r, mp *outsz,
1145 int (*func)(const void *buf, size_t sz, void *p),
1146 void *p)
1147 {
1148 static char kmg[] = { ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 0 };
1149
1150 unsigned percent = 0;
1151 mp *kb = MP_ZERO, *t = MP_NEW;
1152 dstr d = DSTR_INIT;
1153 double now, last;
1154 static char baton[] = "-\\|/";
1155 char *bp;
1156 int rc;
1157 clock_t clk = 0;
1158
1159 /* --- Spit out random data --- */
1160
1161 last = doubletime();
1162 bp = baton;
1163 if (flags & f_progress) {
1164 char *errbuf = xmalloc(BUFSIZ);
1165 setvbuf(stderr, errbuf, _IOLBF, BUFSIZ);
1166 if (outsz)
1167 fprintf(stderr, "[%*s] 0%% 0\r[/\b", 50, "");
1168 else
1169 fputs("[ ] 0\r[/\b", stderr);
1170 fflush(stderr);
1171 }
1172
1173 #ifdef SIGPIPE
1174 signal(SIGPIPE, SIG_IGN);
1175 #endif
1176
1177 while (!outsz || MP_CMP(kb, <, outsz)) {
1178 octet buf[BUFSIZ];
1179 size_t sz = sizeof(buf), left;
1180 clock_t c_start, c_stop;
1181
1182 /* --- Emit a bufferful (or less) of data --- */
1183
1184 if (outsz) {
1185 t = mp_sub(t, outsz, kb);
1186 assert(!MP_NEGP(t));
1187 if (MP_CMP(t, <=, MP_SIZET_MAX)) {
1188 left = mp_tosizet(t);
1189 if (sz > left) sz = left;
1190 }
1191 }
1192 c_start = clock();
1193 r->ops->fill(r, buf, sz);
1194 c_stop = clock();
1195 clk += c_stop - c_start;
1196 if (func && (rc = func(buf, sz, p)) != 0)
1197 return (rc);
1198 t = mp_fromsizet(t, sz);
1199 kb = mp_add(kb, kb, t);
1200
1201 /* --- Update the display --- */
1202
1203 if (flags & f_progress) {
1204 unsigned up = 0;
1205
1206 now = doubletime();
1207
1208 if (percent > 100)
1209 up = 1;
1210
1211 if (!outsz) {
1212 if (now - last > 1.0) {
1213 up = 1;
1214 }
1215 if (up)
1216 fputs(" ] ", stderr);
1217 } else {
1218 unsigned pc;
1219 t = mp_fromulong(t, 100);
1220 t = mp_mul(t, t, kb);
1221 mp_div(&t, 0, t, outsz);
1222 assert(!MP_NEGP(t) && MP_CMP(t, <, MP_UINT_MAX));
1223 pc = mp_touint(t);
1224 if (pc > percent || percent > 100 || now - last > 1.0) {
1225 if (percent > 100)
1226 percent = 0;
1227 percent &= ~1;
1228 for (; percent < (pc & ~1); percent += 2)
1229 putc('.', stderr);
1230 percent = pc;
1231 for (; pc < 100; pc += 2)
1232 putc(' ', stderr);
1233 fprintf(stderr, "] %3i%% ", percent);
1234 up = 1;
1235 }
1236 }
1237
1238 if (up) {
1239 char *kk = kmg;
1240 t = mp_add(t, kb, MP_ZERO);
1241 while (mp_bits(t) >= 14) {
1242 t = mp_lsr(t, t, 10);
1243 kk++;
1244 }
1245 DRESET(&d);
1246 mp_writedstr(t, &d, 10);
1247 fprintf(stderr, "%4s%c\r[", d.buf, *kk);
1248 if (outsz) {
1249 unsigned pc;
1250 for (pc = 0; pc < (percent & ~1); pc += 2)
1251 putc('.', stderr);
1252 }
1253 last = now;
1254 }
1255
1256 if (percent > 100)
1257 percent = 0;
1258
1259 if (percent < 100) {
1260 putc(*bp++, stderr);
1261 putc('\b', stderr);
1262 if (!*bp)
1263 bp = baton;
1264 }
1265 fflush(stderr);
1266 }
1267 }
1268
1269 if (flags & f_progress)
1270 fputc('\n', stderr);
1271 if (flags & f_timer) {
1272 DRESET(&d);
1273 dstr_puts(&d, "generated ");
1274 mp_writedstr(kb, &d, 10);
1275 dstr_puts(&d, " bytes ");
1276 if (!clk)
1277 dstr_puts(&d, "too quickly to measure\n");
1278 else {
1279 char *kk;
1280 double out;
1281 double sec = (double)clk/CLOCKS_PER_SEC;
1282 unsigned long sh;
1283 double bps;
1284
1285 MP_SHRINK(kb);
1286 switch (MP_LEN(kb)) {
1287 case 0: out = 0; break;
1288 case 1: out = kb->v[0]; break;
1289 default:
1290 sh = mp_bits(kb) - MPW_BITS;
1291 t = mp_lsr(t, kb, sh);
1292 out = ldexp(t->v[0], sh);
1293 break;
1294 }
1295 bps = (8*out)/sec;
1296 for (kk = kmg; bps > 1024 && kk[1]; kk++, bps /= 1024)
1297 ;
1298 dstr_putf(&d, "in %g secs (%g %cb/s)\n", sec, bps, *kk);
1299 fwrite(d.buf, 1, d.len, stderr);
1300 }
1301 }
1302
1303 mp_drop(t);
1304 DDESTROY(&d);
1305 return (0);
1306 }
1307
1308 /*----- Main code ---------------------------------------------------------*/
1309
1310 int main(int ac, char *av[])
1311 {
1312 gen *g = &optsg;
1313 grand *r;
1314
1315 /* --- Initialize mLib --- */
1316
1317 ego(av[0]);
1318 sub_init();
1319
1320 /* --- Set up the main Catacomb generator --- */
1321
1322 rand_noisesrc(RAND_GLOBAL, &noise_source);
1323 rand_seed(RAND_GLOBAL, 160);
1324
1325 /* --- Initialize the options table --- */
1326
1327 addopts(sopts, opts);
1328 argc = ac;
1329 argv = av;
1330 outfp = stdout;
1331
1332 /* --- Read the generator out of the first argument --- */
1333
1334 if (argc > 1 && *argv[1] != '-') {
1335 const char *arg = av[1];
1336 size_t sz = strlen(arg);
1337 gen *gg;
1338
1339 g = 0;
1340 for (gg = generators; gg->name; gg++) {
1341 if (strncmp(arg, gg->name, sz) == 0) {
1342 if (gg->name[sz] == 0) {
1343 g = gg;
1344 break;
1345 } else if (g)
1346 die(EXIT_FAILURE, "ambiguous generator name `%s'", arg);
1347 else
1348 g = gg;
1349 }
1350 }
1351 if (!g)
1352 die(EXIT_FAILURE, "unknown generator name `%s'", arg);
1353 argc--;
1354 argv++;
1355 }
1356
1357 /* --- Get a generic random number generator --- */
1358
1359 r = g->seed(g->i);
1360 if (!r || optind != ac - 1) {
1361 usage(stderr);
1362 exit(EXIT_FAILURE);
1363 }
1364
1365 /* --- Do the FIPS test --- */
1366
1367 if (flags & f_fips) {
1368 octet buf[FIPSTEST_BUFSZ];
1369 unsigned rc;
1370 mp *t;
1371 octet *p = buf;
1372
1373 t = mp_fromsizet(MP_NEW, sizeof(buf));
1374 generate(r, t, genbuf, &p);
1375 mp_drop(t);
1376 rc = fipstest(buf);
1377 if (rc & FIPSTEST_MONOBIT)
1378 moan("failed monobit test");
1379 if (rc & FIPSTEST_POKER)
1380 moan("failed poker test");
1381 if (rc & FIPSTEST_RUNS)
1382 moan("failed runs test");
1383 if (rc & FIPSTEST_LONGRUNS)
1384 moan("failed long runs test");
1385 if (!rc && (flags & f_progress))
1386 fputs("test passed\n", stderr);
1387 return (rc ? EXIT_FAILURE : 0);
1388 }
1389
1390 /* --- Do Maurer's test --- */
1391
1392 if (flags & f_maurer) {
1393 size_t bufsz;
1394 unsigned i;
1395 unsigned rc = 0;
1396 mp *t;
1397 genmaurer_ctx g;
1398
1399 static struct { double x; const char *sig; } sigtab[] = {
1400 { 3.2905, "1e-3" },
1401 { 3.0902, "2e-3" },
1402 { 2.8070, "5e-3" },
1403 { 2.5758, "1e-2" },
1404 { 0 , 0 }
1405 };
1406
1407 g.n = maurer_hi - maurer_lo + 1;
1408 g.m = xmalloc(g.n * sizeof(maurer_ctx));
1409 for (i = 0; i < g.n; i++)
1410 maurer_init(&g.m[i], i + maurer_lo);
1411 bufsz = (100 * maurer_hi) << maurer_hi;
1412
1413 t = mp_fromsizet(MP_NEW, bufsz);
1414 generate(r, t, genmaurer, &g);
1415 mp_drop(t);
1416
1417 for (i = maurer_lo; i <= maurer_hi; i++) {
1418 double z = maurer_done(&g.m[i - maurer_lo]);
1419 double zz = fabs(z);
1420 unsigned j;
1421
1422 for (j = 0; sigtab[j].sig; j++) {
1423 if (zz > sigtab[j].x) {
1424 rc = EXIT_FAILURE;
1425 moan("failed, bits = %u, sig = %s, Z_u = %g",
1426 i, sigtab[j].sig, z);
1427 break;
1428 }
1429 }
1430 if (flags & f_progress)
1431 fprintf(stderr, "bits = %u, Z_u = %g\n", i, z);
1432 }
1433
1434 xfree(g.m);
1435 return (rc);
1436 }
1437
1438 /* --- Discard --- */
1439
1440 if (flags & f_discard) {
1441 generate(r, outsz, 0, 0);
1442 return (0);
1443 }
1444
1445 /* --- Write to a file --- */
1446
1447 #ifndef PORTABLE
1448 if (!(flags & f_file) && isatty(STDOUT_FILENO))
1449 die(EXIT_FAILURE, "writing output to a terminal is a bad idea");
1450 #endif
1451
1452 generate(r, outsz, genfile, outfp);
1453
1454 /* --- Done --- */
1455
1456 r->ops->destroy(r);
1457 return (0);
1458 }
1459
1460 /*----- That's all, folks -------------------------------------------------*/