md_rand: FAQ URL to use https and follow a redirect
[openssl.git] / crypto / rand / md_rand.c
index 0eaaf62863cd5909c63c04e4dabf88d1b02fe886..c7be2783da40bddd77a02e432825d378966966cc 100644 (file)
@@ -1,4 +1,3 @@
-/* crypto/rand/md_rand.c */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
 # include <time.h>
 #endif
 
+#include <openssl/opensslconf.h>
 #include <openssl/crypto.h>
 #include <openssl/rand.h>
+#include <openssl/async.h>
 #include "rand_lcl.h"
 
 #include <openssl/err.h>
@@ -171,7 +172,7 @@ static int rand_seed(const void *buf, int num);
 static int rand_add(const void *buf, int num, double add_entropy);
 static int rand_bytes(unsigned char *buf, int num, int pseudo);
 static int rand_nopseudo_bytes(unsigned char *buf, int num);
-#ifndef OPENSSL_NO_DEPRECATED
+#if OPENSSL_API_COMPAT < 0x10100000L
 static int rand_pseudo_bytes(unsigned char *buf, int num);
 #endif
 static int rand_status(void);
@@ -181,7 +182,7 @@ static RAND_METHOD rand_meth = {
     rand_nopseudo_bytes,
     rand_cleanup,
     rand_add,
-#ifndef OPENSSL_NO_DEPRECATED
+#if OPENSSL_API_COMPAT < 0x10100000L
     rand_pseudo_bytes,
 #else
     NULL,
@@ -211,7 +212,7 @@ static int rand_add(const void *buf, int num, double add)
     int i, j, k, st_idx;
     long md_c[2];
     unsigned char local_md[MD_DIGEST_LENGTH];
-    EVP_MD_CTX m;
+    EVP_MD_CTX *m;
     int do_not_lock;
     int rv = 0;
 
@@ -233,7 +234,10 @@ static int rand_add(const void *buf, int num, double add)
      * hash function.
      */
 
-    EVP_MD_CTX_init(&m);
+    m = EVP_MD_CTX_new();
+    if (m == NULL)
+        goto err;
+
     /* check if we already have the lock */
     if (crypto_lock_rand) {
         CRYPTO_THREADID cur;
@@ -283,21 +287,21 @@ static int rand_add(const void *buf, int num, double add)
         j = (num - i);
         j = (j > MD_DIGEST_LENGTH) ? MD_DIGEST_LENGTH : j;
 
-        if (!MD_Init(&m))
+        if (!MD_Init(m))
             goto err;
-        if (!MD_Update(&m, local_md, MD_DIGEST_LENGTH))
+        if (!MD_Update(m, local_md, MD_DIGEST_LENGTH))
             goto err;
         k = (st_idx + j) - STATE_SIZE;
         if (k > 0) {
-            if (!MD_Update(&m, &(state[st_idx]), j - k))
+            if (!MD_Update(m, &(state[st_idx]), j - k))
                 goto err;
-            if (!MD_Update(&m, &(state[0]), k))
+            if (!MD_Update(m, &(state[0]), k))
                 goto err;
-        } else if (!MD_Update(&m, &(state[st_idx]), j))
+        } else if (!MD_Update(m, &(state[st_idx]), j))
             goto err;
 
         /* DO NOT REMOVE THE FOLLOWING CALL TO MD_Update()! */
-        if (!MD_Update(&m, buf, j))
+        if (!MD_Update(m, buf, j))
             goto err;
         /*
          * We know that line may cause programs such as purify and valgrind
@@ -307,9 +311,9 @@ static int rand_add(const void *buf, int num, double add)
          * insecure keys.
          */
 
-        if (!MD_Update(&m, (unsigned char *)&(md_c[0]), sizeof(md_c)))
+        if (!MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c)))
             goto err;
-        if (!MD_Final(&m, local_md))
+        if (!MD_Final(m, local_md))
             goto err;
         md_c[1]++;
 
