From 27d41d48e00db45eeff2b191d54deea890f443b8 Mon Sep 17 00:00:00 2001 From: mdw Date: Mon, 8 Dec 1997 15:29:27 +0000 Subject: [PATCH] Major update: make random number sources configurable. Generate warnings if there isn't enough randomness available. --- src/keygen.c | 178 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 128 insertions(+), 50 deletions(-) diff --git a/src/keygen.c b/src/keygen.c index eba38d9..4e016fa 100644 --- a/src/keygen.c +++ b/src/keygen.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: keygen.c,v 1.3 1997/09/17 15:29:28 mdw Exp $ + * $Id: keygen.c,v 1.4 1997/12/08 15:29:27 mdw Exp $ * * Key generation * @@ -29,7 +29,11 @@ /*----- Revision history --------------------------------------------------* * * $Log: keygen.c,v $ - * Revision 1.3 1997/09/17 15:29:28 mdw + * Revision 1.4 1997/12/08 15:29:27 mdw + * Major update: make random number sources configurable. Generate + * warnings if there isn't enough randomness available. + * + * Revision 1.3 1997/09/17 15:29:28 mdw * Mix the noise from the key timings with some other environmental noise * (obtained from `noise_acquire') for a little bit more randomness. * @@ -434,9 +438,16 @@ int main(int argc, char *argv[]) { unsigned char *uip; size_t sz = 128; + size_t keybits = 0; + unsigned f = 0; const char *file = 0; FILE *fp; + enum { + f_envNoise = 1, + f_keyTimer = 2 + }; + /* --- Formats table --- */ static struct { @@ -456,33 +467,45 @@ int main(int argc, char *argv[]) ego(argv[0]); + f |= f_envNoise | f_keyTimer; + /* --- Read arguments --- */ for (;;) { static struct option opts[] = { - { "help", 0, 0, 'h' }, - { "bits", gFlag_argReq, 0, 'b' }, - { "output", gFlag_argReq, 0, 'o' }, - { "format", gFlag_argReq, 0, 'f' }, - { 0, 0, 0, 0 } + { "help", 0, 0, 'h' }, + { "bits", gFlag_argReq, 0, 'b' }, + { "output", gFlag_argReq, 0, 'o' }, + { "format", gFlag_argReq, 0, 'f' }, + { "key-times", gFlag_negate|gFlag_argOpt, 0, 'k' }, + { "env-noise", gFlag_negate, 0, 'e' }, + { 0, 0, 0, 0 } }; - int i = mdwopt(argc, argv, "hb:o:f:", opts, 0, 0, 0); + int i = mdwopt(argc, argv, "hb:o:f:k+::e+", opts, 0, 0, gFlag_negation); if (i < 0) break; switch (i) { case 'h': printf("" -"Usage: %s [--bits=BITS] [--output=FILE] [--format=FORMAT]\n" +"Usage: %s [-h] [-|+ek] [-b BITS] [-o FILE] [-f FORMAT]\n" "\n" -"Generates BITS (by default, 128) random bits by timing keypresses. The\n" -"resulting number is written to FILE, or standard output in the given\n" -"format. Formats currently supported are:\n" -"\n" -"tx, hex Hexadecimal, with punctuating dashes.\n" -"binary Raw binary.\n" -"base64 Base64-encoded binary; the result is printable ASCII.\n", +"Generates BITS (by default, 128) random bits. The resulting number is\n" +"written to FILE, or standard output.\n\n" +"Randomness is taken from key-timings and environmental noise, although\n" +"you can disable either (or both) of these sources.\n\n" +"Options provided are:\n\n" +"-h, --help Display this help text\n" +"-b, --bits=BITS\t Generate BITS random bits instead of 128\n" +"-o, --output=FILE Write bits to FILE, not standard output\n" +"-f, --format=FORMAT Write bits in FORMAT:\n" +" tx, hex Hexadecimal\n" +" binary Raw binary\n" +" base64 Base64-encoded binary\n" +"-e, --[no-]env-noise Do [not] read environmental noise\n" +"-k, --[no-]key-times[=BITS] Do [not] read key timing information\n" +" (only read BITS bits from key timings)\n", quis()); exit(0); break; @@ -516,29 +539,107 @@ int main(int argc, char *argv[]) if (!fmt) die("unknown format name: `%s'", optarg); break; + case 'e': + f |= f_envNoise; + break; + case 'e' | gFlag_negated: + f &= ~f_envNoise; + break; + case 'k': + f |= f_keyTimer; + if (optarg) { + keybits = atoi(optarg); + if (keybits == 0) + die("bad number of bits (illegible or zero)"); + if (keybits % 8) + die("bad number of bits (must be multiple of 8)"); + } + else + keybits = 0; + break; + case 'k' | gFlag_negated: + f &= ~f_keyTimer; + break; case '?': exit(1); break; } } + /* --- Check the sanity of this request --- */ + + { + size_t bits = 0; + + if (f & f_keyTimer) { + if (!keybits) + keybits = sz; + bits += keybits; + } + if (f & f_envNoise) + bits += 384; /* Estimate */ + + if (bits == 0) + die("no randomness sources given"); + if (bits < sz) + moan("warning: randomness may not be sufficiently high"); + } + if (optind < argc) { - fprintf(stderr, "Usage: %s [--bits=BITS] [--output=FILE]\n", quis()); + fprintf(stderr, "Usage: %s [-opts]\n", quis()); exit(1); } /* --- Allocate memory --- */ - uip = xmalloc(sz / 8); + { + size_t buff = sz / 8; + if (f & f_keyTimer && keybits > sz) + buff = keybits / 8; + uip = xmalloc(buff); + } + + rand_clear(); + + /* --- Fetch randomness from key timings --- */ + + if (f & f_keyTimer) { + + /* --- Open the terminal --- * + * + * I'd like to be able to @fprintf@ to the terminal, so use @fopen@. + */ + + if ((kg__ttyfp = fopen("/dev/tty", "r+")) == 0) + die("couldn't open terminal: %s", strerror(errno)); + kg__tty = fileno(kg__ttyfp); - /* --- Open the terminal --- * - * - * I'd like to be able to @fprintf@ to the terminal, so use @fopen@. - */ + /* --- Tidy up nicely if I die --- */ - if ((kg__ttyfp = fopen("/dev/tty", "r+")) == 0) - die("couldn't open terminal: %s", strerror(errno)); - kg__tty = fileno(kg__ttyfp); + signal(SIGINT, kg__signal); + signal(SIGTERM, kg__signal); + atexit(kg__crepair); + + /* --- Put the terminal into cbreak, read the key, and restore --- */ + + kg__cbreak(); + kg__gen(uip, keybits); + kg__crepair(); + rand_add(uip, keybits / 8); + rand_churn(); + } + + /* --- Find some noise from the environment too --- */ + + if (f & f_envNoise) { + noise_acquire(); + rand_churn(); + } + + /* --- Now write the number and exit --- */ + + rand_extract(uip, sz / 8); + D( fputs("*** ", fp); tx_putBits(uip, sz, stdout); ) /* --- Open the output file, if one is specified --- */ @@ -550,8 +651,8 @@ int main(int argc, char *argv[]) * There's a good reason for this. I want to be able to @fprintf@ (for * the benefit of @tx_putWords@ mainly) but I also want to ensure that * only the user has read permissions for the file. So I'll use @open@ - * with an appropriate mode and then @fdopen@ the file descriptor to get - * a stream. Yuk. + * with an appropriate mode and then @fdopen@ the file descriptor to + * get a stream. Yuk. */ if ((fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) @@ -561,29 +662,6 @@ int main(int argc, char *argv[]) } else fp = stdout; - /* --- Tidy up nicely if I die --- */ - - signal(SIGINT, kg__signal); - signal(SIGTERM, kg__signal); - atexit(kg__crepair); - - /* --- Put the terminal into cbreak, read the key, and restore --- */ - - kg__cbreak(); - kg__gen(uip, sz); - kg__crepair(); - - /* --- Find some noise from the environment too --- */ - - rand_clear(); - noise_acquire(); - rand_add(uip, sz / 8); - rand_churn(); - rand_extract(uip, sz / 8); - - /* --- Now write the number and exit --- */ - - D( fputs("*** ", fp); tx_putBits(uip, sz, stdout); ) fmt(uip, sz, fp); if (file) fclose(fp); -- 2.11.0