chiark / gitweb /
Mollify various warnings which occur in 64-bit builds.
[catacomb] / progs / rspit.c
1 /* -*-c-*-
2  *
3  * Spit out random numbers
4  *
5  * (c) 1999 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Catacomb.
11  *
12  * Catacomb is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * Catacomb is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with Catacomb; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <errno.h>
34 #include <math.h>
35 #include <signal.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <time.h>
40
41 #ifndef PORTABLE
42 #  include <unistd.h>
43 #endif
44
45 #include <mLib/darray.h>
46 #include <mLib/dstr.h>
47 #include <mLib/mdwopt.h>
48 #include <mLib/quis.h>
49 #include <mLib/report.h>
50 #include <mLib/sub.h>
51
52 #include "fipstest.h"
53 #include "grand.h"
54 #include "maurer.h"
55 #include "key.h"
56
57 #include "lcrand.h"
58 #include "fibrand.h"
59 #include "rand.h"
60 #include "noise.h"
61
62 #include "bbs.h"
63 #include "mprand.h"
64
65 #include "rc4.h"
66 #include "seal.h"
67
68 #include "des-ofb.h"
69 #include "des3-ofb.h"
70 #include "rc2-ofb.h"
71 #include "rc5-ofb.h"
72 #include "mars-ofb.h"
73 #include "skipjack-ofb.h"
74 #include "tea-ofb.h"
75 #include "xtea-ofb.h"
76 #include "blowfish-ofb.h"
77 #include "twofish-ofb.h"
78 #include "idea-ofb.h"
79 #include "cast128-ofb.h"
80 #include "cast256-ofb.h"
81 #include "noekeon-ofb.h"
82 #include "rijndael-ofb.h"
83 #include "rijndael192-ofb.h"
84 #include "rijndael256-ofb.h"
85 #include "safer-ofb.h"
86 #include "safersk-ofb.h"
87 #include "square-ofb.h"
88 #include "serpent-ofb.h"
89
90 #include "des-counter.h"
91 #include "des3-counter.h"
92 #include "rc2-counter.h"
93 #include "rc5-counter.h"
94 #include "mars-counter.h"
95 #include "skipjack-counter.h"
96 #include "tea-counter.h"
97 #include "xtea-counter.h"
98 #include "blowfish-counter.h"
99 #include "twofish-counter.h"
100 #include "idea-counter.h"
101 #include "cast128-counter.h"
102 #include "cast256-counter.h"
103 #include "noekeon-counter.h"
104 #include "rijndael-counter.h"
105 #include "rijndael192-counter.h"
106 #include "rijndael256-counter.h"
107 #include "safer-counter.h"
108 #include "safersk-counter.h"
109 #include "square-counter.h"
110 #include "serpent-counter.h"
111
112 #include "md2-mgf.h"
113 #include "md4-mgf.h"
114 #include "md5-mgf.h"
115 #include "sha-mgf.h"
116 #include "tiger-mgf.h"
117 #include "rmd128-mgf.h"
118 #include "rmd160-mgf.h"
119 #include "rmd256-mgf.h"
120 #include "rmd320-mgf.h"
121
122 #include "rmd160.h"
123
124 /*----- Data structures ---------------------------------------------------*/
125
126 typedef struct gen {
127   const char *name;
128   grand *(*seed)(unsigned /*i*/);
129   unsigned i;
130   const char *help;
131 } gen;
132
133 extern gen generators[];
134
135 #define CIPHERS                                                         \
136   E(DES, des)                                                           \
137   E(DES3, des3)                                                         \
138   E(RC2, rc2)                                                           \
139   E(RC5, rc5)                                                           \
140   E(MARS, mars)                                                         \
141   E(SKIPJACK, skipjack)                                                 \
142   E(TEA, tea)                                                           \
143   E(XTEA, xtea)                                                         \
144   E(BLOWFISH, blowfish)                                                 \
145   E(TWOFISH, twofish)                                                   \
146   E(IDEA, idea)                                                         \
147   E(CAST128, cast128)                                                   \
148   E(CAST256, cast256)                                                   \
149   E(SQUARE, square)                                                     \
150   E(SAFER, safer)                                                       \
151   E(SAFERSK, safersk)                                                   \
152   E(NOEKEON, noekeon)                                                   \
153   E(RIJNDAEL, rijndael)                                                 \
154   E(RIJNDAEL192, rijndael192)                                           \
155   E(RIJNDAEL256, rijndael256)                                           \
156   E(SERPENT, serpent)
157
158 #define HASHES                                                          \
159   E(MD2, md2)                                                           \
160   E(MD4, md4)                                                           \
161   E(MD5, md5)                                                           \
162   E(SHA, sha)                                                           \
163   E(TIGER, tiger)                                                       \
164   E(RMD128, rmd128)                                                     \
165   E(RMD160, rmd160)                                                     \
166   E(RMD256, rmd256)                                                     \
167   E(RMD320, rmd320)
168
169 #define E(PRE, pre) CIPHER_##PRE,
170 enum { CIPHERS CIPHER__bogus };
171 #undef E
172
173 #define E(PRE, pre) HASH_##PRE,
174 enum { HASHES HASH__bogus };
175 #undef E
176
177 static struct {
178   const octet *keysz;
179   size_t blksz;
180   grand *(*ofb)(const void */*k*/, size_t /*sz*/);
181   grand *(*counter)(const void */*k*/, size_t /*sz*/);
182 } ciphertab[] = {
183 #define E(PRE, pre)                                                     \
184   { pre##_keysz, PRE##_BLKSZ, pre##_ofbrand, pre##_counterrand },
185   CIPHERS
186 #undef E
187 };
188
189 static struct {
190   const gchash *h;
191   const octet *keysz;
192   grand *(*mgf)(const void */*k*/, size_t /*sz*/);
193 } hashtab[] = {
194 #define E(PRE, pre)                                                     \
195   { &pre, pre##_mgfkeysz, pre##_mgfrand },
196   HASHES
197 #undef E
198 };
199
200 /*----- Miscellaneous static data -----------------------------------------*/
201
202 static FILE *outfp;
203 static size_t outsz = 0;
204 static unsigned maurer_lo = 5, maurer_hi = 8;
205
206 static int argc;
207 static char **argv;
208
209 static unsigned flags = 0;
210
211 #define f_progress 1u
212 #define f_file 2u
213 #define f_fips 4u
214 #define f_maurer 8u
215 #define f_timer 16u
216 #define f_discard 32u
217
218 /*----- Help options ------------------------------------------------------*/
219
220 static void usage(FILE *fp)
221 {
222   pquis(fp, "Usage: $ generator [options]\n");
223 }
224
225 static void version(FILE *fp)
226 {
227   pquis(fp, "$, Catacomb version " VERSION "\n");
228 }
229
230 static void help(FILE *fp)
231 {
232   version(fp);
233   fputc('\n', fp);
234   usage(fp);
235   pquis(fp, "\n\
236 Emits a stream of random bytes suitable for, well, all sorts of things.\n\
237 The primary objective is to be able to generate streams of input for\n\
238 statistical tests, such as Diehard.\n\
239 \n\
240 Options are specific to the particular generator, although there's a\n\
241 common core set:\n\
242 \n\
243 -h, --help              Display this help message.\n\
244 -v, --version           Display the program's version number.\n\
245 -u, --usage             Display a useless usage message.\n\
246 \n\
247 -l, --list              Show a list of the supported generators, with\n\
248                         their options.\n\
249 -f, --fipstest          Run the FIPS 140-1 randomness test.\n\
250 -m, --maurer[=LO-HI]    Run Maurer's universal statistical test.\n\
251 -o, --output FILE       Write output to FILE, not stdout.\n\
252 -z, --size SIZE         Emit SIZE bytes, not an unlimited number.\n\
253 -p, --progress          Show a little progress meter (on stderr).\n\
254 -T, --timer             Keep track of the CPU time used by the generator.\n\
255 -d, --discard           Discard the generated output.\n\
256 \n\
257 (A SIZE may be followed by `g' for gigabytes, `m' for megabytes, or\n\
258 `k' for kilobytes.  If unqualified, an amount in bytes is assumed.)\n\
259 ");
260 }
261
262 /*----- Main options parser -----------------------------------------------*/
263
264 static struct option opts[] = {
265
266   /* --- Standard GNU help options --- */
267
268   { "help",     0,              0,      'h' },
269   { "version",  0,              0,      'v' },
270   { "usage",    0,              0,      'u' },
271
272   /* --- Other useful things --- */
273
274   { "list",     0,              0,      'l' },
275   { "fipstest", 0,              0,      'f' },
276   { "maurer",   OPTF_ARGOPT,    0,      'm' },
277   { "output",   OPTF_ARGREQ,    0,      'o' },
278   { "size",     OPTF_ARGREQ,    0,      'z' },
279   { "progress", 0,              0,      'p' },
280   { "timer",    0,              0,      'T' },
281   { "discard",  0,              0,      'd' },
282
283   /* --- End of main table --- */
284
285   { 0,          0,              0,      0 }
286 };
287
288 static const char *sopts = "hvu lfm::o:z:pTd";
289
290 #ifndef OPTION_V
291    DA_DECL(option_v, struct option);
292 #  define OPTION_V
293 #endif
294
295 static option_v optv = DA_INIT;
296 static dstr optd = DSTR_INIT;
297
298 /* --- @addopts@ --- *
299  *
300  * Arguments:   @const char *s@ = pointer to short options
301  *              @struct option *l@ = pointer to long options
302  *
303  * Returns:     ---
304  *
305  * Use:         Adds a collection of options to the table.
306  */
307
308 static void addopts(const char *s, struct option *l)
309 {
310   dstr_puts(&optd, s);
311   if (DA_LEN(&optv))
312     DA_SHRINK(&optv, 1);
313   while (l->name)
314     DA_PUSH(&optv, *l++);
315   DA_PUSH(&optv, *l);
316 }
317
318 /* --- @opt@ --- *
319  *
320  * Arguments:   ---
321  *
322  * Returns:     Next option from argument array.
323  *
324  * Use:         Fetches options, handling the standard ones.
325  */
326
327 static int opt(void)
328 {
329   for (;;) {
330     int i = mdwopt(argc, argv, optd.buf, DA(&optv), 0, 0, 0);
331     switch (i) {
332       case 'h':
333         help(stdout);
334         exit(0);
335       case 'v':
336         version(stdout);
337         exit(0);
338       case 'u':
339         usage(stdout);
340         exit(0);
341       case 'l': {
342         gen *g;
343         puts("Generators supported:");
344         for (g = generators; g->name; g++)
345           printf("  %s %s\n", g->name, g->help);
346         exit(0);
347       } break;
348       case 'f':
349         flags |= f_fips;
350         break;
351       case 'm':
352         flags |= f_maurer;
353         if (optarg) {
354           char *p;
355           unsigned long lo, hi;
356           lo = strtoul(optarg, &p, 0);
357           if (*p == '-' || *p == ',')
358             hi = strtoul(p + 1, &p, 0);
359           else
360             hi = lo;
361           if (*p != 0 || hi < lo || lo == 0)
362             die(EXIT_FAILURE, "bad bit range `%s'", optarg);
363           maurer_lo = lo;
364           maurer_hi = hi;
365         }
366         break;
367       case 'o':
368         if (flags & f_file)
369           die(EXIT_FAILURE, "already set an output file");
370         if (strcmp(optarg, "-") == 0)
371           outfp = stdout;
372         else {
373           outfp = fopen(optarg, "w");
374           if (!outfp) {
375             die(EXIT_FAILURE, "couldn't open output file `%s': %s",
376                 optarg, strerror(errno));
377           }
378         }
379         flags |= f_file;
380         break;
381       case 'z': {
382         char *p;
383         outsz = strtoul(optarg, &p, 0);
384         if (!outsz)
385           die(EXIT_FAILURE, "bad number `%s'", optarg);
386         switch (*p) {
387           case 'G': case 'g': outsz *= 1024;
388           case 'M': case 'm': outsz *= 1024;
389           case 'K': case 'k': outsz *= 1024;
390           case 0:
391             break;
392           default:
393             die(EXIT_FAILURE, "bad suffix `%s'", p);
394             break;
395         }
396         if (*p && p[1] != 0)
397           die(EXIT_FAILURE, "bad suffix `%s'", p);
398       } break;
399       case 'p':
400         flags |= f_progress;
401         break;
402       case 'T':
403         flags |= f_timer;
404         break;
405       case 'd':
406         flags |= f_discard;
407         break;
408       default:
409         return (i);
410     }
411   }
412 }
413
414 /*----- Manglers for seed strings -----------------------------------------*/
415
416 /* --- @unhex@ --- *
417  *
418  * Arguments:   @const char *p@ = pointer to input string
419  *              @char **end@ = where the end goes
420  *              @dstr *d@ = output buffer
421  *
422  * Returns:     ---
423  *
424  * Use:         Transforms a hex string into a chunk of binary data.
425  */
426
427 static void unhex(const char *p, char **end, dstr *d)
428 {
429   while (p[0] && p[1]) {
430     int x = p[0], y = p[1];
431     if ('0' <= x && x <= '9') x -= '0';
432     else if ('A' <= x && x <= 'F') x -= 'A' - 10;
433     else if ('a' <= x && x <= 'f') x -= 'a' - 10;
434     else x = 0;
435     if ('0' <= y && y <= '9') y -= '0';
436     else if ('A' <= y && y <= 'F') y -= 'A' - 10;
437     else if ('a' <= y && y <= 'f') y -= 'a' - 10;
438     else y = 0;
439     DPUTC(d, (x << 4) + y);
440     p += 2;
441   }
442   *end = (char *)p;
443 }
444
445 /* --- Generate a key --- */
446
447 static void textkey(dstr *d, const char *p, const octet *ksz)
448 {
449   size_t sz = strlen(p);
450
451   if (!sz)
452     die(EXIT_FAILURE, "zero-length key string");
453   if (keysz(sz, ksz) != sz)
454     DPUTM(d, p, sz);
455   else {
456     rmd160_mgfctx g;
457     rmd160_mgfinit(&g, p, sz);
458     sz = keysz(0, ksz);
459     dstr_ensure(d, sz);
460     rmd160_mgfencrypt(&g, 0, d->buf, sz);
461     d->len += sz;
462   }
463   assert(((void)"I can't seem to choose a good key size",
464           keysz(d->len, ksz) == d->len));
465 }
466
467 static void hexkey(dstr *d, const char *p, const octet *ksz)
468 {
469   char *q;
470   unhex(optarg, &q, d);
471   if (*q)
472     die(EXIT_FAILURE, "bad hex key `%s'", p);
473   if (keysz(d->len, ksz) != d->len)
474     die(EXIT_FAILURE, "bad key length");
475 }
476
477 static void randkey(dstr *d, const octet *ksz)
478 {
479   size_t sz = keysz(0, ksz);
480   dstr_ensure(d, sz);
481   rand_get(RAND_GLOBAL, d->buf, sz);
482   d->len += sz;
483 }
484
485 /*----- Generators --------------------------------------------------------*/
486
487 /* --- Blum-Blum-Shub strong generator --- */
488
489 static grand *gen_bbs(unsigned i)
490 {
491   /* --- Default modulus --- *
492    *
493    * The factors of this number are
494    *
495    *  @p = 1229936431484295969649886203367009966370895964206162032259292413@
496    *      @7754313537966036459299022912838407755462506416274551744201653277@
497    *      @313130311731673973886822067@
498    *
499    *  @q = 9798171783943489959487301695884963889684294764514008432498259742@
500    *      @5374320073594018817245784145742769603334292182227671519041431067@
501    *      @61344781426317516045890159@
502    *
503    * Both %$p$% and %$q$% are prime; %$(p - 1)/2$% and %$(q - 1)/2$% have no
504    * common factors.  They were found using this program, with random
505    * starting points.
506    *
507    * I hope that, by publishing these factors, I'll dissuade people from
508    * actually using this modulus in an attempt to attain real security.  The
509    * program is quite quick at finding Blum numbers, so there's no excuse for
510    * not generating your own.
511    */
512
513   const char *mt =
514     "12051128439013574251357214209433471144307319411973256935382082"
515     "84356405274180923922403660880355098909699130818163691602989614"
516     "90135716255689660470370755013177656905237112577648090277537209"
517     "93607817155427455344810369808478266925293635284364998010510985"
518     "0503830397166360721262431179505917248447259735253684659338653";
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, "incompatible 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_hmackeysz);
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_hmackeysz);
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 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
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
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 typedef struct genmaurer_ctx {
1108   size_t n;
1109   maurer_ctx *m;
1110 } genmaurer_ctx;
1111
1112 static int genmaurer(const void *buf, size_t sz, void *p)
1113 {
1114   genmaurer_ctx *g = p;
1115   size_t i;
1116
1117   for (i = 0; i < g->n; i++)
1118     maurer_test(&g->m[i], buf, sz);
1119   return (0);
1120 }
1121
1122 static int generate(grand *r, size_t outsz,
1123                     int (*func)(const void *buf, size_t sz, void *p),
1124                     void *p)
1125 {
1126   static char kmg[] = { ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 0 };
1127
1128   unsigned percent = 0;
1129   size_t kb = 0;
1130   time_t last;
1131   static char baton[] = "-\\|/";
1132   char *bp;
1133   int rc;
1134   clock_t clk = 0;
1135
1136   /* --- Spit out random data --- */
1137
1138   last = time(0);
1139   bp = baton;
1140   if (flags & f_progress) {
1141     char *errbuf = xmalloc(BUFSIZ);
1142     setvbuf(stderr, errbuf, _IOLBF, BUFSIZ);
1143     if (outsz)
1144       fprintf(stderr, "[%*s]   0%%    0\r[/\b", 50, "");
1145     else
1146       fputs("[ ]    0\r[/\b", stderr);
1147     fflush(stderr);
1148   }
1149
1150 #ifdef SIGPIPE
1151   signal(SIGPIPE, SIG_IGN);
1152 #endif
1153
1154   do {
1155     octet buf[BUFSIZ];
1156     size_t sz = sizeof(buf);
1157     clock_t c_start, c_stop;
1158
1159     /* --- Emit a bufferful (or less) of data --- */
1160
1161     if (outsz) {
1162       if (sz > outsz - kb)
1163         sz = outsz - kb;
1164     }
1165     c_start = clock();
1166     r->ops->fill(r, buf, sz);
1167     c_stop = clock();
1168     clk += c_stop - c_start;
1169     if (func && (rc = func(buf, sz, p)) != 0)
1170       return (rc);
1171     kb += sz;
1172
1173     /* --- Update the display --- */
1174
1175     if (flags & f_progress) {
1176       time_t t = time(0);
1177       unsigned up = 0;
1178
1179       if (percent > 100)
1180         up = 1;
1181
1182       if (!outsz) {
1183         if (difftime(t, last) > 1.0) {
1184           up = 1;
1185         }
1186         if (up)
1187           fputs(" ] ", stderr);
1188       } else {
1189         unsigned pc = kb * 100.0 / outsz;
1190         if (pc > percent || percent > 100 || difftime(t, last) > 1.0) {
1191           if (percent > 100)
1192             percent = 0;
1193           percent &= ~1;
1194           for (; percent < (pc & ~1); percent += 2)
1195             putc('.', stderr);
1196           percent = pc;
1197           for (; pc < 100; pc += 2)
1198             putc(' ', stderr);
1199           fprintf(stderr, "] %3i%% ", percent);
1200           up = 1;
1201         }
1202       }
1203
1204       if (up) {
1205         size_t q = kb;
1206         char *kk = kmg;
1207         while (q > 8192 && kk[1]) {
1208           q >>= 10;
1209           kk++;
1210         }
1211         fprintf(stderr, "%4i%c\r[", (int)q, *kk);
1212         if (outsz) {
1213           unsigned pc;
1214           for (pc = 0; pc < (percent & ~1); pc += 2)
1215             putc('.', stderr);
1216         }
1217         last = t;
1218       }
1219
1220       if (percent > 100)
1221         percent = 0;
1222
1223       if (percent < 100) {
1224         putc(*bp++, stderr);
1225         putc('\b', stderr);
1226         if (!*bp)
1227           bp = baton;
1228       }
1229       fflush(stderr);
1230     }
1231
1232     /* --- Terminate the loop --- */
1233
1234   } while (!outsz || kb < outsz);
1235
1236   if (flags & f_progress)
1237     fputc('\n', stderr);
1238   if (flags & f_timer) {
1239     fprintf(stderr, "generated %lu bytes ", (unsigned long)outsz);
1240     if (!clk)
1241       fputs("too quickly to measure\n", stderr);
1242     else {
1243       char *kk;
1244       double sec = (double)clk/CLOCKS_PER_SEC;
1245       double bps = (outsz << 3)/sec;
1246       for (kk = kmg; bps > 1024 && kk[1]; kk++, bps /= 1024)
1247         ;
1248       fprintf(stderr, "in %g secs (%g %cb/s)\n", sec, bps, *kk);
1249     }
1250   }
1251   return (0);
1252 }
1253
1254 /*----- Main code ---------------------------------------------------------*/
1255
1256 int main(int ac, char *av[])
1257 {
1258   gen *g = &optsg;
1259   grand *r;
1260
1261   /* --- Initialize mLib --- */
1262
1263   ego(av[0]);
1264   sub_init();
1265
1266   /* --- Set up the main Catacomb generator --- */
1267
1268   rand_noisesrc(RAND_GLOBAL, &noise_source);
1269   rand_seed(RAND_GLOBAL, 160);
1270
1271   /* --- Initialize the options table --- */
1272
1273   addopts(sopts, opts);
1274   argc = ac;
1275   argv = av;
1276   outfp = stdout;
1277
1278   /* --- Read the generator out of the first argument --- */
1279
1280   if (argc > 1 && *argv[1] != '-') {
1281     const char *arg = av[1];
1282     size_t sz = strlen(arg);
1283     gen *gg;
1284
1285     g = 0;
1286     for (gg = generators; gg->name; gg++) {
1287       if (strncmp(arg, gg->name, sz) == 0) {
1288         if (gg->name[sz] == 0) {
1289           g = gg;
1290           break;
1291         } else if (g)
1292           die(EXIT_FAILURE, "ambiguous generator name `%s'", arg);
1293         else
1294           g = gg;
1295       }
1296     }
1297     if (!g)
1298       die(EXIT_FAILURE, "unknown generator name `%s'", arg);
1299     argc--;
1300     argv++;
1301   }
1302
1303   /* --- Get a generic random number generator --- */
1304
1305   r = g->seed(g->i);
1306   if (!r || optind != ac - 1) {
1307     usage(stderr);
1308     exit(EXIT_FAILURE);
1309   }
1310
1311   /* --- Do the FIPS test --- */
1312
1313   if (flags & f_fips) {
1314     octet buf[FIPSTEST_BUFSZ];
1315     unsigned rc;
1316     octet *p = buf;
1317
1318     generate(r, sizeof(buf), genbuf, &p);
1319     rc = fipstest(buf);
1320     if (rc & FIPSTEST_MONOBIT)
1321       moan("failed monobit test");
1322     if (rc & FIPSTEST_POKER)
1323       moan("failed poker test");
1324     if (rc & FIPSTEST_RUNS)
1325       moan("failed runs test");
1326     if (rc & FIPSTEST_LONGRUNS)
1327       moan("failed long runs test");
1328     if (!rc && (flags & f_progress))
1329       fputs("test passed\n", stderr);
1330     return (rc ? EXIT_FAILURE : 0);
1331   }
1332
1333   /* --- Do Maurer's test --- */
1334
1335   if (flags & f_maurer) {
1336     size_t bufsz;
1337     unsigned i;
1338     unsigned rc = 0;
1339     genmaurer_ctx g;
1340
1341     static struct { double x; const char *sig; } sigtab[] = {
1342       { 3.2905, "1e-3" },
1343       { 3.0902, "2e-3" },
1344       { 2.8070, "5e-3" },
1345       { 2.5758, "1e-2" },
1346       { 0     , 0      }
1347     };
1348
1349     g.n = maurer_hi - maurer_lo + 1;
1350     g.m = xmalloc(g.n * sizeof(maurer_ctx));
1351     for (i = 0; i < g.n; i++)
1352       maurer_init(&g.m[i], i + maurer_lo);
1353     bufsz = (100 * maurer_hi) << maurer_hi;
1354
1355     generate(r, bufsz, genmaurer, &g);
1356
1357     for (i = maurer_lo; i <= maurer_hi; i++) {
1358       double z = maurer_done(&g.m[i - maurer_lo]);
1359       double zz = fabs(z);
1360       unsigned j;
1361
1362       for (j = 0; sigtab[j].sig; j++) {
1363         if (zz > sigtab[j].x) {
1364           rc = EXIT_FAILURE;
1365           moan("failed, bits = %u, sig = %s, Z_u = %g",
1366                i, sigtab[j].sig, z);
1367           break;
1368         }
1369       }
1370       if (flags & f_progress)
1371         fprintf(stderr, "bits = %u, Z_u = %g\n", i, z);
1372     }
1373
1374     xfree(g.m);
1375     return (rc);
1376   }
1377
1378   /* --- Discard --- */
1379
1380   if (flags & f_discard) {
1381     generate(r, outsz, 0, 0);
1382     return (0);
1383   }
1384
1385   /* --- Write to a file --- */
1386
1387 #ifndef PORTABLE
1388   if (!(flags & f_file) && isatty(STDOUT_FILENO))
1389     die(EXIT_FAILURE, "writing output to a terminal is a bad idea");
1390 #endif
1391
1392   generate(r, outsz, genfile, outfp);
1393
1394   /* --- Done --- */
1395
1396   r->ops->destroy(r);
1397   return (0);
1398 }
1399
1400 /*----- That's all, folks -------------------------------------------------*/