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