@ -163,10 +163,10 @@ static int rdrand(uint8_t *buf, size_t len) {
# if defined(BORINGSSL_FIPS)
# if defined(BORINGSSL_FIPS)
void CRYPTO_get_seed_entropy ( uint8_t * out_entropy , size_t out_entropy_len ,
void CRYPTO_get_seed_entropy ( uint8_t * out_entropy , size_t out_entropy_len ,
int * out_used_cpu ) {
int * out_want_additional_input ) {
* out_used_cpu = 0 ;
* out_want_additional_input = 0 ;
if ( have_rdrand ( ) & & rdrand ( out_entropy , out_entropy_len ) ) {
if ( have_rdrand ( ) & & rdrand ( out_entropy , out_entropy_len ) ) {
* out_used_cpu = 1 ;
* out_want_additional_input = 1 ;
} else {
} else {
CRYPTO_sysrand_for_seed ( out_entropy , out_entropy_len ) ;
CRYPTO_sysrand_for_seed ( out_entropy , out_entropy_len ) ;
}
}
@ -188,16 +188,17 @@ struct entropy_buffer {
// bytes_valid indicates the number of bytes of |bytes| that contain valid
// bytes_valid indicates the number of bytes of |bytes| that contain valid
// data.
// data.
size_t bytes_valid ;
size_t bytes_valid ;
// from_cpu is true if any of the contents of |bytes| were obtained directly
// want_additional_input is true if any of the contents of |bytes| were
// from the CPU.
// obtained via a method other than from the kernel. In these cases entropy
int from_cpu ;
// from the kernel is also provided via an additional input to the DRBG.
int want_additional_input ;
} ;
} ;
DEFINE_BSS_GET ( struct entropy_buffer , entropy_buffer ) ;
DEFINE_BSS_GET ( struct entropy_buffer , entropy_buffer ) ;
DEFINE_STATIC_MUTEX ( entropy_buffer_lock ) ;
DEFINE_STATIC_MUTEX ( entropy_buffer_lock ) ;
void RAND_load_entropy ( const uint8_t * entropy , size_t entropy_len ,
void RAND_load_entropy ( const uint8_t * entropy , size_t entropy_len ,
int from_cpu ) {
int want_additional_input ) {
struct entropy_buffer * const buffer = entropy_buffer_bss_get ( ) ;
struct entropy_buffer * const buffer = entropy_buffer_bss_get ( ) ;
CRYPTO_STATIC_MUTEX_lock_write ( entropy_buffer_lock_bss_get ( ) ) ;
CRYPTO_STATIC_MUTEX_lock_write ( entropy_buffer_lock_bss_get ( ) ) ;
@ -208,14 +209,15 @@ void RAND_load_entropy(const uint8_t *entropy, size_t entropy_len,
OPENSSL_memcpy ( & buffer - > bytes [ buffer - > bytes_valid ] , entropy , entropy_len ) ;
OPENSSL_memcpy ( & buffer - > bytes [ buffer - > bytes_valid ] , entropy , entropy_len ) ;
buffer - > bytes_valid + = entropy_len ;
buffer - > bytes_valid + = entropy_len ;
buffer - > from_cpu | = from_cpu & & ( entropy_len ! = 0 ) ;
buffer - > want_additional_input | =
want_additional_input & & ( entropy_len ! = 0 ) ;
CRYPTO_STATIC_MUTEX_unlock_write ( entropy_buffer_lock_bss_get ( ) ) ;
CRYPTO_STATIC_MUTEX_unlock_write ( entropy_buffer_lock_bss_get ( ) ) ;
}
}
// get_seed_entropy fills |out_entropy_len| bytes of |out_entropy| from the
// get_seed_entropy fills |out_entropy_len| bytes of |out_entropy| from the
// global |entropy_buffer|.
// global |entropy_buffer|.
static void get_seed_entropy ( uint8_t * out_entropy , size_t out_entropy_len ,
static void get_seed_entropy ( uint8_t * out_entropy , size_t out_entropy_len ,
int * out_used_cpu ) {
int * out_want_additional_input ) {
struct entropy_buffer * const buffer = entropy_buffer_bss_get ( ) ;
struct entropy_buffer * const buffer = entropy_buffer_bss_get ( ) ;
if ( out_entropy_len > sizeof ( buffer - > bytes ) ) {
if ( out_entropy_len > sizeof ( buffer - > bytes ) ) {
abort ( ) ;
abort ( ) ;
@ -228,23 +230,24 @@ static void get_seed_entropy(uint8_t *out_entropy, size_t out_entropy_len,
CRYPTO_STATIC_MUTEX_lock_write ( entropy_buffer_lock_bss_get ( ) ) ;
CRYPTO_STATIC_MUTEX_lock_write ( entropy_buffer_lock_bss_get ( ) ) ;
}
}
* out_used_cpu = buffer - > from_cpu ;
* out_want_additional_input = buffer - > want_additional_input ;
OPENSSL_memcpy ( out_entropy , buffer - > bytes , out_entropy_len ) ;
OPENSSL_memcpy ( out_entropy , buffer - > bytes , out_entropy_len ) ;
OPENSSL_memmove ( buffer - > bytes , & buffer - > bytes [ out_entropy_len ] ,
OPENSSL_memmove ( buffer - > bytes , & buffer - > bytes [ out_entropy_len ] ,
buffer - > bytes_valid - out_entropy_len ) ;
buffer - > bytes_valid - out_entropy_len ) ;
buffer - > bytes_valid - = out_entropy_len ;
buffer - > bytes_valid - = out_entropy_len ;
if ( buffer - > bytes_valid = = 0 ) {
if ( buffer - > bytes_valid = = 0 ) {
buffer - > from_cpu = 0 ;
buffer - > want_additional_input = 0 ;
}
}
CRYPTO_STATIC_MUTEX_unlock_write ( entropy_buffer_lock_bss_get ( ) ) ;
CRYPTO_STATIC_MUTEX_unlock_write ( entropy_buffer_lock_bss_get ( ) ) ;
}
}
// rand_get_seed fills |seed| with entropy and sets |*out_used_cpu| to one if
// rand_get_seed fills |seed| with entropy and sets
// that entropy came directly from the CPU and zero otherwise.
// |*out_want_additional_input| to one if that entropy came directly from the
// CPU and zero otherwise.
static void rand_get_seed ( struct rand_thread_state * state ,
static void rand_get_seed ( struct rand_thread_state * state ,
uint8_t seed [ CTR_DRBG_ENTROPY_LEN ] ,
uint8_t seed [ CTR_DRBG_ENTROPY_LEN ] ,
int * out_used_cpu ) {
int * out_want_additional_input ) {
if ( ! state - > last_block_valid ) {
if ( ! state - > last_block_valid ) {
int unused ;
int unused ;
get_seed_entropy ( state - > last_block , sizeof ( state - > last_block ) , & unused ) ;
get_seed_entropy ( state - > last_block , sizeof ( state - > last_block ) , & unused ) ;
@ -252,7 +255,7 @@ static void rand_get_seed(struct rand_thread_state *state,
}
}
uint8_t entropy [ CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD ] ;
uint8_t entropy [ CTR_DRBG_ENTROPY_LEN * BORINGSSL_FIPS_OVERREAD ] ;
get_seed_entropy ( entropy , sizeof ( entropy ) , out_used_cpu ) ;
get_seed_entropy ( entropy , sizeof ( entropy ) , out_want_additional_input ) ;
// See FIPS 140-2, section 4.9.2. This is the “continuous random number
// See FIPS 140-2, section 4.9.2. This is the “continuous random number
// generator test” which causes the program to randomly abort. Hopefully the
// generator test” which causes the program to randomly abort. Hopefully the
@ -286,15 +289,16 @@ static void rand_get_seed(struct rand_thread_state *state,
# else
# else
// rand_get_seed fills |seed| with entropy and sets |*out_used_cpu| to one if
// rand_get_seed fills |seed| with entropy and sets
// that entropy came directly from the CPU and zero otherwise.
// |*out_want_additional_input| to one if that entropy came directly from the
// CPU and zero otherwise.
static void rand_get_seed ( struct rand_thread_state * state ,
static void rand_get_seed ( struct rand_thread_state * state ,
uint8_t seed [ CTR_DRBG_ENTROPY_LEN ] ,
uint8_t seed [ CTR_DRBG_ENTROPY_LEN ] ,
int * out_used_cpu ) {
int * out_want_additional_input ) {
// If not in FIPS mode, we don't overread from the system entropy source and
// If not in FIPS mode, we don't overread from the system entropy source and
// we don't depend only on the hardware RDRAND.
// we don't depend only on the hardware RDRAND.
CRYPTO_sysrand_for_seed ( seed , CTR_DRBG_ENTROPY_LEN ) ;
CRYPTO_sysrand_for_seed ( seed , CTR_DRBG_ENTROPY_LEN ) ;
* out_used_cpu = 0 ;
* out_want_additional_input = 0 ;
}
}
# endif
# endif
@ -353,16 +357,16 @@ void RAND_bytes_with_additional_data(uint8_t *out, size_t out_len,
state - > last_block_valid = 0 ;
state - > last_block_valid = 0 ;
uint8_t seed [ CTR_DRBG_ENTROPY_LEN ] ;
uint8_t seed [ CTR_DRBG_ENTROPY_LEN ] ;
int used_cpu ;
int want_additional_input ;
rand_get_seed ( state , seed , & used_cpu ) ;
rand_get_seed ( state , seed , & want_additional_input ) ;
uint8_t personalization [ CTR_DRBG_ENTROPY_LEN ] = { 0 } ;
uint8_t personalization [ CTR_DRBG_ENTROPY_LEN ] = { 0 } ;
size_t personalization_len = 0 ;
size_t personalization_len = 0 ;
# if defined(OPENSSL_URANDOM)
# if defined(OPENSSL_URANDOM)
// If we used RDRAND, also opportunistically read from the system. This
// If we used something other than system entropy then also
// avoids solely relying on the hardware once the entropy pool has been
// opportunistically read from the system. This avoids solely relying on the
// initialized.
// hardware once the entropy pool has been initialized.
if ( used_cpu & &
if ( want_additional_input & &
CRYPTO_sysrand_if_available ( personalization , sizeof ( personalization ) ) ) {
CRYPTO_sysrand_if_available ( personalization , sizeof ( personalization ) ) ) {
personalization_len = sizeof ( personalization ) ;
personalization_len = sizeof ( personalization ) ;
}
}
@ -393,8 +397,8 @@ void RAND_bytes_with_additional_data(uint8_t *out, size_t out_len,
if ( state - > calls > = kReseedInterval | |
if ( state - > calls > = kReseedInterval | |
state - > fork_generation ! = fork_generation ) {
state - > fork_generation ! = fork_generation ) {
uint8_t seed [ CTR_DRBG_ENTROPY_LEN ] ;
uint8_t seed [ CTR_DRBG_ENTROPY_LEN ] ;
int used_cpu ;
int want_additional_input ;
rand_get_seed ( state , seed , & used_cpu ) ;
rand_get_seed ( state , seed , & want_additional_input ) ;
# if defined(BORINGSSL_FIPS)
# if defined(BORINGSSL_FIPS)
// Take a read lock around accesses to |state->drbg|. This is needed to
// Take a read lock around accesses to |state->drbg|. This is needed to
// avoid returning bad entropy if we race with
// avoid returning bad entropy if we race with