The unified diff between revisions [d0935a5d..] and [e0686662..] is displayed below. It can also be downloaded as a raw diff.

This diff has been restricted to the following files: 'random.c'

#
#
# patch "random.c"
#  from [310a24216932705d6c33fd40a1bf51caf0b682af]
#    to [6b27327c1fd2cc9eca918be77a997c93404ab00d]
#
============================================================
--- random.c	310a24216932705d6c33fd40a1bf51caf0b682af
+++ random.c	6b27327c1fd2cc9eca918be77a997c93404ab00d
@@ -25,14 +25,15 @@
 #include "includes.h"
 #include "buffer.h"
 #include "dbutil.h"
+#include "bignum.h"

-int donerandinit = 0;
+static int donerandinit = 0;

 /* this is used to generate unique output from the same hashpool */
-unsigned int counter = 0;
+static unsigned int counter = 0;
 #define MAX_COUNTER 1000000/* the max value for the counter, so it won't loop */

-unsigned char hashpool[SHA1_HASH_SIZE];
+static unsigned char hashpool[SHA1_HASH_SIZE];

 #define INIT_SEED_SIZE 32 /* 256 bits */

@@ -50,6 +51,7 @@ static void readrand(unsigned char* buf,

 static void readrand(unsigned char* buf, unsigned int buflen) {

+	static int already_blocked = 0;
 	int readfd;
 	unsigned int readpos;
 	int readlen;
@@ -92,6 +94,24 @@ static void readrand(unsigned char* buf,
 	/* read the actual random data */
 	readpos = 0;
 	do {
+		if (!already_blocked)
+		{
+			int ret;
+			struct timeval timeout;
+			fd_set read_fds;
+
+			timeout.tv_sec = 2; /* two seconds should be enough */
+			timeout.tv_usec = 0;
+
+			FD_ZERO(&read_fds);
+			FD_SET(readfd, &read_fds);
+			ret = select(readfd + 1, &read_fds, NULL, NULL, &timeout);
+			if (ret == 0)
+			{
+				dropbear_log(LOG_INFO, "Warning: Reading the random source seems to have blocked.\nIf you experience problems, you probably need to find a better entropy source.");
+				already_blocked = 1;
+			}
+		}
 		readlen = read(readfd, &buf[readpos], buflen - readpos);
 		if (readlen <= 0) {
 			if (readlen < 0 && errno == EINTR) {
@@ -159,3 +179,38 @@ void genrandom(unsigned char* buf, unsig
 	}
 	m_burn(hash, sizeof(hash));
 }
+
+/* Generates a random mp_int.
+ * max is a *mp_int specifying an upper bound.
+ * rand must be an initialised *mp_int for the result.
+ * the result rand satisfies:  0 < rand < max
+ * */
+void gen_random_mpint(mp_int *max, mp_int *rand) {
+
+	unsigned char *randbuf = NULL;
+	unsigned int len = 0;
+	const char masks[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f};
+
+	const int size_bits = mp_count_bits(max);
+
+	len = size_bits / 8;
+	if ((size_bits % 8) != 0) {
+		len += 1;
+	}
+
+	randbuf = (unsigned char*)m_malloc(len);
+	do {
+		genrandom(randbuf, len);
+		/* Mask out the unrequired bits - mp_read_unsigned_bin expects
+		 * MSB first.*/
+		randbuf[0] &= masks[size_bits % 8];
+
+		bytes_to_mp(rand, randbuf, len);
+
+		/* keep regenerating until we get one satisfying
+		 * 0 < rand < max    */
+	} while ( ( (max != NULL) && (mp_cmp(rand, max) != MP_LT) )
+			|| (mp_cmp_d(rand, 0) != MP_GT) );
+	m_burn(randbuf, len);
+	m_free(randbuf);
+}