diff options
author | Andrew Bartlett <abartlet@samba.org> | 2007-10-16 01:27:15 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2007-12-21 05:43:03 +0100 |
commit | 6554433fc227baab93398576db703c91db1541f2 (patch) | |
tree | 13437d4d9377c247afa30e4cb946b11a7c98c01c /source4/lib/util | |
parent | 1eaefd15cb7ad20165ea4c754535986b642e24f0 (diff) | |
download | samba-6554433fc227baab93398576db703c91db1541f2.tar.gz samba-6554433fc227baab93398576db703c91db1541f2.tar.bz2 samba-6554433fc227baab93398576db703c91db1541f2.zip |
r25660: Add a new interface 'generate_secret_buffer()', to be used when we
require top-quality entropy. We don't want to waste system enropy
generating challenges (which simply need to be unpredictable, not
secret) or when generating UUIDs.
Rework generate_random_buffer() to use /dev/urandom less often, only
to seed the existing RC4 based PRNG. (With an exception to ensure we
don't waste this setup cost for very small entropy requests).
Perhaps we should be using heimdal's code for this instead?
This should drasticly reduce our entropy use, particularly in the
build farm (automated Samba build on hosts without much other source
of entropy).
Andrew Bartlett
(This used to be commit 6a5630d37191542022f02fae519227b7829ef620)
Diffstat (limited to 'source4/lib/util')
-rw-r--r-- | source4/lib/util/genrand.c | 68 | ||||
-rw-r--r-- | source4/lib/util/util.h | 8 |
2 files changed, 58 insertions, 18 deletions
diff --git a/source4/lib/util/genrand.c b/source4/lib/util/genrand.c index 4d976cecf8..31c0fce633 100644 --- a/source4/lib/util/genrand.c +++ b/source4/lib/util/genrand.c @@ -33,6 +33,10 @@ static unsigned char hash[258]; static uint32_t counter; static bool done_reseed = false; +static unsigned int bytes_since_reseed = 0; + +static int urand_fd = -1; + static void (*reseed_callback)(int *newseed); /** @@ -51,6 +55,7 @@ _PUBLIC_ void set_rand_reseed_callback(void (*fn)(int *)) _PUBLIC_ void set_need_random_reseed(void) { done_reseed = false; + bytes_since_reseed = 0; } static void get_rand_reseed_data(int *reseed_data) @@ -163,12 +168,16 @@ static int do_reseed(bool use_fd, int fd) int reseed_data = 0; if (use_fd) { - if (fd != -1) - return fd; - - fd = open( "/dev/urandom", O_RDONLY,0); - if(fd >= 0) + if (fd == -1) { + fd = open( "/dev/urandom", O_RDONLY,0); + } + if (fd != -1 + && (read(fd, seed_inbuf, sizeof(seed_inbuf)) == sizeof(seed_inbuf))) { + DEBUG(0, ("do_reseed: need %d\n", sizeof(seed_inbuf))); + call_backtrace(); + seed_random_stream(seed_inbuf, sizeof(seed_inbuf)); return fd; + } } /* Add in some secret file contents */ @@ -205,28 +214,33 @@ static int do_reseed(bool use_fd, int fd) /** Interface to the (hopefully) good crypto random number generator. + Will use our internal PRNG if more than 40 bytes of random generation + has been requested, otherwise tries to read from /dev/random **/ _PUBLIC_ void generate_random_buffer(uint8_t *out, int len) { - static int urand_fd = -1; unsigned char md4_buf[64]; unsigned char tmp_buf[16]; unsigned char *p; if(!done_reseed) { - urand_fd = do_reseed(true, urand_fd); - done_reseed = true; - } - - if (urand_fd != -1 && len > 0) { - - if (read(urand_fd, out, len) == len) - return; /* len bytes of random data read from urandom. */ + bytes_since_reseed += len; + + /* Magic constant to try and avoid reading 40 bytes + * and setting up the PRNG if the app only ever wants + * a few bytes */ + if (bytes_since_reseed < 40) { + if (urand_fd == -1) { + urand_fd = open( "/dev/urandom", O_RDONLY,0); + } + DEBUG(0, ("generate_random_buffer: need %d\n", len)); + call_backtrace(); + if(urand_fd != -1 && (read(urand_fd, out, len) == len)) { + return; + } + } - /* Read of urand error, drop back to non urand method. */ - close(urand_fd); - urand_fd = -1; - do_reseed(false, -1); + urand_fd = do_reseed(true, urand_fd); done_reseed = true; } @@ -250,6 +264,24 @@ _PUBLIC_ void generate_random_buffer(uint8_t *out, int len) } /** + Interface to the (hopefully) good crypto random number generator. + Will always use /dev/urandom if available. +**/ +_PUBLIC_ void generate_secret_buffer(uint8_t *out, int len) +{ + if (urand_fd == -1) { + urand_fd = open( "/dev/urandom", O_RDONLY,0); + } + DEBUG(0, ("generate_random_buffer: need %d\n", len)); + call_backtrace(); + if(urand_fd != -1 && (read(urand_fd, out, len) == len)) { + return; + } + + generate_random_buffer(out, len); +} + +/** generate a single random uint32_t **/ _PUBLIC_ uint32_t generate_random(void) diff --git a/source4/lib/util/util.h b/source4/lib/util/util.h index 42dde70a44..fc9cb1e57a 100644 --- a/source4/lib/util/util.h +++ b/source4/lib/util/util.h @@ -226,10 +226,18 @@ _PUBLIC_ void set_need_random_reseed(void); /** Interface to the (hopefully) good crypto random number generator. + Will use our internal PRNG if more than 40 bytes of random generation + has been requested, otherwise tries to read from /dev/random **/ _PUBLIC_ void generate_random_buffer(uint8_t *out, int len); /** + Interface to the (hopefully) good crypto random number generator. + Will always use /dev/urandom if available. +**/ +_PUBLIC_ void generate_secret_buffer(uint8_t *out, int len); + +/** generate a single random uint32_t **/ _PUBLIC_ uint32_t generate_random(void); |