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