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