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