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