summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2007-10-16 01:27:15 +0200
committerStefan Metzmacher <metze@samba.org>2007-12-21 05:43:03 +0100
commit6554433fc227baab93398576db703c91db1541f2 (patch)
tree13437d4d9377c247afa30e4cb946b11a7c98c01c
parent1eaefd15cb7ad20165ea4c754535986b642e24f0 (diff)
downloadsamba-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)
-rw-r--r--source4/auth/ntlmssp/ntlmssp_client.c2
-rw-r--r--source4/lib/util/genrand.c68
-rw-r--r--source4/lib/util/util.h8
3 files changed, 59 insertions, 19 deletions
diff --git a/source4/auth/ntlmssp/ntlmssp_client.c b/source4/auth/ntlmssp/ntlmssp_client.c
index 61d6f1b25f..bff9fc0b8a 100644
--- a/source4/auth/ntlmssp/ntlmssp_client.c
+++ b/source4/auth/ntlmssp/ntlmssp_client.c
@@ -226,7 +226,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
/* Make up a new session key */
uint8_t client_session_key[16];
- generate_random_buffer(client_session_key, sizeof(client_session_key));
+ generate_secret_buffer(client_session_key, sizeof(client_session_key));
/* Encrypt the new session key with the old one */
encrypted_session_key = data_blob_talloc(gensec_ntlmssp_state,
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);