aboutsummaryrefslogtreecommitdiff
path: root/openssl-1.1.0h/crypto/rand
diff options
context:
space:
mode:
Diffstat (limited to 'openssl-1.1.0h/crypto/rand')
-rw-r--r--openssl-1.1.0h/crypto/rand/build.info4
-rw-r--r--openssl-1.1.0h/crypto/rand/md_rand.c667
-rw-r--r--openssl-1.1.0h/crypto/rand/rand_egd.c249
-rw-r--r--openssl-1.1.0h/crypto/rand/rand_err.c43
-rw-r--r--openssl-1.1.0h/crypto/rand/rand_lcl.h46
-rw-r--r--openssl-1.1.0h/crypto/rand/rand_lib.c164
-rw-r--r--openssl-1.1.0h/crypto/rand/rand_unix.c324
-rw-r--r--openssl-1.1.0h/crypto/rand/rand_vms.c133
-rw-r--r--openssl-1.1.0h/crypto/rand/rand_win.c135
-rw-r--r--openssl-1.1.0h/crypto/rand/randfile.c364
10 files changed, 2129 insertions, 0 deletions
diff --git a/openssl-1.1.0h/crypto/rand/build.info b/openssl-1.1.0h/crypto/rand/build.info
new file mode 100644
index 0000000..3ad50e2
--- /dev/null
+++ b/openssl-1.1.0h/crypto/rand/build.info
@@ -0,0 +1,4 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]=\
+ md_rand.c randfile.c rand_lib.c rand_err.c rand_egd.c \
+ rand_win.c rand_unix.c rand_vms.c
diff --git a/openssl-1.1.0h/crypto/rand/md_rand.c b/openssl-1.1.0h/crypto/rand/md_rand.c
new file mode 100644
index 0000000..7d5fcb7
--- /dev/null
+++ b/openssl-1.1.0h/crypto/rand/md_rand.c
@@ -0,0 +1,667 @@
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "e_os.h"
+
+#if !(defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_DSPBIOS))
+# include <sys/time.h>
+#endif
+#if defined(OPENSSL_SYS_VXWORKS)
+# 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>
+
+#include <internal/thread_once.h>
+
+#ifdef OPENSSL_FIPS
+# include <openssl/fips.h>
+#endif
+
+#ifdef BN_DEBUG
+# define PREDICT
+#endif
+
+/* #define PREDICT 1 */
+
+#define STATE_SIZE 1023
+static size_t state_num = 0, state_index = 0;
+static unsigned char state[STATE_SIZE + MD_DIGEST_LENGTH];
+static unsigned char md[MD_DIGEST_LENGTH];
+static long md_count[2] = { 0, 0 };
+
+static double entropy = 0;
+static int initialized = 0;
+
+static CRYPTO_RWLOCK *rand_lock = NULL;
+static CRYPTO_RWLOCK *rand_tmp_lock = NULL;
+static CRYPTO_ONCE rand_lock_init = CRYPTO_ONCE_STATIC_INIT;
+
+/* May be set only when a thread holds rand_lock (to prevent double locking) */
+static unsigned int crypto_lock_rand = 0;
+/* access to locking_threadid is synchronized by rand_tmp_lock */
+/* valid iff crypto_lock_rand is set */
+static CRYPTO_THREAD_ID locking_threadid;
+
+#ifdef PREDICT
+int rand_predictable = 0;
+#endif
+
+static int rand_hw_seed(EVP_MD_CTX *ctx);
+
+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
+};
+
+DEFINE_RUN_ONCE_STATIC(do_rand_lock_init)
+{
+ OPENSSL_init_crypto(0, NULL);
+ rand_lock = CRYPTO_THREAD_lock_new();
+ rand_tmp_lock = CRYPTO_THREAD_lock_new();
+ return rand_lock != NULL && rand_tmp_lock != NULL;
+}
+
+RAND_METHOD *RAND_OpenSSL(void)
+{
+ return (&rand_meth);
+}
+
+static void rand_cleanup(void)
+{
+ OPENSSL_cleanse(state, sizeof(state));
+ state_num = 0;
+ state_index = 0;
+ OPENSSL_cleanse(md, MD_DIGEST_LENGTH);
+ md_count[0] = 0;
+ md_count[1] = 0;
+ entropy = 0;
+ initialized = 0;
+ CRYPTO_THREAD_lock_free(rand_lock);
+ CRYPTO_THREAD_lock_free(rand_tmp_lock);
+}
+
+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;
+ int do_not_lock;
+ int rv = 0;
+
+ if (!num)
+ return 1;
+
+ /*
+ * (Based on the rand(3) manpage)
+ *
+ * The input is chopped up into units of 20 bytes (or less for
+ * the last block). Each of these blocks is run through the hash
+ * function as follows: The data passed to the hash function
+ * is the current 'md', the same number of bytes from the 'state'
+ * (the location determined by in incremented looping index) as
+ * the current 'block', the new key data 'block', and 'count'
+ * (which is incremented after each use).
+ * The result of this is kept in 'md' and also xored into the
+ * 'state' at the same locations that were used as input into the
+ * hash function.
+ */
+
+ m = EVP_MD_CTX_new();
+ if (m == NULL)
+ goto err;
+
+ if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
+ goto err;
+
+ /* check if we already have the lock */
+ if (crypto_lock_rand) {
+ CRYPTO_THREAD_ID cur = CRYPTO_THREAD_get_current_id();
+ CRYPTO_THREAD_read_lock(rand_tmp_lock);
+ do_not_lock = CRYPTO_THREAD_compare_id(locking_threadid, cur);
+ CRYPTO_THREAD_unlock(rand_tmp_lock);
+ } else
+ do_not_lock = 0;
+
+ if (!do_not_lock)
+ CRYPTO_THREAD_write_lock(rand_lock);
+ st_idx = state_index;
+
+ /*
+ * use our own copies of the counters so that even if a concurrent thread
+ * seeds with exactly the same data and uses the same subarray there's
+ * _some_ difference
+ */
+ md_c[0] = md_count[0];
+ md_c[1] = md_count[1];
+
+ memcpy(local_md, md, sizeof(md));
+
+ /* state_index <= state_num <= STATE_SIZE */
+ state_index += num;
+ if (state_index >= STATE_SIZE) {
+ state_index %= STATE_SIZE;
+ state_num = STATE_SIZE;
+ } else if (state_num < STATE_SIZE) {
+ if (state_index > state_num)
+ state_num = state_index;
+ }
+ /* state_index <= state_num <= STATE_SIZE */
+
+ /*
+ * state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE] are what we
+ * will use now, but other threads may use them as well
+ */
+
+ md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0);
+
+ if (!do_not_lock)
+ CRYPTO_THREAD_unlock(rand_lock);
+
+ for (i = 0; i < num; i += MD_DIGEST_LENGTH) {
+ j = (num - i);
+ j = (j > MD_DIGEST_LENGTH) ? MD_DIGEST_LENGTH : j;
+
+ if (!MD_Init(m))
+ goto err;
+ 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))
+ goto err;
+ if (!MD_Update(m, &(state[0]), k))
+ goto err;
+ } 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))
+ goto err;
+ /*
+ * We know that line may cause programs such as purify and valgrind
+ * to complain about use of uninitialized data. The problem is not,
+ * it's with the caller. Removing that line will make sure you get
+ * really bad randomness and thereby other problems such as very
+ * insecure keys.
+ */
+
+ if (!MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c)))
+ goto err;
+ if (!MD_Final(m, local_md))
+ goto err;
+ md_c[1]++;
+
+ buf = (const char *)buf + j;
+
+ for (k = 0; k < j; k++) {
+ /*
+ * 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 (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.
+ */
+ state[st_idx++] ^= local_md[k];
+ if (st_idx >= STATE_SIZE)
+ st_idx = 0;
+ }
+ }
+
+ if (!do_not_lock)
+ CRYPTO_THREAD_write_lock(rand_lock);
+ /*
+ * Don't just copy back local_md into md -- this could mean that other
+ * thread's seeding remains without effect (except for the incremented
+ * counter). By XORing it we keep at least as much entropy as fits into
+ * md.
+ */
+ for (k = 0; k < (int)sizeof(md); k++) {
+ md[k] ^= local_md[k];
+ }
+ if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */
+ entropy += add;
+ if (!do_not_lock)
+ CRYPTO_THREAD_unlock(rand_lock);
+
+ rv = 1;
+ err:
+ EVP_MD_CTX_free(m);
+ return rv;
+}
+
+static int rand_seed(const void *buf, int num)
+{
+ return rand_add(buf, num, (double)num);
+}
+
+static int rand_bytes(unsigned char *buf, int num, int pseudo)
+{
+ static volatile int stirred_pool = 0;
+ int i, j, k;
+ size_t num_ceil, st_idx, st_num;
+ int ok;
+ long md_c[2];
+ unsigned char local_md[MD_DIGEST_LENGTH];
+ EVP_MD_CTX *m;
+#ifndef GETPID_IS_MEANINGLESS
+ pid_t curr_pid = getpid();
+#endif
+ time_t curr_time = time(NULL);
+ int do_stir_pool = 0;
+/* time value for various platforms */
+#ifdef OPENSSL_SYS_WIN32
+ FILETIME tv;
+# ifdef _WIN32_WCE
+ SYSTEMTIME t;
+ GetSystemTime(&t);
+ SystemTimeToFileTime(&t, &tv);
+# else
+ GetSystemTimeAsFileTime(&tv);
+# endif
+#elif defined(OPENSSL_SYS_VXWORKS)
+ struct timespec tv;
+ clock_gettime(CLOCK_REALTIME, &ts);
+#elif defined(OPENSSL_SYS_DSPBIOS)
+ unsigned long long tv, OPENSSL_rdtsc();
+ tv = OPENSSL_rdtsc();
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+#endif
+
+#ifdef PREDICT
+ if (rand_predictable) {
+ static unsigned char val = 0;
+
+ for (i = 0; i < num; i++)
+ buf[i] = val++;
+ return (1);
+ }
+#endif
+
+ if (num <= 0)
+ return 1;
+
+ 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);
+
+ /*
+ * (Based on the rand(3) manpage:)
+ *
+ * For each group of 10 bytes (or less), we do the following:
+ *
+ * Input into the hash function the local 'md' (which is initialized from
+ * the global 'md' before any bytes are generated), the bytes that are to
+ * be overwritten by the random bytes, and bytes from the 'state'
+ * (incrementing looping index). From this digest output (which is kept
+ * in 'md'), the top (up to) 10 bytes are returned to the caller and the
+ * bottom 10 bytes are xored into the 'state'.
+ *
+ * Finally, after we have finished 'num' random bytes for the
+ * caller, 'count' (which is incremented) and the local and global 'md'
+ * are fed into the hash function and the results are kept in the
+ * global 'md'.
+ */
+
+ if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
+ goto err_mem;
+
+ CRYPTO_THREAD_write_lock(rand_lock);
+ /*
+ * 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_THREAD_write_lock(rand_tmp_lock);
+ locking_threadid = CRYPTO_THREAD_get_current_id();
+ CRYPTO_THREAD_unlock(rand_tmp_lock);
+ crypto_lock_rand = 1;
+
+ if (!initialized) {
+ RAND_poll();
+ initialized = 1;
+ }
+
+ if (!stirred_pool)
+ do_stir_pool = 1;
+
+ ok = (entropy >= ENTROPY_NEEDED);
+ if (!ok) {
+ /*
+ * If the PRNG state is not yet unpredictable, then seeing the PRNG
+ * output may help attackers to determine the new state; thus we have
+ * to decrease the entropy estimate. Once we've had enough initial
+ * seeding we don't bother to adjust the entropy count, though,
+ * because we're not ambitious to provide *information-theoretic*
+ * randomness. NOTE: This approach fails if the program forks before
+ * we have enough entropy. Entropy should be collected in a separate
+ * input pool and be transferred to the output pool only when the
+ * entropy limit has been reached.
+ */
+ entropy -= num;
+ if (entropy < 0)
+ entropy = 0;
+ }
+
+ if (do_stir_pool) {
+ /*
+ * 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 (rand_add) chains all of 'md', which makes it more
+ * suitable for this purpose.
+ */
+
+ int n = STATE_SIZE; /* so that the complete pool gets accessed */
+ while (n > 0) {
+#if MD_DIGEST_LENGTH > 20
+# error "Please adjust DUMMY_SEED."
+#endif
+#define DUMMY_SEED "...................." /* at least MD_DIGEST_LENGTH */
+ /*
+ * Note that the seed does not matter, it's just that
+ * rand_add expects to have something to hash.
+ */
+ rand_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0);
+ n -= MD_DIGEST_LENGTH;
+ }
+ if (ok)
+ stirred_pool = 1;
+ }
+
+ st_idx = state_index;
+ st_num = state_num;
+ md_c[0] = md_count[0];
+ md_c[1] = md_count[1];
+ memcpy(local_md, md, sizeof(md));
+
+ state_index += num_ceil;
+ if (state_index > state_num)
+ state_index %= state_num;
+
+ /*
+ * state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num] are now
+ * ours (but other threads may use them too)
+ */
+
+ md_count[0] += 1;
+
+ /* before unlocking, we must clear 'crypto_lock_rand' */
+ crypto_lock_rand = 0;
+ ASYNC_unblock_pause();
+ CRYPTO_THREAD_unlock(rand_lock);
+
+ 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))
+ 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)))
+ 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)))
+ goto err;
+ if (!MD_Update(m, (unsigned char *)&tv, sizeof(tv)))
+ goto err;
+ curr_time = 0;
+ if (!rand_hw_seed(m))
+ goto err;
+ }
+ if (!MD_Update(m, local_md, MD_DIGEST_LENGTH))
+ goto err;
+ if (!MD_Update(m, (unsigned char *)&(md_c[0]), sizeof(md_c)))
+ goto err;
+
+ k = (st_idx + MD_DIGEST_LENGTH / 2) - st_num;
+ if (k > 0) {
+ if (!MD_Update(m, &(state[st_idx]), MD_DIGEST_LENGTH / 2 - k))
+ goto err;
+ if (!MD_Update(m, &(state[0]), k))
+ goto err;
+ } else if (!MD_Update(m, &(state[st_idx]), MD_DIGEST_LENGTH / 2))
+ goto err;
+ if (!MD_Final(m, local_md))
+ goto err;
+
+ for (i = 0; i < MD_DIGEST_LENGTH / 2; i++) {
+ /* may compete with other threads */
+ state[st_idx++] ^= local_md[i];
+ if (st_idx >= st_num)
+ st_idx = 0;
+ if (i < j)
+ *(buf++) = local_md[i + MD_DIGEST_LENGTH / 2];
+ }
+ }
+
+ 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_THREAD_write_lock(rand_lock);
+ /*
+ * 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)) {
+ ASYNC_unblock_pause();
+ CRYPTO_THREAD_unlock(rand_lock);
+ goto err;
+ }
+ ASYNC_unblock_pause();
+ CRYPTO_THREAD_unlock(rand_lock);
+
+ EVP_MD_CTX_free(m);
+ if (ok)
+ return (1);
+ else if (pseudo)
+ return 0;
+ else {
+ RANDerr(RAND_F_RAND_BYTES, RAND_R_PRNG_NOT_SEEDED);
+ ERR_add_error_data(1, "You need to read the OpenSSL FAQ, "
+ "https://www.openssl.org/docs/faq.html");
+ return (0);
+ }
+ err:
+ 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 rand_nopseudo_bytes(unsigned char *buf, int num)
+{
+ 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 rand_pseudo_bytes(unsigned char *buf, int num)
+{
+ return rand_bytes(buf, num, 1);
+}
+#endif
+
+static int rand_status(void)
+{
+ CRYPTO_THREAD_ID cur;
+ int ret;
+ int do_not_lock;
+
+ if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
+ return 0;
+
+ cur = CRYPTO_THREAD_get_current_id();
+ /*
+ * check if we already have the lock (could happen if a RAND_poll()
+ * implementation calls RAND_status())
+ */
+ if (crypto_lock_rand) {
+ CRYPTO_THREAD_read_lock(rand_tmp_lock);
+ do_not_lock = CRYPTO_THREAD_compare_id(locking_threadid, cur);
+ CRYPTO_THREAD_unlock(rand_tmp_lock);
+ } else
+ do_not_lock = 0;
+
+ if (!do_not_lock) {
+ CRYPTO_THREAD_write_lock(rand_lock);
+ /*
+ * Prevent deadlocks in case we end up in an async engine
+ */
+ ASYNC_block_pause();
+
+ /*
+ * prevent rand_bytes() from trying to obtain the lock again
+ */
+ CRYPTO_THREAD_write_lock(rand_tmp_lock);
+ locking_threadid = cur;
+ CRYPTO_THREAD_unlock(rand_tmp_lock);
+ crypto_lock_rand = 1;
+ }
+
+ if (!initialized) {
+ RAND_poll();
+ initialized = 1;
+ }
+
+ ret = entropy >= ENTROPY_NEEDED;
+
+ if (!do_not_lock) {
+ /* before unlocking, we must clear 'crypto_lock_rand' */
+ crypto_lock_rand = 0;
+
+ ASYNC_unblock_pause();
+ CRYPTO_THREAD_unlock(rand_lock);
+ }
+
+ return ret;
+}
+
+/*
+ * rand_hw_seed: get seed data from any available hardware RNG. only
+ * currently supports rdrand.
+ */
+
+/* Adapted from eng_rdrand.c */
+
+#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(OPENSSL_NO_RDRAND)
+
+# define RDRAND_CALLS 4
+
+size_t OPENSSL_ia32_rdrand(void);
+extern unsigned int OPENSSL_ia32cap_P[];
+
+static int rand_hw_seed(EVP_MD_CTX *ctx)
+{
+ int i;
+ if (!(OPENSSL_ia32cap_P[1] & (1 << (62 - 32))))
+ return 1;
+ for (i = 0; i < RDRAND_CALLS; i++) {
+ size_t rnd;
+ rnd = OPENSSL_ia32_rdrand();
+ if (rnd == 0)
+ return 1;
+ if (!MD_Update(ctx, (unsigned char *)&rnd, sizeof(size_t)))
+ return 0;
+ }
+ return 1;
+}
+
+/* XOR an existing buffer with random data */
+
+void rand_hw_xor(unsigned char *buf, size_t num)
+{
+ size_t rnd;
+ if (!(OPENSSL_ia32cap_P[1] & (1 << (62 - 32))))
+ return;
+ while (num >= sizeof(size_t)) {
+ rnd = OPENSSL_ia32_rdrand();
+ if (rnd == 0)
+ return;
+ *((size_t *)buf) ^= rnd;
+ buf += sizeof(size_t);
+ num -= sizeof(size_t);
+ }
+ if (num) {
+ rnd = OPENSSL_ia32_rdrand();
+ if (rnd == 0)
+ return;
+ while (num) {
+ *buf ^= rnd & 0xff;
+ rnd >>= 8;
+ buf++;
+ num--;
+ }
+ }
+}
+
+#else
+
+static int rand_hw_seed(EVP_MD_CTX *ctx)
+{
+ return 1;
+}
+
+void rand_hw_xor(unsigned char *buf, size_t num)
+{
+ return;
+}
+
+#endif
diff --git a/openssl-1.1.0h/crypto/rand/rand_egd.c b/openssl-1.1.0h/crypto/rand/rand_egd.c
new file mode 100644
index 0000000..50963b8
--- /dev/null
+++ b/openssl-1.1.0h/crypto/rand/rand_egd.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#ifdef OPENSSL_NO_EGD
+NON_EMPTY_TRANSLATION_UNIT
+#else
+
+# include <openssl/crypto.h>
+# include <openssl/e_os2.h>
+# include <openssl/rand.h>
+
+/*-
+ * Query the EGD <URL: http://www.lothar.com/tech/crypto/>.
+ *
+ * This module supplies three routines:
+ *
+ * RAND_query_egd_bytes(path, buf, bytes)
+ * will actually query "bytes" bytes of entropy form the egd-socket located
+ * at path and will write them to buf (if supplied) or will directly feed
+ * it to RAND_seed() if buf==NULL.
+ * The number of bytes is not limited by the maximum chunk size of EGD,
+ * which is 255 bytes. If more than 255 bytes are wanted, several chunks
+ * of entropy bytes are requested. The connection is left open until the
+ * query is competed.
+ * RAND_query_egd_bytes() returns with
+ * -1 if an error occurred during connection or communication.
+ * num the number of bytes read from the EGD socket. This number is either
+ * the number of bytes requested or smaller, if the EGD pool is
+ * drained and the daemon signals that the pool is empty.
+ * This routine does not touch any RAND_status(). This is necessary, since
+ * PRNG functions may call it during initialization.
+ *
+ * RAND_egd_bytes(path, bytes) will query "bytes" bytes and have them
+ * used to seed the PRNG.
+ * RAND_egd_bytes() is a wrapper for RAND_query_egd_bytes() with buf=NULL.
+ * Unlike RAND_query_egd_bytes(), RAND_status() is used to test the
+ * seed status so that the return value can reflect the seed state:
+ * -1 if an error occurred during connection or communication _or_
+ * if the PRNG has still not received the required seeding.
+ * num the number of bytes read from the EGD socket. This number is either
+ * the number of bytes requested or smaller, if the EGD pool is
+ * drained and the daemon signals that the pool is empty.
+ *
+ * RAND_egd(path) will query 255 bytes and use the bytes retrieved to seed
+ * the PRNG.
+ * RAND_egd() is a wrapper for RAND_egd_bytes() with numbytes=255.
+ */
+
+# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_VOS) || defined(OPENSSL_SYS_UEFI)
+int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
+{
+ return (-1);
+}
+
+int RAND_egd(const char *path)
+{
+ return (-1);
+}
+
+int RAND_egd_bytes(const char *path, int bytes)
+{
+ return (-1);
+}
+# else
+# include <openssl/opensslconf.h>
+# include OPENSSL_UNISTD
+# include <stddef.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+# ifndef NO_SYS_UN_H
+# ifdef OPENSSL_SYS_VXWORKS
+# include <streams/un.h>
+# else
+# include <sys/un.h>
+# endif
+# else
+struct sockaddr_un {
+ short sun_family; /* AF_UNIX */
+ char sun_path[108]; /* path name (gag) */
+};
+# endif /* NO_SYS_UN_H */
+# include <string.h>
+# include <errno.h>
+
+int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
+{
+ int ret = 0;
+ struct sockaddr_un addr;
+ int len, num, numbytes;
+ int fd = -1;
+ int success;
+ unsigned char egdbuf[2], tempbuf[255], *retrievebuf;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (strlen(path) >= sizeof(addr.sun_path))
+ return (-1);
+ OPENSSL_strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
+ len = offsetof(struct sockaddr_un, sun_path) + strlen(path);
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1)
+ return (-1);
+ success = 0;
+ while (!success) {
+ if (connect(fd, (struct sockaddr *)&addr, len) == 0)
+ success = 1;
+ else {
+ switch (errno) {
+# ifdef EINTR
+ case EINTR:
+# endif
+# ifdef EAGAIN
+ case EAGAIN:
+# endif
+# ifdef EINPROGRESS
+ case EINPROGRESS:
+# endif
+# ifdef EALREADY
+ case EALREADY:
+# endif
+ /* No error, try again */
+ break;
+# ifdef EISCONN
+ case EISCONN:
+ success = 1;
+ break;
+# endif
+ default:
+ ret = -1;
+ goto err; /* failure */
+ }
+ }
+ }
+
+ while (bytes > 0) {
+ egdbuf[0] = 1;
+ egdbuf[1] = bytes < 255 ? bytes : 255;
+ numbytes = 0;
+ while (numbytes != 2) {
+ num = write(fd, egdbuf + numbytes, 2 - numbytes);
+ if (num >= 0)
+ numbytes += num;
+ else {
+ switch (errno) {
+# ifdef EINTR
+ case EINTR:
+# endif
+# ifdef EAGAIN
+ case EAGAIN:
+# endif
+ /* No error, try again */
+ break;
+ default:
+ ret = -1;
+ goto err; /* failure */
+ }
+ }
+ }
+ numbytes = 0;
+ while (numbytes != 1) {
+ num = read(fd, egdbuf, 1);
+ if (num == 0)
+ goto err; /* descriptor closed */
+ else if (num > 0)
+ numbytes += num;
+ else {
+ switch (errno) {
+# ifdef EINTR
+ case EINTR:
+# endif
+# ifdef EAGAIN
+ case EAGAIN:
+# endif
+ /* No error, try again */
+ break;
+ default:
+ ret = -1;
+ goto err; /* failure */
+ }
+ }
+ }
+ if (egdbuf[0] == 0)
+ goto err;
+ if (buf)
+ retrievebuf = buf + ret;
+ else
+ retrievebuf = tempbuf;
+ numbytes = 0;
+ while (numbytes != egdbuf[0]) {
+ num = read(fd, retrievebuf + numbytes, egdbuf[0] - numbytes);
+ if (num == 0)
+ goto err; /* descriptor closed */
+ else if (num > 0)
+ numbytes += num;
+ else {
+ switch (errno) {
+# ifdef EINTR
+ case EINTR:
+# endif
+# ifdef EAGAIN
+ case EAGAIN:
+# endif
+ /* No error, try again */
+ break;
+ default:
+ ret = -1;
+ goto err; /* failure */
+ }
+ }
+ }
+ ret += egdbuf[0];
+ bytes -= egdbuf[0];
+ if (!buf)
+ RAND_seed(tempbuf, egdbuf[0]);
+ }
+ err:
+ if (fd != -1)
+ close(fd);
+ return (ret);
+}
+
+int RAND_egd_bytes(const char *path, int bytes)
+{
+ int num, ret = -1;
+
+ num = RAND_query_egd_bytes(path, NULL, bytes);
+ if (num < 0)
+ goto err;
+ if (RAND_status() == 1)
+ ret = num;
+ err:
+ return (ret);
+}
+
+int RAND_egd(const char *path)
+{
+ return (RAND_egd_bytes(path, 255));
+}
+
+# endif
+
+#endif
diff --git a/openssl-1.1.0h/crypto/rand/rand_err.c b/openssl-1.1.0h/crypto/rand/rand_err.c
new file mode 100644
index 0000000..5543126
--- /dev/null
+++ b/openssl-1.1.0h/crypto/rand/rand_err.c
@@ -0,0 +1,43 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+
+# define ERR_FUNC(func) ERR_PACK(ERR_LIB_RAND,func,0)
+# define ERR_REASON(reason) ERR_PACK(ERR_LIB_RAND,0,reason)
+
+static ERR_STRING_DATA RAND_str_functs[] = {
+ {ERR_FUNC(RAND_F_RAND_BYTES), "RAND_bytes"},
+ {0, NULL}
+};
+
+static ERR_STRING_DATA RAND_str_reasons[] = {
+ {ERR_REASON(RAND_R_PRNG_NOT_SEEDED), "PRNG not seeded"},
+ {0, NULL}
+};
+
+#endif
+
+int ERR_load_RAND_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+
+ if (ERR_func_error_string(RAND_str_functs[0].error) == NULL) {
+ ERR_load_strings(0, RAND_str_functs);
+ ERR_load_strings(0, RAND_str_reasons);
+ }
+#endif
+ return 1;
+}
diff --git a/openssl-1.1.0h/crypto/rand/rand_lcl.h b/openssl-1.1.0h/crypto/rand/rand_lcl.h
new file mode 100644
index 0000000..d98c90e
--- /dev/null
+++ b/openssl-1.1.0h/crypto/rand/rand_lcl.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef HEADER_RAND_LCL_H
+# define HEADER_RAND_LCL_H
+
+# define ENTROPY_NEEDED 32 /* require 256 bits = 32 bytes of randomness */
+
+# if !defined(USE_MD5_RAND) && !defined(USE_SHA1_RAND) && !defined(USE_MDC2_RAND) && !defined(USE_MD2_RAND)
+# define USE_SHA1_RAND
+# endif
+
+# include <openssl/evp.h>
+# define MD_Update(a,b,c) EVP_DigestUpdate(a,b,c)
+# define MD_Final(a,b) EVP_DigestFinal_ex(a,b,NULL)
+# if defined(USE_MD5_RAND)
+# include <openssl/md5.h>
+# define MD_DIGEST_LENGTH MD5_DIGEST_LENGTH
+# define MD_Init(a) EVP_DigestInit_ex(a,EVP_md5(), NULL)
+# define MD(a,b,c) EVP_Digest(a,b,c,NULL,EVP_md5(), NULL)
+# elif defined(USE_SHA1_RAND)
+# include <openssl/sha.h>
+# define MD_DIGEST_LENGTH SHA_DIGEST_LENGTH
+# define MD_Init(a) EVP_DigestInit_ex(a,EVP_sha1(), NULL)
+# define MD(a,b,c) EVP_Digest(a,b,c,NULL,EVP_sha1(), NULL)
+# elif defined(USE_MDC2_RAND)
+# include <openssl/mdc2.h>
+# define MD_DIGEST_LENGTH MDC2_DIGEST_LENGTH
+# define MD_Init(a) EVP_DigestInit_ex(a,EVP_mdc2(), NULL)
+# define MD(a,b,c) EVP_Digest(a,b,c,NULL,EVP_mdc2(), NULL)
+# elif defined(USE_MD2_RAND)
+# include <openssl/md2.h>
+# define MD_DIGEST_LENGTH MD2_DIGEST_LENGTH
+# define MD_Init(a) EVP_DigestInit_ex(a,EVP_md2(), NULL)
+# define MD(a,b,c) EVP_Digest(a,b,c,NULL,EVP_md2(), NULL)
+# endif
+
+void rand_hw_xor(unsigned char *buf, size_t num);
+
+#endif
diff --git a/openssl-1.1.0h/crypto/rand/rand_lib.c b/openssl-1.1.0h/crypto/rand/rand_lib.c
new file mode 100644
index 0000000..62770d4
--- /dev/null
+++ b/openssl-1.1.0h/crypto/rand/rand_lib.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include "internal/cryptlib.h"
+#include <openssl/opensslconf.h>
+#include "internal/rand.h"
+#include <openssl/engine.h>
+#include "internal/thread_once.h"
+
+#ifdef OPENSSL_FIPS
+# include <openssl/fips.h>
+# include <openssl/fips_rand.h>
+#endif
+
+#ifndef OPENSSL_NO_ENGINE
+/* non-NULL if default_RAND_meth is ENGINE-provided */
+static ENGINE *funct_ref = NULL;
+static CRYPTO_RWLOCK *rand_engine_lock = NULL;
+#endif
+static const RAND_METHOD *default_RAND_meth = NULL;
+static CRYPTO_RWLOCK *rand_meth_lock = NULL;
+static CRYPTO_ONCE rand_lock_init = CRYPTO_ONCE_STATIC_INIT;
+
+DEFINE_RUN_ONCE_STATIC(do_rand_lock_init)
+{
+ int ret = 1;
+#ifndef OPENSSL_NO_ENGINE
+ rand_engine_lock = CRYPTO_THREAD_lock_new();
+ ret &= rand_engine_lock != NULL;
+#endif
+ rand_meth_lock = CRYPTO_THREAD_lock_new();
+ ret &= rand_meth_lock != NULL;
+ return ret;
+}
+
+int RAND_set_rand_method(const RAND_METHOD *meth)
+{
+ if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
+ return 0;
+
+ CRYPTO_THREAD_write_lock(rand_meth_lock);
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE_finish(funct_ref);
+ funct_ref = NULL;
+#endif
+ default_RAND_meth = meth;
+ CRYPTO_THREAD_unlock(rand_meth_lock);
+ return 1;
+}
+
+const RAND_METHOD *RAND_get_rand_method(void)
+{
+ const RAND_METHOD *tmp_meth = NULL;
+
+ if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
+ return NULL;
+
+ CRYPTO_THREAD_write_lock(rand_meth_lock);
+ if (!default_RAND_meth) {
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE *e = ENGINE_get_default_RAND();
+ if (e) {
+ default_RAND_meth = ENGINE_get_RAND(e);
+ if (default_RAND_meth == NULL) {
+ ENGINE_finish(e);
+ e = NULL;
+ }
+ }
+ if (e)
+ funct_ref = e;
+ else
+#endif
+ default_RAND_meth = RAND_OpenSSL();
+ }
+ tmp_meth = default_RAND_meth;
+ CRYPTO_THREAD_unlock(rand_meth_lock);
+ return tmp_meth;
+}
+
+#ifndef OPENSSL_NO_ENGINE
+int RAND_set_rand_engine(ENGINE *engine)
+{
+ const RAND_METHOD *tmp_meth = NULL;
+
+ if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
+ return 0;
+
+ if (engine) {
+ if (!ENGINE_init(engine))
+ return 0;
+ tmp_meth = ENGINE_get_RAND(engine);
+ if (tmp_meth == NULL) {
+ ENGINE_finish(engine);
+ return 0;
+ }
+ }
+ CRYPTO_THREAD_write_lock(rand_engine_lock);
+ /* This function releases any prior ENGINE so call it first */
+ RAND_set_rand_method(tmp_meth);
+ funct_ref = engine;
+ CRYPTO_THREAD_unlock(rand_engine_lock);
+ return 1;
+}
+#endif
+
+void rand_cleanup_int(void)
+{
+ const RAND_METHOD *meth = default_RAND_meth;
+ if (meth && meth->cleanup)
+ meth->cleanup();
+ RAND_set_rand_method(NULL);
+ CRYPTO_THREAD_lock_free(rand_meth_lock);
+#ifndef OPENSSL_NO_ENGINE
+ CRYPTO_THREAD_lock_free(rand_engine_lock);
+#endif
+}
+
+void RAND_seed(const void *buf, int num)
+{
+ const RAND_METHOD *meth = RAND_get_rand_method();
+ if (meth && meth->seed)
+ meth->seed(buf, num);
+}
+
+void RAND_add(const void *buf, int num, double entropy)
+{
+ const RAND_METHOD *meth = RAND_get_rand_method();
+ if (meth && meth->add)
+ meth->add(buf, num, entropy);
+}
+
+int RAND_bytes(unsigned char *buf, int num)
+{
+ const RAND_METHOD *meth = RAND_get_rand_method();
+ if (meth && meth->bytes)
+ return meth->bytes(buf, num);
+ return (-1);
+}
+
+#if OPENSSL_API_COMPAT < 0x10100000L
+int RAND_pseudo_bytes(unsigned char *buf, int num)
+{
+ const RAND_METHOD *meth = RAND_get_rand_method();
+ if (meth && meth->pseudorand)
+ return meth->pseudorand(buf, num);
+ return (-1);
+}
+#endif
+
+int RAND_status(void)
+{
+ const RAND_METHOD *meth = RAND_get_rand_method();
+ if (meth && meth->status)
+ return meth->status();
+ return 0;
+}
diff --git a/openssl-1.1.0h/crypto/rand/rand_unix.c b/openssl-1.1.0h/crypto/rand/rand_unix.c
new file mode 100644
index 0000000..7a5a948
--- /dev/null
+++ b/openssl-1.1.0h/crypto/rand/rand_unix.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+
+#define USE_SOCKETS
+#include "e_os.h"
+#include "internal/cryptlib.h"
+#include <openssl/rand.h>
+#include "rand_lcl.h"
+
+#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI))
+
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/times.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <unistd.h>
+# include <time.h>
+# if defined(OPENSSL_SYS_LINUX) /* should actually be available virtually
+ * everywhere */
+# include <poll.h>
+# endif
+# include <limits.h>
+# ifndef FD_SETSIZE
+# define FD_SETSIZE (8*sizeof(fd_set))
+# endif
+
+# if defined(OPENSSL_SYS_VOS)
+
+/*
+ * The following algorithm repeatedly samples the real-time clock (RTC) to
+ * generate a sequence of unpredictable data. The algorithm relies upon the
+ * uneven execution speed of the code (due to factors such as cache misses,
+ * interrupts, bus activity, and scheduling) and upon the rather large
+ * relative difference between the speed of the clock and the rate at which
+ * it can be read.
+ *
+ * If this code is ported to an environment where execution speed is more
+ * constant or where the RTC ticks at a much slower rate, or the clock can be
+ * read with fewer instructions, it is likely that the results would be far
+ * more predictable.
+ *
+ * As a precaution, we generate 4 times the minimum required amount of seed
+ * data.
+ */
+
+int RAND_poll(void)
+{
+ short int code;
+ gid_t curr_gid;
+ pid_t curr_pid;
+ uid_t curr_uid;
+ int i, k;
+ struct timespec ts;
+ unsigned char v;
+
+# ifdef OPENSSL_SYS_VOS_HPPA
+ long duration;
+ extern void s$sleep(long *_duration, short int *_code);
+# else
+# ifdef OPENSSL_SYS_VOS_IA32
+ long long duration;
+ extern void s$sleep2(long long *_duration, short int *_code);
+# else
+# error "Unsupported Platform."
+# endif /* OPENSSL_SYS_VOS_IA32 */
+# endif /* OPENSSL_SYS_VOS_HPPA */
+
+ /*
+ * Seed with the gid, pid, and uid, to ensure *some* variation between
+ * different processes.
+ */
+
+ curr_gid = getgid();
+ RAND_add(&curr_gid, sizeof(curr_gid), 1);
+ curr_gid = 0;
+
+ curr_pid = getpid();
+ RAND_add(&curr_pid, sizeof(curr_pid), 1);
+ curr_pid = 0;
+
+ curr_uid = getuid();
+ RAND_add(&curr_uid, sizeof(curr_uid), 1);
+ curr_uid = 0;
+
+ for (i = 0; i < (ENTROPY_NEEDED * 4); i++) {
+ /*
+ * burn some cpu; hope for interrupts, cache collisions, bus
+ * interference, etc.
+ */
+ for (k = 0; k < 99; k++)
+ ts.tv_nsec = random();
+
+# ifdef OPENSSL_SYS_VOS_HPPA
+ /* sleep for 1/1024 of a second (976 us). */
+ duration = 1;
+ s$sleep(&duration, &code);
+# else
+# ifdef OPENSSL_SYS_VOS_IA32
+ /* sleep for 1/65536 of a second (15 us). */
+ duration = 1;
+ s$sleep2(&duration, &code);
+# endif /* OPENSSL_SYS_VOS_IA32 */
+# endif /* OPENSSL_SYS_VOS_HPPA */
+
+ /* get wall clock time. */
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ /* take 8 bits */
+ v = (unsigned char)(ts.tv_nsec % 256);
+ RAND_add(&v, sizeof(v), 1);
+ v = 0;
+ }
+ return 1;
+}
+# elif defined __OpenBSD__
+int RAND_poll(void)
+{
+ u_int32_t rnd = 0, i;
+ unsigned char buf[ENTROPY_NEEDED];
+
+ for (i = 0; i < sizeof(buf); i++) {
+ if (i % 4 == 0)
+ rnd = arc4random();
+ buf[i] = rnd;
+ rnd >>= 8;
+ }
+ RAND_add(buf, sizeof(buf), ENTROPY_NEEDED);
+ OPENSSL_cleanse(buf, sizeof(buf));
+
+ return 1;
+}
+# else /* !defined(__OpenBSD__) */
+int RAND_poll(void)
+{
+ unsigned long l;
+ pid_t curr_pid = getpid();
+# if defined(DEVRANDOM) || (!defined(OPENSS_NO_EGD) && defined(DEVRANDOM_EGD))
+ unsigned char tmpbuf[ENTROPY_NEEDED];
+ int n = 0;
+# endif
+# ifdef DEVRANDOM
+ static const char *randomfiles[] = { DEVRANDOM };
+ struct stat randomstats[OSSL_NELEM(randomfiles)];
+ int fd;
+ unsigned int i;
+# endif
+# if !defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD)
+ static const char *egdsockets[] = { DEVRANDOM_EGD, NULL };
+ const char **egdsocket = NULL;
+# endif
+
+# ifdef DEVRANDOM
+ memset(randomstats, 0, sizeof(randomstats));
+ /*
+ * Use a random entropy pool device. Linux, FreeBSD and OpenBSD have
+ * this. Use /dev/urandom if you can as /dev/random may block if it runs
+ * out of random entries.
+ */
+
+ for (i = 0; (i < OSSL_NELEM(randomfiles)) && (n < ENTROPY_NEEDED); i++) {
+ if ((fd = open(randomfiles[i], O_RDONLY
+# ifdef O_NONBLOCK
+ | O_NONBLOCK
+# endif
+# ifdef O_BINARY
+ | O_BINARY
+# endif
+# ifdef O_NOCTTY /* If it happens to be a TTY (god forbid), do
+ * not make it our controlling tty */
+ | O_NOCTTY
+# endif
+ )) >= 0) {
+ int usec = 10 * 1000; /* spend 10ms on each file */
+ int r;
+ unsigned int j;
+ struct stat *st = &randomstats[i];
+
+ /*
+ * Avoid using same input... Used to be O_NOFOLLOW above, but
+ * it's not universally appropriate...
+ */
+ if (fstat(fd, st) != 0) {
+ close(fd);
+ continue;
+ }
+ for (j = 0; j < i; j++) {
+ if (randomstats[j].st_ino == st->st_ino &&
+ randomstats[j].st_dev == st->st_dev)
+ break;
+ }
+ if (j < i) {
+ close(fd);
+ continue;
+ }
+
+ do {
+ int try_read = 0;
+
+# if defined(OPENSSL_SYS_LINUX)
+ /* use poll() */
+ struct pollfd pset;
+
+ pset.fd = fd;
+ pset.events = POLLIN;
+ pset.revents = 0;
+
+ if (poll(&pset, 1, usec / 1000) < 0)
+ usec = 0;
+ else
+ try_read = (pset.revents & POLLIN) != 0;
+
+# else
+ /* use select() */
+ fd_set fset;
+ struct timeval t;
+
+ t.tv_sec = 0;
+ t.tv_usec = usec;
+
+ if (FD_SETSIZE > 0 && (unsigned)fd >= FD_SETSIZE) {
+ /*
+ * can't use select, so just try to read once anyway
+ */
+ try_read = 1;
+ } else {
+ FD_ZERO(&fset);
+ FD_SET(fd, &fset);
+
+ if (select(fd + 1, &fset, NULL, NULL, &t) >= 0) {
+ usec = t.tv_usec;
+ if (FD_ISSET(fd, &fset))
+ try_read = 1;
+ } else
+ usec = 0;
+ }
+# endif
+
+ if (try_read) {
+ r = read(fd, (unsigned char *)tmpbuf + n,
+ ENTROPY_NEEDED - n);
+ if (r > 0)
+ n += r;
+ } else
+ r = -1;
+
+ /*
+ * Some Unixen will update t in select(), some won't. For
+ * those who won't, or if we didn't use select() in the first
+ * place, give up here, otherwise, we will do this once again
+ * for the remaining time.
+ */
+ if (usec == 10 * 1000)
+ usec = 0;
+ }
+ while ((r > 0 ||
+ (errno == EINTR || errno == EAGAIN)) && usec != 0
+ && n < ENTROPY_NEEDED);
+
+ close(fd);
+ }
+ }
+# endif /* defined(DEVRANDOM) */
+
+# if !defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD)
+ /*
+ * Use an EGD socket to read entropy from an EGD or PRNGD entropy
+ * collecting daemon.
+ */
+
+ for (egdsocket = egdsockets; *egdsocket && n < ENTROPY_NEEDED;
+ egdsocket++) {
+ int r;
+
+ r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf + n,
+ ENTROPY_NEEDED - n);
+ if (r > 0)
+ n += r;
+ }
+# endif /* defined(DEVRANDOM_EGD) */
+
+# if defined(DEVRANDOM) || (!defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD))
+ if (n > 0) {
+ RAND_add(tmpbuf, sizeof(tmpbuf), (double)n);
+ OPENSSL_cleanse(tmpbuf, n);
+ }
+# endif
+
+ /* put in some default random data, we need more than just this */
+ l = curr_pid;
+ RAND_add(&l, sizeof(l), 0.0);
+ l = getuid();
+ RAND_add(&l, sizeof(l), 0.0);
+
+ l = time(NULL);
+ RAND_add(&l, sizeof(l), 0.0);
+
+# if defined(DEVRANDOM) || (!defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD))
+ return 1;
+# else
+ return 0;
+# endif
+}
+
+# endif /* defined(__OpenBSD__) */
+#endif /* !(defined(OPENSSL_SYS_WINDOWS) ||
+ * defined(OPENSSL_SYS_WIN32) ||
+ * defined(OPENSSL_SYS_VMS) ||
+ * defined(OPENSSL_SYS_VXWORKS) */
+
+#if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)
+int RAND_poll(void)
+{
+ return 0;
+}
+#endif
diff --git a/openssl-1.1.0h/crypto/rand/rand_vms.c b/openssl-1.1.0h/crypto/rand/rand_vms.c
new file mode 100644
index 0000000..9c462dd
--- /dev/null
+++ b/openssl-1.1.0h/crypto/rand/rand_vms.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Modified by VMS Software, Inc (2016)
+ * Eliminate looping through all processes (performance)
+ * Add additional randomizations using rand() function
+ */
+
+#include <openssl/rand.h>
+#include "rand_lcl.h"
+
+#if defined(OPENSSL_SYS_VMS)
+# include <descrip.h>
+# include <jpidef.h>
+# include <ssdef.h>
+# include <starlet.h>
+# include <efndef>
+# ifdef __DECC
+# pragma message disable DOLLARID
+# endif
+
+/*
+ * Use 32-bit pointers almost everywhere. Define the type to which to cast a
+ * pointer passed to an external function.
+ */
+# if __INITIAL_POINTER_SIZE == 64
+# define PTR_T __void_ptr64
+# pragma pointer_size save
+# pragma pointer_size 32
+# else /* __INITIAL_POINTER_SIZE == 64 */
+# define PTR_T void *
+# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
+
+static struct items_data_st {
+ short length, code; /* length is number of bytes */
+} items_data[] = {
+ {4, JPI$_BUFIO},
+ {4, JPI$_CPUTIM},
+ {4, JPI$_DIRIO},
+ {4, JPI$_IMAGECOUNT},
+ {8, JPI$_LAST_LOGIN_I},
+ {8, JPI$_LOGINTIM},
+ {4, JPI$_PAGEFLTS},
+ {4, JPI$_PID},
+ {4, JPI$_PPGCNT},
+ {4, JPI$_WSPEAK},
+ {4, JPI$_FINALEXC},
+ {0, 0} /* zero terminated */
+};
+
+int RAND_poll(void)
+{
+
+ /* determine the number of items in the JPI array */
+
+ struct items_data_st item_entry;
+ int item_entry_count = sizeof(items_data)/sizeof(item_entry);
+
+ /* Create the JPI itemlist array to hold item_data content */
+
+ struct {
+ short length, code;
+ int *buffer;
+ int *retlen;
+ } item[item_entry_count], *pitem; /* number of entries in items_data */
+
+ struct items_data_st *pitems_data;
+ int data_buffer[(item_entry_count*2)+4]; /* 8 bytes per entry max */
+ int iosb[2];
+ int sys_time[2];
+ int *ptr;
+ int i, j ;
+ int tmp_length = 0;
+ int total_length = 0;
+
+ pitems_data = items_data;
+ pitem = item;
+
+
+ /* Setup itemlist for GETJPI */
+ while (pitems_data->length) {
+ pitem->length = pitems_data->length;
+ pitem->code = pitems_data->code;
+ pitem->buffer = &data_buffer[total_length];
+ pitem->retlen = 0;
+ /* total_length is in longwords */
+ total_length += pitems_data->length/4;
+ pitems_data++;
+ pitem ++;
+ }
+ pitem->length = pitem->code = 0;
+
+ /* Fill data_buffer with various info bits from this process */
+ /* and twist that data to seed the SSL random number init */
+
+ if (sys$getjpiw(EFN$C_ENF, NULL, NULL, item, &iosb, 0, 0) == SS$_NORMAL) {
+ for (i = 0; i < total_length; i++) {
+ sys$gettim((struct _generic_64 *)&sys_time[0]);
+ srand(sys_time[0] * data_buffer[0] * data_buffer[1] + i);
+
+ if (i == (total_length - 1)) { /* for JPI$_FINALEXC */
+ ptr = &data_buffer[i];
+ for (j = 0; j < 4; j++) {
+ data_buffer[i + j] = ptr[j];
+ /* OK to use rand() just to scramble the seed */
+ data_buffer[i + j] ^= (sys_time[0] ^ rand());
+ tmp_length++;
+ }
+ } else {
+ /* OK to use rand() just to scramble the seed */
+ data_buffer[i] ^= (sys_time[0] ^ rand());
+ }
+ }
+
+ total_length += (tmp_length - 1);
+
+ /* size of seed is total_length*4 bytes (64bytes) */
+ RAND_add((PTR_T) data_buffer, total_length*4, total_length * 2);
+ } else {
+ return 0;
+ }
+
+ return 1;
+}
+
+#endif
diff --git a/openssl-1.1.0h/crypto/rand/rand_win.c b/openssl-1.1.0h/crypto/rand/rand_win.c
new file mode 100644
index 0000000..1be0ed3
--- /dev/null
+++ b/openssl-1.1.0h/crypto/rand/rand_win.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include <openssl/rand.h>
+#include "rand_lcl.h"
+
+#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
+# include <windows.h>
+/* On Windows 7 or higher use BCrypt instead of the legacy CryptoAPI */
+# if defined(_MSC_VER) && defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0601
+# define RAND_WINDOWS_USE_BCRYPT
+# endif
+
+# ifdef RAND_WINDOWS_USE_BCRYPT
+# include <bcrypt.h>
+# pragma comment(lib, "bcrypt.lib")
+# ifndef STATUS_SUCCESS
+# define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+# endif
+# else
+# include <wincrypt.h>
+/*
+ * Intel hardware RNG CSP -- available from
+ * http://developer.intel.com/design/security/rng/redist_license.htm
+ */
+# define PROV_INTEL_SEC 22
+# define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider"
+# endif
+
+static void readtimer(void);
+
+int RAND_poll(void)
+{
+ MEMORYSTATUS mst;
+# ifndef RAND_WINDOWS_USE_BCRYPT
+ HCRYPTPROV hProvider;
+# endif
+ DWORD w;
+ BYTE buf[64];
+
+# ifdef RAND_WINDOWS_USE_BCRYPT
+ if (BCryptGenRandom(NULL, buf, (ULONG)sizeof(buf), BCRYPT_USE_SYSTEM_PREFERRED_RNG) == STATUS_SUCCESS) {
+ RAND_add(buf, sizeof(buf), sizeof(buf));
+ }
+# else
+ /* poll the CryptoAPI PRNG */
+ /* The CryptoAPI returns sizeof(buf) bytes of randomness */
+ if (CryptAcquireContextW(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+ if (CryptGenRandom(hProvider, (DWORD)sizeof(buf), buf) != 0) {
+ RAND_add(buf, sizeof(buf), sizeof(buf));
+ }
+ CryptReleaseContext(hProvider, 0);
+ }
+
+ /* poll the Pentium PRG with CryptoAPI */
+ if (CryptAcquireContextW(&hProvider, NULL, INTEL_DEF_PROV, PROV_INTEL_SEC, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+ if (CryptGenRandom(hProvider, (DWORD)sizeof(buf), buf) != 0) {
+ RAND_add(buf, sizeof(buf), sizeof(buf));
+ }
+ CryptReleaseContext(hProvider, 0);
+ }
+# endif
+
+ /* timer data */
+ readtimer();
+
+ /* memory usage statistics */
+ GlobalMemoryStatus(&mst);
+ RAND_add(&mst, sizeof(mst), 1);
+
+ /* process ID */
+ w = GetCurrentProcessId();
+ RAND_add(&w, sizeof(w), 1);
+
+ return (1);
+}
+
+#if OPENSSL_API_COMPAT < 0x10100000L
+int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ RAND_poll();
+ return RAND_status();
+}
+
+void RAND_screen(void)
+{
+ RAND_poll();
+}
+#endif
+
+/* feed timing information to the PRNG */
+static void readtimer(void)
+{
+ DWORD w;
+ LARGE_INTEGER l;
+ static int have_perfc = 1;
+# if defined(_MSC_VER) && defined(_M_X86)
+ static int have_tsc = 1;
+ DWORD cyclecount;
+
+ if (have_tsc) {
+ __try {
+ __asm {
+ _emit 0x0f _emit 0x31 mov cyclecount, eax}
+ RAND_add(&cyclecount, sizeof(cyclecount), 1);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ have_tsc = 0;
+ }
+ }
+# else
+# define have_tsc 0
+# endif
+
+ if (have_perfc) {
+ if (QueryPerformanceCounter(&l) == 0)
+ have_perfc = 0;
+ else
+ RAND_add(&l, sizeof(l), 0);
+ }
+
+ if (!have_tsc && !have_perfc) {
+ w = GetTickCount();
+ RAND_add(&w, sizeof(w), 0);
+ }
+}
+
+#endif
diff --git a/openssl-1.1.0h/crypto/rand/randfile.c b/openssl-1.1.0h/crypto/rand/randfile.c
new file mode 100644
index 0000000..dbd03ff
--- /dev/null
+++ b/openssl-1.1.0h/crypto/rand/randfile.c
@@ -0,0 +1,364 @@
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+#include <openssl/buffer.h>
+
+#ifdef OPENSSL_SYS_VMS
+# include <unixio.h>
+#endif
+#include <sys/types.h>
+#ifndef OPENSSL_NO_POSIX_IO
+# include <sys/stat.h>
+# include <fcntl.h>
+/*
+ * Following should not be needed, and we could have been stricter
+ * and demand S_IS*. But some systems just don't comply... Formally
+ * below macros are "anatomically incorrect", because normally they
+ * would look like ((m) & MASK == TYPE), but since MASK availability
+ * is as questionable, we settle for this poor-man fallback...
+ */
+# if !defined(S_ISBLK)
+# if defined(_S_IFBLK)
+# define S_ISBLK(m) ((m) & _S_IFBLK)
+# elif defined(S_IFBLK)
+# define S_ISBLK(m) ((m) & S_IFBLK)
+# elif defined(_WIN32)
+# define S_ISBLK(m) 0 /* no concept of block devices on Windows */
+# endif
+# endif
+# if !defined(S_ISCHR)
+# if defined(_S_IFCHR)
+# define S_ISCHR(m) ((m) & _S_IFCHR)
+# elif defined(S_IFCHR)
+# define S_ISCHR(m) ((m) & S_IFCHR)
+# endif
+# endif
+#endif
+
+#ifdef _WIN32
+# define stat _stat
+# define chmod _chmod
+# define open _open
+# define fdopen _fdopen
+# define fstat _fstat
+# define fileno _fileno
+#endif
+
+#undef BUFSIZE
+#define BUFSIZE 1024
+#define RAND_DATA 1024
+
+#ifdef OPENSSL_SYS_VMS
+/*
+ * Misc hacks needed for specific cases.
+ *
+ * __FILE_ptr32 is a type provided by DEC C headers (types.h specifically)
+ * to make sure the FILE* is a 32-bit pointer no matter what. We know that
+ * stdio function return this type (a study of stdio.h proves it).
+ * Additionally, we create a similar char pointer type for the sake of
+ * vms_setbuf below.
+ */
+# if __INITIAL_POINTER_SIZE == 64
+# pragma pointer_size save
+# pragma pointer_size 32
+typedef char *char_ptr32;
+# pragma pointer_size restore
+/*
+ * On VMS, setbuf() will only take 32-bit pointers, and a compilation
+ * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here.
+ * Since we know that the FILE* really is a 32-bit pointer expanded to
+ * 64 bits, we also know it's safe to convert it back to a 32-bit pointer.
+ * As for the buffer parameter, we only use NULL here, so that passes as
+ * well...
+ */
+# define setbuf(fp,buf) (setbuf)((__FILE_ptr32)(fp), (char_ptr32)(buf))
+# endif
+
+/*
+ * This declaration is a nasty hack to get around vms' extension to fopen for
+ * passing in sharing options being disabled by /STANDARD=ANSI89
+ */
+static __FILE_ptr32 (*const vms_fopen)(const char *, const char *, ...) =
+ (__FILE_ptr32 (*)(const char *, const char *, ...))fopen;
+# define VMS_OPEN_ATTRS "shr=get,put,upd,del","ctx=bin,stm","rfm=stm","rat=none","mrs=0"
+
+# define openssl_fopen(fname,mode) vms_fopen((fname), (mode), VMS_OPEN_ATTRS)
+#endif
+
+#define RFILE ".rnd"
+
+/*
+ * Note that these functions are intended for seed files only. Entropy
+ * devices and EGD sockets are handled in rand_unix.c
+ */
+
+int RAND_load_file(const char *file, long bytes)
+{
+ /*-
+ * If bytes >= 0, read up to 'bytes' bytes.
+ * if bytes == -1, read complete file.
+ */
+
+ unsigned char buf[BUFSIZE];
+#ifndef OPENSSL_NO_POSIX_IO
+ struct stat sb;
+#endif
+ int i, ret = 0, n;
+ FILE *in = NULL;
+
+ if (file == NULL)
+ return 0;
+
+ if (bytes == 0)
+ return ret;
+
+ in = openssl_fopen(file, "rb");
+ if (in == NULL)
+ goto err;
+
+#ifndef OPENSSL_NO_POSIX_IO
+ /*
+ * struct stat can have padding and unused fields that may not be
+ * initialized in the call to stat(). We need to clear the entire
+ * structure before calling RAND_add() to avoid complaints from
+ * applications such as Valgrind.
+ */
+ memset(&sb, 0, sizeof(sb));
+ if (fstat(fileno(in), &sb) < 0)
+ goto err;
+ RAND_add(&sb, sizeof(sb), 0.0);
+
+# if defined(S_ISBLK) && defined(S_ISCHR)
+ if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) {
+ /*
+ * this file is a device. we don't want read an infinite number of
+ * bytes from a random device, nor do we want to use buffered I/O
+ * because we will waste system entropy.
+ */
+ bytes = (bytes == -1) ? 2048 : bytes; /* ok, is 2048 enough? */
+ setbuf(in, NULL); /* don't do buffered reads */
+ }
+# endif
+#endif
+ for (;;) {
+ if (bytes > 0)
+ n = (bytes < BUFSIZE) ? (int)bytes : BUFSIZE;
+ else
+ n = BUFSIZE;
+ i = fread(buf, 1, n, in);
+ if (i <= 0)
+ break;
+
+ RAND_add(buf, i, (double)i);
+ ret += i;
+ if (bytes > 0) {
+ bytes -= n;
+ if (bytes <= 0)
+ break;
+ }
+ }
+ OPENSSL_cleanse(buf, BUFSIZE);
+ err:
+ if (in != NULL)
+ fclose(in);
+ return ret;
+}
+
+int RAND_write_file(const char *file)
+{
+ unsigned char buf[BUFSIZE];
+ int i, ret = 0, rand_err = 0;
+ FILE *out = NULL;
+ int n;
+#ifndef OPENSSL_NO_POSIX_IO
+ struct stat sb;
+
+# if defined(S_ISBLK) && defined(S_ISCHR)
+# ifdef _WIN32
+ /*
+ * Check for |file| being a driver as "ASCII-safe" on Windows,
+ * because driver paths are always ASCII.
+ */
+# endif
+ i = stat(file, &sb);
+ if (i != -1) {
+ if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) {
+ /*
+ * this file is a device. we don't write back to it. we
+ * "succeed" on the assumption this is some sort of random
+ * device. Otherwise attempting to write to and chmod the device
+ * causes problems.
+ */
+ return 1;
+ }
+ }
+# endif
+#endif
+
+#if defined(O_CREAT) && !defined(OPENSSL_NO_POSIX_IO) && \
+ !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_WINDOWS)
+ {
+# ifndef O_BINARY
+# define O_BINARY 0
+# endif
+ /*
+ * chmod(..., 0600) is too late to protect the file, permissions
+ * should be restrictive from the start
+ */
+ int fd = open(file, O_WRONLY | O_CREAT | O_BINARY, 0600);
+ if (fd != -1)
+ out = fdopen(fd, "wb");
+ }
+#endif
+
+#ifdef OPENSSL_SYS_VMS
+ /*
+ * VMS NOTE: Prior versions of this routine created a _new_ version of
+ * the rand file for each call into this routine, then deleted all
+ * existing versions named ;-1, and finally renamed the current version
+ * as ';1'. Under concurrent usage, this resulted in an RMS race
+ * condition in rename() which could orphan files (see vms message help
+ * for RMS$_REENT). With the fopen() calls below, openssl/VMS now shares
+ * the top-level version of the rand file. Note that there may still be
+ * conditions where the top-level rand file is locked. If so, this code
+ * will then create a new version of the rand file. Without the delete
+ * and rename code, this can result in ascending file versions that stop
+ * at version 32767, and this routine will then return an error. The
+ * remedy for this is to recode the calling application to avoid
+ * concurrent use of the rand file, or synchronize usage at the
+ * application level. Also consider whether or not you NEED a persistent
+ * rand file in a concurrent use situation.
+ */
+
+ out = openssl_fopen(file, "rb+");
+#endif
+ if (out == NULL)
+ out = openssl_fopen(file, "wb");
+ if (out == NULL)
+ goto err;
+
+#if !defined(NO_CHMOD) && !defined(OPENSSL_NO_POSIX_IO)
+ chmod(file, 0600);
+#endif
+ n = RAND_DATA;
+ for (;;) {
+ i = (n > BUFSIZE) ? BUFSIZE : n;
+ n -= BUFSIZE;
+ if (RAND_bytes(buf, i) <= 0)
+ rand_err = 1;
+ i = fwrite(buf, 1, i, out);
+ if (i <= 0) {
+ ret = 0;
+ break;
+ }
+ ret += i;
+ if (n <= 0)
+ break;
+ }
+
+ fclose(out);
+ OPENSSL_cleanse(buf, BUFSIZE);
+ err:
+ return (rand_err ? -1 : ret);
+}
+
+const char *RAND_file_name(char *buf, size_t size)
+{
+ char *s = NULL;
+ int use_randfile = 1;
+#ifdef __OpenBSD__
+ struct stat sb;
+#endif
+
+#if defined(_WIN32) && defined(CP_UTF8)
+ DWORD len;
+ WCHAR *var, *val;
+
+ if ((var = L"RANDFILE",
+ len = GetEnvironmentVariableW(var, NULL, 0)) == 0
+ && (var = L"HOME", use_randfile = 0,
+ len = GetEnvironmentVariableW(var, NULL, 0)) == 0
+ && (var = L"USERPROFILE",
+ len = GetEnvironmentVariableW(var, NULL, 0)) == 0) {
+ var = L"SYSTEMROOT",
+ len = GetEnvironmentVariableW(var, NULL, 0);
+ }
+
+ if (len != 0) {
+ int sz;
+
+ val = _alloca(len * sizeof(WCHAR));
+
+ if (GetEnvironmentVariableW(var, val, len) < len
+ && (sz = WideCharToMultiByte(CP_UTF8, 0, val, -1, NULL, 0,
+ NULL, NULL)) != 0) {
+ s = _alloca(sz);
+ if (WideCharToMultiByte(CP_UTF8, 0, val, -1, s, sz,
+ NULL, NULL) == 0)
+ s = NULL;
+ }
+ }
+#else
+ if (OPENSSL_issetugid() != 0) {
+ use_randfile = 0;
+ } else {
+ s = getenv("RANDFILE");
+ if (s == NULL || *s == '\0') {
+ use_randfile = 0;
+ s = getenv("HOME");
+ }
+ }
+#endif
+#ifdef DEFAULT_HOME
+ if (!use_randfile && s == NULL) {
+ s = DEFAULT_HOME;
+ }
+#endif
+ if (s != NULL && *s) {
+ size_t len = strlen(s);
+
+ if (use_randfile && len + 1 < size) {
+ if (OPENSSL_strlcpy(buf, s, size) >= size)
+ return NULL;
+ } else if (len + strlen(RFILE) + 2 < size) {
+ OPENSSL_strlcpy(buf, s, size);
+#ifndef OPENSSL_SYS_VMS
+ OPENSSL_strlcat(buf, "/", size);
+#endif
+ OPENSSL_strlcat(buf, RFILE, size);
+ }
+ } else {
+ buf[0] = '\0'; /* no file name */
+ }
+
+#ifdef __OpenBSD__
+ /*
+ * given that all random loads just fail if the file can't be seen on a
+ * stat, we stat the file we're returning, if it fails, use /dev/arandom
+ * instead. this allows the user to use their own source for good random
+ * data, but defaults to something hopefully decent if that isn't
+ * available.
+ */
+
+ if (!buf[0] || stat(buf, &sb) == -1)
+ if (OPENSSL_strlcpy(buf, "/dev/arandom", size) >= size) {
+ return NULL;
+ }
+#endif
+ return buf[0] ? buf : NULL;
+}