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