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