Latest update

This commit is contained in:
2018-11-01 00:59:10 +09:00
parent 95369e3f0a
commit 35dea6db7e
107 changed files with 4513 additions and 1163 deletions
+102 -39
View File
@@ -374,6 +374,13 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
max_entropylen += drbg->max_noncelen;
}
drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
if (drbg->reseed_next_counter) {
drbg->reseed_next_counter++;
if(!drbg->reseed_next_counter)
drbg->reseed_next_counter = 1;
}
if (drbg->get_entropy != NULL)
entropylen = drbg->get_entropy(drbg, &entropy, min_entropy,
min_entropylen, max_entropylen, 0);
@@ -401,27 +408,13 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
drbg->state = DRBG_READY;
drbg->reseed_gen_counter = 1;
drbg->reseed_time = time(NULL);
if (drbg->reseed_prop_counter > 0) {
if (drbg->parent == NULL)
drbg->reseed_prop_counter++;
else
drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter;
}
tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
end:
if (entropy != NULL && drbg->cleanup_entropy != NULL)
drbg->cleanup_entropy(drbg, entropy, entropylen);
if (nonce != NULL && drbg->cleanup_nonce != NULL)
drbg->cleanup_nonce(drbg, nonce, noncelen);
if (drbg->pool != NULL) {
if (drbg->state == DRBG_READY) {
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED);
drbg->state = DRBG_ERROR;
}
rand_pool_free(drbg->pool);
drbg->pool = NULL;
}
if (drbg->state == DRBG_READY)
return 1;
return 0;
@@ -498,6 +491,14 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
}
drbg->state = DRBG_ERROR;
drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
if (drbg->reseed_next_counter) {
drbg->reseed_next_counter++;
if(!drbg->reseed_next_counter)
drbg->reseed_next_counter = 1;
}
if (drbg->get_entropy != NULL)
entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
drbg->min_entropylen,
@@ -515,12 +516,7 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
drbg->state = DRBG_READY;
drbg->reseed_gen_counter = 1;
drbg->reseed_time = time(NULL);
if (drbg->reseed_prop_counter > 0) {
if (drbg->parent == NULL)
drbg->reseed_prop_counter++;
else
drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter;
}
tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
end:
if (entropy != NULL && drbg->cleanup_entropy != NULL)
@@ -625,14 +621,8 @@ int rand_drbg_restart(RAND_DRBG *drbg,
}
}
/* check whether a given entropy pool was cleared properly during reseed */
if (drbg->pool != NULL) {
drbg->state = DRBG_ERROR;
RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR);
rand_pool_free(drbg->pool);
drbg->pool = NULL;
return 0;
}
rand_pool_free(drbg->pool);
drbg->pool = NULL;
return drbg->state == DRBG_READY;
}
@@ -691,8 +681,11 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
|| now - drbg->reseed_time >= drbg->reseed_time_interval)
reseed_required = 1;
}
if (drbg->reseed_prop_counter > 0 && drbg->parent != NULL) {
if (drbg->reseed_prop_counter != drbg->parent->reseed_prop_counter)
if (drbg->parent != NULL) {
unsigned int reseed_counter = tsan_load(&drbg->reseed_prop_counter);
if (reseed_counter > 0
&& tsan_load(&drbg->parent->reseed_prop_counter)
!= reseed_counter)
reseed_required = 1;
}
@@ -764,7 +757,8 @@ int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
RAND_DRBG_get_nonce_fn get_nonce,
RAND_DRBG_cleanup_nonce_fn cleanup_nonce)
{
if (drbg->state != DRBG_UNINITIALISED)
if (drbg->state != DRBG_UNINITIALISED
|| drbg->parent != NULL)
return 0;
drbg->get_entropy = get_entropy;
drbg->cleanup_entropy = cleanup_entropy;
@@ -942,7 +936,7 @@ static RAND_DRBG *drbg_setup(RAND_DRBG *parent, int drbg_type)
goto err;
/* enable seed propagation */
drbg->reseed_prop_counter = 1;
tsan_store(&drbg->reseed_prop_counter, 1);
/*
* Ignore instantiation error to support just-in-time instantiation.
@@ -1031,11 +1025,53 @@ static int drbg_bytes(unsigned char *out, int count)
return ret;
}
/*
* Calculates the minimum length of a full entropy buffer
* which is necessary to seed (i.e. instantiate) the DRBG
* successfully.
*
* NOTE: There is a copy of this function in drbgtest.c.
* If you change anything here, you need to update
* the copy accordingly.
*/
static size_t rand_drbg_seedlen(RAND_DRBG *drbg)
{
/*
* If no os entropy source is available then RAND_seed(buffer, bufsize)
* is expected to succeed if and only if the buffer length satisfies
* the following requirements, which follow from the calculations
* in RAND_DRBG_instantiate().
*/
size_t min_entropy = drbg->strength;
size_t min_entropylen = drbg->min_entropylen;
/*
* Extra entropy for the random nonce in the absence of a
* get_nonce callback, see comment in RAND_DRBG_instantiate().
*/
if (drbg->min_noncelen > 0 && drbg->get_nonce == NULL) {
min_entropy += drbg->strength / 2;
min_entropylen += drbg->min_noncelen;
}
/*
* Convert entropy requirement from bits to bytes
* (dividing by 8 without rounding upwards, because
* all entropy requirements are divisible by 8).
*/
min_entropy >>= 3;
/* Return a value that satisfies both requirements */
return min_entropy > min_entropylen ? min_entropy : min_entropylen;
}
/* Implements the default OpenSSL RAND_add() method */
static int drbg_add(const void *buf, int num, double randomness)
{
int ret = 0;
RAND_DRBG *drbg = RAND_DRBG_get0_master();
size_t buflen;
size_t seedlen;
if (drbg == NULL)
return 0;
@@ -1043,7 +1079,37 @@ static int drbg_add(const void *buf, int num, double randomness)
if (num < 0 || randomness < 0.0)
return 0;
if (randomness > (double)RAND_DRBG_STRENGTH) {
rand_drbg_lock(drbg);
seedlen = rand_drbg_seedlen(drbg);
buflen = (size_t)num;
if (buflen < seedlen || randomness < (double) seedlen) {
#if defined(OPENSSL_RAND_SEED_NONE)
/*
* If no os entropy source is available, a reseeding will fail
* inevitably. So we use a trick to mix the buffer contents into
* the DRBG state without forcing a reseeding: we generate a
* dummy random byte, using the buffer content as additional data.
* Note: This won't work with RAND_DRBG_FLAG_CTR_NO_DF.
*/
unsigned char dummy[1];
ret = RAND_DRBG_generate(drbg, dummy, sizeof(dummy), 0, buf, buflen);
rand_drbg_unlock(drbg);
return ret;
#else
/*
* If an os entropy source is avaible then we declare the buffer content
* as additional data by setting randomness to zero and trigger a regular
* reseeding.
*/
randomness = 0.0;
#endif
}
if (randomness > (double)seedlen) {
/*
* The purpose of this check is to bound |randomness| by a
* relatively small value in order to prevent an integer
@@ -1052,13 +1118,10 @@ static int drbg_add(const void *buf, int num, double randomness)
* not bits, so this value corresponds to eight times the
* security strength.
*/
randomness = (double)RAND_DRBG_STRENGTH;
randomness = (double)seedlen;
}
rand_drbg_lock(drbg);
ret = rand_drbg_restart(drbg, buf,
(size_t)(unsigned int)num,
(size_t)(8*randomness));
ret = rand_drbg_restart(drbg, buf, buflen, (size_t)(8 * randomness));
rand_drbg_unlock(drbg);
return ret;
+5 -1
View File
@@ -16,6 +16,9 @@
# include <openssl/hmac.h>
# include <openssl/ec.h>
# include <openssl/rand_drbg.h>
# include "internal/tsan_assist.h"
# include "internal/numbers.h"
/* How many times to read the TSC as a randomness source. */
# define TSC_READ_COUNT 4
@@ -256,7 +259,8 @@ struct rand_drbg_st {
* is added by RAND_add() or RAND_seed() will have an immediate effect on
* the output of RAND_bytes() resp. RAND_priv_bytes().
*/
unsigned int reseed_prop_counter;
TSAN_QUALIFIER unsigned int reseed_prop_counter;
unsigned int reseed_next_counter;
size_t seedlen;
DRBG_STATUS state;
+8 -3
View File
@@ -151,6 +151,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
pool->entropy_requested = entropy;
} else {
pool = rand_pool_new(entropy, min_len, max_len);
if (pool == NULL)
return 0;
}
if (drbg->parent) {
@@ -172,6 +174,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
prediction_resistance,
NULL, 0) != 0)
bytes = bytes_needed;
drbg->reseed_next_counter
= tsan_load(&drbg->parent->reseed_prop_counter);
rand_drbg_unlock(drbg->parent);
rand_pool_add_end(pool, bytes, 8 * bytes);
@@ -200,7 +204,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
}
err:
rand_pool_free(pool);
if (drbg->pool == NULL)
rand_pool_free(pool);
return ret;
}
@@ -213,8 +218,6 @@ void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
{
if (drbg->pool == NULL)
OPENSSL_secure_clear_free(out, outlen);
else
drbg->pool = NULL;
}
@@ -539,6 +542,8 @@ unsigned char *rand_pool_detach(RAND_POOL *pool)
{
unsigned char *ret = pool->buffer;
pool->buffer = NULL;
pool->len = 0;
pool->entropy = 0;
return ret;
}
+29 -9
View File
@@ -16,6 +16,7 @@
#include <openssl/crypto.h>
#include <openssl/rand.h>
#include <openssl/rand_drbg.h>
#include <openssl/buffer.h>
#ifdef OPENSSL_SYS_VMS
@@ -48,7 +49,7 @@
# define S_ISREG(m) ((m) & S_IFREG)
# endif
#define RAND_FILE_SIZE 1024
#define RAND_BUF_SIZE 1024
#define RFILE ".rnd"
#ifdef OPENSSL_SYS_VMS
@@ -74,7 +75,16 @@ static __FILE_ptr32 (*const vms_fopen)(const char *, const char *, ...) =
*/
int RAND_load_file(const char *file, long bytes)
{
unsigned char buf[RAND_FILE_SIZE];
/*
* The load buffer size exceeds the chunk size by the comfortable amount
* of 'RAND_DRBG_STRENGTH' bytes (not bits!). This is done on purpose
* to avoid calling RAND_add() with a small final chunk. Instead, such
* a small final chunk will be added together with the previous chunk
* (unless it's the only one).
*/
#define RAND_LOAD_BUF_SIZE (RAND_BUF_SIZE + RAND_DRBG_STRENGTH)
unsigned char buf[RAND_LOAD_BUF_SIZE];
#ifndef OPENSSL_NO_POSIX_IO
struct stat sb;
#endif
@@ -98,8 +108,12 @@ int RAND_load_file(const char *file, long bytes)
return -1;
}
if (!S_ISREG(sb.st_mode) && bytes < 0)
bytes = 256;
if (bytes < 0) {
if (S_ISREG(sb.st_mode))
bytes = sb.st_size;
else
bytes = RAND_DRBG_STRENGTH;
}
#endif
/*
* On VMS, setbuf() will only take 32-bit pointers, and a compilation
@@ -124,9 +138,9 @@ int RAND_load_file(const char *file, long bytes)
for ( ; ; ) {
if (bytes > 0)
n = (bytes < RAND_FILE_SIZE) ? (int)bytes : RAND_FILE_SIZE;
n = (bytes <= RAND_LOAD_BUF_SIZE) ? (int)bytes : RAND_BUF_SIZE;
else
n = RAND_FILE_SIZE;
n = RAND_LOAD_BUF_SIZE;
i = fread(buf, 1, n, in);
#ifdef EINTR
if (ferror(in) && errno == EINTR){
@@ -148,12 +162,18 @@ int RAND_load_file(const char *file, long bytes)
OPENSSL_cleanse(buf, sizeof(buf));
fclose(in);
if (!RAND_status()) {
RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_RESEED_ERROR);
ERR_add_error_data(2, "Filename=", file);
return -1;
}
return ret;
}
int RAND_write_file(const char *file)
{
unsigned char buf[RAND_FILE_SIZE];
unsigned char buf[RAND_BUF_SIZE];
int ret = -1;
FILE *out = NULL;
#ifndef OPENSSL_NO_POSIX_IO
@@ -222,9 +242,9 @@ int RAND_write_file(const char *file)
chmod(file, 0600);
#endif
ret = fwrite(buf, 1, RAND_FILE_SIZE, out);
ret = fwrite(buf, 1, RAND_BUF_SIZE, out);
fclose(out);
OPENSSL_cleanse(buf, RAND_FILE_SIZE);
OPENSSL_cleanse(buf, RAND_BUF_SIZE);
return ret;
}