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