Add test cases for NV seed functionality

A standard 'test' that writes a seed file is added so that regular tests
still can succeed. This is in lieu of a 'SUITE_PRE_CODE' kind of
arrangement where a suite can run code before (and after) all other code
runs.

A test is added that checks if we can read and write the standard NV
seed file

A test is added that actually checks if the entropy and seed file values
that are the result of just using the NV seed are the same as the manual
calculation.
This commit is contained in:
Paul Bakker 2016-06-01 15:36:18 +01:00
parent 960292337c
commit ffbfb4c24c
2 changed files with 218 additions and 0 deletions

View file

@ -1,3 +1,6 @@
Create NV seed_file
nv_seed_file_create:
Entropy write/update seed file
entropy_seed_file:"data_files/entropy_seed":0
@ -37,5 +40,17 @@ entropy_threshold:16:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
Entropy thershold #4
entropy_threshold:1024:1:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
Check NV seed standard IO
entropy_nv_seed_std_io:
Check NV seed manually #1
entropy_nv_seed:"00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
Check NV seed manually #2
entropy_nv_seed:"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
Check NV seed manually #3
entropy_nv_seed:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
Entropy self test
entropy_selftest:

View file

@ -1,5 +1,6 @@
/* BEGIN_HEADER */
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
/*
* Number of calls made to entropy_dummy_source()
@ -33,6 +34,86 @@ static int entropy_dummy_source( void *data, unsigned char *output,
return( 0 );
}
/*
* Ability to clear entropy sources to allow testing with just predefined
* entropy sources. This function or tests depending on it might break if there
* are internal changes to how entropy sources are registered.
*
* To be called immediately after mbedtls_entropy_init().
*
* Just resetting the counter. New sources will overwrite existing ones.
* This might break memory checks in the future if sources need 'free-ing' then
* as well.
*/
static void entropy_clear_sources( mbedtls_entropy_context *ctx )
{
ctx->source_count = 0;
}
/*
* NV seed read/write functions that use a buffer instead of a file
*/
static unsigned char buffer_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
static int buffer_nv_seed_read( unsigned char *buf, size_t buf_len )
{
if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
return( -1 );
memcpy( buf, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
return( 0 );
}
static int buffer_nv_seed_write( unsigned char *buf, size_t buf_len )
{
if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
return( -1 );
memcpy( buffer_seed, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
return( 0 );
}
/*
* NV seed read/write helpers that fill the base seedfile
*/
static int write_nv_seed( unsigned char *buf, size_t buf_len )
{
FILE *f;
if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
return( -1 );
if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL )
return( -1 );
if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) !=
MBEDTLS_ENTROPY_BLOCK_SIZE )
return( -1 );
fclose( f );
return( 0 );
}
static int read_nv_seed( unsigned char *buf, size_t buf_len )
{
FILE *f;
if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
return( -1 );
if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL )
return( -1 );
if( fread( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) !=
MBEDTLS_ENTROPY_BLOCK_SIZE )
return( -1 );
fclose( f );
return( 0 );
}
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@ -160,6 +241,10 @@ void entropy_threshold( int threshold, int chunk_size, int result )
if( result >= 0 )
{
TEST_ASSERT( ret == 0 );
#if defined(MBEDTLS_ENTROPY_NV_SEED)
// Two times as much calls due to the NV seed update
result *= 2;
#endif
TEST_ASSERT( entropy_dummy_calls == (size_t) result );
}
else
@ -172,6 +257,124 @@ exit:
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
void nv_seed_file_create()
{
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
TEST_ASSERT( write_nv_seed( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
void entropy_nv_seed_std_io()
{
unsigned char io_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
memset( io_seed, 1, MBEDTLS_ENTROPY_BLOCK_SIZE );
memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
mbedtls_platform_set_nv_seed( mbedtls_platform_std_nv_seed_read,
mbedtls_platform_std_nv_seed_write );
/* Check if platform NV read and write manipulate the same data */
TEST_ASSERT( write_nv_seed( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
TEST_ASSERT( mbedtls_nv_seed_read( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) ==
MBEDTLS_ENTROPY_BLOCK_SIZE );
TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
/* Check if platform NV write and raw read manipulate the same data */
TEST_ASSERT( mbedtls_nv_seed_write( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) ==
MBEDTLS_ENTROPY_BLOCK_SIZE );
TEST_ASSERT( read_nv_seed( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PLATFORM_NV_SEED_ALT:MBEDTLS_SHA512_C */
void entropy_nv_seed( char *read_seed_str )
{
mbedtls_sha512_context accumulator;
mbedtls_entropy_context ctx;
unsigned char header[2];
unsigned char entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
unsigned char empty[MBEDTLS_ENTROPY_BLOCK_SIZE];
unsigned char read_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
unsigned char check_entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
memset( entropy, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
memset( buffer_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
memset( empty, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
memset( check_seed, 2, MBEDTLS_ENTROPY_BLOCK_SIZE );
memset( check_entropy, 3, MBEDTLS_ENTROPY_BLOCK_SIZE );
// Set the initial NV seed to read
unhexify( read_seed, read_seed_str );
memcpy( buffer_seed, read_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
// Make sure we read/write NV seed from our buffers
mbedtls_platform_set_nv_seed( buffer_nv_seed_read, buffer_nv_seed_write );
mbedtls_entropy_init( &ctx );
entropy_clear_sources( &ctx );
TEST_ASSERT( mbedtls_entropy_add_source( &ctx, mbedtls_nv_seed_poll, NULL,
MBEDTLS_ENTROPY_BLOCK_SIZE,
MBEDTLS_ENTROPY_SOURCE_STRONG ) == 0 );
// Do an entropy run
TEST_ASSERT( mbedtls_entropy_func( &ctx, entropy, sizeof( entropy ) ) == 0 );
// Determine what should have happened with manual entropy internal logic
// Only use the SHA-512 version to check
// Init accumulator
header[1] = MBEDTLS_ENTROPY_BLOCK_SIZE;
mbedtls_sha512_starts( &accumulator, 0 );
// First run for updating write_seed
header[0] = 0;
mbedtls_sha512_update( &accumulator, header, 2 );
mbedtls_sha512_update( &accumulator, read_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
mbedtls_sha512_finish( &accumulator, buf );
memset( &accumulator, 0, sizeof( mbedtls_sha512_context ) );
mbedtls_sha512_starts( &accumulator, 0 );
mbedtls_sha512_update( &accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_seed, 0 );
// Second run for actual entropy (triggers mbedtls_entropy_update_nv_seed)
header[0] = MBEDTLS_ENTROPY_SOURCE_MANUAL;
mbedtls_sha512_update( &accumulator, header, 2 );
mbedtls_sha512_update( &accumulator, empty, MBEDTLS_ENTROPY_BLOCK_SIZE );
header[0] = 0;
mbedtls_sha512_update( &accumulator, header, 2 );
mbedtls_sha512_update( &accumulator, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
mbedtls_sha512_finish( &accumulator, buf );
mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_entropy, 0 );
// Check result of both NV file and entropy received with the manual calculations
TEST_ASSERT( memcmp( check_seed, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
TEST_ASSERT( memcmp( check_entropy, entropy, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
mbedtls_entropy_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void entropy_selftest( )
{