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