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