Modify the DEVRANDOM source so that the files are kept open persistently.
[openssl.git] / crypto / rand / rand_lib.c
index 5ae51a16a224a53b7b0dcc82dacc7ef2261e0748..d31735c5c45a1b01ca266072995edf3a78f30c8e 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) {
@@ -303,26 +303,43 @@ void rand_drbg_cleanup_additional_data(unsigned char *out, size_t outlen)
     OPENSSL_secure_clear_free(out, outlen);
 }
 
-void rand_fork()
+void rand_fork(void)
 {
     rand_fork_count++;
 }
 
 DEFINE_RUN_ONCE_STATIC(do_rand_init)
 {
-    int ret = 1;
-
 #ifndef OPENSSL_NO_ENGINE
     rand_engine_lock = CRYPTO_THREAD_lock_new();
-    ret &= rand_engine_lock != NULL;
+    if (rand_engine_lock == NULL)
+        return 0;
 #endif
+
     rand_meth_lock = CRYPTO_THREAD_lock_new();
-    ret &= rand_meth_lock != NULL;
+    if (rand_meth_lock == NULL)
+        goto err1;
 
     rand_nonce_lock = CRYPTO_THREAD_lock_new();
-    ret &= rand_meth_lock != NULL;
+    if (rand_nonce_lock == NULL)
+        goto err2;
 
-    return ret;
+    if (!rand_pool_init())
+        goto err3;
+
+    return 1;
+
+err3:
+    rand_pool_cleanup();
+err2:
+    CRYPTO_THREAD_lock_free(rand_meth_lock);
+    rand_meth_lock = NULL;
+err1:
+#ifndef OPENSSL_NO_ENGINE
+    CRYPTO_THREAD_lock_free(rand_engine_lock);
+    rand_engine_lock = NULL;
+#endif
+    return 0;
 }
 
 void rand_cleanup_int(void)
@@ -331,12 +348,25 @@ void rand_cleanup_int(void)
 
     if (meth != NULL && meth->cleanup != NULL)
         meth->cleanup();
+    rand_pool_cleanup();
     RAND_set_rand_method(NULL);
 #ifndef OPENSSL_NO_ENGINE
     CRYPTO_THREAD_lock_free(rand_engine_lock);
+    rand_engine_lock = NULL;
 #endif
     CRYPTO_THREAD_lock_free(rand_meth_lock);
+    rand_meth_lock = NULL;
     CRYPTO_THREAD_lock_free(rand_nonce_lock);
+    rand_nonce_lock = NULL;
+}
+
+/*
+ * RAND_close_seed_files() ensures that any seed file decriptors are
+ * closed after use.
+ */
+void RAND_keep_random_devices_open(int keep)
+{
+    rand_pool_keep_random_devices_open(keep);
 }
 
 /*
@@ -473,11 +503,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)
 
 
 /*
@@ -514,21 +544,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 */