Add a new self test to entropy module
The self test is a quick way to check at startup whether the entropy sources are functioning correctly. The self test only polls 8 bytes from the default entropy source and performs the following checks: - The bytes are not all 0x00 or 0xFF. - The hardware does not return an error when polled. - The entropy does not provide data in a patter. Only check pattern at byte, word and long word sizes.
This commit is contained in:
parent
0e7d38739f
commit
b34e42e69e
@ -258,6 +258,15 @@ int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *
|
||||
* \return 0 if successful, or 1 if a test failed
|
||||
*/
|
||||
int mbedtls_entropy_self_test( int verbose );
|
||||
|
||||
#if !defined(MBEDTLS_TEST_NULL_ENTROPY) && defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if a test failed
|
||||
*/
|
||||
int mbedtls_entropy_self_test_bias( int verbose );
|
||||
#endif /* !MBEDTLS_TEST_NULL_ENTROPY && MBEDTLS_ENTROPY_HARDWARE_ALT */
|
||||
#endif /* MBEDTLS_SELF_TEST */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -470,6 +470,94 @@ static int entropy_dummy_source( void *data, unsigned char *output,
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_TEST_NULL_ENTROPY) && defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
|
||||
|
||||
#define MBEDTLS_SELF_TEST_BIAS_PATTERN( buf_len, type ) \
|
||||
{ \
|
||||
size_t i; \
|
||||
int has_pat = 1; \
|
||||
for( i = 0; i < buf_len; i += sizeof( type ) ) \
|
||||
{ \
|
||||
has_pat &= memcmp( buf, buf + i, sizeof( type ) ) == 0; \
|
||||
} \
|
||||
if( ( ret = has_pat ) != 0 ) \
|
||||
goto cleanup; \
|
||||
} while( 0 ) \
|
||||
|
||||
/*
|
||||
* A quick test to ensure hat the entropy sources are functioning correctly
|
||||
* and there is no obvious bias. The test performs the following checks:
|
||||
* - The entropy source is not providing only 0s (all bits unset) or 1s (all
|
||||
* bits set).
|
||||
* - The entropy source is not providing values in a pattern. Because the
|
||||
* hardware could be providing data in an arbitrary length, this check is
|
||||
* only perform for bytes, words and long words.
|
||||
* - The error code returned by the entropy source is not an error.
|
||||
*/
|
||||
int mbedtls_entropy_self_test_bias( int verbose )
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char buf[2 * sizeof( unsigned long long int )];
|
||||
mbedtls_entropy_context ctx;
|
||||
size_t entropy_len;
|
||||
size_t olen;
|
||||
size_t gather_tries;
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " ENTROPY_BIAS test: " );
|
||||
|
||||
memset( buf, 0x00, sizeof( buf ) );
|
||||
|
||||
mbedtls_entropy_init( &ctx );
|
||||
|
||||
/* The hardware entropy source could return less than the amount of
|
||||
* bytes we requested, so we poll the source as many times as there are
|
||||
* bytes */
|
||||
gather_tries = sizeof( buf );
|
||||
entropy_len = 0;
|
||||
while( gather_tries > 0 && entropy_len < sizeof( buf ) )
|
||||
{
|
||||
if( ( ret = mbedtls_hardware_poll( &ctx, buf + entropy_len,
|
||||
sizeof( buf ) - entropy_len, &olen ) ) != 0 )
|
||||
goto cleanup;
|
||||
|
||||
entropy_len += olen;
|
||||
gather_tries--;
|
||||
}
|
||||
|
||||
if( entropy_len < sizeof( buf ) )
|
||||
{
|
||||
/* We still do not have enough entropy: fail */
|
||||
ret = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Make sure that the entropy source is not returning values in a
|
||||
* pattern */
|
||||
/* Byte */
|
||||
MBEDTLS_SELF_TEST_BIAS_PATTERN( 2 * sizeof( unsigned long long int ), unsigned char );
|
||||
/* Word */
|
||||
MBEDTLS_SELF_TEST_BIAS_PATTERN( 2 * sizeof( unsigned long long int ), unsigned long );
|
||||
/* Long word */
|
||||
MBEDTLS_SELF_TEST_BIAS_PATTERN( 2 * sizeof( unsigned long long int ), unsigned long long int );
|
||||
|
||||
cleanup:
|
||||
mbedtls_entropy_free( &ctx );
|
||||
|
||||
if( verbose != 0 )
|
||||
{
|
||||
if( ret != 0 )
|
||||
mbedtls_printf( "failed\n" );
|
||||
else
|
||||
mbedtls_printf( "passed\n" );
|
||||
|
||||
mbedtls_printf( "\n" );
|
||||
}
|
||||
|
||||
return( ret != 0 );
|
||||
}
|
||||
#endif /* !MBEDTLS_TEST_NULL_ENTROPY && MBEDTLS_ENTROPY_HARDWARE_ALT */
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -375,6 +375,12 @@ int main( int argc, char *argv[] )
|
||||
{
|
||||
suites_failed++;
|
||||
}
|
||||
#if !defined(MBEDTLS_TEST_NULL_ENTROPY) && defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
|
||||
if( mbedtls_entropy_self_test_bias( v ) != 0)
|
||||
{
|
||||
suites_failed++;
|
||||
}
|
||||
#endif
|
||||
suites_tested++;
|
||||
#endif
|
||||
|
||||
|
@ -381,5 +381,8 @@ void entropy_nv_seed( char *read_seed_str )
|
||||
void entropy_selftest( )
|
||||
{
|
||||
TEST_ASSERT( mbedtls_entropy_self_test( 0 ) == 0 );
|
||||
#if !defined(MBEDTLS_TEST_NULL_ENTROPY) && defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
|
||||
TEST_ASSERT( mbedtls_entropy_self_test_bias( 0 ) == 0 );
|
||||
#endif
|
||||
}
|
||||
/* END_CASE */
|
||||
|
Loading…
Reference in New Issue
Block a user