Change rand_pool_bytes_needed to handle less entropy than 1 per 8 bits
authorRichard Levitte <levitte@openssl.org>
Wed, 2 May 2018 04:24:20 +0000 (06:24 +0200)
committerRichard Levitte <levitte@openssl.org>
Wed, 2 May 2018 08:18:29 +0000 (10:18 +0200)
rand_pool_bytes_needed() was constructed in such a way that the
smallest acceptable entropy factor was 1 entropy bits per 8 bits of
data.  At the same time, we have a DRBG_MINMAX_FACTOR that allows
weaker source, as small as 1 bit of entropy per 128 bits of data.
The conclusion is that rand_pool_bytes_needed() needs to change to
support weaker entropy sources.  We therefore change the input of
entropy per byte to be an entropy factor instead.  This entropy factor
expresses how many bits of data it takes (on average) to get 1 bit of
entropy.

Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
(Merged from https://github.com/openssl/openssl/pull/6150)

crypto/include/internal/rand_int.h
crypto/rand/rand_lib.c
crypto/rand/rand_unix.c
crypto/rand/rand_vms.c
crypto/rand/rand_win.c

index cf82e4a..daec926 100644 (file)
@@ -63,7 +63,8 @@ size_t rand_pool_length(RAND_POOL *pool);
 
 size_t rand_pool_entropy_available(RAND_POOL *pool);
 size_t rand_pool_entropy_needed(RAND_POOL *pool);
-size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_per_byte);
+/* |entropy_factor| expresses how many bits of data contain 1 bit of entropy */
+size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor);
 size_t rand_pool_bytes_remaining(RAND_POOL *pool);
 
 int rand_pool_add(RAND_POOL *pool,
index 8a657c5..050c9d2 100644 (file)
@@ -87,7 +87,7 @@ size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool)
     size_t bytes_needed;
     unsigned char *buffer;
 
