-/* 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>
int rand_predictable = 0;
#endif
-const char RAND_version[] = "RAND" OPENSSL_VERSION_PTEXT;
-
static void rand_hw_seed(EVP_MD_CTX *ctx);
-static void ssleay_rand_cleanup(void);
-static int ssleay_rand_seed(const void *buf, int num);
-static int ssleay_rand_add(const void *buf, int num, double add_entropy);
-static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo);
-static int ssleay_rand_nopseudo_bytes(unsigned char *buf, int num);
-static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num);
-static int ssleay_rand_status(void);
-
-static RAND_METHOD rand_ssleay_meth = {
- ssleay_rand_seed,
- ssleay_rand_nopseudo_bytes,
- ssleay_rand_cleanup,
- ssleay_rand_add,
- ssleay_rand_pseudo_bytes,
- ssleay_rand_status
+static void rand_cleanup(void);
+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);
+#if OPENSSL_API_COMPAT < 0x10100000L
+static int rand_pseudo_bytes(unsigned char *buf, int num);
+#endif
+static int rand_status(void);
+
+static RAND_METHOD rand_meth = {
+ rand_seed,
+ rand_nopseudo_bytes,
+ rand_cleanup,
+ rand_add,
+#if OPENSSL_API_COMPAT < 0x10100000L
+ rand_pseudo_bytes,
+#else
+ NULL,
+#endif
+ rand_status
};
-RAND_METHOD *RAND_SSLeay(void)
+RAND_METHOD *RAND_OpenSSL(void)
{
- return (&rand_ssleay_meth);
+ return (&rand_meth);
}
-static void ssleay_rand_cleanup(void)
+static void rand_cleanup(void)
{
OPENSSL_cleanse(state, sizeof(state));
state_num = 0;
initialized = 0;
}
-static int ssleay_rand_add(const void *buf, int num, double add)
+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;
* 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;
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
* 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]++;
/*
* 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.
#endif
rv = 1;
err:
- EVP_MD_CTX_cleanup(&m);
+ EVP_MD_CTX_free(m);
return rv;
}
-static int ssleay_rand_seed(const void *buf, int num)
+static int rand_seed(const void *buf, int num)
{
- return ssleay_rand_add(buf, num, (double)num);
+ return rand_add(buf, num, (double)num);
}
-static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo)
+static int rand_bytes(unsigned char *buf, int num, int pseudo)
{
static volatile int stirred_pool = 0;
int i, j, k, st_num, st_idx;
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
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);
*/
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 ssleay_rand_bytes() from trying to obtain the lock again */
+ /* prevent rand_bytes() from trying to obtain the lock again */
CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
CRYPTO_THREADID_current(&locking_threadid);
CRYPTO_w_unlock(CRYPTO_LOCK_RAND2);
* In the output function only half of 'md' remains secret, so we
* better make sure that the required entropy gets 'evenly
* distributed' through 'state', our randomness pool. The input
- * function (ssleay_rand_add) chains all of 'md', which makes it more
+ * function (rand_add) chains all of 'md', which makes it more
* suitable for this purpose.
*/
#define DUMMY_SEED "...................." /* at least MD_DIGEST_LENGTH */
/*
* Note that the seed does not matter, it's just that
- * ssleay_rand_add expects to have something to hash.
+ * rand_add expects to have something to hash.
*/
- ssleay_rand_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0);
+ rand_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0);
n -= MD_DIGEST_LENGTH;
}
if (ok)
/* 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))
- goto err;
- if (!MD_Update(&m, (unsigned char *)&(md_c[0]), sizeof(md_c)))
+ if (!MD_Update(m, local_md, MD_DIGEST_LENGTH))
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))
+ if (!MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c)))
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++) {
}
}
- 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)
return 0;
else {
- RANDerr(RAND_F_SSLEAY_RAND_BYTES, RAND_R_PRNG_NOT_SEEDED);
+ 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_SSLEAY_RAND_BYTES, ERR_R_EVP_LIB);
+ 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;
}
-static int ssleay_rand_nopseudo_bytes(unsigned char *buf, int num)
+static int rand_nopseudo_bytes(unsigned char *buf, int num)
{
- return ssleay_rand_bytes(buf, num, 0);
+ return rand_bytes(buf, num, 0);
}
+#if OPENSSL_API_COMPAT < 0x10100000L
/*
* pseudo-random bytes that are guaranteed to be unique but not unpredictable
*/
-static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num)
+static int rand_pseudo_bytes(unsigned char *buf, int num)
{
- return ssleay_rand_bytes(buf, num, 1);
+ return rand_bytes(buf, num, 1);
}
+#endif
-static int ssleay_rand_status(void)
+static int rand_status(void)
{
CRYPTO_THREADID cur;
int ret;
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 ssleay_rand_bytes() from trying to obtain the lock again
+ * prevent rand_bytes() from trying to obtain the lock again
*/
CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
CRYPTO_THREADID_cpy(&locking_threadid, &cur);
/* before unlocking, we must clear 'crypto_lock_rand' */
crypto_lock_rand = 0;
+ ASYNC_unblock_pause();
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
}
#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