svn commit: samba r25660 - in branches/SAMBA_4_0/source: auth/ntlmssp lib/util

abartlet at samba.org abartlet at samba.org
Tue Oct 16 01:27:18 GMT 2007


Author: abartlet
Date: 2007-10-16 01:27:15 +0000 (Tue, 16 Oct 2007)
New Revision: 25660

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=25660

Log:
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

Modified:
   branches/SAMBA_4_0/source/auth/ntlmssp/ntlmssp_client.c
   branches/SAMBA_4_0/source/lib/util/genrand.c
   branches/SAMBA_4_0/source/lib/util/util.h


Changeset:
Modified: branches/SAMBA_4_0/source/auth/ntlmssp/ntlmssp_client.c
===================================================================
--- branches/SAMBA_4_0/source/auth/ntlmssp/ntlmssp_client.c	2007-10-15 20:19:20 UTC (rev 25659)
+++ branches/SAMBA_4_0/source/auth/ntlmssp/ntlmssp_client.c	2007-10-16 01:27:15 UTC (rev 25660)
@@ -226,7 +226,7 @@
 	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, 

Modified: branches/SAMBA_4_0/source/lib/util/genrand.c
===================================================================
--- branches/SAMBA_4_0/source/lib/util/genrand.c	2007-10-15 20:19:20 UTC (rev 25659)
+++ branches/SAMBA_4_0/source/lib/util/genrand.c	2007-10-16 01:27:15 UTC (rev 25660)
@@ -33,6 +33,10 @@
 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_need_random_reseed(void)
 {
 	done_reseed = false;
+	bytes_since_reseed = 0;
 }
 
 static void get_rand_reseed_data(int *reseed_data)
@@ -163,12 +168,16 @@
 	int reseed_data = 0;
 
 	if (use_fd) {
-		if (fd != -1)
+		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;
-
-		fd = open( "/dev/urandom", O_RDONLY,0);
-		if(fd >= 0)
-			return fd;
+		}
 	}
 
 	/* Add in some secret file contents */
@@ -205,31 +214,36 @@
 
 /**
  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) {
+		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;
+			}
+		}
+
 		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. */
-
-		/* Read of urand error, drop back to non urand method. */
-		close(urand_fd);
-		urand_fd = -1;
-		do_reseed(false, -1);
-		done_reseed = true;
-	}
-
 	/*
 	 * Generate random numbers in chunks of 64 bytes,
 	 * then md4 them & copy to the output buffer.
@@ -250,6 +264,24 @@
 }
 
 /**
+ 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)

Modified: branches/SAMBA_4_0/source/lib/util/util.h
===================================================================
--- branches/SAMBA_4_0/source/lib/util/util.h	2007-10-15 20:19:20 UTC (rev 25659)
+++ branches/SAMBA_4_0/source/lib/util/util.h	2007-10-16 01:27:15 UTC (rev 25660)
@@ -226,10 +226,18 @@
 
 /**
  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);



More information about the samba-cvs mailing list