3 * $Id: rspit.c,v 1.8 2000/07/29 22:05:47 mdw Exp $
5 * Spit out random numbers
7 * (c) 1999 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
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.
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.
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,
30 /*----- Revision history --------------------------------------------------*
33 * Revision 1.8 2000/07/29 22:05:47 mdw
34 * Fix error in help message about Maurer test syntax.
36 * Revision 1.7 2000/07/18 23:01:26 mdw
37 * Improve progress indications, and allow user to choose chunk sizes for
40 * Revision 1.6 2000/07/15 20:53:35 mdw
41 * Add a load of new ciphers and hashes.
43 * Revision 1.5 2000/07/01 11:27:03 mdw
44 * Portability fix: don't assume that `stdout' is a constant expression.
45 * Remove old type name `bbs_param'.
47 * Revision 1.4 2000/06/17 12:08:28 mdw
48 * Restructure handling of cipher-based generators. Add counter-mode
49 * ciphers and MGF-1 hash functions. Add FIPS 140-1 and Maurer's tests.
51 * Revision 1.3 2000/02/12 18:21:03 mdw
52 * Overhaul of key management (again).
54 * Revision 1.2 1999/12/22 15:59:51 mdw
55 * New prime-search system. Read BBS keys from key files.
57 * Revision 1.1 1999/12/10 23:29:13 mdw
58 * Emit random numbers for statistical tests.
62 /*----- Header files ------------------------------------------------------*/
79 #include <mLib/darray.h>
80 #include <mLib/dstr.h>
81 #include <mLib/mdwopt.h>
82 #include <mLib/quis.h>
83 #include <mLib/report.h>
103 #include "des3-ofb.h"
106 #include "skipjack-ofb.h"
108 #include "xtea-ofb.h"
109 #include "blowfish-ofb.h"
110 #include "twofish-ofb.h"
111 #include "idea-ofb.h"
112 #include "cast128-ofb.h"
113 #include "cast256-ofb.h"
114 #include "rijndael-ofb.h"
115 #include "square-ofb.h"
116 #include "serpent-ofb.h"
118 #include "des-counter.h"
119 #include "des3-counter.h"
120 #include "rc2-counter.h"
121 #include "rc5-counter.h"
122 #include "skipjack-counter.h"
123 #include "tea-counter.h"
124 #include "xtea-counter.h"
125 #include "blowfish-counter.h"
126 #include "twofish-counter.h"
127 #include "idea-counter.h"
128 #include "cast128-counter.h"
129 #include "cast256-counter.h"
130 #include "rijndael-counter.h"
131 #include "square-counter.h"
132 #include "serpent-counter.h"
137 #include "tiger-mgf.h"
138 #include "rmd128-mgf.h"
139 #include "rmd160-mgf.h"
140 #include "rmd256-mgf.h"
141 #include "rmd320-mgf.h"
145 /*----- Data structures ---------------------------------------------------*/
149 grand *(*seed)(unsigned /*i*/);
154 static gen generators[];
161 E(SKIPJACK, skipjack) \
164 E(BLOWFISH, blowfish) \
165 E(TWOFISH, twofish) \
167 E(CAST128, cast128) \
168 E(CAST256, cast256) \
170 E(RIJNDAEL, rijndael) \
183 #define E(PRE, pre) CIPHER_##PRE,
184 enum { CIPHERS CIPHER__bogus };
187 #define E(PRE, pre) HASH_##PRE,
188 enum { HASHES HASH__bogus };
194 grand *(*ofb)(const void */*k*/, size_t /*sz*/);
195 grand *(*counter)(const void */*k*/, size_t /*sz*/);
197 #define E(PRE, pre) \
198 { pre##_keysz, PRE##_BLKSZ, pre##_ofbrand, pre##_counterrand },
206 grand *(*mgf)(const void */*k*/, size_t /*sz*/);
208 #define E(PRE, pre) \
209 { &pre, pre##_mgfkeysz, pre##_mgfrand },
214 /*----- Miscellaneous static data -----------------------------------------*/
217 static size_t outsz = 0;
218 static unsigned maurer_lo = 5, maurer_hi = 8;
223 static unsigned flags = 0;
232 /*----- Help options ------------------------------------------------------*/
234 static void usage(FILE *fp)
236 pquis(fp, "Usage: $ generator [options]\n");
239 static void version(FILE *fp)
241 pquis(fp, "$, Catacomb version " VERSION "\n");
244 static void help(FILE *fp)
250 Emits a stream of random bytes suitable for, well, all sorts of things.\n\
251 The primary objective is to be able to generate streams of input for\n\
252 statistical tests, such as Diehard.\n\
254 Options are specific to the particular generator, although there's a\n\
257 -h, --help Display this help message.\n\
258 -v, --version Display the program's version number.\n\
259 -u, --usage Display a useless usage message.\n\
261 -l, --list Show a list of the supported generators, with\n\
263 -f, --fipstest Run the FIPS 140-1 randomness test.\n\
264 -m, --maurer[=LO-HI] Run Maurer's universal statistical test.\n\
265 -o, --output FILE Write output to FILE, not stdout.\n\
266 -z, --size SIZE Emit SIZE bytes, not an unlimited number.\n\
267 -p, --progress Show a little progress meter (on stderr).\n\
269 (A SIZE may be followed by `g' for gigabytes, `m' for megabytes, or\n\
270 `k' for kilobytes. If unqualified, an amount in bytes is assumed.)\n\
274 /*----- Main options parser -----------------------------------------------*/
276 static struct option opts[] = {
278 /* --- Standard GNU help options --- */
280 { "help", 0, 0, 'h' },
281 { "version", 0, 0, 'v' },
282 { "usage", 0, 0, 'u' },
284 /* --- Other useful things --- */
286 { "list", 0, 0, 'l' },
287 { "fipstest", 0, 0, 'f' },
288 { "maurer", OPTF_ARGOPT, 0, 'm' },
289 { "output", OPTF_ARGREQ, 0, 'o' },
290 { "size", OPTF_ARGREQ, 0, 'z' },
291 { "progress", 0, 0, 'p' },
293 /* --- End of main table --- */
298 static const char *sopts = "hvu lfm::o:z:p";
301 DA_DECL(option_v, struct option);
305 static option_v optv = DA_INIT;
306 static dstr optd = DSTR_INIT;
308 /* --- @addopts@ --- *
310 * Arguments: @const char *s@ = pointer to short options
311 * @struct option *l@ = pointer to long options
315 * Use: Adds a collection of options to the table.
318 static void addopts(const char *s, struct option *l)
324 DA_PUSH(&optv, *l++);
332 * Returns: Next option from argument array.
334 * Use: Fetches options, handling the standard ones.
340 int i = mdwopt(argc, argv, optd.buf, DA(&optv), 0, 0, 0);
353 puts("Generators supported:");
354 for (g = generators; g->name; g++)
355 printf(" %s %s\n", g->name, g->help);
365 unsigned long lo, hi;
366 lo = strtoul(optarg, &p, 0);
368 hi = strtoul(p + 1, &p, 0);
371 if (*p != 0 || hi < lo || lo == 0)
372 die(EXIT_FAILURE, "bad bit range `%s'", optarg);
379 die(EXIT_FAILURE, "already set an output file");
380 if (strcmp(optarg, "-") == 0)
383 outfp = fopen(optarg, "w");
385 die(EXIT_FAILURE, "couldn't open output file `%s': %s",
386 optarg, strerror(errno));
393 outsz = strtoul(optarg, &p, 0);
395 die(EXIT_FAILURE, "bad number `%s'", optarg);
397 case 'G': case 'g': outsz *= 1024;
398 case 'M': case 'm': outsz *= 1024;
399 case 'K': case 'k': outsz *= 1024;
403 die(EXIT_FAILURE, "bad suffix `%s'", p);
407 die(EXIT_FAILURE, "bad suffix `%s'", p);
418 /*----- Manglers for seed strings -----------------------------------------*/
422 * Arguments: @const char *p@ = pointer to input string
423 * @char **end@ = where the end goes
424 * @dstr *d@ = output buffer
428 * Use: Transforms a hex string into a chunk of binary data.
431 static void unhex(const char *p, char **end, dstr *d)
433 while (p[0] && p[1]) {
434 int x = p[0], y = p[1];
435 if ('0' <= x && x <= '9') x -= '0';
436 else if ('A' <= x && x <= 'F') x -= 'A' - 10;
437 else if ('a' <= x && x <= 'f') x -= 'a' - 10;
439 if ('0' <= y && y <= '9') y -= '0';
440 else if ('A' <= y && y <= 'F') y -= 'A' - 10;
441 else if ('a' <= y && y <= 'f') y -= 'a' - 10;
443 DPUTC(d, (x << 4) + y);
449 /* --- Generate a key --- */
451 static void textkey(dstr *d, const char *p, const octet *ksz)
453 size_t sz = strlen(p);
456 die(EXIT_FAILURE, "zero-length key string");
457 if (keysz(sz, ksz) != sz)
461 rmd160_mgfinit(&g, p, sz);
464 rmd160_mgfencrypt(&g, 0, d->buf, sz);
467 assert(((void)"I can't seem to choose a good key size",
468 keysz(d->len, ksz) == d->len));
471 static void hexkey(dstr *d, const char *p, const octet *ksz)
474 unhex(optarg, &q, d);
476 die(EXIT_FAILURE, "bad hex key `%s'", p);
477 if (keysz(d->len, ksz) != d->len)
478 die(EXIT_FAILURE, "bad key length");
481 static void randkey(dstr *d, const octet *ksz)
483 size_t sz = keysz(0, ksz);
485 rand_get(RAND_GLOBAL, d->buf, sz);
489 /*----- Generators --------------------------------------------------------*/
491 /* --- Blum-Blum-Shub strong generator --- */
493 static grand *gen_bbs(unsigned i)
495 /* --- Default modulus --- *
497 * The factors of this number are
499 * @p = 1229936431484295969649886203367009966370895964206162032259292413@
500 * @7754313537966036459299022912838407755462506416274551744201653277@
501 * @313130311731673973886822067@
503 * @q = 9798171783943489959487301695884963889684294764514008432498259742@
504 * @5374320073594018817245784145742769603334292182227671519041431067@
505 * @61344781426317516045890159@
507 * Both %$p$% and %$q$% are prime; %$(p - 1)/2$% and %$(q - 1)/2$% have no
508 * common factors. They were found using this program, with random
511 * I hope that, by publishing these factors, I'll dissuade people from
512 * actually using this modulus in an attempt to attain real security. The
513 * program is quite quick at finding Blum numbers, so there's no excuse for
514 * not generating your own.
518 "120511284390135742513572142094334711443073194119732569353820828435640527418092392240366088035509890969913081816369160298961490135716255689660470370755013177656905237112577648090277537209936078171554274553448103698084782669252936352843649980105109850503830397166360721262431179505917248447259735253684659338653";
520 /* --- Other things --- */
524 unsigned bits = 1024;
527 const char *kfile = 0, *id = 0, *ktype = 0;
529 /* --- Parse options --- */
531 static struct option opts[] = {
532 { "modulus", OPTF_ARGREQ, 0, 'M' },
533 { "generate", 0, 0, 'g' },
534 { "seed", OPTF_ARGREQ, 0, 's' },
535 { "bits", OPTF_ARGREQ, 0, 'b' },
536 { "show", 0, 0, 'S' },
537 { "keyring", OPTF_ARGREQ, 0, 'k' },
538 { "id", OPTF_ARGREQ, 0, 'i' },
539 { "type", OPTF_ARGREQ, 0, 't' },
543 addopts("M:gs:b:Sk:i:t:", opts);
560 bits = strtoul(optarg, 0, 0);
562 die(EXIT_FAILURE, "bad number of bits `%s'", optarg);
584 /* --- Generate a modulus if one is requested --- */
588 m = mp_readstring(MP_NEW, mt, &p, 0);
589 if (!m || *p || (m->v[0] & 3) != 1)
590 die(EXIT_FAILURE, "bad modulus `%s'", mt);
591 /* Unfortunately I don't know how to test for a Blum integer */
592 } else if (kfile || id || ktype) {
597 /* --- Open the key file --- */
601 if (key_open(&kf, kfile, KOPEN_READ, key_moan, 0)) {
602 die(EXIT_FAILURE, "error opening key file `%s': %s",
603 kfile, strerror(errno));
606 /* --- Find the key --- */
609 if ((kk = key_bytag(&kf, id)) == 0)
610 die(EXIT_FAILURE, "key `%s' not found", id);
614 if ((kk = key_bytype(&kf, ktype)) == 0)
615 die(EXIT_FAILURE, "no suitable key with type `%s' found", ktype);
618 /* --- Read the key data --- */
620 if ((kk->k.e & KF_ENCMASK) != KENC_STRUCT)
621 die(EXIT_FAILURE, "key is not structured");
622 if ((kd = key_structfind(&kk->k, "n")) == 0)
623 die(EXIT_FAILURE, "key has no subkey `n'");
624 if ((kd->e & KF_ENCMASK) != KENC_MP)
625 die(EXIT_FAILURE, "incomatible subkey encoding");
626 m = MP_COPY(kd->u.m);
631 if (bbs_gen(&bp, bits, &rand_global, 0,
632 (flags & f_progress) ? pgen_ev : 0, 0))
633 die(EXIT_FAILURE, "modulus generation failed");
637 fputs("p = ", stderr);
638 mp_writefile(bp.p, stderr, 10);
639 fputs("\nq = ", stderr);
640 mp_writefile(bp.q, stderr, 10);
641 fputs("\nn = ", stderr);
642 mp_writefile(bp.n, stderr, 10);
650 /* --- Set up a seed --- */
653 x = mprand(MP_NEW, mp_bits(m) - 1, &rand_global, 1);
656 x = mp_readstring(MP_NEW, xt, &p, 0);
658 die(EXIT_FAILURE, "bad modulus `%s'", xt);
670 /* --- Catacomb's random number generator --- */
672 static grand *gen_rand(unsigned i)
674 grand *r = rand_create();
677 static struct option opts[] = {
678 { "key", OPTF_ARGREQ, 0, 'k' },
679 { "text", OPTF_ARGREQ, 0, 't' },
680 { "hex", OPTF_ARGREQ, 0, 'H' },
684 addopts("k:t:H:n", opts);
686 r->ops->misc(r, RAND_NOISESRC, &noise_source);
687 r->ops->misc(r, RAND_SEED, 160);
696 textkey(&d, optarg, rmd160_mackeysz);
697 r->ops->misc(r, RAND_KEY, d.buf, d.len);
700 r->ops->misc(r, GRAND_SEEDBLOCK, optarg, strlen(optarg));
704 hexkey(&d, optarg, rmd160_mackeysz);
705 r->ops->misc(r, GRAND_SEEDBLOCK, d.buf, d.len);
714 /* --- RC4 output --- */
716 static grand *gen_rc4(unsigned i)
721 static struct option opts[] = {
722 { "key", OPTF_ARGREQ, 0, 'k' },
723 { "hex", OPTF_ARGREQ, 0, 'H' },
727 addopts("k:H:", opts);
736 textkey(&d, optarg, rc4_keysz);
740 hexkey(&d, optarg, rc4_keysz);
748 randkey(&d, rc4_keysz);
749 r = rc4_rand(d.buf, d.len);
754 /* --- SEAL output --- */
756 static grand *gen_seal(unsigned i)
762 static struct option opts[] = {
763 { "key", OPTF_ARGREQ, 0, 'k' },
764 { "hex", OPTF_ARGREQ, 0, 'H' },
765 { "sequence", OPTF_ARGREQ, 0, 'n' },
769 addopts("k:H:n:", opts);
778 textkey(&d, optarg, seal_keysz);
782 hexkey(&d, optarg, seal_keysz);
786 n = strtoul(optarg, &p, 0);
788 die(EXIT_FAILURE, "bad number `%s'", optarg);
796 randkey(&d, seal_keysz);
797 r = seal_rand(d.buf, d.len, n);
802 /* --- Output feedback generators --- */
804 static grand *gen_ofb(unsigned i)
810 static struct option opts[] = {
811 { "key", OPTF_ARGREQ, 0, 'k' },
812 { "hex", OPTF_ARGREQ, 0, 'H' },
813 { "iv", OPTF_ARGREQ, 0, 'i' },
817 addopts("k:H:i:", opts);
826 textkey(&d, optarg, ciphertab[i].keysz);
830 hexkey(&d, optarg, ciphertab[i].keysz);
834 unhex(optarg, &p, &iv);
836 die(EXIT_FAILURE, "bad hex IV `%s'", optarg);
844 randkey(&d, ciphertab[i].keysz);
845 r = ciphertab[i].ofb(d.buf, d.len);
847 if (iv.len != ciphertab[i].blksz) {
848 die(EXIT_FAILURE, "bad IV length %lu (must be %lu)",
849 (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz);
851 r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf);
859 /* --- Counter generators --- */
861 static grand *gen_counter(unsigned i)
867 static struct option opts[] = {
868 { "key", OPTF_ARGREQ, 0, 'k' },
869 { "hex", OPTF_ARGREQ, 0, 'H' },
870 { "iv", OPTF_ARGREQ, 0, 'i' },
874 addopts("k:H:i:", opts);
883 textkey(&d, optarg, ciphertab[i].keysz);
887 hexkey(&d, optarg, ciphertab[i].keysz);
891 unhex(optarg, &p, &iv);
893 die(EXIT_FAILURE, "bad hex IV `%s'", optarg);
901 randkey(&d, ciphertab[i].keysz);
902 r = ciphertab[i].counter(d.buf, d.len);
904 if (iv.len != ciphertab[i].blksz) {
905 die(EXIT_FAILURE, "bad IV length %lu (must be %lu)",
906 (unsigned long)iv.len, (unsigned long)ciphertab[i].blksz);
908 r->ops->misc(r, GRAND_SEEDBLOCK, iv.buf);
916 /* --- Mask generators --- */
918 static grand *gen_mgf(unsigned i)
924 static struct option opts[] = {
925 { "key", OPTF_ARGREQ, 0, 'k' },
926 { "hex", OPTF_ARGREQ, 0, 'H' },
927 { "index", OPTF_ARGREQ, 0, 'i' },
931 addopts("k:H:i:", opts);
940 textkey(&d, optarg, hashtab[i].keysz);
944 hexkey(&d, optarg, hashtab[i].keysz);
948 c = strtoul(optarg, &p, 0);
950 die(EXIT_FAILURE, "bad index `%s'", optarg);
958 randkey(&d, hashtab[i].keysz);
960 r = hashtab[i].mgf(d.buf, d.len);
962 r->ops->misc(r, GRAND_SEEDUINT32, c);
968 /* --- Fibonacci generator --- */
970 static grand *gen_fib(unsigned i)
977 static struct option opts[] = {
978 { "seed", OPTF_ARGREQ, 0, 's' },
990 s = strtoul(optarg, &p, 0);
992 die(EXIT_FAILURE, "bad integer `%s'", optarg);
999 r = fibrand_create(s);
1001 r->ops->misc(r, GRAND_SEEDRAND, &rand_global);
1005 /* --- LC generator --- */
1007 static grand *gen_lc(unsigned i)
1013 static struct option opts[] = {
1014 { "seed", OPTF_ARGREQ, 0, 's' },
1018 addopts("s:", opts);
1026 s = strtoul(optarg, &p, 0);
1028 die(EXIT_FAILURE, "bad integer `%s'", optarg);
1037 s = rand_global.ops->range(&rand_global, LCRAND_P);
1038 while (s == LCRAND_FIXEDPT);
1040 return (lcrand_create(s));
1043 /* --- Basic options parser -- can't generate output --- */
1045 static grand *gen_opts(unsigned i)
1052 /*----- Generators table --------------------------------------------------*/
1054 static gen generators[] = {
1055 { "fibonacci", gen_fib, 0,
1059 #define E(PRE, pre) \
1060 { #pre "-ofb", gen_ofb, CIPHER_##PRE, \
1061 "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" },
1064 #define E(PRE, pre) \
1065 { #pre "-counter", gen_counter, CIPHER_##PRE, \
1066 "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" },
1069 #define E(PRE, pre) \
1070 { #pre "-mgf", gen_mgf, HASH_##PRE, \
1071 "[-k KEY-PHRASE] [-H HEX-KEY] [-i INDEX]" },
1074 { "rc4", gen_rc4, 0,
1075 "[-k KEY-PHRASE] [-H HEX-KEY]" },
1076 { "seal", gen_seal, 0,
1077 "[-k KEY-PHRASE] [-H HEX-KEY] [-n SEQ]" },
1078 { "rand", gen_rand, 0,
1079 "[-n] [-k KEY-PHRASE] [-t TEXT-BLOCK] [-H HEX-BLOCK]" },
1080 { "bbs", gen_bbs, 0,
1081 "[-gS] [-s SEED] [-M MODULUS] [-b BITS] [-k KEYRING] [-i TAG] [-t TYPE]"
1086 static gen optsg = { "options", gen_opts, 0,
1087 "This message shouldn't be printed." };
1089 /*----- Random number generation ------------------------------------------*/
1091 static int genfile(const void *buf, size_t sz, void *p)
1094 if (fwrite(buf, 1, sz, fp) != sz)
1095 die(EXIT_FAILURE, "error writing to file: %s", strerror(errno));
1099 static int genbuf(const void *buf, size_t sz, void *p)
1102 memcpy(*pp, buf, sz);
1107 static int generate(grand *r, size_t outsz,
1108 int (*func)(const void *buf, size_t sz, void *p),
1111 unsigned percent = 0;
1114 static char baton[] = "-\\|/";
1118 /* --- Spit out random data --- */
1122 if (flags & f_progress) {
1123 char *errbuf = xmalloc(BUFSIZ);
1124 setvbuf(stderr, errbuf, _IOLBF, BUFSIZ);
1126 fprintf(stderr, "[%*s] 0%% 0\r[/\b", 50, "");
1128 fputs("[ ] 0\r[/\b", stderr);
1133 signal(SIGPIPE, SIG_IGN);
1138 size_t sz = sizeof(buf);
1140 /* --- Emit a bufferful (or less) of data --- */
1143 if (sz > outsz - kb)
1146 r->ops->fill(r, buf, sz);
1147 if ((rc = func(buf, sz, p)) != 0)
1151 /* --- Update the display --- */
1153 if (flags & f_progress) {
1161 if (difftime(t, last) > 1.0) {
1165 fputs(" ] ", stderr);
1167 unsigned pc = kb * 100.0 / outsz;
1168 if (pc > percent || percent > 100 || difftime(t, last) > 1.0) {
1172 for (; percent < (pc & ~1); percent += 2)
1175 for (; pc < 100; pc += 2)
1177 fprintf(stderr, "] %3i%% ", percent);
1184 char *suff = " KMG";
1185 while (q > 8192 && suff[1]) {
1189 fprintf(stderr, "%4i%c\r[", q, *suff);
1192 for (pc = 0; pc < (percent & ~1); pc += 2)
1201 if (percent < 100) {
1202 putc(*bp++, stderr);
1210 /* --- Terminate the loop --- */
1212 if (outsz && kb >= outsz)
1216 if (flags & f_progress)
1217 fputc('\n', stderr);
1221 /*----- Main code ---------------------------------------------------------*/
1223 int main(int ac, char *av[])
1228 /* --- Initialize mLib --- */
1233 /* --- Set up the main Catacomb generator --- */
1235 rand_noisesrc(RAND_GLOBAL, &noise_source);
1236 rand_seed(RAND_GLOBAL, 160);
1238 /* --- Initialize the options table --- */
1240 addopts(sopts, opts);
1245 /* --- Read the generator out of the first argument --- */
1247 if (argc > 1 && *argv[1] != '-') {
1248 const char *arg = av[1];
1249 size_t sz = strlen(arg);
1253 for (gg = generators; gg->name; gg++) {
1254 if (strncmp(arg, gg->name, sz) == 0) {
1255 if (gg->name[sz] == 0) {
1259 die(EXIT_FAILURE, "ambiguous generator name `%s'", arg);
1265 die(EXIT_FAILURE, "unknown generator name `%s'", arg);
1270 /* --- Get a generic random number generator --- */
1273 if (!r || optind != ac - 1) {
1278 /* --- Do the FIPS test --- */
1280 if (flags & f_fips) {
1281 octet buf[FIPSTEST_BUFSZ];
1285 generate(r, sizeof(buf), genbuf, &p);
1287 if (rc & FIPSTEST_MONOBIT)
1288 moan("failed monobit test");
1289 if (rc & FIPSTEST_POKER)
1290 moan("failed poker test");
1291 if (rc & FIPSTEST_RUNS)
1292 moan("failed runs test");
1293 if (rc & FIPSTEST_LONGRUNS)
1294 moan("failed long runs test");
1295 if (!rc && (flags & f_progress))
1296 puts("test passed");
1297 return (rc ? EXIT_FAILURE : 0);
1300 /* --- Do Maurer's test --- */
1302 if (flags & f_maurer) {
1307 unsigned f = 0, jj = 0;
1311 static struct { double x; const char *sig; } sigtab[] = {
1319 bufsz = (100 * maurer_hi) << maurer_hi;
1320 if ((buf = a_alloc(arena_global, bufsz)) == 0)
1321 die(EXIT_FAILURE, "not enough memory for data buffer");
1323 generate(r, bufsz, genbuf, &p);
1325 for (i = maurer_lo; i <= maurer_hi; i++) {
1326 double z = maurer(buf, bufsz, i);
1327 double zz = fabs(z);
1330 for (j = 0; sigtab[j].sig; j++) {
1331 if (zz > sigtab[j].x) {
1332 if (zz > fabs(maxz)) {
1338 moan("failed, bits = %u, sig = %s, Z_u = %g",
1339 i, sigtab[j].sig, z);
1343 if (flags & f_progress)
1344 printf("bits = %u, Z_u = %g\n", i, z);
1350 /* --- Write to a file --- */
1353 if (!(flags & f_file) && isatty(STDOUT_FILENO))
1354 die(EXIT_FAILURE, "writing output to a terminal is a bad idea");
1357 generate(r, outsz, genfile, outfp);
1365 /*----- That's all, folks -------------------------------------------------*/