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