Latest update.
This commit is contained in:
@@ -354,7 +354,7 @@ static int drbg_ctr_uninstantiate(RAND_DRBG *drbg)
|
||||
{
|
||||
EVP_CIPHER_CTX_free(drbg->data.ctr.ctx);
|
||||
EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_df);
|
||||
EVP_CIPHER_meth_free(drbg->data.ctr.cipher);
|
||||
EVP_CIPHER_free(drbg->data.ctr.cipher);
|
||||
OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr));
|
||||
return 1;
|
||||
}
|
||||
@@ -392,7 +392,7 @@ int drbg_ctr_init(RAND_DRBG *drbg)
|
||||
if (cipher == NULL)
|
||||
return 0;
|
||||
|
||||
EVP_CIPHER_meth_free(ctr->cipher);
|
||||
EVP_CIPHER_free(ctr->cipher);
|
||||
ctr->cipher = cipher;
|
||||
|
||||
drbg->meth = &drbg_ctr_meth;
|
||||
|
||||
@@ -290,7 +290,7 @@ static int drbg_hash_generate(RAND_DRBG *drbg,
|
||||
|
||||
static int drbg_hash_uninstantiate(RAND_DRBG *drbg)
|
||||
{
|
||||
EVP_MD_meth_free(drbg->data.hash.md);
|
||||
EVP_MD_free(drbg->data.hash.md);
|
||||
EVP_MD_CTX_free(drbg->data.hash.ctx);
|
||||
OPENSSL_cleanse(&drbg->data.hash, sizeof(drbg->data.hash));
|
||||
return 1;
|
||||
@@ -346,12 +346,12 @@ int drbg_hash_init(RAND_DRBG *drbg)
|
||||
if (hash->ctx == NULL) {
|
||||
hash->ctx = EVP_MD_CTX_new();
|
||||
if (hash->ctx == NULL) {
|
||||
EVP_MD_meth_free(md);
|
||||
EVP_MD_free(md);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
EVP_MD_meth_free(hash->md);
|
||||
EVP_MD_free(hash->md);
|
||||
hash->md = md;
|
||||
|
||||
/* These are taken from SP 800-90 10.1 Table 2 */
|
||||
|
||||
@@ -184,7 +184,7 @@ static int drbg_hmac_generate(RAND_DRBG *drbg,
|
||||
|
||||
static int drbg_hmac_uninstantiate(RAND_DRBG *drbg)
|
||||
{
|
||||
EVP_MD_meth_free(drbg->data.hmac.md);
|
||||
EVP_MD_free(drbg->data.hmac.md);
|
||||
HMAC_CTX_free(drbg->data.hmac.ctx);
|
||||
OPENSSL_cleanse(&drbg->data.hmac, sizeof(drbg->data.hmac));
|
||||
return 1;
|
||||
@@ -239,13 +239,13 @@ int drbg_hmac_init(RAND_DRBG *drbg)
|
||||
if (hmac->ctx == NULL) {
|
||||
hmac->ctx = HMAC_CTX_new();
|
||||
if (hmac->ctx == NULL) {
|
||||
EVP_MD_meth_free(md);
|
||||
EVP_MD_free(md);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* These are taken from SP 800-90 10.1 Table 2 */
|
||||
EVP_MD_meth_free(hmac->md);
|
||||
EVP_MD_free(hmac->md);
|
||||
hmac->md = md;
|
||||
hmac->blocklen = EVP_MD_size(md);
|
||||
/* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
|
||||
|
||||
+19
-9
@@ -191,6 +191,9 @@ static void drbg_ossl_ctx_free(void *vdgbl)
|
||||
{
|
||||
DRBG_GLOBAL *dgbl = vdgbl;
|
||||
|
||||
if (dgbl == NULL)
|
||||
return;
|
||||
|
||||
RAND_DRBG_free(dgbl->master_drbg);
|
||||
CRYPTO_THREAD_cleanup_local(&dgbl->private_drbg);
|
||||
CRYPTO_THREAD_cleanup_local(&dgbl->public_drbg);
|
||||
@@ -230,6 +233,9 @@ static void drbg_nonce_ossl_ctx_free(void *vdngbl)
|
||||
{
|
||||
DRBG_NONCE_GLOBAL *dngbl = vdngbl;
|
||||
|
||||
if (dngbl == NULL)
|
||||
return;
|
||||
|
||||
CRYPTO_THREAD_lock_free(dngbl->rand_nonce_lock);
|
||||
|
||||
OPENSSL_free(dngbl);
|
||||
@@ -265,7 +271,7 @@ size_t rand_drbg_get_nonce(RAND_DRBG *drbg,
|
||||
return 0;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
pool = rand_pool_new(0, min_len, max_len);
|
||||
pool = rand_pool_new(0, 0, min_len, max_len);
|
||||
if (pool == NULL)
|
||||
return 0;
|
||||
|
||||
@@ -295,7 +301,7 @@ size_t rand_drbg_get_nonce(RAND_DRBG *drbg,
|
||||
void rand_drbg_cleanup_nonce(RAND_DRBG *drbg,
|
||||
unsigned char *out, size_t outlen)
|
||||
{
|
||||
OPENSSL_secure_clear_free(out, outlen);
|
||||
OPENSSL_clear_free(out, outlen);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -409,7 +415,7 @@ static RAND_DRBG *rand_drbg_new(OPENSSL_CTX *ctx,
|
||||
|
||||
drbg->libctx = ctx;
|
||||
drbg->secure = secure && CRYPTO_secure_allocated(drbg);
|
||||
drbg->fork_count = rand_fork_count;
|
||||
drbg->fork_id = openssl_get_fork_id();
|
||||
drbg->parent = parent;
|
||||
|
||||
if (parent == NULL) {
|
||||
@@ -535,9 +541,10 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
|
||||
}
|
||||
|
||||
if (drbg->state != DRBG_UNINITIALISED) {
|
||||
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
|
||||
drbg->state == DRBG_ERROR ? RAND_R_IN_ERROR_STATE
|
||||
: RAND_R_ALREADY_INSTANTIATED);
|
||||
if (drbg->state == DRBG_ERROR)
|
||||
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_IN_ERROR_STATE);
|
||||
else
|
||||
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ALREADY_INSTANTIATED);
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -823,6 +830,7 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
|
||||
int prediction_resistance,
|
||||
const unsigned char *adin, size_t adinlen)
|
||||
{
|
||||
int fork_id;
|
||||
int reseed_required = 0;
|
||||
|
||||
if (drbg->state != DRBG_READY) {
|
||||
@@ -848,8 +856,10 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (drbg->fork_count != rand_fork_count) {
|
||||
drbg->fork_count = rand_fork_count;
|
||||
fork_id = openssl_get_fork_id();
|
||||
|
||||
if (drbg->fork_id != fork_id) {
|
||||
drbg->fork_id = fork_id;
|
||||
reseed_required = 1;
|
||||
}
|
||||
|
||||
@@ -909,7 +919,7 @@ int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen)
|
||||
if (drbg->adin_pool == NULL) {
|
||||
if (drbg->type == 0)
|
||||
goto err;
|
||||
drbg->adin_pool = rand_pool_new(0, 0, drbg->max_adinlen);
|
||||
drbg->adin_pool = rand_pool_new(0, 0, 0, drbg->max_adinlen);
|
||||
if (drbg->adin_pool == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ static void *rand_crng_ossl_ctx_new(OPENSSL_CTX *ctx)
|
||||
return NULL;
|
||||
|
||||
if ((crngt_glob->crngt_pool
|
||||
= rand_pool_new(0, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) {
|
||||
= rand_pool_new(0, 1, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) {
|
||||
OPENSSL_free(crngt_glob);
|
||||
return NULL;
|
||||
}
|
||||
@@ -87,7 +87,7 @@ int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx,
|
||||
if (r != 0)
|
||||
memcpy(buf, p, CRNGT_BUFSIZ);
|
||||
rand_pool_reattach(pool, p);
|
||||
EVP_MD_meth_free(fmd);
|
||||
EVP_MD_free(fmd);
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
@@ -110,7 +110,7 @@ size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
|
||||
if (crngt_glob == NULL)
|
||||
return 0;
|
||||
|
||||
if ((pool = rand_pool_new(entropy, min_len, max_len)) == NULL)
|
||||
if ((pool = rand_pool_new(entropy, 1, min_len, max_len)) == NULL)
|
||||
return 0;
|
||||
|
||||
while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) {
|
||||
|
||||
+1
-44
@@ -13,47 +13,6 @@
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static const ERR_STRING_DATA RAND_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_BYTES, 0), "drbg_bytes"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_CTR_INIT, 0), "drbg_ctr_init"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_DRBG_GET_ENTROPY, 0), "drbg_get_entropy"},
|
||||
{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_BYTES_EX, 0), "rand_bytes_ex"},
|
||||
{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_GET_ENTROPY, 0),
|
||||
"rand_drbg_get_entropy"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_GET_NONCE, 0),
|
||||
"rand_drbg_get_nonce"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_INSTANTIATE, 0),
|
||||
"RAND_DRBG_instantiate"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_NEW, 0), "RAND_DRBG_new"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_RESEED, 0), "RAND_DRBG_reseed"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_RESTART, 0), "rand_drbg_restart"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_SET, 0), "RAND_DRBG_set"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_SET_DEFAULTS, 0),
|
||||
"RAND_DRBG_set_defaults"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_DRBG_UNINSTANTIATE, 0),
|
||||
"RAND_DRBG_uninstantiate"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_LOAD_FILE, 0), "RAND_load_file"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ACQUIRE_ENTROPY, 0),
|
||||
"rand_pool_acquire_entropy"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD, 0), "rand_pool_add"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD_BEGIN, 0),
|
||||
"rand_pool_add_begin"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ADD_END, 0), "rand_pool_add_end"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_ATTACH, 0), "rand_pool_attach"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_BYTES_NEEDED, 0),
|
||||
"rand_pool_bytes_needed"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_POOL_NEW, 0), "rand_pool_new"},
|
||||
{ERR_PACK(ERR_LIB_RAND, RAND_F_RAND_WRITE_FILE, 0), "RAND_write_file"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const ERR_STRING_DATA RAND_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ADDITIONAL_INPUT_TOO_LONG),
|
||||
"additional input too long"},
|
||||
@@ -130,10 +89,8 @@ static const ERR_STRING_DATA RAND_str_reasons[] = {
|
||||
int ERR_load_RAND_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
if (ERR_func_error_string(RAND_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings_const(RAND_str_functs);
|
||||
if (ERR_reason_error_string(RAND_str_reasons[0].error) == NULL)
|
||||
ERR_load_strings_const(RAND_str_reasons);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
+31
-18
@@ -54,7 +54,13 @@
|
||||
# define DRBG_MAX_LENGTH INT32_MAX
|
||||
|
||||
/* The default nonce */
|
||||
#ifdef CHARSET_EBCDIC
|
||||
# define DRBG_DEFAULT_PERS_STRING { 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53, \
|
||||
0x4c, 0x20, 0x4e, 0x49, 0x53, 0x54, 0x20, 0x53, 0x50, 0x20, 0x38, 0x30, \
|
||||
0x30, 0x2d, 0x39, 0x30, 0x41, 0x20, 0x44, 0x52, 0x42, 0x47, 0x00};
|
||||
#else
|
||||
# define DRBG_DEFAULT_PERS_STRING "OpenSSL NIST SP 800-90A DRBG"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Maximum allocation size for RANDOM_POOL buffers
|
||||
@@ -82,6 +88,24 @@
|
||||
* 1.5 * (RAND_DRBG_STRENGTH / 8))
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initial allocation minimum.
|
||||
*
|
||||
* There is a distinction between the secure and normal allocation minimums.
|
||||
* Ideally, the secure allocation size should be a power of two. The normal
|
||||
* allocation size doesn't have any such restriction.
|
||||
*
|
||||
* The secure value is based on 128 bits of secure material, which is 16 bytes.
|
||||
* Typically, the DRBGs will set a minimum larger than this so optimal
|
||||
* allocation ought to take place (for full quality seed material).
|
||||
*
|
||||
* The normal value has been chosed by noticing that the rand_drbg_get_nonce
|
||||
* function is usually the largest of the built in allocation (twenty four
|
||||
* bytes and then appending another sixteen bytes). This means the buffer ends
|
||||
* with 40 bytes. The value of forty eight is comfortably above this which
|
||||
* allows some slack in the platform specific values used.
|
||||
*/
|
||||
# define RAND_POOL_MIN_ALLOCATION(secure) ((secure) ? 16 : 48)
|
||||
|
||||
/* DRBG status values */
|
||||
typedef enum drbg_status_e {
|
||||
@@ -180,9 +204,11 @@ struct rand_pool_st {
|
||||
size_t len; /* current number of random bytes contained in the pool */
|
||||
|
||||
int attached; /* true pool was attached to existing buffer */
|
||||
int secure; /* 1: allocated on the secure heap, 0: otherwise */
|
||||
|
||||
size_t min_len; /* minimum number of random bytes requested */
|
||||
size_t max_len; /* maximum number of random bytes (allocated buffer size) */
|
||||
size_t alloc_len; /* current number of bytes allocated */
|
||||
size_t entropy; /* current entropy count in bits */
|
||||
size_t entropy_requested; /* requested entropy count in bits */
|
||||
};
|
||||
@@ -199,12 +225,12 @@ struct rand_drbg_st {
|
||||
int secure; /* 1: allocated on the secure heap, 0: otherwise */
|
||||
int type; /* the nid of the underlying algorithm */
|
||||
/*
|
||||
* Stores the value of the rand_fork_count global as of when we last
|
||||
* reseeded. The DRBG reseeds automatically whenever drbg->fork_count !=
|
||||
* rand_fork_count. Used to provide fork-safety and reseed this DRBG in
|
||||
* the child process.
|
||||
* Stores the return value of openssl_get_fork_id() as of when we last
|
||||
* reseeded. The DRBG reseeds automatically whenever drbg->fork_id !=
|
||||
* openssl_get_fork_id(). Used to provide fork-safety and reseed this
|
||||
* DRBG in the child process.
|
||||
*/
|
||||
int fork_count;
|
||||
int fork_id;
|
||||
unsigned short flags; /* various external flags */
|
||||
|
||||
/*
|
||||
@@ -305,19 +331,6 @@ struct rand_drbg_st {
|
||||
/* The global RAND method, and the global buffer and DRBG instance. */
|
||||
extern RAND_METHOD rand_meth;
|
||||
|
||||
/*
|
||||
* A "generation count" of forks. Incremented in the child process after a
|
||||
* fork. Since rand_fork_count is increment-only, and only ever written to in
|
||||
* the child process of the fork, which is guaranteed to be single-threaded, no
|
||||
* locking is needed for normal (read) accesses; the rest of pthread fork
|
||||
* processing is assumed to introduce the necessary memory barriers. Sibling
|
||||
* children of a given parent will produce duplicate values, but this is not
|
||||
* problematic because the reseeding process pulls input from the system CSPRNG
|
||||
* and/or other global sources, so the siblings will end up generating
|
||||
* different output streams.
|
||||
*/
|
||||
extern int rand_fork_count;
|
||||
|
||||
/* DRBG helpers */
|
||||
int rand_drbg_restart(RAND_DRBG *drbg,
|
||||
const unsigned char *buffer, size_t len, size_t entropy);
|
||||
|
||||
+120
-21
@@ -30,8 +30,6 @@ static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
|
||||
static int rand_inited = 0;
|
||||
#endif /* FIPS_MODE */
|
||||
|
||||
int rand_fork_count;
|
||||
|
||||
#ifdef OPENSSL_RAND_SEED_RDTSC
|
||||
/*
|
||||
* IMPORTANT NOTE: It is not currently possible to use this code
|
||||
@@ -69,8 +67,6 @@ size_t rand_acquire_entropy_from_tsc(RAND_POOL *pool)
|
||||
size_t OPENSSL_ia32_rdseed_bytes(unsigned char *buf, size_t len);
|
||||
size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len);
|
||||
|
||||
extern unsigned int OPENSSL_ia32cap_P[];
|
||||
|
||||
/*
|
||||
* Acquire entropy using Intel-specific cpu instructions
|
||||
*
|
||||
@@ -149,7 +145,7 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
|
||||
pool = drbg->seed_pool;
|
||||
pool->entropy_requested = entropy;
|
||||
} else {
|
||||
pool = rand_pool_new(entropy, min_len, max_len);
|
||||
pool = rand_pool_new(entropy, drbg->secure, min_len, max_len);
|
||||
if (pool == NULL)
|
||||
return 0;
|
||||
}
|
||||
@@ -162,7 +158,9 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
|
||||
size_t bytes = 0;
|
||||
|
||||
/*
|
||||
* Get random from parent, include our state as additional input.
|
||||
* Get random data from parent. Include our address as additional input,
|
||||
* in order to provide some additional distinction between different
|
||||
* DRBG child instances.
|
||||
* Our lock is already held, but we need to lock our parent before
|
||||
* generating bits from it. (Note: taking the lock will be a no-op
|
||||
* if locking if drbg->parent->lock == NULL.)
|
||||
@@ -171,7 +169,7 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
|
||||
if (RAND_DRBG_generate(drbg->parent,
|
||||
buffer, bytes_needed,
|
||||
prediction_resistance,
|
||||
NULL, 0) != 0)
|
||||
(unsigned char *)&drbg, sizeof(drbg)) != 0)
|
||||
bytes = bytes_needed;
|
||||
drbg->reseed_next_counter
|
||||
= tsan_load(&drbg->parent->reseed_prop_counter);
|
||||
@@ -203,8 +201,12 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
|
||||
void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
|
||||
unsigned char *out, size_t outlen)
|
||||
{
|
||||
if (drbg->seed_pool == NULL)
|
||||
OPENSSL_secure_clear_free(out, outlen);
|
||||
if (drbg->seed_pool == NULL) {
|
||||
if (drbg->secure)
|
||||
OPENSSL_secure_clear_free(out, outlen);
|
||||
else
|
||||
OPENSSL_clear_free(out, outlen);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -236,11 +238,6 @@ void rand_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out)
|
||||
rand_pool_reattach(pool, out);
|
||||
}
|
||||
|
||||
void rand_fork(void)
|
||||
{
|
||||
rand_fork_count++;
|
||||
}
|
||||
|
||||
#ifndef FIPS_MODE
|
||||
DEFINE_RUN_ONCE_STATIC(do_rand_init)
|
||||
{
|
||||
@@ -331,7 +328,7 @@ int RAND_poll(void)
|
||||
RAND_POOL *pool = NULL;
|
||||
|
||||
/* fill random pool and seed the current legacy RNG */
|
||||
pool = rand_pool_new(RAND_DRBG_STRENGTH,
|
||||
pool = rand_pool_new(RAND_DRBG_STRENGTH, 1,
|
||||
(RAND_DRBG_STRENGTH + 7) / 8,
|
||||
RAND_POOL_MAX_LENGTH);
|
||||
if (pool == NULL)
|
||||
@@ -360,9 +357,11 @@ int RAND_poll(void)
|
||||
* Allocate memory and initialize a new random pool
|
||||
*/
|
||||
|
||||
RAND_POOL *rand_pool_new(int entropy_requested, size_t min_len, size_t max_len)
|
||||
RAND_POOL *rand_pool_new(int entropy_requested, int secure,
|
||||
size_t min_len, size_t max_len)
|
||||
{
|
||||
RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool));
|
||||
size_t min_alloc_size = RAND_POOL_MIN_ALLOCATION(secure);
|
||||
|
||||
if (pool == NULL) {
|
||||
RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE);
|
||||
@@ -372,14 +371,22 @@ RAND_POOL *rand_pool_new(int entropy_requested, size_t min_len, size_t max_len)
|
||||
pool->min_len = min_len;
|
||||
pool->max_len = (max_len > RAND_POOL_MAX_LENGTH) ?
|
||||
RAND_POOL_MAX_LENGTH : max_len;
|
||||
pool->alloc_len = min_len < min_alloc_size ? min_alloc_size : min_len;
|
||||
if (pool->alloc_len > pool->max_len)
|
||||
pool->alloc_len = pool->max_len;
|
||||
|
||||
if (secure)
|
||||
pool->buffer = OPENSSL_secure_zalloc(pool->alloc_len);
|
||||
else
|
||||
pool->buffer = OPENSSL_zalloc(pool->alloc_len);
|
||||
|
||||
pool->buffer = OPENSSL_secure_zalloc(pool->max_len);
|
||||
if (pool->buffer == NULL) {
|
||||
RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
pool->entropy_requested = entropy_requested;
|
||||
pool->secure = secure;
|
||||
|
||||
return pool;
|
||||
|
||||
@@ -414,7 +421,7 @@ RAND_POOL *rand_pool_attach(const unsigned char *buffer, size_t len,
|
||||
|
||||
pool->attached = 1;
|
||||
|
||||
pool->min_len = pool->max_len = pool->len;
|
||||
pool->min_len = pool->max_len = pool->alloc_len = pool->len;
|
||||
pool->entropy = entropy;
|
||||
|
||||
return pool;
|
||||
@@ -434,8 +441,13 @@ void rand_pool_free(RAND_POOL *pool)
|
||||
* to rand_pool_attach() as `const unsigned char*`.
|
||||
* (see corresponding comment in rand_pool_attach()).
|
||||
*/
|
||||
if (!pool->attached)
|
||||
OPENSSL_secure_clear_free(pool->buffer, pool->max_len);
|
||||
if (!pool->attached) {
|
||||
if (pool->secure)
|
||||
OPENSSL_secure_clear_free(pool->buffer, pool->alloc_len);
|
||||
else
|
||||
OPENSSL_clear_free(pool->buffer, pool->alloc_len);
|
||||
}
|
||||
|
||||
OPENSSL_free(pool);
|
||||
}
|
||||
|
||||
@@ -528,6 +540,42 @@ size_t rand_pool_entropy_needed(RAND_POOL *pool)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Increase the allocation size -- not usable for an attached pool */
|
||||
static int rand_pool_grow(RAND_POOL *pool, size_t len)
|
||||
{
|
||||
if (len > pool->alloc_len - pool->len) {
|
||||
unsigned char *p;
|
||||
const size_t limit = pool->max_len / 2;
|
||||
size_t newlen = pool->alloc_len;
|
||||
|
||||
if (pool->attached || len > pool->max_len - pool->len) {
|
||||
RANDerr(RAND_F_RAND_POOL_GROW, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
do
|
||||
newlen = newlen < limit ? newlen * 2 : pool->max_len;
|
||||
while (len > newlen - pool->len);
|
||||
|
||||
if (pool->secure)
|
||||
p = OPENSSL_secure_zalloc(newlen);
|
||||
else
|
||||
p = OPENSSL_zalloc(newlen);
|
||||
if (p == NULL) {
|
||||
RANDerr(RAND_F_RAND_POOL_GROW, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
memcpy(p, pool->buffer, pool->len);
|
||||
if (pool->secure)
|
||||
OPENSSL_secure_clear_free(pool->buffer, pool->alloc_len);
|
||||
else
|
||||
OPENSSL_clear_free(pool->buffer, pool->alloc_len);
|
||||
pool->buffer = p;
|
||||
pool->alloc_len = newlen;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of bytes needed to fill the pool, assuming
|
||||
* the input has 1 / |entropy_factor| entropy bits per data bit.
|
||||
@@ -557,6 +605,24 @@ size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor)
|
||||
/* to meet the min_len requirement */
|
||||
bytes_needed = pool->min_len - pool->len;
|
||||
|
||||
/*
|
||||
* Make sure the buffer is large enough for the requested amount
|
||||
* of data. This guarantees that existing code patterns where
|
||||
* rand_pool_add_begin, rand_pool_add_end or rand_pool_add
|
||||
* are used to collect entropy data without any error handling
|
||||
* whatsoever, continue to be valid.
|
||||
* Furthermore if the allocation here fails once, make sure that
|
||||
* we don't fall back to a less secure or even blocking random source,
|
||||
* as that could happen by the existing code patterns.
|
||||
* This is not a concern for additional data, therefore that
|
||||
* is not needed if rand_pool_grow fails in other places.
|
||||
*/
|
||||
if (!rand_pool_grow(pool, bytes_needed)) {
|
||||
/* persistent error for this pool */
|
||||
pool->max_len = pool->len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bytes_needed;
|
||||
}
|
||||
|
||||
@@ -589,6 +655,27 @@ int rand_pool_add(RAND_POOL *pool,
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
/*
|
||||
* This is to protect us from accidentally passing the buffer
|
||||
* returned from rand_pool_add_begin.
|
||||
* The check for alloc_len makes sure we do not compare the
|
||||
* address of the end of the allocated memory to something
|
||||
* different, since that comparison would have an
|
||||
* indeterminate result.
|
||||
*/
|
||||
if (pool->alloc_len > pool->len && pool->buffer + pool->len == buffer) {
|
||||
RANDerr(RAND_F_RAND_POOL_ADD, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* We have that only for cases when a pool is used to collect
|
||||
* additional data.
|
||||
* For entropy data, as long as the allocation request stays within
|
||||
* the limits given by rand_pool_bytes_needed this rand_pool_grow
|
||||
* below is guaranteed to succeed, thus no allocation happens.
|
||||
*/
|
||||
if (!rand_pool_grow(pool, len))
|
||||
return 0;
|
||||
memcpy(pool->buffer + pool->len, buffer, len);
|
||||
pool->len += len;
|
||||
pool->entropy += entropy;
|
||||
@@ -624,6 +711,18 @@ unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* As long as the allocation request stays within the limits given
|
||||
* by rand_pool_bytes_needed this rand_pool_grow below is guaranteed
|
||||
* to succeed, thus no allocation happens.
|
||||
* We have that only for cases when a pool is used to collect
|
||||
* additional data. Then the buffer might need to grow here,
|
||||
* and of course the caller is responsible to check the return
|
||||
* value of this function.
|
||||
*/
|
||||
if (!rand_pool_grow(pool, len))
|
||||
return NULL;
|
||||
|
||||
return pool->buffer + pool->len;
|
||||
}
|
||||
|
||||
@@ -638,7 +737,7 @@ unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len)
|
||||
*/
|
||||
int rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy)
|
||||
{
|
||||
if (len > pool->max_len - pool->len) {
|
||||
if (len > pool->alloc_len - pool->len) {
|
||||
RANDerr(RAND_F_RAND_POOL_ADD_END, RAND_R_RANDOM_POOL_OVERFLOW);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+141
-26
@@ -14,12 +14,17 @@
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include "rand_lcl.h"
|
||||
#include "internal/rand_int.h"
|
||||
#include <stdio.h>
|
||||
#include "internal/dso.h"
|
||||
#if defined(__linux)
|
||||
# include <asm/unistd.h>
|
||||
#ifdef __linux
|
||||
# include <sys/syscall.h>
|
||||
# ifdef DEVRANDOM_WAIT
|
||||
# include <sys/shm.h>
|
||||
# include <sys/utsname.h>
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__FreeBSD__) && !defined(OPENSSL_SYS_UEFI)
|
||||
# include <sys/types.h>
|
||||
@@ -254,6 +259,17 @@ static ssize_t sysctl_random(char *buf, size_t buflen)
|
||||
# endif
|
||||
|
||||
# if defined(OPENSSL_RAND_SEED_GETRANDOM)
|
||||
|
||||
# if defined(__linux) && !defined(__NR_getrandom)
|
||||
# if defined(__arm__) && defined(__NR_SYSCALL_BASE)
|
||||
# define __NR_getrandom (__NR_SYSCALL_BASE+384)
|
||||
# elif defined(__i386__)
|
||||
# define __NR_getrandom 355
|
||||
# elif defined(__x86_64__) && !defined(__ILP32__)
|
||||
# define __NR_getrandom 318
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/*
|
||||
* syscall_random(): Try to get random data using a system call
|
||||
* returns the number of bytes returned in buf, or < 0 on error.
|
||||
@@ -325,6 +341,96 @@ static struct random_device {
|
||||
} random_devices[OSSL_NELEM(random_device_paths)];
|
||||
static int keep_random_devices_open = 1;
|
||||
|
||||
# if defined(__linux) && defined(DEVRANDOM_WAIT)
|
||||
static void *shm_addr;
|
||||
|
||||
# if !defined(FIPS_MODE)
|
||||
static void cleanup_shm(void)
|
||||
{
|
||||
shmdt(shm_addr);
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Ensure that the system randomness source has been adequately seeded.
|
||||
* This is done by having the first start of libcrypto, wait until the device
|
||||
* /dev/random becomes able to supply a byte of entropy. Subsequent starts
|
||||
* of the library and later reseedings do not need to do this.
|
||||
*/
|
||||
static int wait_random_seeded(void)
|
||||
{
|
||||
static int seeded = OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID < 0;
|
||||
static const int kernel_version[] = { DEVRANDOM_SAFE_KERNEL };
|
||||
int kernel[2];
|
||||
int shm_id, fd, r;
|
||||
char c, *p;
|
||||
struct utsname un;
|
||||
fd_set fds;
|
||||
|
||||
if (!seeded) {
|
||||
/* See if anything has created the global seeded indication */
|
||||
if ((shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1, 0)) == -1) {
|
||||
/*
|
||||
* Check the kernel's version and fail if it is too recent.
|
||||
*
|
||||
* Linux kernels from 4.8 onwards do not guarantee that
|
||||
* /dev/urandom is properly seeded when /dev/random becomes
|
||||
* readable. However, such kernels support the getentropy(2)
|
||||
* system call and this should always succeed which renders
|
||||
* this alternative but essentially identical source moot.
|
||||
*/
|
||||
if (uname(&un) == 0) {
|
||||
kernel[0] = atoi(un.release);
|
||||
p = strchr(un.release, '.');
|
||||
kernel[1] = p == NULL ? 0 : atoi(p + 1);
|
||||
if (kernel[0] > kernel_version[0]
|
||||
|| (kernel[0] == kernel_version[0]
|
||||
&& kernel[1] >= kernel_version[1])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Open /dev/random and wait for it to be readable */
|
||||
if ((fd = open(DEVRANDOM_WAIT, O_RDONLY)) != -1) {
|
||||
if (DEVRANDM_WAIT_USE_SELECT && fd < FD_SETSIZE) {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
while ((r = select(fd + 1, &fds, NULL, NULL, NULL)) < 0
|
||||
&& errno == EINTR);
|
||||
} else {
|
||||
while ((r = read(fd, &c, 1)) < 0 && errno == EINTR);
|
||||
}
|
||||
close(fd);
|
||||
if (r == 1) {
|
||||
seeded = 1;
|
||||
/* Create the shared memory indicator */
|
||||
shm_id = shmget(OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID, 1,
|
||||
IPC_CREAT | S_IRUSR | S_IRGRP | S_IROTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shm_id != -1) {
|
||||
seeded = 1;
|
||||
/*
|
||||
* Map the shared memory to prevent its premature destruction.
|
||||
* If this call fails, it isn't a big problem.
|
||||
*/
|
||||
shm_addr = shmat(shm_id, NULL, SHM_RDONLY);
|
||||
# ifndef FIPS_MODE
|
||||
/* TODO 3.0: The FIPS provider doesn't have OPENSSL_atexit */
|
||||
if (shm_addr != (void *)-1)
|
||||
OPENSSL_atexit(&cleanup_shm);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
return seeded;
|
||||
}
|
||||
# else /* defined __linux */
|
||||
static int wait_random_seeded(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Verify that the file descriptor associated with the random source is
|
||||
* still valid. The rationale for doing this is the fact that it is not
|
||||
@@ -451,12 +557,12 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
|
||||
# if defined(OPENSSL_RAND_SEED_NONE)
|
||||
return rand_pool_entropy_available(pool);
|
||||
# else
|
||||
size_t bytes_needed;
|
||||
size_t entropy_available = 0;
|
||||
unsigned char *buffer;
|
||||
size_t entropy_available;
|
||||
|
||||
# if defined(OPENSSL_RAND_SEED_GETRANDOM)
|
||||
{
|
||||
size_t bytes_needed;
|
||||
unsigned char *buffer;
|
||||
ssize_t bytes;
|
||||
/* Maximum allowed number of consecutive unsuccessful attempts */
|
||||
int attempts = 3;
|
||||
@@ -486,13 +592,16 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
|
||||
# endif
|
||||
|
||||
# if defined(OPENSSL_RAND_SEED_DEVRANDOM)
|
||||
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
|
||||
{
|
||||
if (wait_random_seeded()) {
|
||||
size_t bytes_needed;
|
||||
unsigned char *buffer;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths); i++) {
|
||||
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
|
||||
for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths);
|
||||
i++) {
|
||||
ssize_t bytes = 0;
|
||||
/* Maximum allowed number of consecutive unsuccessful attempts */
|
||||
/* Maximum number of consecutive unsuccessful attempts */
|
||||
int attempts = 3;
|
||||
const int fd = get_random_device(i);
|
||||
|
||||
@@ -506,7 +615,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
|
||||
if (bytes > 0) {
|
||||
rand_pool_add_end(pool, bytes, 8 * bytes);
|
||||
bytes_needed -= bytes;
|
||||
attempts = 3; /* reset counter after successful attempt */
|
||||
attempts = 3; /* reset counter on successful attempt */
|
||||
} else if (bytes < 0 && errno != EINTR) {
|
||||
break;
|
||||
}
|
||||
@@ -514,7 +623,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
|
||||
if (bytes < 0 || !keep_random_devices_open)
|
||||
close_random_device(i);
|
||||
|
||||
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
|
||||
bytes_needed = rand_pool_bytes_needed(pool, 1);
|
||||
}
|
||||
entropy_available = rand_pool_entropy_available(pool);
|
||||
if (entropy_available > 0)
|
||||
@@ -535,26 +644,29 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
|
||||
# endif
|
||||
|
||||
# if defined(OPENSSL_RAND_SEED_EGD)
|
||||
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
|
||||
if (bytes_needed > 0) {
|
||||
{
|
||||
static const char *paths[] = { DEVRANDOM_EGD, NULL };
|
||||
size_t bytes_needed;
|
||||
unsigned char *buffer;
|
||||
int i;
|
||||
|
||||
for (i = 0; paths[i] != NULL; i++) {
|
||||
buffer = rand_pool_add_begin(pool, bytes_needed);
|
||||
if (buffer != NULL) {
|
||||
size_t bytes = 0;
|
||||
int num = RAND_query_egd_bytes(paths[i],
|
||||
buffer, (int)bytes_needed);
|
||||
if (num == (int)bytes_needed)
|
||||
bytes = bytes_needed;
|
||||
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
|
||||
for (i = 0; bytes_needed > 0 && paths[i] != NULL; i++) {
|
||||
size_t bytes = 0;
|
||||
int num;
|
||||
|
||||
rand_pool_add_end(pool, bytes, 8 * bytes);
|
||||
entropy_available = rand_pool_entropy_available(pool);
|
||||
}
|
||||
if (entropy_available > 0)
|
||||
return entropy_available;
|
||||
buffer = rand_pool_add_begin(pool, bytes_needed);
|
||||
num = RAND_query_egd_bytes(paths[i],
|
||||
buffer, (int)bytes_needed);
|
||||
if (num == (int)bytes_needed)
|
||||
bytes = bytes_needed;
|
||||
|
||||
rand_pool_add_end(pool, bytes, 8 * bytes);
|
||||
bytes_needed = rand_pool_bytes_needed(pool, 1);
|
||||
}
|
||||
entropy_available = rand_pool_entropy_available(pool);
|
||||
if (entropy_available > 0)
|
||||
return entropy_available;
|
||||
}
|
||||
# endif
|
||||
|
||||
@@ -592,6 +704,7 @@ int rand_pool_add_nonce_data(RAND_POOL *pool)
|
||||
int rand_pool_add_additional_data(RAND_POOL *pool)
|
||||
{
|
||||
struct {
|
||||
int fork_id;
|
||||
CRYPTO_THREAD_ID tid;
|
||||
uint64_t time;
|
||||
} data;
|
||||
@@ -601,9 +714,11 @@ int rand_pool_add_additional_data(RAND_POOL *pool)
|
||||
|
||||
/*
|
||||
* Add some noise from the thread id and a high resolution timer.
|
||||
* The fork_id adds some extra fork-safety.
|
||||
* The thread id adds a little randomness if the drbg is accessed
|
||||
* concurrently (which is the case for the <master> drbg).
|
||||
*/
|
||||
data.fork_id = openssl_get_fork_id();
|
||||
data.tid = CRYPTO_THREAD_get_current_id();
|
||||
data.time = get_timer_bits();
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
|
||||
# include <windows.h>
|
||||
/* On Windows Vista or higher use BCrypt instead of the legacy CryptoAPI */
|
||||
# if defined(_MSC_VER) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600
|
||||
# if defined(_MSC_VER) && _MSC_VER > 1500 /* 1500 = Visual Studio 2008 */ \
|
||||
&& defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600
|
||||
# define USE_BCRYPTGENRANDOM
|
||||
# endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user