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 */ 166void entropy_too_many_sources( ) 167{ 168 mbedtls_entropy_context ctx; 169 size_t i; 170 171 mbedtls_entropy_init( &ctx ); 172 173 /* 174 * It's hard to tell precisely when the error will occur, 175 * since we don't know how many sources were automatically added. 176 */ 177 for( i = 0; i < MBEDTLS_ENTROPY_MAX_SOURCES; i++ ) 178 (void) mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 179 16, MBEDTLS_ENTROPY_SOURCE_WEAK ); 180 181 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 182 16, MBEDTLS_ENTROPY_SOURCE_WEAK ) 183 == MBEDTLS_ERR_ENTROPY_MAX_SOURCES ); 184 185exit: 186 mbedtls_entropy_free( &ctx ); 187} 188/* END_CASE */ 189 190/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */ 191void entropy_func_len( int len, int ret ) 192{ 193 mbedtls_entropy_context ctx; 194 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 }; 195 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 }; 196 size_t i, j; 197 198 mbedtls_entropy_init( &ctx ); 199 200 /* 201 * See comments in mbedtls_entropy_self_test() 202 */ 203 for( i = 0; i < 8; i++ ) 204 { 205 TEST_ASSERT( mbedtls_entropy_func( &ctx, buf, len ) == ret ); 206 for( j = 0; j < sizeof( buf ); j++ ) 207 acc[j] |= buf[j]; 208 } 209 210 if( ret == 0 ) 211 for( j = 0; j < (size_t) len; j++ ) 212 TEST_ASSERT( acc[j] != 0 ); 213 214 for( j = len; j < sizeof( buf ); j++ ) 215 TEST_ASSERT( acc[j] == 0 ); 216 217exit: 218 mbedtls_entropy_free( &ctx ); 219} 220/* END_CASE */ 221 222/* BEGIN_CASE */ 223void entropy_source_fail( char * path ) 224{ 225 mbedtls_entropy_context ctx; 226 int fail = -1; 227 unsigned char buf[16]; 228 229 mbedtls_entropy_init( &ctx ); 230 231 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, 232 &fail, 16, 233 MBEDTLS_ENTROPY_SOURCE_WEAK ) 234 == 0 ); 235 236 TEST_ASSERT( mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) 237 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 238 TEST_ASSERT( mbedtls_entropy_gather( &ctx ) 239 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 240#if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_NV_SEED) 241 TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, path ) 242 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 243 TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, path ) 244 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 245#else 246 ((void) path); 247#endif 248 249exit: 250 mbedtls_entropy_free( &ctx ); 251} 252/* END_CASE */ 253 254/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */ 255void entropy_threshold( int threshold, int chunk_size, int result ) 256{ 257 mbedtls_entropy_context ctx; 258 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; 259 int ret; 260 261 mbedtls_entropy_init( &ctx ); 262 263 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, 264 &chunk_size, threshold, 265 MBEDTLS_ENTROPY_SOURCE_WEAK ) == 0 ); 266 267 entropy_dummy_calls = 0; 268 ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ); 269 270 if( result >= 0 ) 271 { 272 TEST_ASSERT( ret == 0 ); 273#if defined(MBEDTLS_ENTROPY_NV_SEED) 274 // Two times as much calls due to the NV seed update 275 result *= 2; 276#endif 277 TEST_ASSERT( entropy_dummy_calls == (size_t) result ); 278 } 279 else 280 { 281 TEST_ASSERT( ret == result ); 282 } 283 284exit: 285 mbedtls_entropy_free( &ctx ); 286} 287/* END_CASE */ 288 289/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */ 290void nv_seed_file_create( ) 291{ 292 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 293 294 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 295 296 TEST_ASSERT( write_nv_seed( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 297} 298/* END_CASE */ 299 300/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO:MBEDTLS_PLATFORM_NV_SEED_ALT */ 301void entropy_nv_seed_std_io( ) 302{ 303 unsigned char io_seed[MBEDTLS_ENTROPY_BLOCK_SIZE]; 304 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE]; 305 306 memset( io_seed, 1, MBEDTLS_ENTROPY_BLOCK_SIZE ); 307 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 308 309 mbedtls_platform_set_nv_seed( mbedtls_platform_std_nv_seed_read, 310 mbedtls_platform_std_nv_seed_write ); 311 312 /* Check if platform NV read and write manipulate the same data */ 313 TEST_ASSERT( write_nv_seed( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 314 TEST_ASSERT( mbedtls_nv_seed_read( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 315 MBEDTLS_ENTROPY_BLOCK_SIZE ); 316 317 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 318 319 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 320 321 /* Check if platform NV write and raw read manipulate the same data */ 322 TEST_ASSERT( mbedtls_nv_seed_write( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 323 MBEDTLS_ENTROPY_BLOCK_SIZE ); 324 TEST_ASSERT( read_nv_seed( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 325 326 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 327} 328/* END_CASE */ 329 330/* BEGIN_CASE depends_on:MBEDTLS_MD_C:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PLATFORM_NV_SEED_ALT */ 331void entropy_nv_seed( data_t * read_seed ) 332{ 333#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 334 const mbedtls_md_info_t *md_info = 335 mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); 336#elif defined(MBEDTLS_ENTROPY_SHA256_ACCUMULATOR) 337 const mbedtls_md_info_t *md_info = 338 mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); 339#else 340#error "Unsupported entropy accumulator" 341#endif 342 mbedtls_md_context_t accumulator; 343 mbedtls_entropy_context ctx; 344 int (*original_mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = 345 mbedtls_nv_seed_read; 346 int (*original_mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = 347 mbedtls_nv_seed_write; 348 349 unsigned char header[2]; 350 unsigned char entropy[MBEDTLS_ENTROPY_BLOCK_SIZE]; 351 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 352 unsigned char empty[MBEDTLS_ENTROPY_BLOCK_SIZE]; 353 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE]; 354 unsigned char check_entropy[MBEDTLS_ENTROPY_BLOCK_SIZE]; 355 356 memset( entropy, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 357 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 358 memset( empty, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 359 memset( check_seed, 2, MBEDTLS_ENTROPY_BLOCK_SIZE ); 360 memset( check_entropy, 3, MBEDTLS_ENTROPY_BLOCK_SIZE ); 361 362 // Make sure we read/write NV seed from our buffers 363 mbedtls_platform_set_nv_seed( buffer_nv_seed_read, buffer_nv_seed_write ); 364 365 mbedtls_md_init( &accumulator ); 366 mbedtls_entropy_init( &ctx ); 367 entropy_clear_sources( &ctx ); 368 369 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, mbedtls_nv_seed_poll, NULL, 370 MBEDTLS_ENTROPY_BLOCK_SIZE, 371 MBEDTLS_ENTROPY_SOURCE_STRONG ) == 0 ); 372 373 // Set the initial NV seed to read 374 TEST_ASSERT( read_seed->len >= MBEDTLS_ENTROPY_BLOCK_SIZE ); 375 memcpy( buffer_seed, read_seed->x, MBEDTLS_ENTROPY_BLOCK_SIZE ); 376 377 // Do an entropy run 378 TEST_ASSERT( mbedtls_entropy_func( &ctx, entropy, sizeof( entropy ) ) == 0 ); 379 // Determine what should have happened with manual entropy internal logic 380 381 // Init accumulator 382 header[1] = MBEDTLS_ENTROPY_BLOCK_SIZE; 383 TEST_ASSERT( mbedtls_md_setup( &accumulator, md_info, 0 ) == 0 ); 384 385 // First run for updating write_seed 386 header[0] = 0; 387 TEST_ASSERT( mbedtls_md_starts( &accumulator ) == 0 ); 388 TEST_ASSERT( mbedtls_md_update( &accumulator, header, 2 ) == 0 ); 389 TEST_ASSERT( mbedtls_md_update( &accumulator, 390 read_seed->x, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 391 TEST_ASSERT( mbedtls_md_finish( &accumulator, buf ) == 0 ); 392 393 TEST_ASSERT( mbedtls_md_starts( &accumulator ) == 0 ); 394 TEST_ASSERT( mbedtls_md_update( &accumulator, 395 buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 396 397 TEST_ASSERT( mbedtls_md( md_info, buf, MBEDTLS_ENTROPY_BLOCK_SIZE, 398 check_seed ) == 0 ); 399 400 // Second run for actual entropy (triggers mbedtls_entropy_update_nv_seed) 401 header[0] = MBEDTLS_ENTROPY_SOURCE_MANUAL; 402 TEST_ASSERT( mbedtls_md_update( &accumulator, header, 2 ) == 0 ); 403 TEST_ASSERT( mbedtls_md_update( &accumulator, 404 empty, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 405 406 header[0] = 0; 407 TEST_ASSERT( mbedtls_md_update( &accumulator, header, 2 ) == 0 ); 408 TEST_ASSERT( mbedtls_md_update( &accumulator, 409 check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 410 TEST_ASSERT( mbedtls_md_finish( &accumulator, buf ) == 0 ); 411 412 TEST_ASSERT( mbedtls_md( md_info, buf, MBEDTLS_ENTROPY_BLOCK_SIZE, 413 check_entropy ) == 0 ); 414 415 // Check result of both NV file and entropy received with the manual calculations 416 TEST_ASSERT( memcmp( check_seed, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 417 TEST_ASSERT( memcmp( check_entropy, entropy, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 418 419exit: 420 mbedtls_md_free( &accumulator ); 421 mbedtls_entropy_free( &ctx ); 422 mbedtls_nv_seed_read = original_mbedtls_nv_seed_read; 423 mbedtls_nv_seed_write = original_mbedtls_nv_seed_write; 424} 425/* END_CASE */ 426 427/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG:MBEDTLS_SELF_TEST */ 428void entropy_selftest( int result ) 429{ 430 TEST_ASSERT( mbedtls_entropy_self_test( 1 ) == result ); 431} 432/* END_CASE */ 433