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