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