X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Frand%2Fmd_rand.c;h=4b874e3bedf4a9459e1ee8487769076983938e02;hp=ef43966814c3ca254cb0adcc6db3721c4eba9875;hb=1150999e04ab826a9e8607e87db7fdd72f688ec4;hpb=68b00c237298b2e7e382686ffd583847d57bbc0b diff --git a/crypto/rand/md_rand.c b/crypto/rand/md_rand.c index ef43966814..4b874e3bed 100644 --- a/crypto/rand/md_rand.c +++ b/crypto/rand/md_rand.c @@ -1,121 +1,12 @@ -/* crypto/rand/md_rand.c */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * 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 */ -#ifdef MD_RAND_DEBUG -# ifndef NDEBUG -# define NDEBUG -# endif -#endif - -#include #include #include @@ -128,8 +19,10 @@ # include #endif +#include #include #include +#include #include "rand_lcl.h" #include @@ -153,44 +46,57 @@ static long md_count[2] = { 0, 0 }; static double entropy = 0; static int initialized = 0; -static unsigned int crypto_lock_rand = 0; /* may be set only when a thread - * holds CRYPTO_LOCK_RAND (to - * prevent double locking) */ -/* access to lockin_thread is synchronized by CRYPTO_LOCK_RAND2 */ +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_THREADID locking_threadid; +static CRYPTO_THREAD_ID locking_threadid; #ifdef PREDICT 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) +static void do_rand_lock_init(void) +{ + rand_lock = CRYPTO_THREAD_lock_new(); + rand_tmp_lock = CRYPTO_THREAD_lock_new(); +} + +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; @@ -200,14 +106,16 @@ static void ssleay_rand_cleanup(void) md_count[1] = 0; entropy = 0; initialized = 0; + CRYPTO_THREAD_lock_free(rand_lock); + CRYPTO_THREAD_lock_free(rand_tmp_lock); } -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; @@ -229,19 +137,23 @@ static int ssleay_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; + + CRYPTO_THREAD_run_once(&rand_lock_init, do_rand_lock_init); + /* check if we already have the lock */ if (crypto_lock_rand) { - CRYPTO_THREADID cur; - CRYPTO_THREADID_current(&cur); - CRYPTO_r_lock(CRYPTO_LOCK_RAND2); - do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur); - CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); + 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_w_lock(CRYPTO_LOCK_RAND); + CRYPTO_THREAD_write_lock(rand_lock); st_idx = state_index; /* @@ -273,27 +185,27 @@ static int ssleay_rand_add(const void *buf, int num, double add) md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0); if (!do_not_lock) - CRYPTO_w_unlock(CRYPTO_LOCK_RAND); + 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)) + 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 @@ -303,9 +215,9 @@ static int ssleay_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]++; @@ -315,7 +227,7 @@ static int ssleay_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. @@ -327,7 +239,7 @@ static int ssleay_rand_add(const void *buf, int num, double add) } if (!do_not_lock) - CRYPTO_w_lock(CRYPTO_LOCK_RAND); + 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 @@ -340,23 +252,20 @@ static int ssleay_rand_add(const void *buf, int num, double add) if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */ entropy += add; if (!do_not_lock) - CRYPTO_w_unlock(CRYPTO_LOCK_RAND); + CRYPTO_THREAD_unlock(rand_lock); -#if !defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) - assert(md_c[1] == md_count[1]); -#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; @@ -364,7 +273,7 @@ static int ssleay_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 @@ -404,7 +313,10 @@ static int ssleay_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); @@ -427,12 +339,18 @@ static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo) * global 'md'. */ - CRYPTO_w_lock(CRYPTO_LOCK_RAND); + CRYPTO_THREAD_run_once(&rand_lock_init, do_rand_lock_init); + 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 ssleay_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); + /* 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) { @@ -466,7 +384,7 @@ static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo) * 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. */ @@ -478,9 +396,9 @@ static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo) #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) @@ -506,55 +424,44 @@ static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo) /* before unlocking, we must clear 'crypto_lock_rand' */ crypto_lock_rand = 0; - CRYPTO_w_unlock(CRYPTO_LOCK_RAND); + 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)) + 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++) { @@ -567,75 +474,91 @@ static int ssleay_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)) { - CRYPTO_w_unlock(CRYPTO_LOCK_RAND); + 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)) { + CRYPTO_THREAD_unlock(rand_lock); goto err; } - CRYPTO_w_unlock(CRYPTO_LOCK_RAND); + ASYNC_unblock_pause(); + CRYPTO_THREAD_unlock(rand_lock); - 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; + CRYPTO_THREAD_ID cur; int ret; int do_not_lock; - CRYPTO_THREADID_current(&cur); + CRYPTO_THREAD_run_once(&rand_lock_init, do_rand_lock_init); + 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_r_lock(CRYPTO_LOCK_RAND2); - do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur); - CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); + 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_w_lock(CRYPTO_LOCK_RAND); + CRYPTO_THREAD_write_lock(rand_lock); + /* + * 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); - CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); + CRYPTO_THREAD_write_lock(rand_tmp_lock); + locking_threadid = cur; + CRYPTO_THREAD_unlock(rand_tmp_lock); crypto_lock_rand = 1; } @@ -650,7 +573,8 @@ static int ssleay_rand_status(void) /* before unlocking, we must clear 'crypto_lock_rand' */ crypto_lock_rand = 0; - CRYPTO_w_unlock(CRYPTO_LOCK_RAND); + ASYNC_unblock_pause(); + CRYPTO_THREAD_unlock(rand_lock); } return ret; @@ -665,7 +589,8 @@ static int ssleay_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