diff options
author | Richard Levitte <levitte@openssl.org> | 2017-04-06 11:30:03 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2017-04-07 04:56:13 +0200 |
commit | 67114d93b47aa02192272182595c2b5d1bba8298 (patch) | |
tree | e81094c09e187576ff59b5c7cd6efd6d33b019f4 /crypto | |
parent | 9317235bbb43fbe8ee21cc3bfe0effb9ab6dee2e (diff) |
Make getting and setting the RAND default method thread safe
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3137)
(cherry picked from commit 87975cfa91c3f06a52f2550ed2ef632644be6dde)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/rand/rand_lib.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 60c1b17fba..9939540fe8 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -12,8 +12,8 @@ #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> @@ -23,21 +23,44 @@ #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) +{ +#ifndef OPENSSL_NO_ENGINE + rand_engine_lock = CRYPTO_THREAD_lock_new(); +#endif + rand_meth_lock = CRYPTO_THREAD_lock_new(); + return rand_engine_lock != NULL && rand_meth_lock != NULL; +} 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(); @@ -54,13 +77,19 @@ const RAND_METHOD *RAND_get_rand_method(void) #endif default_RAND_meth = RAND_OpenSSL(); } - return default_RAND_meth; + 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; @@ -70,9 +99,11 @@ int RAND_set_rand_engine(ENGINE *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 @@ -83,6 +114,8 @@ void rand_cleanup_int(void) if (meth && meth->cleanup) meth->cleanup(); RAND_set_rand_method(NULL); + CRYPTO_THREAD_lock_free(rand_meth_lock); + CRYPTO_THREAD_lock_free(rand_engine_lock); } void RAND_seed(const void *buf, int num) |