diff --git a/include/polarssl/entropy.h b/include/polarssl/entropy.h index 55b262f8f..3b5d692bc 100644 --- a/include/polarssl/entropy.h +++ b/include/polarssl/entropy.h @@ -230,6 +230,15 @@ int entropy_write_seed_file( entropy_context *ctx, const char *path ); int entropy_update_seed_file( entropy_context *ctx, const char *path ); #endif /* POLARSSL_FS_IO */ +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int entropy_self_test( int verbose ); +#endif /* POLARSSL_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/library/entropy.c b/library/entropy.c index b50049188..c01acf38d 100644 --- a/library/entropy.c +++ b/library/entropy.c @@ -372,4 +372,97 @@ int entropy_update_seed_file( entropy_context *ctx, const char *path ) } #endif /* POLARSSL_FS_IO */ +#if defined(POLARSSL_SELF_TEST) + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + +/* + * Dummy source function + */ +static int entropy_dummy_source( void *data, unsigned char *output, + size_t len, size_t *olen ) +{ + ((void) data); + + memset( output, 0x2a, len ); + *olen = len; + + return( 0 ); +} + +/* + * The actual entropy quality is hard to test, but we can at least + * test that the functions don't cause errors and write the correct + * amount of data to buffers. + */ +int entropy_self_test( int verbose ) +{ + int ret = 0; + entropy_context ctx; + unsigned char buf[ENTROPY_BLOCK_SIZE] = { 0 }; + unsigned char acc[ENTROPY_BLOCK_SIZE] = { 0 }; + size_t i, j; + + if( verbose != 0 ) + polarssl_printf( " ENTROPY test: " ); + + entropy_init( &ctx ); + + ret = entropy_add_source( &ctx, entropy_dummy_source, NULL, 16 ); + if( ret != 0 ) + goto cleanup; + + if( ( ret = entropy_gather( &ctx ) ) != 0 ) + goto cleanup; + + if( ( ret = entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) + goto cleanup; + + /* + * To test that entropy_func writes correct number of bytes: + * - use the whole buffer and rely on ASan to detect overruns + * - collect entropy 8 times and OR the result in an accumulator: + * any byte should then be 0 with probably 2^(-64), so requiring + * each of the 32 or 64 bytes to be non-zero has a false failure rate + * of at most 2^(-58) which is acceptable. + */ + for( i = 0; i < 8; i++ ) + { + if( ( ret = entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) + goto cleanup; + + for( j = 0; j < sizeof( buf ); j++ ) + acc[j] |= buf[j]; + } + + for( j = 0; j < sizeof( buf ); j++ ) + { + if( acc[j] == 0 ) + { + ret = 1; + goto cleanup; + } + } + +cleanup: + entropy_free( &ctx ); + + if( verbose != 0 ) + { + if( ret != 0 ) + polarssl_printf( "failed\n" ); + else + polarssl_printf( "passed\n" ); + + polarssl_printf( "\n" ); + } + + return( ret != 0 ); +} +#endif /* POLARSSL_SELF_TEST */ + #endif /* POLARSSL_ENTROPY_C */ diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 07e2b122a..edb133150 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -32,6 +32,7 @@ #include #include +#include "polarssl/entropy.h" #include "polarssl/hmac_drbg.h" #include "polarssl/ctr_drbg.h" #include "polarssl/dhm.h" @@ -193,6 +194,11 @@ int main( int argc, char *argv[] ) return( ret ); #endif +#if defined(POLARSSL_ENTROPY_C) + if( ( ret = entropy_self_test( v ) ) != 0 ) + return( ret ); +#endif + /* Slow tests last */ #if defined(POLARSSL_PBKDF2_C)