2 #include "mbedtls/entropy.h"
3 #include "mbedtls/entropy_poll.h"
7 * Number of calls made to entropy_dummy_source()
9 static size_t entropy_dummy_calls;
12 * Dummy entropy source
14 * If data is NULL, write exactly the requested length.
15 * Otherwise, write the length indicated by data or error if negative
17 static int entropy_dummy_source( void *data, unsigned char *output,
18 size_t len, size_t *olen )
20 entropy_dummy_calls++;
26 int *d = (int *) data;
29 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
34 memset( output, 0x2a, *olen );
39 #if defined(MBEDTLS_ENTROPY_NV_SEED)
41 * Ability to clear entropy sources to allow testing with just predefined
42 * entropy sources. This function or tests depending on it might break if there
43 * are internal changes to how entropy sources are registered.
45 * To be called immediately after mbedtls_entropy_init().
47 * Just resetting the counter. New sources will overwrite existing ones.
48 * This might break memory checks in the future if sources need 'free-ing' then
51 static void entropy_clear_sources( mbedtls_entropy_context *ctx )
53 ctx->source_count = 0;
57 * NV seed read/write functions that use a buffer instead of a file
59 static unsigned char buffer_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
61 static int buffer_nv_seed_read( unsigned char *buf, size_t buf_len )
63 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
66 memcpy( buf, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
70 static int buffer_nv_seed_write( unsigned char *buf, size_t buf_len )
72 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
75 memcpy( buffer_seed, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
80 * NV seed read/write helpers that fill the base seedfile
82 static int write_nv_seed( unsigned char *buf, size_t buf_len )
86 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
89 if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL )
92 if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) !=
93 MBEDTLS_ENTROPY_BLOCK_SIZE )
101 static int read_nv_seed( unsigned char *buf, size_t buf_len )
105 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
108 if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL )
111 if( fread( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) !=
112 MBEDTLS_ENTROPY_BLOCK_SIZE )
119 #endif /* MBEDTLS_ENTROPY_NV_SEED */
122 /* BEGIN_DEPENDENCIES
123 * depends_on:MBEDTLS_ENTROPY_C
127 /* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
128 void entropy_seed_file( char * path, int ret )
130 mbedtls_entropy_context ctx;
132 mbedtls_entropy_init( &ctx );
134 TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, path ) == ret );
135 TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, path ) == ret );
138 mbedtls_entropy_free( &ctx );
143 void entropy_too_many_sources( )
145 mbedtls_entropy_context ctx;
148 mbedtls_entropy_init( &ctx );
151 * It's hard to tell precisely when the error will occur,
152 * since we don't know how many sources were automatically added.
154 for( i = 0; i < MBEDTLS_ENTROPY_MAX_SOURCES; i++ )
155 (void) mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL,
156 16, MBEDTLS_ENTROPY_SOURCE_WEAK );
158 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL,
159 16, MBEDTLS_ENTROPY_SOURCE_WEAK )
160 == MBEDTLS_ERR_ENTROPY_MAX_SOURCES );
163 mbedtls_entropy_free( &ctx );
167 /* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */
168 void entropy_func_len( int len, int ret )
170 mbedtls_entropy_context ctx;
171 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 };
172 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 };
175 mbedtls_entropy_init( &ctx );
178 * See comments in mbedtls_entropy_self_test()
180 for( i = 0; i < 8; i++ )
182 TEST_ASSERT( mbedtls_entropy_func( &ctx, buf, len ) == ret );
183 for( j = 0; j < sizeof( buf ); j++ )
188 for( j = 0; j < (size_t) len; j++ )
189 TEST_ASSERT( acc[j] != 0 );
191 for( j = len; j < sizeof( buf ); j++ )
192 TEST_ASSERT( acc[j] == 0 );
197 void entropy_source_fail( char * path )
199 mbedtls_entropy_context ctx;
201 unsigned char buf[16];
203 mbedtls_entropy_init( &ctx );
205 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
207 MBEDTLS_ENTROPY_SOURCE_WEAK )
210 TEST_ASSERT( mbedtls_entropy_func( &ctx, buf, sizeof( buf ) )
211 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
212 TEST_ASSERT( mbedtls_entropy_gather( &ctx )
213 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
214 #if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_NV_SEED)
215 TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, path )
216 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
217 TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, path )
218 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
224 mbedtls_entropy_free( &ctx );
228 /* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */
229 void entropy_threshold( int threshold, int chunk_size, int result )
231 mbedtls_entropy_context ctx;
232 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
235 mbedtls_entropy_init( &ctx );
237 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
238 &chunk_size, threshold,
239 MBEDTLS_ENTROPY_SOURCE_WEAK ) == 0 );
241 entropy_dummy_calls = 0;
242 ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) );
246 TEST_ASSERT( ret == 0 );
247 #if defined(MBEDTLS_ENTROPY_NV_SEED)
248 // Two times as much calls due to the NV seed update
251 TEST_ASSERT( entropy_dummy_calls == (size_t) result );
255 TEST_ASSERT( ret == result );
259 mbedtls_entropy_free( &ctx );
263 /* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
264 void nv_seed_file_create( )
266 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
268 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
270 TEST_ASSERT( write_nv_seed( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
274 /* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO:MBEDTLS_PLATFORM_NV_SEED_ALT */
275 void entropy_nv_seed_std_io( )
277 unsigned char io_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
278 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
280 memset( io_seed, 1, MBEDTLS_ENTROPY_BLOCK_SIZE );
281 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
283 mbedtls_platform_set_nv_seed( mbedtls_platform_std_nv_seed_read,
284 mbedtls_platform_std_nv_seed_write );
286 /* Check if platform NV read and write manipulate the same data */
287 TEST_ASSERT( write_nv_seed( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
288 TEST_ASSERT( mbedtls_nv_seed_read( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) ==
289 MBEDTLS_ENTROPY_BLOCK_SIZE );
291 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
293 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
295 /* Check if platform NV write and raw read manipulate the same data */
296 TEST_ASSERT( mbedtls_nv_seed_write( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) ==
297 MBEDTLS_ENTROPY_BLOCK_SIZE );
298 TEST_ASSERT( read_nv_seed( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
300 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
304 /* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PLATFORM_NV_SEED_ALT:MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
305 void entropy_nv_seed( data_t * read_seed )
307 mbedtls_sha512_context accumulator;
308 mbedtls_entropy_context ctx;
310 unsigned char header[2];
311 unsigned char entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
312 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
313 unsigned char empty[MBEDTLS_ENTROPY_BLOCK_SIZE];
314 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
315 unsigned char check_entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
317 memset( entropy, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
318 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
319 memset( buffer_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
320 memset( empty, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
321 memset( check_seed, 2, MBEDTLS_ENTROPY_BLOCK_SIZE );
322 memset( check_entropy, 3, MBEDTLS_ENTROPY_BLOCK_SIZE );
324 // Set the initial NV seed to read
325 memcpy( buffer_seed, read_seed->x, read_seed->len );
327 // Make sure we read/write NV seed from our buffers
328 mbedtls_platform_set_nv_seed( buffer_nv_seed_read, buffer_nv_seed_write );
330 mbedtls_entropy_init( &ctx );
331 entropy_clear_sources( &ctx );
333 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, mbedtls_nv_seed_poll, NULL,
334 MBEDTLS_ENTROPY_BLOCK_SIZE,
335 MBEDTLS_ENTROPY_SOURCE_STRONG ) == 0 );
338 TEST_ASSERT( mbedtls_entropy_func( &ctx, entropy, sizeof( entropy ) ) == 0 );
340 // Determine what should have happened with manual entropy internal logic
341 // Only use the SHA-512 version to check
344 header[1] = MBEDTLS_ENTROPY_BLOCK_SIZE;
345 mbedtls_sha512_starts( &accumulator, 0 );
347 // First run for updating write_seed
349 mbedtls_sha512_update( &accumulator, header, 2 );
350 mbedtls_sha512_update( &accumulator, read_seed->x, read_seed->len );
351 mbedtls_sha512_finish( &accumulator, buf );
353 memset( &accumulator, 0, sizeof( mbedtls_sha512_context ) );
354 mbedtls_sha512_starts( &accumulator, 0 );
355 mbedtls_sha512_update( &accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
357 mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_seed, 0 );
359 // Second run for actual entropy (triggers mbedtls_entropy_update_nv_seed)
360 header[0] = MBEDTLS_ENTROPY_SOURCE_MANUAL;
361 mbedtls_sha512_update( &accumulator, header, 2 );
362 mbedtls_sha512_update( &accumulator, empty, MBEDTLS_ENTROPY_BLOCK_SIZE );
365 mbedtls_sha512_update( &accumulator, header, 2 );
366 mbedtls_sha512_update( &accumulator, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
367 mbedtls_sha512_finish( &accumulator, buf );
369 mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_entropy, 0 );
371 // Check result of both NV file and entropy received with the manual calculations
372 TEST_ASSERT( memcmp( check_seed, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
373 TEST_ASSERT( memcmp( check_entropy, entropy, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
375 mbedtls_entropy_free( &ctx );
379 /* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG:MBEDTLS_SELF_TEST */
380 void entropy_selftest( int result )
382 TEST_ASSERT( mbedtls_entropy_self_test( 1 ) == result );