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