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