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