-    bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     if (bytes_needed > 0) {
         buffer = rand_pool_add_begin(pool, bytes_needed);
 
@@ -158,7 +158,7 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
     }
 
     if (drbg->parent) {
-        size_t bytes_needed = rand_pool_bytes_needed(pool, 8);
+        size_t bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
         unsigned char *buffer = rand_pool_add_begin(pool, bytes_needed);
 
         if (buffer != NULL) {
@@ -488,11 +488,11 @@ unsigned char *rand_pool_detach(RAND_POOL *pool)
 
 
 /*
- * If every byte of the input contains |entropy_per_bytes| bits of entropy,
- * how many bytes does one need to obtain at least |bits| bits of entropy?
+ * If |entropy_factor| bits contain 1 bit of entropy, how many bytes does one
+ * need to obtain at least |bits| bits of entropy?
  */
-#define ENTROPY_TO_BYTES(bits, entropy_per_bytes) \
-    (((bits) + ((entropy_per_bytes) - 1))/(entropy_per_bytes))
+#define ENTROPY_TO_BYTES(bits, entropy_factor) \
+    (((bits) * (entropy_factor) + 7) / 8)
 
 
 /*
@@ -529,21 +529,21 @@ size_t rand_pool_entropy_needed(RAND_POOL *pool)
 
 /*
  * Returns the number of bytes needed to fill the pool, assuming
- * the input has 'entropy_per_byte' entropy bits per byte.
+ * the input has 1 / |entropy_factor| entropy bits per data bit.
  * In case of an error, 0 is returned.
  */
 
-size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_per_byte)
+size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor)
 {
     size_t bytes_needed;
     size_t entropy_needed = rand_pool_entropy_needed(pool);
 
-    if (entropy_per_byte < 1 || entropy_per_byte > 8) {
+    if (entropy_factor < 1) {
         RANDerr(RAND_F_RAND_POOL_BYTES_NEEDED, RAND_R_ARGUMENT_OUT_OF_RANGE);
         return 0;
     }
 
-    bytes_needed = ENTROPY_TO_BYTES(entropy_needed, entropy_per_byte);
+    bytes_needed = ENTROPY_TO_BYTES(entropy_needed, entropy_factor);
 
     if (bytes_needed > pool->max_len - pool->len) {
         /* not enough space left */
index 9b6971c..1f0084d 100644 (file)
@@ -124,7 +124,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
     extern void s$sleep2(long long *_duration, short int *_code);
 #  endif
 
-    bytes_needed = rand_pool_bytes_needed(pool, 2 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 4 /*entropy_factor*/);
 
     for (i = 0; i < bytes_needed; i++) {
         /*
@@ -278,7 +278,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
     unsigned char *buffer;
 
 #   ifdef OPENSSL_RAND_SEED_GETRANDOM
-    bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     buffer = rand_pool_add_begin(pool, bytes_needed);
     if (buffer != NULL) {
         size_t bytes = 0;
@@ -300,7 +300,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
 #   endif
 
 #   ifdef OPENSSL_RAND_SEED_DEVRANDOM
-    bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     if (bytes_needed > 0) {
         static const char *paths[] = { DEVRANDOM, NULL };
         FILE *fp;
@@ -323,7 +323,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
             if (entropy_available > 0)
                 return entropy_available;
 
-            bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+            bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
         }
     }
 #   endif
@@ -341,7 +341,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
 #   endif
 
 #   ifdef OPENSSL_RAND_SEED_EGD
-    bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     if (bytes_needed > 0) {
         static const char *paths[] = { DEVRANDOM_EGD, NULL };
         int i;
index c50b4b2..5561abc 100644 (file)
@@ -58,10 +58,12 @@ static struct items_data_st {
 };
 
 /*
- * We assume there we get about 4 bits of entropy per byte from the items
- * above, with a bit of scrambling added rand_pool_acquire_entropy()
+ * This number expresses how many bits of data contain 1 bit of entropy.
+ *
+ * For the moment, we assume about 0.5 entropy bits per data bit, or 1
+ * bit of entropy per 2 data bits.
  */
-#define ENTROPY_BITS_PER_BYTE   4
+#define ENTROPY_FACTOR  2
 
 size_t rand_pool_acquire_entropy(RAND_POOL *pool)
 {
@@ -83,7 +85,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
     size_t i, j ;
     size_t tmp_length   = 0;
     size_t total_length = 0;
-    size_t bytes_needed = rand_pool_bytes_needed(pool, ENTROPY_BITS_PER_BYTE);
+    size_t bytes_needed = rand_pool_bytes_needed(pool, ENTROPY_FACTOR);
     size_t bytes_remaining = rand_pool_bytes_remaining(pool);
 
     /* Setup itemlist for GETJPI */
@@ -149,8 +151,9 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
     if (total_length > bytes_remaining)
         total_length = bytes_remaining;
 
+    /* We give the pessimistic value for the amount of entropy */
     rand_pool_add(pool, (PTR_T)data_buffer, total_length,
-                  total_length * ENTROPY_BITS_PER_BYTE);
+                  total_length / ENTROPY_FACTOR);
     return rand_pool_entropy_available(pool);
 }
 
index 1d44204..f2059eb 100644 (file)
@@ -62,7 +62,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
 # endif
 
 # ifdef USE_BCRYPTGENRANDOM
-    bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     buffer = rand_pool_add_begin(pool, bytes_needed);
     if (buffer != NULL) {
         size_t bytes = 0;
@@ -76,7 +76,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
     if (entropy_available > 0)
         return entropy_available;
 # else
-    bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     buffer = rand_pool_add_begin(pool, bytes_needed);
     if (buffer != NULL) {
         size_t bytes = 0;
@@ -95,7 +95,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
     if (entropy_available > 0)
         return entropy_available;
 
-    bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/);
+    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
     buffer = rand_pool_add_begin(pool, bytes_needed);
     if (buffer != NULL) {
         size_t bytes = 0;