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