Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default entropy source #1872

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 47 additions & 16 deletions crypto/fipsmodule/rand/entropy/entropy_sources.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,65 @@
#include <openssl/base.h>

#include "internal.h"
#include "../internal.h"
#include "../../delocate.h"

static int fake_void(void) {
static int entropy_default_initialize(void) {
return 1;
}

static int fake_rand(uint8_t a[CTR_DRBG_ENTROPY_LEN]) {
OPENSSL_cleanse(a, CTR_DRBG_ENTROPY_LEN);
static void entropy_default_cleanup(void) {
}

static int entropy_default_get_seed(uint8_t seed[CTR_DRBG_ENTROPY_LEN]) {
CRYPTO_sysrand_for_seed(seed, CTR_DRBG_ENTROPY_LEN);
return 1;
}

static int fake_rand_(uint8_t a[RAND_PRED_RESISTANCE_LEN]) {
OPENSSL_cleanse(a, RAND_PRED_RESISTANCE_LEN);
static int entropy_default_get_prediction_resistance(
uint8_t pred_resistance[RAND_PRED_RESISTANCE_LEN]) {
if (have_fast_rdrand() == 1 &&
rdrand(pred_resistance, RAND_PRED_RESISTANCE_LEN) != 1) {
return 0;
}
return 1;
}

int get_entropy_source(struct entropy_source *entropy_source) {
static int entropy_default_randomize(void) {
dkostic marked this conversation as resolved.
Show resolved Hide resolved
return 1;
}

// In the future this function will lazily initialise a global entropy source.
// The default entropy source configuration using
// - OS randomness source for seeding.
// - Doesn't have a personalization string source.
// - If run-time is on an Intel CPU and it supports rdrand, use it as a source
// for prediction resistance. Otherwise, no source.
DEFINE_LOCAL_DATA(struct entropy_source, default_entropy_source) {
out->initialize = entropy_default_initialize;
out->cleanup = entropy_default_cleanup;
out->get_seed = entropy_default_get_seed;
out->get_personalization_string = NULL;
if (have_fast_rdrand() == 1) {
out->get_prediction_resistance = entropy_default_get_prediction_resistance;
} else {
out->get_prediction_resistance = NULL;
}
out->randomize = entropy_default_randomize;
}

GUARD_PTR(entropy_source);
const struct entropy_source * get_entropy_source(void) {
const struct entropy_source *ent_source = default_entropy_source();

entropy_source->is_initialized = 1;
entropy_source->initialize = fake_void;
entropy_source->cleanup = fake_void;
entropy_source->get_seed = fake_rand;
entropy_source->get_personalization_string = fake_rand;
entropy_source->get_prediction_resistance = fake_rand_;
entropy_source->randomize = fake_void;
// Make sure that the function table contains the minimal number of callbacks
// that we expect. Also make sure that the entropy source is initialized such
// that calling code can assume that.
if (ent_source->cleanup == NULL ||
ent_source->get_seed == NULL ||
ent_source->randomize == NULL ||
ent_source->initialize == NULL ||
ent_source->initialize() != 1) {
return NULL;
}

return 1;
return ent_source;
}
7 changes: 3 additions & 4 deletions crypto/fipsmodule/rand/entropy/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,16 @@ extern "C" {

// I could make these array types!
struct entropy_source {
int is_initialized;
int (*initialize)(void);
int (*cleanup)(void);
void (*cleanup)(void);
int (*get_seed)(uint8_t seed[CTR_DRBG_ENTROPY_LEN]);
int (*get_personalization_string)(uint8_t personalization_string[CTR_DRBG_ENTROPY_LEN]);
int (*get_prediction_resistance)(uint8_t pred_resistance[RAND_PRED_RESISTANCE_LEN]);
int (*randomize)(void);
};

// get_entropy_source will configure an entropy source in |entropy_source|.
int get_entropy_source(struct entropy_source *entropy_source);
// get_entropy_source will return an entropy source configured for the platform.
const struct entropy_source * get_entropy_source(void);

#if defined(__cplusplus)
} // extern C
Expand Down
2 changes: 2 additions & 0 deletions crypto/fipsmodule/rand/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ OPENSSL_EXPORT int CTR_DRBG_init(CTR_DRBG_STATE *drbg,
const uint8_t *personalization,
size_t personalization_len);

int rdrand(uint8_t *buf, const size_t len);

#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM)

OPENSSL_INLINE int have_rdrand(void) {
Expand Down
32 changes: 20 additions & 12 deletions crypto/fipsmodule/rand/new_rand.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct rand_thread_local_state {
uint64_t generate_calls_since_seed;

// Entropy source. UBE volatile state.
struct entropy_source entropy_source;
const struct entropy_source *entropy_source;
};

// rand_thread_local_state frees a |rand_thread_local_state|. This is called
Expand All @@ -35,6 +35,12 @@ static void rand_thread_local_state_free(void *state_in) {
return;
}

// Potentially, something could kill the thread before an entropy source has
// been associated to the thread-local randomness generator object.
if (state->entropy_source != NULL) {
state->entropy_source->cleanup();
}

OPENSSL_free(state);
}

Expand All @@ -60,7 +66,7 @@ static int rand_ensure_ctr_drbg_uniquness(struct rand_thread_local_state *state,
// |*pred_resistance_len| is set to 0 if no prediction resistance source is
// available and |RAND_PRED_RESISTANCE_LEN| otherwise.
static void rand_maybe_get_ctr_drbg_pred_resistance(
struct entropy_source *entropy_source,
const struct entropy_source *entropy_source,
uint8_t pred_resistance[RAND_PRED_RESISTANCE_LEN],
size_t *pred_resistance_len) {

Expand All @@ -70,7 +76,9 @@ static void rand_maybe_get_ctr_drbg_pred_resistance(
*pred_resistance_len = 0;

if (entropy_source->get_prediction_resistance != NULL) {
entropy_source->get_prediction_resistance(pred_resistance);
if (entropy_source->get_prediction_resistance(pred_resistance) != 1) {
abort();
}
*pred_resistance_len = RAND_PRED_RESISTANCE_LEN;
}
}
Expand All @@ -83,7 +91,8 @@ static void rand_maybe_get_ctr_drbg_pred_resistance(
//
// |*personalization_string_len| is set to 0 if no personalization string source
// is available and |CTR_DRBG_ENTROPY_LEN| otherwise.
static void rand_get_ctr_drbg_seed_entropy(struct entropy_source *entropy_source,
static void rand_get_ctr_drbg_seed_entropy(
const struct entropy_source *entropy_source,
uint8_t seed[CTR_DRBG_ENTROPY_LEN],
uint8_t personalization_string[CTR_DRBG_ENTROPY_LEN],
size_t *personalization_string_len) {
Expand All @@ -93,10 +102,8 @@ static void rand_get_ctr_drbg_seed_entropy(struct entropy_source *entropy_source

*personalization_string_len = 0;

// If not initialized or the seed source is missing it is impossible to source
// any entropy.
if (entropy_source->is_initialized == 0 ||
entropy_source->get_seed(seed) != 1) {
// If the seed source is missing it is impossible to source any entropy.
if (entropy_source->get_seed(seed) != 1) {
abort();
}

Expand All @@ -118,7 +125,7 @@ static void rand_ctr_drbg_reseed(struct rand_thread_local_state *state) {
uint8_t seed[CTR_DRBG_ENTROPY_LEN];
uint8_t personalization_string[CTR_DRBG_ENTROPY_LEN];
size_t personalization_string_len = 0;
rand_get_ctr_drbg_seed_entropy(&(state->entropy_source), seed,
rand_get_ctr_drbg_seed_entropy(state->entropy_source, seed,
personalization_string, &personalization_string_len);

assert(personalization_string_len == 0 ||
Expand All @@ -141,14 +148,15 @@ static void rand_state_initialize(struct rand_thread_local_state *state) {

GUARD_PTR_ABORT(state);

if (get_entropy_source(&(state->entropy_source)) != 1) {
state->entropy_source = get_entropy_source();
if (state->entropy_source == NULL) {
abort();
}

uint8_t seed[CTR_DRBG_ENTROPY_LEN];
uint8_t personalization_string[CTR_DRBG_ENTROPY_LEN];
size_t personalization_string_len = 0;
rand_get_ctr_drbg_seed_entropy(&(state->entropy_source), seed,
rand_get_ctr_drbg_seed_entropy(state->entropy_source, seed,
personalization_string, &personalization_string_len);

assert(personalization_string_len == 0 ||
Expand Down Expand Up @@ -192,7 +200,7 @@ static void RAND_bytes_core(
// ensuring that its state is randomized before generating output.
size_t first_pred_resistance_len = 0;
uint8_t pred_resistance[RAND_PRED_RESISTANCE_LEN] = {0};
rand_maybe_get_ctr_drbg_pred_resistance(&(state->entropy_source),
rand_maybe_get_ctr_drbg_pred_resistance(state->entropy_source,
pred_resistance, &first_pred_resistance_len);

// If caller input user-controlled prediction resistance, use it.
Expand Down
4 changes: 2 additions & 2 deletions crypto/fipsmodule/rand/rand.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ OPENSSL_STATIC_ASSERT(RDRAND_MAX_RETRIES > 0, rdrand_max_retries_must_be_positiv

// rdrand should only be called if either |have_rdrand| or |have_fast_rdrand|
// returned true.
static int rdrand(uint8_t *buf, const size_t len) {
int rdrand(uint8_t *buf, const size_t len) {
const size_t len_multiple8 = len & ~7;
CALL_RDRAND_WITH_RETRY(CRYPTO_rdrand_multiple8_buf(buf, len_multiple8), 0)
const size_t remainder = len - len_multiple8;
Expand All @@ -319,7 +319,7 @@ static int rdrand(uint8_t *buf, const size_t len) {

#else

static int rdrand(uint8_t *buf, size_t len) {
int rdrand(uint8_t *buf, const size_t len) {
return 0;
}

Expand Down
Loading