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