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