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