3 * Spit out random numbers
5 * (c) 1999 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Catacomb.
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
28 /*----- Header files ------------------------------------------------------*/
43 # include <sys/time.h>
46 #include <mLib/darray.h>
47 #include <mLib/dstr.h>
48 #include <mLib/mdwopt.h>
49 #include <mLib/quis.h>
50 #include <mLib/report.h>
74 #include "salsa20-core.h"
83 #include "skipjack-ofb.h"
86 #include "blowfish-ofb.h"
87 #include "twofish-ofb.h"
89 #include "cast128-ofb.h"
90 #include "cast256-ofb.h"
91 #include "noekeon-ofb.h"
92 #include "rijndael-ofb.h"
93 #include "rijndael192-ofb.h"
94 #include "rijndael256-ofb.h"
95 #include "safer-ofb.h"
96 #include "safersk-ofb.h"
97 #include "square-ofb.h"
98 #include "serpent-ofb.h"
100 #include "des-counter.h"
101 #include "des3-counter.h"
102 #include "rc2-counter.h"
103 #include "rc5-counter.h"
104 #include "mars-counter.h"
105 #include "skipjack-counter.h"
106 #include "tea-counter.h"
107 #include "xtea-counter.h"
108 #include "blowfish-counter.h"
109 #include "twofish-counter.h"
110 #include "idea-counter.h"
111 #include "cast128-counter.h"
112 #include "cast256-counter.h"
113 #include "noekeon-counter.h"
114 #include "rijndael-counter.h"
115 #include "rijndael192-counter.h"
116 #include "rijndael256-counter.h"
117 #include "safer-counter.h"
118 #include "safersk-counter.h"
119 #include "square-counter.h"
120 #include "serpent-counter.h"
126 #include "tiger-mgf.h"
127 #include "rmd128-mgf.h"
128 #include "rmd160-mgf.h"
129 #include "rmd256-mgf.h"
130 #include "rmd320-mgf.h"
134 /*----- Data structures ---------------------------------------------------*/
138 grand
*(*seed
)(unsigned /*i*/);
143 extern gen generators
[];
151 E(SKIPJACK, skipjack) \
154 E(BLOWFISH, blowfish) \
155 E(TWOFISH, twofish) \
157 E(CAST128, cast128) \
158 E(CAST256, cast256) \
161 E(SAFERSK, safersk) \
162 E(NOEKEON, noekeon) \
163 E(RIJNDAEL, rijndael) \
164 E(RIJNDAEL192, rijndael192) \
165 E(RIJNDAEL256, rijndael256) \
179 #define E(PRE, pre) CIPHER_##PRE,
180 enum { CIPHERS CIPHER__bogus
};
183 #define E(PRE, pre) HASH_##PRE,
184 enum { HASHES HASH__bogus
};
187 static const struct {
190 grand
*(*ofb
)(const void */
*k*/
, size_t /*sz*/);
191 grand
*(*counter
)(const void */
*k*/
, size_t /*sz*/);
193 #define E(PRE, pre) \
194 { pre##_keysz, PRE##_BLKSZ, pre##_ofbrand, pre##_counterrand },
199 static const struct {
202 grand
*(*mgf
)(const void */
*k*/
, size_t /*sz*/);
204 #define E(PRE, pre) \
205 { &pre, pre##_mgfkeysz, pre##_mgfrand },
211 E(salsa20, 20,, SALSA20) \
212 E(salsa20, 12,, SALSA20) \
213 E(salsa20, 8,, SALSA20) \
214 E(xsalsa20, 20, X, SALSA20) \
215 E(xsalsa20, 12, X, SALSA20) \
216 E(xsalsa20, 8, X, SALSA20) \
217 E(chacha, 20,, CHACHA) \
218 E(chacha, 12,, CHACHA) \
219 E(chacha, 8,, CHACHA) \
220 E(xchacha, 20, X, CHACHA) \
221 E(xchacha, 12, X, CHACHA) \
222 E(xchacha, 8, X, CHACHA)
224 #define E(pre, r, x, BASE) pre##_##r##_INDEX,
225 enum { SALSAE BOGUS_SALSA
};
228 #define SALSA20_GEN(pre, r) SALSA20_DECOR(pre, r, _rand)
229 #define CHACHA_GEN(pre, r) pre##r##_rand
231 #define SALSA20_NAME(r) SALSA20_NAME_##r
232 #define XSALSA20_NAME(r) "x" SALSA20_NAME_##r
233 #define CHACHA_NAME(r) "chacha" #r
234 #define XCHACHA_NAME(r) "xchacha" #r
236 static const struct {
238 grand
*(*gen
)(const void *, size_t, const void *);
240 #define E(pre, r, x, BASE) { x##BASE##_NONCESZ, BASE##_GEN(pre, r) },
245 #define SHAKES E(128) E(256)
248 #define E(sz) SHAKE##sz##_INDEX,
254 static const struct {
256 grand
*(*shake
)(const void *, size_t, const void *, size_t,
257 const void *, size_t);
258 grand
*(*kmac
)(const void *, size_t,
259 const void *, size_t);
261 #define E(sz) { shake##sz##_keysz, cshake##sz##_rand, kmac##sz##_rand },
266 /*----- Miscellaneous static data -----------------------------------------*/
269 static mp
*outsz
= 0;
270 static unsigned maurer_lo
= 5, maurer_hi
= 8;
275 static unsigned flags
= 0;
277 #define f_progress 1u
282 #define f_discard 32u
284 /*----- Help options ------------------------------------------------------*/
286 static void usage(FILE *fp
)
288 pquis(fp
, "Usage: $ generator [options]\n");
291 static void version(FILE *fp
)
293 pquis(fp
, "$, Catacomb version " VERSION
"\n");
296 static void help(FILE *fp
)
302 Emits a stream of random bytes suitable for, well, all sorts of things.\n\
303 The primary objective is to be able to generate streams of input for\n\
304 statistical tests, such as Diehard.\n\
306 Options are specific to the particular generator, although there's a\n\
309 -h, --help Display this help message.\n\
310 -v, --version Display the program's version number.\n\
311 -u, --usage Display a useless usage message.\n\
313 -l, --list Show a list of the supported generators, with\n\
315 -f, --fipstest Run the FIPS 140-1 randomness test.\n\
316 -m, --maurer[=LO-HI] Run Maurer's universal statistical test.\n\
317 -o, --output FILE Write output to FILE, not stdout.\n\
318 -z, --size SIZE Emit SIZE bytes, not an unlimited number.\n\
319 -p, --progress Show a little progress meter (on stderr).\n\
320 -T, --timer Keep track of the CPU time used by the generator.\n\
321 -d, --discard Discard the generated output.\n\
323 (A SIZE may be followed by `g' for gigabytes, `m' for megabytes, or\n\
324 `k' for kilobytes. If unqualified, an amount in bytes is assumed.)\n\
328 /*----- Main options parser -----------------------------------------------*/
330 static struct option opts
[] = {
332 /* --- Standard GNU help options --- */
334 { "help", 0, 0, 'h' },
335 { "version", 0, 0, 'v' },
336 { "usage", 0, 0, 'u' },
338 /* --- Other useful things --- */
340 { "list", 0, 0, 'l' },
341 { "fipstest", 0, 0, 'f' },
342 { "maurer", OPTF_ARGOPT
, 0, 'm' },
343 { "output", OPTF_ARGREQ
, 0, 'o' },
344 { "size", OPTF_ARGREQ
, 0, 'z' },
345 { "progress", 0, 0, 'p' },
346 { "timer", 0, 0, 'T' },
347 { "discard", 0, 0, 'd' },
349 /* --- End of main table --- */
354 static const char *sopts
= "hvu lfm::o:z:pTd";
357 DA_DECL(option_v
, struct option
);
361 static option_v optv
= DA_INIT
;
362 static dstr optd
= DSTR_INIT
;
364 /* --- @addopts@ --- *
366 * Arguments: @const char *s@ = pointer to short options
367 * @struct option *l@ = pointer to long options
371 * Use: Adds a collection of options to the table.
374 static void addopts(const char *s
, struct option
*l
)
380 DA_PUSH(&optv
, *l
++);
388 * Returns: Next option from argument array.
390 * Use: Fetches options, handling the standard ones.
396 int i
= mdwopt(argc
, argv
, optd
.buf
, DA(&optv
), 0, 0, 0);
409 puts("Generators supported:");
410 for (g
= generators
; g
->name
; g
++)
411 printf(" %s %s\n", g
->name
, g
->help
);
421 unsigned long lo
, hi
;
422 lo
= strtoul(optarg
, &p
, 0);
423 if (*p
== '-' || *p
== ',')
424 hi
= strtoul(p
+ 1, &p
, 0);
427 if (*p
!= 0 || hi
< lo
|| lo
== 0)
428 die(EXIT_FAILURE
, "bad bit range `%s'", optarg
);
435 die(EXIT_FAILURE
, "already set an output file");
436 if (strcmp(optarg
, "-") == 0)
439 outfp
= fopen(optarg
, "w");
441 die(EXIT_FAILURE
, "couldn't open output file `%s': %s",
442 optarg
, strerror(errno
));
449 outsz
= mp_readstring(outsz
, optarg
, &p
, 0);
450 if (!outsz
|| MP_NEGP(outsz
))
451 die(EXIT_FAILURE
, "bad number `%s'", optarg
);
453 case 'G': case 'g': outsz
= mp_lsl(outsz
, outsz
, 10);
454 case 'M': case 'm': outsz
= mp_lsl(outsz
, outsz
, 10);
455 case 'K': case 'k': outsz
= mp_lsl(outsz
, outsz
, 10);
459 die(EXIT_FAILURE
, "bad suffix `%s'", p
);
463 die(EXIT_FAILURE
, "bad suffix `%s'", p
);
480 /*----- Manglers for seed strings -----------------------------------------*/
484 * Arguments: @const char *p@ = pointer to input string
485 * @char **end@ = where the end goes
486 * @dstr *d@ = output buffer
490 * Use: Transforms a hex string into a chunk of binary data.
493 static void unhex(const char *p
, char **end
, dstr
*d
)
495 while (p
[0] && p
[1]) {
496 int x
= p
[0], y
= p
[1];
497 if ('0' <= x
&& x
<= '9') x
-= '0';
498 else if ('A' <= x
&& x
<= 'F') x
-= 'A' - 10;
499 else if ('a' <= x
&& x
<= 'f') x
-= 'a' - 10;
501 if ('0' <= y
&& y
<= '9') y
-= '0';
502 else if ('A' <= y
&& y
<= 'F') y
-= 'A' - 10;
503 else if ('a' <= y
&& y
<= 'f') y
-= 'a' - 10;
505 DPUTC(d
, (x
<< 4) + y
);
511 /* --- Generate a key --- */
513 static void textkey(dstr
*d
, const char *p
, const octet
*ksz
)
515 size_t sz
= strlen(p
);
518 die(EXIT_FAILURE
, "zero-length key string");
519 if (keysz(sz
, ksz
) != sz
)
523 rmd160_mgfinit(&g
, p
, sz
);
526 rmd160_mgfencrypt(&g
, 0, d
->buf
, sz
);
529 assert(((void)"I can't seem to choose a good key size",
530 keysz(d
->len
, ksz
) == d
->len
));
533 static void hexkey(dstr
*d
, const char *p
, const octet
*ksz
)
536 unhex(optarg
, &q
, d
);
538 die(EXIT_FAILURE
, "bad hex key `%s'", p
);
539 if (keysz(d
->len
, ksz
) != d
->len
)
540 die(EXIT_FAILURE
, "bad key length");
543 static void randkey(dstr
*d
, const octet
*ksz
)
545 size_t sz
= keysz(0, ksz
);
547 rand_get(RAND_GLOBAL
, d
->buf
, sz
);
551 /*----- Generators --------------------------------------------------------*/
553 /* --- Blum-Blum-Shub strong generator --- */
555 static grand
*gen_bbs(unsigned i
)
557 /* --- Default modulus --- *
559 * The factors of this number are
561 * @p = 1229936431484295969649886203367009966370895964206162032259292413@
562 * @7754313537966036459299022912838407755462506416274551744201653277@
563 * @313130311731673973886822067@
565 * @q = 9798171783943489959487301695884963889684294764514008432498259742@
566 * @5374320073594018817245784145742769603334292182227671519041431067@
567 * @61344781426317516045890159@
569 * Both %$p$% and %$q$% are prime; %$(p - 1)/2$% and %$(q - 1)/2$% have no
570 * common factors. They were found using this program, with random
573 * I hope that, by publishing these factors, I'll dissuade people from
574 * actually using this modulus in an attempt to attain real security. The
575 * program is quite quick at finding Blum numbers, so there's no excuse for
576 * not generating your own.
580 "12051128439013574251357214209433471144307319411973256935382082"
581 "84356405274180923922403660880355098909699130818163691602989614"
582 "90135716255689660470370755013177656905237112577648090277537209"
583 "93607817155427455344810369808478266925293635284364998010510985"
584 "0503830397166360721262431179505917248447259735253684659338653";
586 /* --- Other things --- */
590 unsigned bits
= 1024;
593 const char *kfile
= 0, *id
= 0, *ktype
= 0;
595 /* --- Parse options --- */
597 static struct option opts
[] = {
598 { "modulus", OPTF_ARGREQ
, 0, 'M' },
599 { "generate", 0, 0, 'g' },
600 { "seed", OPTF_ARGREQ
, 0, 's' },
601 { "bits", OPTF_ARGREQ
, 0, 'b' },
602 { "show", 0, 0, 'S' },
603 { "keyring", OPTF_ARGREQ
, 0, 'k' },
604 { "id", OPTF_ARGREQ
, 0, 'i' },
605 { "type", OPTF_ARGREQ
, 0, 't' },
609 addopts("M:gs:b:Sk:i:t:", opts
);
626 bits
= strtoul(optarg
, 0, 0);
628 die(EXIT_FAILURE
, "bad number of bits `%s'", optarg
);
650 /* --- Generate a modulus if one is requested --- */
654 m
= mp_readstring(MP_NEW
, mt
, &p
, 0);
655 if (!m
|| *p
|| (m
->v
[0] & 3) != 1)
656 die(EXIT_FAILURE
, "bad modulus `%s'", mt
);
657 /* Unfortunately I don't know how to test for a Blum integer */
658 } else if (kfile
|| id
|| ktype
) {
663 /* --- Open the key file --- */
667 if (key_open(&kf
, kfile
, KOPEN_READ
, key_moan
, 0)) {
668 die(EXIT_FAILURE
, "error opening key file `%s': %s",
669 kfile
, strerror(errno
));
672 /* --- Find the key --- */
675 if ((kk
= key_bytag(&kf
, id
)) == 0)
676 die(EXIT_FAILURE
, "key `%s' not found", id
);
680 if ((kk
= key_bytype(&kf
, ktype
)) == 0)
681 die(EXIT_FAILURE
, "no suitable key with type `%s' found", ktype
);
684 /* --- Read the key data --- */
686 if ((kk
->k
->e
& KF_ENCMASK
) != KENC_STRUCT
)
687 die(EXIT_FAILURE
, "key is not structured");
688 if ((kd
= key_structfind(kk
->k
, "n")) == 0)
689 die(EXIT_FAILURE
, "key has no subkey `n'");
690 if ((kd
->e
& KF_ENCMASK
) != KENC_MP
)
691 die(EXIT_FAILURE
, "incompatible subkey encoding");
692 m
= MP_COPY(kd
->u
.m
);
697 if (bbs_gen(&bp
, bits
, &rand_global
, 0,
698 (flags
& f_progress
) ? pgen_ev
: 0, 0))
699 die(EXIT_FAILURE
, "modulus generation failed");
703 fputs("p = ", stderr
);
704 mp_writefile(bp
.p
, stderr
, 10);
705 fputs("\nq = ", stderr
);
706 mp_writefile(bp
.q
, stderr
, 10);
707 fputs("\nn = ", stderr
);
708 mp_writefile(bp
.n
, stderr
, 10);
716 /* --- Set up a seed --- */
719 x
= mprand(MP_NEW
, mp_bits(m
) - 1, &rand_global
, 1);
722 x
= mp_readstring(MP_NEW
, xt
, &p
, 0);
724 die(EXIT_FAILURE
, "bad modulus `%s'", xt
);
736 /* --- Catacomb's random number generator --- */
738 static grand
*gen_rand(unsigned i
)
740 grand
*r
= rand_create();
743 static struct option opts
[] = {
744 { "key", OPTF_ARGREQ
, 0, 'k' },
745 { "text", OPTF_ARGREQ
, 0, 't' },
746 { "hex", OPTF_ARGREQ
, 0, 'H' },
750 addopts("k:t:H:n", opts
);
752 r
->ops
->misc(r
, RAND_NOISESRC
, &noise_source
);
753 r
->ops
->misc(r
, RAND_SEED
, 160);
762 textkey(&d
, optarg
, rmd160_hmackeysz
);
763 r
->ops
->misc(r
, RAND_KEY
, d
.buf
, d
.len
);
766 r
->ops
->misc(r
, GRAND_SEEDBLOCK
, optarg
, strlen(optarg
));
770 hexkey(&d
, optarg
, rmd160_hmackeysz
);
771 r
->ops
->misc(r
, GRAND_SEEDBLOCK
, d
.buf
, d
.len
);
780 /* --- RC4 output --- */
782 static grand
*gen_rc4(unsigned i
)
787 static struct option opts
[] = {
788 { "key", OPTF_ARGREQ
, 0, 'k' },
789 { "hex", OPTF_ARGREQ
, 0, 'H' },
793 addopts("k:H:", opts
);
802 textkey(&d
, optarg
, rc4_keysz
);
806 hexkey(&d
, optarg
, rc4_keysz
);
814 randkey(&d
, rc4_keysz
);
815 r
= rc4_rand(d
.buf
, d
.len
);
820 /* --- SEAL output --- */
822 static grand
*gen_seal(unsigned i
)
828 static struct option opts
[] = {
829 { "key", OPTF_ARGREQ
, 0, 'k' },
830 { "hex", OPTF_ARGREQ
, 0, 'H' },
831 { "sequence", OPTF_ARGREQ
, 0, 'n' },
835 addopts("k:H:n:", opts
);
844 textkey(&d
, optarg
, seal_keysz
);
848 hexkey(&d
, optarg
, seal_keysz
);
852 n
= strtoul(optarg
, &p
, 0);
854 die(EXIT_FAILURE
, "bad number `%s'", optarg
);
862 randkey(&d
, seal_keysz
);
863 r
= seal_rand(d
.buf
, d
.len
, n
);
868 /* --- Salsa20, XSalsa20, ChaCha, and XChaCha --- */
870 static grand
*gen_salsae(unsigned i
)
876 kludge64 pos
= { 0 };
880 static struct option opts
[] = {
881 { "key", OPTF_ARGREQ
, 0, 'k' },
882 { "hex", OPTF_ARGREQ
, 0, 'H' },
883 { "nonce", OPTF_ARGREQ
, 0, 'n' },
884 { "seek", OPTF_ARGREQ
, 0, 's' },
888 addopts("k:H:n:s:", opts
);
897 textkey(&d
, optarg
, salsa20_keysz
);
901 hexkey(&d
, optarg
, salsa20_keysz
);
905 unhex(optarg
, &p
, &n
);
907 die(EXIT_FAILURE
, "bad hex IV `%s'", optarg
);
908 if (n
.len
!= salsatab
[i
].noncesz
) {
909 die(EXIT_FAILURE
, "bad nonce length %lu (must be %lu)",
910 (unsigned long)n
.len
, (unsigned long)salsatab
[i
].noncesz
);
914 x
= mp_readstring(MP_NEW
, optarg
, &p
, 0);
915 if (*p
|| MP_NEGP(x
) || mp_bits(x
) > 64)
916 die(EXIT_FAILURE
, "bad position `%s'", optarg
);
917 mp_storeb(x
, posbuf
, sizeof(posbuf
));
919 LOAD64_(pos
, posbuf
);
927 randkey(&d
, salsa20_keysz
);
928 r
= salsatab
[i
].gen(d
.buf
, d
.len
, n
.len ? n
.buf
: 0);
929 r
->ops
->misc(r
, SALSA20_SEEKU64
, pos
);
937 /* --- Output feedback generators --- */
939 static grand
*gen_ofb(unsigned i
)
945 static struct option opts
[] = {
946 { "key", OPTF_ARGREQ
, 0, 'k' },
947 { "hex", OPTF_ARGREQ
, 0, 'H' },
948 { "iv", OPTF_ARGREQ
, 0, 'i' },
952 addopts("k:H:i:", opts
);
961 textkey(&d
, optarg
, ciphertab
[i
].keysz
);
965 hexkey(&d
, optarg
, ciphertab
[i
].keysz
);
970 unhex(optarg
, &p
, &iv
);
972 die(EXIT_FAILURE
, "bad hex IV `%s'", optarg
);
973 if (iv
.len
!= ciphertab
[i
].blksz
) {
974 die(EXIT_FAILURE
, "bad IV length %lu (must be %lu)",
975 (unsigned long)iv
.len
, (unsigned long)ciphertab
[i
].blksz
);
984 randkey(&d
, ciphertab
[i
].keysz
);
985 r
= ciphertab
[i
].ofb(d
.buf
, d
.len
);
987 r
->ops
->misc(r
, GRAND_SEEDBLOCK
, iv
.buf
);
994 /* --- Counter generators --- */
996 static grand
*gen_counter(unsigned i
)
1000 dstr iv
= DSTR_INIT
;
1002 static struct option opts
[] = {
1003 { "key", OPTF_ARGREQ
, 0, 'k' },
1004 { "hex", OPTF_ARGREQ
, 0, 'H' },
1005 { "iv", OPTF_ARGREQ
, 0, 'i' },
1009 addopts("k:H:i:", opts
);
1018 textkey(&d
, optarg
, ciphertab
[i
].keysz
);
1022 hexkey(&d
, optarg
, ciphertab
[i
].keysz
);
1027 unhex(optarg
, &p
, &iv
);
1029 die(EXIT_FAILURE
, "bad hex IV `%s'", optarg
);
1030 if (iv
.len
!= ciphertab
[i
].blksz
) {
1031 die(EXIT_FAILURE
, "bad IV length %lu (must be %lu)",
1032 (unsigned long)iv
.len
, (unsigned long)ciphertab
[i
].blksz
);
1041 randkey(&d
, ciphertab
[i
].keysz
);
1042 r
= ciphertab
[i
].counter(d
.buf
, d
.len
);
1044 r
->ops
->misc(r
, GRAND_SEEDBLOCK
, iv
.buf
);
1051 /* --- Mask generators --- */
1053 static grand
*gen_mgf(unsigned i
)
1059 static struct option opts
[] = {
1060 { "key", OPTF_ARGREQ
, 0, 'k' },
1061 { "hex", OPTF_ARGREQ
, 0, 'H' },
1062 { "index", OPTF_ARGREQ
, 0, 'i' },
1066 addopts("k:H:i:", opts
);
1075 textkey(&d
, optarg
, hashtab
[i
].keysz
);
1079 hexkey(&d
, optarg
, hashtab
[i
].keysz
);
1083 c
= strtoul(optarg
, &p
, 0);
1085 die(EXIT_FAILURE
, "bad index `%s'", optarg
);
1093 randkey(&d
, hashtab
[i
].keysz
);
1095 r
= hashtab
[i
].mgf(d
.buf
, d
.len
);
1097 r
->ops
->misc(r
, GRAND_SEEDUINT32
, c
);
1103 /* --- SHAKE generators --- */
1105 static grand
*gen_shake(unsigned i
)
1108 const char *func
= 0, *perso
= 0;
1111 static struct option opts
[] = {
1112 { "function", OPTF_ARGREQ
, 0, 'F' },
1113 { "personalization", OPTF_ARGREQ
, 0, 'P' },
1114 { "key", OPTF_ARGREQ
, 0, 'k' },
1115 { "hex", OPTF_ARGREQ
, 0, 'H' },
1119 addopts("F:P:k:H:", opts
);
1134 textkey(&d
, optarg
, shaketab
[i
].ksz
);
1138 hexkey(&d
, optarg
, shaketab
[i
].ksz
);
1145 if (!d
.len
) randkey(&d
, shaketab
[i
].ksz
);
1146 r
= shaketab
[i
].shake(func
, func ?
strlen(func
) : 0,
1147 perso
, perso ?
strlen(perso
) : 0,
1153 /* --- KMAC generators --- */
1155 static grand
*gen_kmac(unsigned i
)
1157 dstr d
= DSTR_INIT
, m
= DSTR_INIT
;
1158 const char *perso
= 0;
1162 static struct option opts
[] = {
1163 { "personalization", OPTF_ARGREQ
, 0, 'P' },
1164 { "key", OPTF_ARGREQ
, 0, 'k' },
1165 { "hex", OPTF_ARGREQ
, 0, 'H' },
1166 { "message", OPTF_ARGREQ
, 0, 'M' },
1167 { "msghex", OPTF_ARGREQ
, 0, 'N' },
1171 addopts("P:k:H:M:N:", opts
);
1183 textkey(&d
, optarg
, shaketab
[i
].ksz
);
1187 hexkey(&d
, optarg
, shaketab
[i
].ksz
);
1195 unhex(optarg
, &q
, &m
);
1196 if (*q
) die(EXIT_FAILURE
, "bad hex");
1203 if (!d
.len
) randkey(&d
, shaketab
[i
].ksz
);
1204 r
= shaketab
[i
].kmac(perso
, perso ?
strlen(perso
) : 0, d
.buf
, d
.len
);
1205 r
->ops
->misc(r
, GRAND_SEEDBLOCK
, (void *)m
.buf
, m
.len
);
1206 dstr_destroy(&d
); dstr_destroy(&m
);
1210 /* --- Fibonacci generator --- */
1212 static grand
*gen_fib(unsigned i
)
1219 static struct option opts
[] = {
1220 { "seed", OPTF_ARGREQ
, 0, 's' },
1224 addopts("s:", opts
);
1232 s
= strtoul(optarg
, &p
, 0);
1234 die(EXIT_FAILURE
, "bad integer `%s'", optarg
);
1241 r
= fibrand_create(s
);
1243 r
->ops
->misc(r
, GRAND_SEEDRAND
, &rand_global
);
1247 /* --- LC generator --- */
1249 static grand
*gen_lc(unsigned i
)
1255 static struct option opts
[] = {
1256 { "seed", OPTF_ARGREQ
, 0, 's' },
1260 addopts("s:", opts
);
1268 s
= strtoul(optarg
, &p
, 0);
1270 die(EXIT_FAILURE
, "bad integer `%s'", optarg
);
1279 s
= rand_global
.ops
->range(&rand_global
, LCRAND_P
);
1280 while (s
== LCRAND_FIXEDPT
);
1282 return (lcrand_create(s
));
1285 /* --- Basic options parser -- can't generate output --- */
1287 static grand
*gen_opts(unsigned i
)
1294 /*----- Generators table --------------------------------------------------*/
1296 gen generators
[] = {
1297 { "fibonacci", gen_fib
, 0,
1301 #define E(PRE, pre) \
1302 { #pre "-ofb", gen_ofb, CIPHER_##PRE, \
1303 "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" },
1306 #define E(PRE, pre) \
1307 { #pre "-counter", gen_counter, CIPHER_##PRE, \
1308 "[-k KEY-PHRASE] [-H HEX-KEY] [-i HEX-IV]" },
1311 #define E(PRE, pre) \
1312 { #pre "-mgf", gen_mgf, HASH_##PRE, \
1313 "[-k KEY-PHRASE] [-H HEX-KEY] [-i INDEX]" },
1316 #define E(pre, r, x, BASE) \
1317 { x##BASE##_NAME(r), gen_salsae, pre##_##r##_INDEX, \
1318 "[-k KEY-PHRASE] [-H HEX-KEY] [-n NONCE]" },
1322 { "shake" #sz, gen_shake, SHAKE##sz##_INDEX, \
1323 "[-k KEY-PHRASE] [-H HEX-KEY]" },
1327 { "kmac" #sz, gen_kmac, SHAKE##sz##_INDEX, \
1328 "[-k KEY-PHRASE] [-H HEX-KEY] [-m MSG]" },
1331 { "rc4", gen_rc4
, 0,
1332 "[-k KEY-PHRASE] [-H HEX-KEY]" },
1333 { "seal", gen_seal
, 0,
1334 "[-k KEY-PHRASE] [-H HEX-KEY] [-n SEQ]" },
1335 { "rand", gen_rand
, 0,
1336 "[-n] [-k KEY-PHRASE] [-t TEXT-BLOCK] [-H HEX-BLOCK]" },
1337 { "bbs", gen_bbs
, 0,
1338 "[-gS] [-s SEED] [-M MODULUS] [-b BITS] [-k KEYRING] [-i TAG] [-t TYPE]"
1343 static gen optsg
= { "options", gen_opts
, 0,
1344 "This message shouldn't be printed." };
1346 /*----- Random number generation ------------------------------------------*/
1348 static int genfile(const void *buf
, size_t sz
, void *p
)
1351 if (fwrite(buf
, 1, sz
, fp
) != sz
)
1352 die(EXIT_FAILURE
, "error writing to file: %s", strerror(errno
));
1356 static int genbuf(const void *buf
, size_t sz
, void *p
)
1359 memcpy(*pp
, buf
, sz
);
1364 typedef struct genmaurer_ctx
{
1369 static int genmaurer(const void *buf
, size_t sz
, void *p
)
1371 genmaurer_ctx
*g
= p
;
1374 for (i
= 0; i
< g
->n
; i
++)
1375 maurer_test(&g
->m
[i
], buf
, sz
);
1379 static double doubletime(void)
1382 static time_t start
= (time_t)-1;
1383 time_t now
= time(0);
1385 if (start
== (time_t)-1) start
= now
;
1386 return difftime(now
, start
);
1390 gettimeofday(&tv
, 0);
1391 return (tv
.tv_sec
+ tv
.tv_usec
/1000000.0);
1395 static int generate(grand
*r
, mp
*outsz
,
1396 int (*func
)(const void *buf
, size_t sz
, void *p
),
1399 static char kmg
[] = { ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 0 };
1401 unsigned percent
= 0;
1402 mp
*kb
= MP_ZERO
, *t
= MP_NEW
;
1405 static char baton
[] = "-\\|/";
1410 /* --- Spit out random data --- */
1412 last
= doubletime();
1414 if (flags
& f_progress
) {
1415 char *errbuf
= xmalloc(BUFSIZ
);
1416 setvbuf(stderr
, errbuf
, _IOLBF
, BUFSIZ
);
1418 fprintf(stderr
, "[%*s] 0%% 0\r[/\b", 50, "");
1420 fputs("[ ] 0\r[/\b", stderr
);
1425 signal(SIGPIPE
, SIG_IGN
);
1428 while (!outsz
|| MP_CMP(kb
, <, outsz
)) {
1430 size_t sz
= sizeof(buf
), left
;
1431 clock_t c_start
, c_stop
;
1433 /* --- Emit a bufferful (or less) of data --- */
1436 t
= mp_sub(t
, outsz
, kb
);
1437 assert(!MP_NEGP(t
));
1438 if (MP_CMP(t
, <=, MP_SIZET_MAX
)) {
1439 left
= mp_tosizet(t
);
1440 if (sz
> left
) sz
= left
;
1444 r
->ops
->fill(r
, buf
, sz
);
1446 clk
+= c_stop
- c_start
;
1447 if (func
&& (rc
= func(buf
, sz
, p
)) != 0)
1449 t
= mp_fromsizet(t
, sz
);
1450 kb
= mp_add(kb
, kb
, t
);
1452 /* --- Update the display --- */
1454 if (flags
& f_progress
) {
1463 if (now
- last
> 0.1) {
1467 fputs(" ] ", stderr
);
1470 t
= mp_fromulong(t
, 100);
1471 t
= mp_mul(t
, t
, kb
);
1472 mp_div(&t
, 0, t
, outsz
);
1473 assert(!MP_NEGP(t
) && MP_CMP(t
, <, MP_UINT_MAX
));
1475 if (pc
> percent
|| percent
> 100 || now
- last
> 0.1) {
1479 for (; percent
< (pc
& ~1); percent
+= 2)
1482 for (; pc
< 100; pc
+= 2)
1484 fprintf(stderr
, "] %3i%% ", percent
);
1491 t
= mp_add(t
, kb
, MP_ZERO
);
1492 while (mp_bits(t
) >= 14) {
1493 t
= mp_lsr(t
, t
, 10);
1497 mp_writedstr(t
, &d
, 10);
1498 fprintf(stderr
, "%4s%c\r[", d
.buf
, *kk
);
1501 for (pc
= 0; pc
< (percent
& ~1); pc
+= 2)
1510 if (percent
< 100 && up
) {
1511 putc(*bp
++, stderr
);
1520 if (flags
& f_progress
)
1521 fputc('\n', stderr
);
1522 if (flags
& f_timer
) {
1524 dstr_puts(&d
, "generated ");
1525 mp_writedstr(kb
, &d
, 10);
1526 dstr_puts(&d
, " bytes ");
1528 dstr_puts(&d
, "too quickly to measure\n");
1532 double sec
= (double)clk
/CLOCKS_PER_SEC
;
1537 switch (MP_LEN(kb
)) {
1538 case 0: out
= 0; break;
1539 case 1: out
= kb
->v
[0]; break;
1541 sh
= mp_bits(kb
) - MPW_BITS
;
1542 t
= mp_lsr(t
, kb
, sh
);
1543 out
= ldexp(t
->v
[0], sh
);
1547 for (kk
= kmg
; bps
> 1024 && kk
[1]; kk
++, bps
/= 1024)
1549 dstr_putf(&d
, "in %g secs (%g %cb/s)\n", sec
, bps
, *kk
);
1550 fwrite(d
.buf
, 1, d
.len
, stderr
);
1559 /*----- Main code ---------------------------------------------------------*/
1561 int main(int ac
, char *av
[])
1566 /* --- Initialize mLib --- */
1571 /* --- Set up the main Catacomb generator --- */
1573 rand_noisesrc(RAND_GLOBAL
, &noise_source
);
1574 rand_seed(RAND_GLOBAL
, 160);
1576 /* --- Initialize the options table --- */
1578 addopts(sopts
, opts
);
1583 /* --- Read the generator out of the first argument --- */
1585 if (argc
> 1 && *argv
[1] != '-') {
1586 const char *arg
= av
[1];
1587 size_t sz
= strlen(arg
);
1591 for (gg
= generators
; gg
->name
; gg
++) {
1592 if (strncmp(arg
, gg
->name
, sz
) == 0) {
1593 if (gg
->name
[sz
] == 0) {
1597 die(EXIT_FAILURE
, "ambiguous generator name `%s'", arg
);
1603 die(EXIT_FAILURE
, "unknown generator name `%s'", arg
);
1608 /* --- Get a generic random number generator --- */
1611 if (!r
|| optind
!= ac
- 1) {
1616 /* --- Do the FIPS test --- */
1618 if (flags
& f_fips
) {
1619 octet buf
[FIPSTEST_BUFSZ
];
1624 t
= mp_fromsizet(MP_NEW
, sizeof(buf
));
1625 generate(r
, t
, genbuf
, &p
);
1628 if (rc
& FIPSTEST_MONOBIT
)
1629 moan("failed monobit test");
1630 if (rc
& FIPSTEST_POKER
)
1631 moan("failed poker test");
1632 if (rc
& FIPSTEST_RUNS
)
1633 moan("failed runs test");
1634 if (rc
& FIPSTEST_LONGRUNS
)
1635 moan("failed long runs test");
1636 if (!rc
&& (flags
& f_progress
))
1637 fputs("test passed\n", stderr
);
1638 return (rc ? EXIT_FAILURE
: 0);
1641 /* --- Do Maurer's test --- */
1643 if (flags
& f_maurer
) {
1650 static struct { double x
; const char *sig
; } sigtab
[] = {
1658 g
.n
= maurer_hi
- maurer_lo
+ 1;
1659 g
.m
= xmalloc(g
.n
* sizeof(maurer_ctx
));
1660 for (i
= 0; i
< g
.n
; i
++)
1661 maurer_init(&g
.m
[i
], i
+ maurer_lo
);
1662 bufsz
= (100 * maurer_hi
) << maurer_hi
;
1664 t
= mp_fromsizet(MP_NEW
, bufsz
);
1665 generate(r
, t
, genmaurer
, &g
);
1668 for (i
= maurer_lo
; i
<= maurer_hi
; i
++) {
1669 double z
= maurer_done(&g
.m
[i
- maurer_lo
]);
1670 double zz
= fabs(z
);
1673 for (j
= 0; sigtab
[j
].sig
; j
++) {
1674 if (zz
> sigtab
[j
].x
) {
1676 moan("failed, bits = %u, sig = %s, Z_u = %g",
1677 i
, sigtab
[j
].sig
, z
);
1681 if (flags
& f_progress
)
1682 fprintf(stderr
, "bits = %u, Z_u = %g\n", i
, z
);
1689 /* --- Discard --- */
1691 if (flags
& f_discard
) {
1692 generate(r
, outsz
, 0, 0);
1696 /* --- Write to a file --- */
1699 if (!(flags
& f_file
) && isatty(STDOUT_FILENO
))
1700 die(EXIT_FAILURE
, "writing output to a terminal is a bad idea");
1703 generate(r
, outsz
, genfile
, outfp
);
1711 /*----- That's all, folks -------------------------------------------------*/