@ -29,6 +29,9 @@
*/
# include "utils/includes.h"
# ifdef __linux__
# include <fcntl.h>
# endif /* __linux__ */
# include "utils/common.h"
# include "sha1.h"
@ -42,14 +45,18 @@
# define POOL_TAP4 7
# define POOL_TAP5 1
# define EXTRACT_LEN 16
# define MIN_READY_MARK 2
static u32 pool [ POOL_WORDS ] ;
static unsigned int input_rotate = 0 ;
static unsigned int pool_pos = 0 ;
static const u8 dummy_key [ 20 ] ;
static u8 dummy_key [ 20 ] ;
static size_t dummy_key_avail = 0 ;
static unsigned int own_pool_ready = 0 ;
# define MIN_COLLECT_ENTROPY 1000
static unsigned int entropy = 0 ;
static unsigned int total_collected = 0 ;
static u32 __ROL32 ( u32 x , u32 y )
@ -135,6 +142,7 @@ void random_add_randomness(const void *buf, size_t len)
wpa_hexdump_key ( MSG_EXCESSIVE , " random pool " ,
( const u8 * ) pool , sizeof ( pool ) ) ;
entropy + + ;
total_collected + + ;
}
@ -174,3 +182,77 @@ int random_get_bytes(void *buf, size_t len)
return ret ;
}
int random_pool_ready ( void )
{
# ifdef __linux__
int fd ;
ssize_t res ;
/*
* Make sure that there is reasonable entropy available before allowing
* some key derivation operations to proceed .
*/
if ( dummy_key_avail = = sizeof ( dummy_key ) )
return 1 ; /* Already initialized - good to continue */
/*
* Try to fetch some more data from the kernel high quality
* / dev / random . There may not be enough data available at this point ,
* so use non - blocking read to avoid blocking the application
* completely .
*/
fd = open ( " /dev/random " , O_RDONLY | O_NONBLOCK ) ;
if ( fd < 0 ) {
int error = errno ;
perror ( " open(/dev/random) " ) ;
wpa_printf ( MSG_ERROR , " random: Cannot open /dev/random: %s " ,
strerror ( error ) ) ;
return - 1 ;
}
res = read ( fd , dummy_key + dummy_key_avail ,
sizeof ( dummy_key ) - dummy_key_avail ) ;
if ( res < 0 ) {
wpa_printf ( MSG_ERROR , " random: Cannot read from /dev/random: "
" %s " , strerror ( errno ) ) ;
res = 0 ;
}
wpa_printf ( MSG_DEBUG , " random: Got %u/%u bytes from "
" /dev/random " , ( unsigned ) res ,
( unsigned ) ( sizeof ( dummy_key ) - dummy_key_avail ) ) ;
dummy_key_avail + = res ;
close ( fd ) ;
if ( dummy_key_avail = = sizeof ( dummy_key ) )
return 1 ;
wpa_printf ( MSG_INFO , " random: Only %u/%u bytes of strong "
" random data available from /dev/random " ,
( unsigned ) dummy_key_avail , ( unsigned ) sizeof ( dummy_key ) ) ;
if ( own_pool_ready > = MIN_READY_MARK | |
total_collected + 10 * own_pool_ready > MIN_COLLECT_ENTROPY ) {
wpa_printf ( MSG_INFO , " random: Allow operation to proceed "
" based on internal entropy " ) ;
return 1 ;
}
wpa_printf ( MSG_INFO , " random: Not enough entropy pool available for "
" secure operations " ) ;
return 0 ;
# else /* __linux__ */
/* TODO: could do similar checks on non-Linux platforms */
return 1 ;
# endif /* __linux__ */
}
void random_mark_pool_ready ( void )
{
own_pool_ready + + ;
wpa_printf ( MSG_DEBUG , " random: Mark internal entropy pool to be "
" ready (count=%u/%u) " , own_pool_ready , MIN_READY_MARK ) ;
}