void entropy_init( entropy_context *ctx ) { memset( ctx, 0, sizeof(entropy_context) ); #if defined(POLARSSL_THREADING_C) polarssl_mutex_init( &ctx->mutex ); #endif #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) sha512_starts( &ctx->accumulator, 0 ); #else sha256_starts( &ctx->accumulator, 0 ); #endif #if defined(POLARSSL_HAVEGE_C) havege_init( &ctx->havege_data ); #endif #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES) #if !defined(POLARSSL_NO_PLATFORM_ENTROPY) 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_MIN_HARDCLOCK ); #endif #if defined(POLARSSL_HAVEGE_C) entropy_add_source( ctx, havege_poll, &ctx->havege_data, ENTROPY_MIN_HAVEGE ); #endif #endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */ }
static void sha512_starts_wrap( void *ctx ) { sha512_starts( (sha512_context *) ctx, 0 ); }
int entropy_func( void *data, unsigned char *output, size_t len ) { int ret, count = 0, i, reached; entropy_context *ctx = (entropy_context *) data; unsigned char buf[ENTROPY_BLOCK_SIZE]; if( len > ENTROPY_BLOCK_SIZE ) return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); #if defined(POLARSSL_THREADING_C) if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) return( ret ); #endif /* * Always gather extra entropy before a call */ do { if( count++ > ENTROPY_MAX_LOOP ) { ret = POLARSSL_ERR_ENTROPY_SOURCE_FAILED; goto exit; } if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) goto exit; reached = 0; for( i = 0; i < ctx->source_count; i++ ) if( ctx->source[i].size >= ctx->source[i].threshold ) reached++; } while( reached != ctx->source_count ); memset( buf, 0, ENTROPY_BLOCK_SIZE ); #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) sha512_finish( &ctx->accumulator, buf ); /* * Reset accumulator and counters and recycle existing entropy */ memset( &ctx->accumulator, 0, sizeof( sha512_context ) ); sha512_starts( &ctx->accumulator, 0 ); sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); /* * Perform second SHA-512 on entropy */ sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); #else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */ sha256_finish( &ctx->accumulator, buf ); /* * Reset accumulator and counters and recycle existing entropy */ memset( &ctx->accumulator, 0, sizeof( sha256_context ) ); sha256_starts( &ctx->accumulator, 0 ); sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); /* * Perform second SHA-256 on entropy */ sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); #endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */ for( i = 0; i < ctx->source_count; i++ ) ctx->source[i].size = 0; memcpy( output, buf, len ); ret = 0; exit: #if defined(POLARSSL_THREADING_C) if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); #endif return( ret ); }