提交 3ce1c27b 编写于 作者: D Dr. Matthias St. Pierre

DRBG: add locking api

This commit adds three new accessors to the internal DRBG lock

   int RAND_DRBG_lock(RAND_DRBG *drbg)
   int RAND_DRBG_unlock(RAND_DRBG *drbg)
   int RAND_DRBG_enable_locking(RAND_DRBG *drbg)

The three shared DRBGs are intended to be used concurrently, so they
have locking enabled by default. It is the callers responsibility to
guard access to the shared DRBGs by calls to RAND_DRBG_lock() and
RAND_DRBG_unlock().

All other DRBG instances don't have locking enabled by default, because
they are intendended to be used by a single thread. If it is desired,
locking can be enabled by using RAND_DRBG_enable_locking().
Reviewed-by: NRich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5294)
上级 fcd21502
......@@ -890,6 +890,7 @@ RAND_F_DRBG_GET_ENTROPY:105:drbg_get_entropy
RAND_F_DRBG_SETUP:117:drbg_setup
RAND_F_GET_ENTROPY:106:get_entropy
RAND_F_RAND_BYTES:100:RAND_bytes
RAND_F_RAND_DRBG_ENABLE_LOCKING:119:RAND_DRBG_enable_locking
RAND_F_RAND_DRBG_GENERATE:107:RAND_DRBG_generate
RAND_F_RAND_DRBG_INSTANTIATE:108:RAND_DRBG_instantiate
RAND_F_RAND_DRBG_NEW:109:RAND_DRBG_new
......@@ -2256,6 +2257,7 @@ RAND_R_ADDITIONAL_INPUT_TOO_LONG:102:additional input too long
RAND_R_ALREADY_INSTANTIATED:103:already instantiated
RAND_R_ARGUMENT_OUT_OF_RANGE:105:argument out of range
RAND_R_CANNOT_OPEN_FILE:121:Cannot open file
RAND_R_DRBG_ALREADY_INITIALIZED:129:drbg already initialized
RAND_R_DRBG_NOT_INITIALISED:104:drbg not initialised
RAND_R_ENTROPY_INPUT_TOO_LONG:106:entropy input too long
RAND_R_ENTROPY_OUT_OF_RANGE:124:entropy out of range
......@@ -2274,6 +2276,7 @@ RAND_R_IN_ERROR_STATE:114:in error state
RAND_R_NOT_A_REGULAR_FILE:122:Not a regular file
RAND_R_NOT_INSTANTIATED:115:not instantiated
RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED:128:no drbg implementation selected
RAND_R_PARENT_LOCKING_NOT_ENABLED:130:parent locking not enabled
RAND_R_PERSONALISATION_STRING_TOO_LONG:116:personalisation string too long
RAND_R_PRNG_NOT_SEEDED:100:PRNG not seeded
RAND_R_RANDOM_POOL_OVERFLOW:125:random pool overflow
......
......@@ -90,6 +90,21 @@ static RAND_DRBG *drbg_private;
* |randomness| argument). This will immediately reseed the <master> DRBG.
* The <public> and <private> DRBG will detect this on their next generate
* call and reseed, pulling randomness from <master>.
*
* LOCKING
*
* The three shared DRBGs are intended to be used concurrently, so they
* support locking by default. It is the callers responsibility to wrap
* calls to functions like RAND_DRBG_generate() which modify the DRBGs
* internal state with calls to RAND_DRBG_lock() and RAND_DRBG_unlock().
* The functions RAND_bytes() and RAND_priv_bytes() take the locks
* automatically, so using the RAND api is thread safe as before.
*
* All other DRBG instances don't have locking enabled by default, because
* they are intendended to be used by a single thread. If it is desired,
* locking can be enabled using RAND_DRBG_enable_locking(). However, instead
* of accessing a single DRBG instance concurrently from different threads,
* it is recommended to instantiate a separate DRBG instance per thread.
*/
......@@ -656,6 +671,69 @@ int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval)
return 1;
}
/*
* Locks the given drbg. Locking a drbg which does not have locking
* enabled is considered a successful no-op.
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_lock(RAND_DRBG *drbg)
{
if (drbg->lock != NULL)
return CRYPTO_THREAD_write_lock(drbg->lock);
return 1;
}
/*
* Unlocks the given drbg. Unlocking a drbg which does not have locking
* enabled is considered a successful no-op.
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_unlock(RAND_DRBG *drbg)
{
if (drbg->lock != NULL)
return CRYPTO_THREAD_unlock(drbg->lock);
return 1;
}
/*
* Enables locking for the given drbg
*
* Locking can only be enabled if the random generator
* is in the uninitialized state.
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_enable_locking(RAND_DRBG *drbg)
{
if (drbg->state != DRBG_UNINITIALISED) {
RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING,
RAND_R_DRBG_ALREADY_INITIALIZED);
return 0;
}
if (drbg->lock == NULL) {
if (drbg->parent != NULL && drbg->lock == NULL) {
RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING,
RAND_R_PARENT_LOCKING_NOT_ENABLED);
return 0;
}
drbg->lock = CRYPTO_THREAD_lock_new();
if (drbg->lock == NULL) {
RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING,
RAND_R_FAILED_TO_CREATE_LOCK);
return 0;
}
}
return 1;
}
/*
* Get and set the EXDATA
*/
......@@ -782,9 +860,9 @@ static int drbg_bytes(unsigned char *out, int count)
if (drbg == NULL)
return 0;
CRYPTO_THREAD_write_lock(drbg->lock);
RAND_DRBG_lock(drbg);
ret = RAND_DRBG_bytes(drbg, out, count);
CRYPTO_THREAD_unlock(drbg->lock);
RAND_DRBG_unlock(drbg);
return ret;
}
......@@ -811,11 +889,11 @@ static int drbg_add(const void *buf, int num, double randomness)
return 0;
}
CRYPTO_THREAD_write_lock(drbg->lock);
RAND_DRBG_lock(drbg);
ret = rand_drbg_restart(drbg, buf,
(size_t)(unsigned int)num,
(size_t)(8*randomness));
CRYPTO_THREAD_unlock(drbg->lock);
RAND_DRBG_unlock(drbg);
return ret;
}
......@@ -835,9 +913,9 @@ static int drbg_status(void)
if (drbg == NULL)
return 0;
CRYPTO_THREAD_write_lock(drbg->lock);
RAND_DRBG_lock(drbg);
ret = drbg->state == DRBG_READY ? 1 : 0;
CRYPTO_THREAD_unlock(drbg->lock);
RAND_DRBG_unlock(drbg);
return ret;
}
......
......@@ -19,6 +19,8 @@ static const ERR_STRING_DATA RAND_str_functs[] = {
{ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_SETUP, 0), "drbg_setup"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_GET_ENTROPY, 0), "get_entropy"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_BYTES, 0), "RAND_bytes"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_ENABLE_LOCKING, 0),
"RAND_DRBG_enable_locking"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_GENERATE, 0),
"RAND_DRBG_generate"},
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_INSTANTIATE, 0),
......@@ -49,6 +51,8 @@ static const ERR_STRING_DATA RAND_str_reasons[] = {
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ARGUMENT_OUT_OF_RANGE),
"argument out of range"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_CANNOT_OPEN_FILE), "Cannot open file"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_DRBG_ALREADY_INITIALIZED),
"drbg already initialized"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_DRBG_NOT_INITIALISED),
"drbg not initialised"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ENTROPY_INPUT_TOO_LONG),
......@@ -80,6 +84,8 @@ static const ERR_STRING_DATA RAND_str_reasons[] = {
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_INSTANTIATED), "not instantiated"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED),
"no drbg implementation selected"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PARENT_LOCKING_NOT_ENABLED),
"parent locking not enabled"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PERSONALISATION_STRING_TOO_LONG),
"personalisation string too long"},
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PRNG_NOT_SEEDED), "PRNG not seeded"},
......
......@@ -200,17 +200,16 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
/*
* Get random from parent, include our state as additional input.
* Our lock is already held, but we need to lock our parent before
* generating bits from it.
* generating bits from it. (Note: taking the lock will be a no-op
* if locking if drbg->parent->lock == NULL.)
*/
if (drbg->parent->lock)
CRYPTO_THREAD_write_lock(drbg->parent->lock);
RAND_DRBG_lock(drbg->parent);
if (RAND_DRBG_generate(drbg->parent,
buffer, bytes_needed,
0,
(unsigned char *)drbg, sizeof(*drbg)) != 0)
bytes = bytes_needed;
if (drbg->parent->lock)
CRYPTO_THREAD_unlock(drbg->parent->lock);
RAND_DRBG_unlock(drbg->parent);
entropy_available = RAND_POOL_add_end(pool, bytes, 8 * bytes);
}
......@@ -406,9 +405,9 @@ int RAND_poll(void)
if (drbg == NULL)
return 0;
CRYPTO_THREAD_write_lock(drbg->lock);
RAND_DRBG_lock(drbg);
ret = rand_drbg_restart(drbg, NULL, 0, 0);
CRYPTO_THREAD_unlock(drbg->lock);
RAND_DRBG_unlock(drbg);
return ret;
......@@ -798,9 +797,9 @@ int RAND_priv_bytes(unsigned char *buf, int num)
return 0;
/* We have to lock the DRBG before generating bits from it. */
CRYPTO_THREAD_write_lock(drbg->lock);
RAND_DRBG_lock(drbg);
ret = RAND_DRBG_bytes(drbg, buf, num);
CRYPTO_THREAD_unlock(drbg->lock);
RAND_DRBG_unlock(drbg);
return ret;
}
......
......@@ -47,6 +47,10 @@ int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen);
int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval);
int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval);
int RAND_DRBG_lock(RAND_DRBG *drbg);
int RAND_DRBG_unlock(RAND_DRBG *drbg);
int RAND_DRBG_enable_locking(RAND_DRBG *drbg);
RAND_DRBG *RAND_DRBG_get0_master(void);
RAND_DRBG *RAND_DRBG_get0_public(void);
RAND_DRBG *RAND_DRBG_get0_private(void);
......
......@@ -24,6 +24,7 @@ int ERR_load_RAND_strings(void);
# define RAND_F_DRBG_SETUP 117
# define RAND_F_GET_ENTROPY 106
# define RAND_F_RAND_BYTES 100
# define RAND_F_RAND_DRBG_ENABLE_LOCKING 119
# define RAND_F_RAND_DRBG_GENERATE 107
# define RAND_F_RAND_DRBG_INSTANTIATE 108
# define RAND_F_RAND_DRBG_NEW 109
......@@ -46,6 +47,7 @@ int ERR_load_RAND_strings(void);
# define RAND_R_ALREADY_INSTANTIATED 103
# define RAND_R_ARGUMENT_OUT_OF_RANGE 105
# define RAND_R_CANNOT_OPEN_FILE 121
# define RAND_R_DRBG_ALREADY_INITIALIZED 129
# define RAND_R_DRBG_NOT_INITIALISED 104
# define RAND_R_ENTROPY_INPUT_TOO_LONG 106
# define RAND_R_ENTROPY_OUT_OF_RANGE 124
......@@ -64,6 +66,7 @@ int ERR_load_RAND_strings(void);
# define RAND_R_NOT_A_REGULAR_FILE 122
# define RAND_R_NOT_INSTANTIATED 115
# define RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED 128
# define RAND_R_PARENT_LOCKING_NOT_ENABLED 130
# define RAND_R_PERSONALISATION_STRING_TOO_LONG 116
# define RAND_R_PRNG_NOT_SEEDED 100
# define RAND_R_RANDOM_POOL_OVERFLOW 125
......
......@@ -4501,3 +4501,6 @@ EVP_sha512_256 4442 1_1_1 EXIST::FUNCTION:
EVP_sha512_224 4443 1_1_1 EXIST::FUNCTION:
OCSP_basic_sign_ctx 4444 1_1_1 EXIST::FUNCTION:OCSP
RAND_DRBG_bytes 4445 1_1_1 EXIST::FUNCTION:
RAND_DRBG_lock 4446 1_1_1 EXIST::FUNCTION:
RAND_DRBG_unlock 4447 1_1_1 EXIST::FUNCTION:
RAND_DRBG_enable_locking 4448 1_1_1 EXIST::FUNCTION:
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册