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