From bd4a9d0cdaac48493468de4bbe7391851784e894 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sat, 10 Dec 2011 17:02:19 +0000 Subject: [PATCH] - Changed entropy accumulator to have per-source thresholds --- include/polarssl/entropy.h | 22 ++++++++++++++---- include/polarssl/entropy_poll.h | 7 ++++++ library/entropy.c | 41 ++++++++++++++++++++++----------- 3 files changed, 52 insertions(+), 18 deletions(-) diff --git a/include/polarssl/entropy.h b/include/polarssl/entropy.h index 46df9293f..0c1f13fa9 100644 --- a/include/polarssl/entropy.h +++ b/include/polarssl/entropy.h @@ -34,7 +34,6 @@ #define POLARSSL_ERR_ENTROPY_SOURCE_FAILED -0x003A /**< Critical entropy source failure. */ #define POLARSSL_ERR_ENTROPY_MAX_SOURCES -0x003C /**< No more sources can be added. */ -#define ENTROPY_MIN_POOL 128 /**< Minimum amount of pool entropy needed for release */ #define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ #define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ #define ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ @@ -58,16 +57,26 @@ extern "C" { */ typedef int (*f_source_ptr)(void *, unsigned char *, size_t, size_t *); +/** + * \brief Entropy source state + */ +typedef struct +{ + f_source_ptr f_source; /**< The entropy source callback */ + void * p_source; /**< The callback data pointer */ + size_t size; /**< Amount received */ + size_t threshold; /**< Minimum level required before release */ +} +source_state; + /** * \brief Entropy context structure */ typedef struct { sha4_context accumulator; - size_t size; int source_count; - f_source_ptr f_source[ENTROPY_MAX_SOURCES]; - void * p_source[ENTROPY_MAX_SOURCES]; + source_state source[ENTROPY_MAX_SOURCES]; } entropy_context; @@ -84,11 +93,14 @@ void entropy_init( entropy_context *ctx ); * \param ctx Entropy context * \param f_source Entropy function * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with entropy_func() ) * * \return 0 is successful or POLARSSL_ERR_ENTROPY_MAX_SOURCES */ int entropy_add_source( entropy_context *ctx, - f_source_ptr f_source, void *p_source ); + f_source_ptr f_source, void *p_source, + size_t threshold ); /** * \brief Trigger an extra gather poll for the accumulator diff --git a/include/polarssl/entropy_poll.h b/include/polarssl/entropy_poll.h index d9acbe5a5..011659829 100644 --- a/include/polarssl/entropy_poll.h +++ b/include/polarssl/entropy_poll.h @@ -35,6 +35,13 @@ extern "C" { #endif +/* + * Default thresholds for built-in sources + */ +#define ENTROPY_MIN_PLATFORM 128 /**< Minimum for platform source */ +#define ENTROPY_MIN_HAVEGE 128 /**< Minimum for HAVEGE */ +#define ENTROPY_MIN_HARDCLOCK 32 /**< Minimum for hardclock() */ + #if !defined(POLARSSL_NO_PLATFORM_ENTROPY) /** * \brief Platform-specific entropy poll callback diff --git a/library/entropy.c b/library/entropy.c index 0ece3457a..bc0e141b2 100644 --- a/library/entropy.c +++ b/library/entropy.c @@ -39,21 +39,26 @@ void entropy_init( entropy_context *ctx ) sha4_starts( &ctx->accumulator, 0 ); #if !defined(POLARSSL_NO_PLATFORM_ENTROPY) - entropy_add_source( ctx, platform_entropy_poll, NULL ); + entropy_add_source( ctx, platform_entropy_poll, NULL, + ENTROPY_MIN_PLATFORM ); #endif #if defined(POLARSSL_TIMING_C) - entropy_add_source( ctx, hardclock_poll, NULL ); + entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK ); #endif } int entropy_add_source( entropy_context *ctx, - f_source_ptr f_source, void *p_source ) + f_source_ptr f_source, void *p_source, + size_t threshold ) { - if( ctx->source_count >= ENTROPY_MAX_SOURCES ) + int index = ctx->source_count; + + if( index >= ENTROPY_MAX_SOURCES ) return( POLARSSL_ERR_ENTROPY_MAX_SOURCES ); - ctx->f_source[ctx->source_count] = f_source; - ctx->p_source[ctx->source_count] = p_source; + ctx->source[index].f_source = f_source; + ctx->source[index].p_source = p_source; + ctx->source[index].threshold = threshold; ctx->source_count++; @@ -85,8 +90,6 @@ int entropy_update( entropy_context *ctx, unsigned char source_id, sha4_update( &ctx->accumulator, header, 2 ); sha4_update( &ctx->accumulator, p, use_len ); - ctx->size += use_len; - return( 0 ); } @@ -111,7 +114,7 @@ int entropy_gather( entropy_context *ctx ) for( i = 0; i < ctx->source_count; i++ ) { olen = 0; - if ( ( ret = ctx->f_source[i]( ctx->p_source[i], + if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 ) { return( ret ); @@ -121,7 +124,10 @@ int entropy_gather( entropy_context *ctx ) * Add if we actually gathered something */ if( olen > 0 ) + { entropy_update( ctx, (unsigned char) i, buf, olen ); + ctx->source[i].size += olen; + } } return( 0 ); @@ -129,7 +135,7 @@ int entropy_gather( entropy_context *ctx ) int entropy_func( void *data, unsigned char *output, size_t len ) { - int ret, count = 0; + int ret, count = 0, i, reached; entropy_context *ctx = (entropy_context *) data; unsigned char buf[ENTROPY_BLOCK_SIZE]; @@ -146,8 +152,14 @@ int entropy_func( void *data, unsigned char *output, size_t len ) if( ( ret = entropy_gather( ctx ) ) != 0 ) return( ret ); + + reached = 0; + + for( i = 0; i < ctx->source_count; i++ ) + if( ctx->source[i].size >= ctx->source[i].threshold ) + reached++; } - while( ctx->size < ENTROPY_MIN_POOL ); + while( reached != ctx->source_count ); memset( buf, 0, ENTROPY_BLOCK_SIZE ); @@ -159,11 +171,14 @@ int entropy_func( void *data, unsigned char *output, size_t len ) sha4( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); /* - * Reset accumulator + * Reset accumulator and counters and recycle existing entropy */ memset( &ctx->accumulator, 0, sizeof( sha4_context ) ); sha4_starts( &ctx->accumulator, 0 ); - ctx->size = 0; + sha4_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); + + for( i = 0; i < ctx->source_count; i++ ) + ctx->source[i].size = 0; memcpy( output, buf, len );