@@ -319,7 +323,7 @@ static int rand_add(const void *buf, int num, double add)
             /*
              * Parallel threads may interfere with this, but always each byte
              * of the new state is the XOR of some previous value of its and
-             * local_md (itermediate values may be lost). Alway using locking
+             * local_md (intermediate values may be lost). Alway using locking
              * could hurt performance more than necessary given that
              * conflicts occur only when the total seeding is longer than the
              * random state.
@@ -351,7 +355,7 @@ static int rand_add(const void *buf, int num, double add)
 #endif
     rv = 1;
  err:
-    EVP_MD_CTX_cleanup(&m);
+    EVP_MD_CTX_free(m);
     return rv;
 }
 
@@ -368,7 +372,7 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo)
     int ok;
     long md_c[2];
     unsigned char local_md[MD_DIGEST_LENGTH];
-    EVP_MD_CTX m;
+    EVP_MD_CTX *m;
 #ifndef GETPID_IS_MEANINGLESS
     pid_t curr_pid = getpid();
 #endif
@@ -408,7 +412,10 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo)
     if (num <= 0)
         return 1;
 
-    EVP_MD_CTX_init(&m);
+    m = EVP_MD_CTX_new();
+    if (m == NULL)
+        goto err_mem;
+
     /* round upwards to multiple of MD_DIGEST_LENGTH/2 */
     num_ceil =
         (1 + (num - 1) / (MD_DIGEST_LENGTH / 2)) * (MD_DIGEST_LENGTH / 2);
@@ -432,6 +439,11 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo)
      */
 
     CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+    /*
+     * We could end up in an async engine while holding this lock so ensure
+     * we don't pause and cause a deadlock
+     */
+    ASYNC_block_pause();
 
     /* prevent rand_bytes() from trying to obtain the lock again */
     CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
@@ -510,55 +522,44 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo)
 
     /* before unlocking, we must clear 'crypto_lock_rand' */
     crypto_lock_rand = 0;
+    ASYNC_unblock_pause();
     CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
 
     while (num > 0) {
         /* num_ceil -= MD_DIGEST_LENGTH/2 */
         j = (num >= MD_DIGEST_LENGTH / 2) ? MD_DIGEST_LENGTH / 2 : num;
         num -= j;
-        if (!MD_Init(&m))
+        if (!MD_Init(m))
             goto err;
 #ifndef GETPID_IS_MEANINGLESS
         if (curr_pid) {         /* just in the first iteration to save time */
-            if (!MD_Update(&m, (unsigned char *)&curr_pid, sizeof curr_pid))
+            if (!MD_Update(m, (unsigned char *)&curr_pid, sizeof curr_pid))
                 goto err;
             curr_pid = 0;
         }
 #endif
         if (curr_time) {        /* just in the first iteration to save time */
-            if (!MD_Update(&m, (unsigned char *)&curr_time, sizeof curr_time))
+            if (!MD_Update(m, (unsigned char *)&curr_time, sizeof curr_time))
                 goto err;
-            if (!MD_Update(&m, (unsigned char *)&tv, sizeof tv))
+            if (!MD_Update(m, (unsigned char *)&tv, sizeof tv))
                 goto err;
             curr_time = 0;
-            rand_hw_seed(&m);
+            rand_hw_seed(m);
         }
-        if (!MD_Update(&m, local_md, MD_DIGEST_LENGTH))
+        if (!MD_Update(m, local_md, MD_DIGEST_LENGTH))
             goto err;
-        if (!MD_Update(&m, (unsigned char *)&(md_c[0]), sizeof(md_c)))
+        if (!MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c)))
             goto err;
 
