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