basic/random-util: use most of the pseudorandom bytes from rand()
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 25 Jun 2017 21:32:53 +0000 (17:32 -0400)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 28 Jun 2017 14:24:53 +0000 (10:24 -0400)
The only implementation that we care about — glibc — provides us
with 31 bits of entropy. Let's use 24 bits of that, instead of throwing
all but 8 away.

src/basic/random-util.c
src/basic/random-util.h

index b216be5..b2ca2cc 100644 (file)
@@ -121,19 +121,44 @@ void initialize_srand(void) {
         srand_called = true;
 }
 
-void random_bytes(void *p, size_t n) {
+/* INT_MAX gives us only 31 bits, so use 24 out of that. */
+#if RAND_MAX >= INT_MAX
+#  define RAND_STEP 3
+#else
+/* SHORT_INT_MAX or lower gives at most 15 bits, we just just 8 out of that. */
+#  define RAND_STEP 1
+#endif
+
+void pseudorandom_bytes(void *p, size_t n) {
         uint8_t *q;
+
+        initialize_srand();
+
+        for (q = p; q < (uint8_t*) p + n; q += RAND_STEP) {
+                unsigned rr;
+
+                rr = (unsigned) rand();
+
+#if RAND_STEP >= 3
+                if (q - (uint8_t*) p + 2 < n)
+                        q[2] = rr >> 16;
+#endif
+#if RAND_STEP >= 2
+                if (q - (uint8_t*) p + 1 < n)
+                        q[1] = rr >> 8;
+#endif
+                q[0] = rr;
+        }
+}
+
+void random_bytes(void *p, size_t n) {
         int r;
 
         r = dev_urandom(p, n);
         if (r >= 0)
                 return;
 
-        /* If some idiot made /dev/urandom unavailable to us, he'll
-         * get a PRNG instead. */
-
-        initialize_srand();
-
-        for (q = p; q < (uint8_t*) p + n; q ++)
-                *q = rand();
+        /* If some idiot made /dev/urandom unavailable to us, or the
+         * kernel has no entropy, use a PRNG instead. */
+        return pseudorandom_bytes(p, n);
 }
index 3cee4c5..294ef4d 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdint.h>
 
 int dev_urandom(void *p, size_t n);
+void pseudorandom_bytes(void *p, size_t n);
 void random_bytes(void *p, size_t n);
 void initialize_srand(void);