-#ifndef PURIFY                  /* purify complains */
-        /*
-         * The following line uses the supplied buffer as a small source of
-         * entropy: since this buffer is often uninitialised it may cause
-         * programs such as purify or valgrind to complain. So for those
-         * builds it is not used: the removal of such a small source of
-         * entropy has negligible impact on security.
-         */
-        if (!MD_Update(&m, buf, j))
-            goto err;
-#endif
-
         k = (st_idx + MD_DIGEST_LENGTH / 2) - st_num;
         if (k > 0) {
-            if (!MD_Update(&m, &(state[st_idx]), MD_DIGEST_LENGTH / 2 - k))
+            if (!MD_Update(m, &(state[st_idx]), MD_DIGEST_LENGTH / 2 - k))
                 goto err;
-            if (!MD_Update(&m, &(state[0]), k))
+            if (!MD_Update(m, &(state[0]), k))
                 goto err;
-        } else if (!MD_Update(&m, &(state[st_idx]), MD_DIGEST_LENGTH / 2))
+        } else if (!MD_Update(m, &(state[st_idx]), MD_DIGEST_LENGTH / 2))
             goto err;
-        if (!MD_Final(&m, local_md))
+        if (!MD_Final(m, local_md))
             goto err;
 
         for (i = 0; i < MD_DIGEST_LENGTH / 2; i++) {
@@ -571,18 +572,23 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo)
         }
     }
 
-    if (!MD_Init(&m)
-        || !MD_Update(&m, (unsigned char *)&(md_c[0]), sizeof(md_c))
-        || !MD_Update(&m, local_md, MD_DIGEST_LENGTH))
+    if (!MD_Init(m)
+        || !MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c))
+        || !MD_Update(m, local_md, MD_DIGEST_LENGTH))
         goto err;
     CRYPTO_w_lock(CRYPTO_LOCK_RAND);
-    if (!MD_Update(&m, md, MD_DIGEST_LENGTH) || !MD_Final(&m, md)) {
+    /*
+     * Prevent deadlocks if we end up in an async engine
+     */
+    ASYNC_block_pause();
+    if (!MD_Update(m, md, MD_DIGEST_LENGTH) || !MD_Final(m, md)) {
         CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
         goto err;
     }
+    ASYNC_unblock_pause();
     CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
 
-    EVP_MD_CTX_cleanup(&m);
+    EVP_MD_CTX_free(m);
     if (ok)
         return (1);
     else if (pseudo)
@@ -590,12 +596,16 @@ static int rand_bytes(unsigned char *buf, int num, int pseudo)
     else {
         RANDerr(RAND_F_RAND_BYTES, RAND_R_PRNG_NOT_SEEDED);
         ERR_add_error_data(1, "You need to read the OpenSSL FAQ, "
-                           "http://www.openssl.org/support/faq.html");
+                           "https://www.openssl.org/docs/faq.html");
         return (0);
     }
  err:
-    EVP_MD_CTX_cleanup(&m);
     RANDerr(RAND_F_RAND_BYTES, ERR_R_EVP_LIB);
+    EVP_MD_CTX_free(m);
+    return 0;
+ err_mem:
+    RANDerr(RAND_F_RAND_BYTES, ERR_R_MALLOC_FAILURE);
+    EVP_MD_CTX_free(m);
     return 0;
 
 }
@@ -605,7 +615,7 @@ static int rand_nopseudo_bytes(unsigned char *buf, int num)
     return rand_bytes(buf, num, 0);
 }
 
-#ifndef OPENSSL_NO_DEPRECATED
+#if OPENSSL_API_COMPAT < 0x10100000L
 /*
  * pseudo-random bytes that are guaranteed to be unique but not unpredictable
  */
@@ -635,6 +645,10 @@ static int rand_status(void)
 
     if (!do_not_lock) {
         CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+        /*
+         * Prevent deadlocks in case we end up in an async engine
+         */
+        ASYNC_block_pause();
 
         /*
          * prevent rand_bytes() from trying to obtain the lock again
@@ -656,6 +670,7 @@ static int rand_status(void)
         /* before unlocking, we must clear 'crypto_lock_rand' */
         crypto_lock_rand = 0;
 
+        ASYNC_unblock_pause();
         CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
     }
 
@@ -671,7 +686,8 @@ static int rand_status(void)
 
 #if (defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
      defined(__x86_64) || defined(__x86_64__) || \
-     defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ)
+     defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ) \
+     && !defined(OPENSSL_NO_RDRAND)
 
 # define RDRAND_CALLS    4