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