1/* BEGIN_HEADER */ 2#include "mbedtls/entropy.h" 3#include "mbedtls/entropy_poll.h" 4#include "mbedtls/md.h" 5#include "string.h" 6 7/* 8 * Number of calls made to entropy_dummy_source() 9 */ 10static size_t entropy_dummy_calls; 11 12/* 13 * Dummy entropy source 14 * 15 * If data is NULL, write exactly the requested length. 16 * Otherwise, write the length indicated by data or error if negative 17 */ 18static int entropy_dummy_source( void *data, unsigned char *output, 19 size_t len, size_t *olen ) 20{ 21 entropy_dummy_calls++; 22 23 if( data == NULL ) 24 *olen = len; 25 else 26 { 27 int *d = (int *) data; 28 29 if( *d < 0 ) 30 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 31 else 32 *olen = *d; 33 } 34 35 memset( output, 0x2a, *olen ); 36 37 return( 0 ); 38} 39 40#if defined(MBEDTLS_ENTROPY_NV_SEED) 41/* 42 * Ability to clear entropy sources to allow testing with just predefined 43 * entropy sources. This function or tests depending on it might break if there 44 * are internal changes to how entropy sources are registered. 45 * 46 * To be called immediately after mbedtls_entropy_init(). 47 * 48 * Just resetting the counter. New sources will overwrite existing ones. 49 * This might break memory checks in the future if sources need 'free-ing' then 50 * as well. 51 */ 52void entropy_clear_sources( mbedtls_entropy_context *ctx ) 53{ 54 ctx->source_count = 0; 55} 56 57/* 58 * NV seed read/write functions that use a buffer instead of a file 59 */ 60static unsigned char buffer_seed[MBEDTLS_ENTROPY_BLOCK_SIZE]; 61 62int buffer_nv_seed_read( unsigned char *buf, size_t buf_len ) 63{ 64 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE ) 65 return( -1 ); 66 67 memcpy( buf, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ); 68 return( 0 ); 69} 70 71int buffer_nv_seed_write( unsigned char *buf, size_t buf_len ) 72{ 73 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE ) 74 return( -1 ); 75 76 memcpy( buffer_seed, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); 77 return( 0 ); 78} 79 80/* 81 * NV seed read/write helpers that fill the base seedfile 82 */ 83int write_nv_seed( unsigned char *buf, size_t buf_len ) 84{ 85 FILE *f; 86 87 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE ) 88 return( -1 ); 89 90 if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) 91 return( -1 ); 92 93 if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != 94 MBEDTLS_ENTROPY_BLOCK_SIZE ) 95 return( -1 ); 96 97 fclose( f ); 98 99 return( 0 ); 100} 101 102int read_nv_seed( unsigned char *buf, size_t buf_len ) 103{ 104 FILE *f; 105 106 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE ) 107 return( -1 ); 108 109 if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) 110 return( -1 ); 111 112 if( fread( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != 113 MBEDTLS_ENTROPY_BLOCK_SIZE ) 114 return( -1 ); 115 116 fclose( f ); 117 118 return( 0 ); 119} 120#endif /* MBEDTLS_ENTROPY_NV_SEED */ 121/* END_HEADER */ 122 123/* BEGIN_DEPENDENCIES 124 * depends_on:MBEDTLS_ENTROPY_C 125 * END_DEPENDENCIES 126 */ 127 128/* BEGIN_CASE */ 129void entropy_init_free( int reinit ) 130{ 131 mbedtls_entropy_context ctx; 132 133 /* Double free is not explicitly documented to work, but it is convenient 134 * to call mbedtls_entropy_free() unconditionally on an error path without 135 * checking whether it has already been called in the success path. */ 136 137 mbedtls_entropy_init( &ctx ); 138 mbedtls_entropy_free( &ctx ); 139 140 if( reinit ) 141 mbedtls_entropy_init( &ctx ); 142 mbedtls_entropy_free( &ctx ); 143 144 /* This test case always succeeds, functionally speaking. A plausible 145 * bug might trigger an invalid pointer dereference or a memory leak. */ 146 goto exit; 147} 148/* END_CASE */ 149 150/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */ 151void entropy_seed_file( char * path, int ret ) 152{ 153 mbedtls_entropy_context ctx; 154 155 mbedtls_entropy_init( &ctx ); 156 157 TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, path ) == ret ); 158 TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, path ) == ret ); 159 160exit: 161 mbedtls_entropy_free( &ctx ); 162} 163/* END_CASE */ 164 165/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */ 166void entropy_write_base_seed_file( int ret ) 167{ 168 mbedtls_entropy_context ctx; 169 170 mbedtls_entropy_init( &ctx ); 171 172 TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, MBEDTLS_PLATFORM_STD_NV_SEED_FILE ) == ret ); 173 TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, MBEDTLS_PLATFORM_STD_NV_SEED_FILE ) == ret ); 174 175exit: 176 mbedtls_entropy_free( &ctx ); 177} 178/* END_CASE */ 179 180/* BEGIN_CASE */ 181void entropy_too_many_sources( ) 182{ 183 mbedtls_entropy_context ctx; 184 size_t i; 185 186 mbedtls_entropy_init( &ctx ); 187 188 /* 189 * It's hard to tell precisely when the error will occur, 190 * since we don't know how many sources were automatically added. 191 */ 192 for( i = 0; i < MBEDTLS_ENTROPY_MAX_SOURCES; i++ ) 193 (void) mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 194 16, MBEDTLS_ENTROPY_SOURCE_WEAK ); 195 196 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 197 16, MBEDTLS_ENTROPY_SOURCE_WEAK ) 198 == MBEDTLS_ERR_ENTROPY_MAX_SOURCES ); 199 200exit: 201 mbedtls_entropy_free( &ctx ); 202} 203/* END_CASE */ 204 205/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */ 206void entropy_func_len( int len, int ret ) 207{ 208 mbedtls_entropy_context ctx; 209 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 }; 210 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 }; 211 size_t i, j; 212 213 mbedtls_entropy_init( &ctx ); 214 215 /* 216 * See comments in mbedtls_entropy_self_test() 217 */ 218 for( i = 0; i < 8; i++ ) 219 { 220 TEST_ASSERT( mbedtls_entropy_func( &ctx, buf, len ) == ret ); 221 for( j = 0; j < sizeof( buf ); j++ ) 222 acc[j] |= buf[j]; 223 } 224 225 if( ret == 0 ) 226 for( j = 0; j < (size_t) len; j++ ) 227 TEST_ASSERT( acc[j] != 0 ); 228 229 for( j = len; j < sizeof( buf ); j++ ) 230 TEST_ASSERT( acc[j] == 0 ); 231 232exit: 233 mbedtls_entropy_free( &ctx ); 234} 235/* END_CASE */ 236 237/* BEGIN_CASE */ 238void entropy_source_fail( char * path ) 239{ 240 mbedtls_entropy_context ctx; 241 int fail = -1; 242 unsigned char buf[16]; 243 244 mbedtls_entropy_init( &ctx ); 245 246 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, 247 &fail, 16, 248 MBEDTLS_ENTROPY_SOURCE_WEAK ) 249 == 0 ); 250 251 TEST_ASSERT( mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) 252 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 253 TEST_ASSERT( mbedtls_entropy_gather( &ctx ) 254 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 255#if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_NV_SEED) 256 TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, path ) 257 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 258 TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, path ) 259 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 260#else 261 ((void) path); 262#endif 263 264exit: 265 mbedtls_entropy_free( &ctx ); 266} 267/* END_CASE */ 268 269/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */ 270void entropy_threshold( int threshold, int chunk_size, int result ) 271{ 272 mbedtls_entropy_context ctx; 273 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; 274 int ret; 275 276 mbedtls_entropy_init( &ctx ); 277 278 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, 279 &chunk_size, threshold, 280 MBEDTLS_ENTROPY_SOURCE_WEAK ) == 0 ); 281 282 entropy_dummy_calls = 0; 283 ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ); 284 285 if( result >= 0 ) 286 { 287 TEST_ASSERT( ret == 0 ); 288#if defined(MBEDTLS_ENTROPY_NV_SEED) 289 // Two times as much calls due to the NV seed update 290 result *= 2; 291#endif 292 TEST_ASSERT( entropy_dummy_calls == (size_t) result ); 293 } 294 else 295 { 296 TEST_ASSERT( ret == result ); 297 } 298 299exit: 300 mbedtls_entropy_free( &ctx ); 301} 302/* END_CASE */ 303 304/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */ 305void nv_seed_file_create( ) 306{ 307 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 308 309 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 310 311 TEST_ASSERT( write_nv_seed( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 312} 313/* END_CASE */ 314 315/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO:MBEDTLS_PLATFORM_NV_SEED_ALT */ 316void entropy_nv_seed_std_io( ) 317{ 318 unsigned char io_seed[MBEDTLS_ENTROPY_BLOCK_SIZE]; 319 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE]; 320 321 memset( io_seed, 1, MBEDTLS_ENTROPY_BLOCK_SIZE ); 322 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 323 324 mbedtls_platform_set_nv_seed( mbedtls_platform_std_nv_seed_read, 325 mbedtls_platform_std_nv_seed_write ); 326 327 /* Check if platform NV read and write manipulate the same data */ 328 TEST_ASSERT( write_nv_seed( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 329 TEST_ASSERT( mbedtls_nv_seed_read( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 330 MBEDTLS_ENTROPY_BLOCK_SIZE ); 331 332 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 333 334 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 335 336 /* Check if platform NV write and raw read manipulate the same data */ 337 TEST_ASSERT( mbedtls_nv_seed_write( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 338 MBEDTLS_ENTROPY_BLOCK_SIZE ); 339 TEST_ASSERT( read_nv_seed( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 340 341 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 342} 343/* END_CASE */ 344 345/* BEGIN_CASE depends_on:MBEDTLS_MD_C:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PLATFORM_NV_SEED_ALT */ 346void entropy_nv_seed( data_t * read_seed ) 347{ 348#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 349 const mbedtls_md_info_t *md_info = 350 mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); 351#elif defined(MBEDTLS_ENTROPY_SHA256_ACCUMULATOR) 352 const mbedtls_md_info_t *md_info = 353 mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); 354#else 355#error "Unsupported entropy accumulator" 356#endif 357 mbedtls_md_context_t accumulator; 358 mbedtls_entropy_context ctx; 359 int (*original_mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = 360 mbedtls_nv_seed_read; 361 int (*original_mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = 362 mbedtls_nv_seed_write; 363 364 unsigned char header[2]; 365 unsigned char entropy[MBEDTLS_ENTROPY_BLOCK_SIZE]; 366 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 367 unsigned char empty[MBEDTLS_ENTROPY_BLOCK_SIZE]; 368 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE]; 369 unsigned char check_entropy[MBEDTLS_ENTROPY_BLOCK_SIZE]; 370 371 memset( entropy, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 372 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 373 memset( empty, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 374 memset( check_seed, 2, MBEDTLS_ENTROPY_BLOCK_SIZE ); 375 memset( check_entropy, 3, MBEDTLS_ENTROPY_BLOCK_SIZE ); 376 377 // Make sure we read/write NV seed from our buffers 378 mbedtls_platform_set_nv_seed( buffer_nv_seed_read, buffer_nv_seed_write ); 379 380 mbedtls_md_init( &accumulator ); 381 mbedtls_entropy_init( &ctx ); 382 entropy_clear_sources( &ctx ); 383 384 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, mbedtls_nv_seed_poll, NULL, 385 MBEDTLS_ENTROPY_BLOCK_SIZE, 386 MBEDTLS_ENTROPY_SOURCE_STRONG ) == 0 ); 387 388 // Set the initial NV seed to read 389 TEST_ASSERT( read_seed->len >= MBEDTLS_ENTROPY_BLOCK_SIZE ); 390 memcpy( buffer_seed, read_seed->x, MBEDTLS_ENTROPY_BLOCK_SIZE ); 391 392 // Do an entropy run 393 TEST_ASSERT( mbedtls_entropy_func( &ctx, entropy, sizeof( entropy ) ) == 0 ); 394 // Determine what should have happened with manual entropy internal logic 395 396 // Init accumulator 397 header[1] = MBEDTLS_ENTROPY_BLOCK_SIZE; 398 TEST_ASSERT( mbedtls_md_setup( &accumulator, md_info, 0 ) == 0 ); 399 400 // First run for updating write_seed 401 header[0] = 0; 402 TEST_ASSERT( mbedtls_md_starts( &accumulator ) == 0 ); 403 TEST_ASSERT( mbedtls_md_update( &accumulator, header, 2 ) == 0 ); 404 TEST_ASSERT( mbedtls_md_update( &accumulator, 405 read_seed->x, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 406 TEST_ASSERT( mbedtls_md_finish( &accumulator, buf ) == 0 ); 407 408 TEST_ASSERT( mbedtls_md_starts( &accumulator ) == 0 ); 409 TEST_ASSERT( mbedtls_md_update( &accumulator, 410 buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 411 412 TEST_ASSERT( mbedtls_md( md_info, buf, MBEDTLS_ENTROPY_BLOCK_SIZE, 413 check_seed ) == 0 ); 414 415 // Second run for actual entropy (triggers mbedtls_entropy_update_nv_seed) 416 header[0] = MBEDTLS_ENTROPY_SOURCE_MANUAL; 417 TEST_ASSERT( mbedtls_md_update( &accumulator, header, 2 ) == 0 ); 418 TEST_ASSERT( mbedtls_md_update( &accumulator, 419 empty, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 420 421 header[0] = 0; 422 TEST_ASSERT( mbedtls_md_update( &accumulator, header, 2 ) == 0 ); 423 TEST_ASSERT( mbedtls_md_update( &accumulator, 424 check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 425 TEST_ASSERT( mbedtls_md_finish( &accumulator, buf ) == 0 ); 426 427 TEST_ASSERT( mbedtls_md( md_info, buf, MBEDTLS_ENTROPY_BLOCK_SIZE, 428 check_entropy ) == 0 ); 429 430 // Check result of both NV file and entropy received with the manual calculations 431 TEST_ASSERT( memcmp( check_seed, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 432 TEST_ASSERT( memcmp( check_entropy, entropy, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 433 434exit: 435 mbedtls_md_free( &accumulator ); 436 mbedtls_entropy_free( &ctx ); 437 mbedtls_nv_seed_read = original_mbedtls_nv_seed_read; 438 mbedtls_nv_seed_write = original_mbedtls_nv_seed_write; 439} 440/* END_CASE */ 441 442/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG:MBEDTLS_SELF_TEST */ 443void entropy_selftest( int result ) 444{ 445 TEST_ASSERT( mbedtls_entropy_self_test( 1 ) == result ); 446} 447/* END_CASE */ 448