1/* BEGIN_HEADER */ 2#include "mbedtls/entropy.h" 3#include "mbedtls/entropy_poll.h" 4#include "string.h" 5 6/* 7 * Number of calls made to entropy_dummy_source() 8 */ 9static size_t entropy_dummy_calls; 10 11/* 12 * Dummy entropy source 13 * 14 * If data is NULL, write exactly the requested length. 15 * Otherwise, write the length indicated by data or error if negative 16 */ 17static int entropy_dummy_source( void *data, unsigned char *output, 18 size_t len, size_t *olen ) 19{ 20 entropy_dummy_calls++; 21 22 if( data == NULL ) 23 *olen = len; 24 else 25 { 26 int *d = (int *) data; 27 28 if( *d < 0 ) 29 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 30 else 31 *olen = *d; 32 } 33 34 memset( output, 0x2a, *olen ); 35 36 return( 0 ); 37} 38 39#if defined(MBEDTLS_ENTROPY_NV_SEED) 40/* 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. 44 * 45 * To be called immediately after mbedtls_entropy_init(). 46 * 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 49 * as well. 50 */ 51static void entropy_clear_sources( mbedtls_entropy_context *ctx ) 52{ 53 ctx->source_count = 0; 54} 55 56/* 57 * NV seed read/write functions that use a buffer instead of a file 58 */ 59static unsigned char buffer_seed[MBEDTLS_ENTROPY_BLOCK_SIZE]; 60 61static int buffer_nv_seed_read( unsigned char *buf, size_t buf_len ) 62{ 63 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE ) 64 return( -1 ); 65 66 memcpy( buf, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ); 67 return( 0 ); 68} 69 70static int buffer_nv_seed_write( unsigned char *buf, size_t buf_len ) 71{ 72 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE ) 73 return( -1 ); 74 75 memcpy( buffer_seed, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); 76 return( 0 ); 77} 78 79/* 80 * NV seed read/write helpers that fill the base seedfile 81 */ 82static int write_nv_seed( unsigned char *buf, size_t buf_len ) 83{ 84 FILE *f; 85 86 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE ) 87 return( -1 ); 88 89 if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) 90 return( -1 ); 91 92 if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != 93 MBEDTLS_ENTROPY_BLOCK_SIZE ) 94 return( -1 ); 95 96 fclose( f ); 97 98 return( 0 ); 99} 100 101static int read_nv_seed( unsigned char *buf, size_t buf_len ) 102{ 103 FILE *f; 104 105 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE ) 106 return( -1 ); 107 108 if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) 109 return( -1 ); 110 111 if( fread( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != 112 MBEDTLS_ENTROPY_BLOCK_SIZE ) 113 return( -1 ); 114 115 fclose( f ); 116 117 return( 0 ); 118} 119#endif /* MBEDTLS_ENTROPY_NV_SEED */ 120/* END_HEADER */ 121 122/* BEGIN_DEPENDENCIES 123 * depends_on:MBEDTLS_ENTROPY_C 124 * END_DEPENDENCIES 125 */ 126 127/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */ 128void entropy_seed_file( char * path, int ret ) 129{ 130 mbedtls_entropy_context ctx; 131 132 mbedtls_entropy_init( &ctx ); 133 134 TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, path ) == ret ); 135 TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, path ) == ret ); 136 137exit: 138 mbedtls_entropy_free( &ctx ); 139} 140/* END_CASE */ 141 142/* BEGIN_CASE */ 143void entropy_too_many_sources( ) 144{ 145 mbedtls_entropy_context ctx; 146 size_t i; 147 148 mbedtls_entropy_init( &ctx ); 149 150 /* 151 * It's hard to tell precisely when the error will occur, 152 * since we don't know how many sources were automatically added. 153 */ 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 ); 157 158 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 159 16, MBEDTLS_ENTROPY_SOURCE_WEAK ) 160 == MBEDTLS_ERR_ENTROPY_MAX_SOURCES ); 161 162exit: 163 mbedtls_entropy_free( &ctx ); 164} 165/* END_CASE */ 166 167/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */ 168void entropy_func_len( int len, int ret ) 169{ 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 }; 173 size_t i, j; 174 175 mbedtls_entropy_init( &ctx ); 176 177 /* 178 * See comments in mbedtls_entropy_self_test() 179 */ 180 for( i = 0; i < 8; i++ ) 181 { 182 TEST_ASSERT( mbedtls_entropy_func( &ctx, buf, len ) == ret ); 183 for( j = 0; j < sizeof( buf ); j++ ) 184 acc[j] |= buf[j]; 185 } 186 187 if( ret == 0 ) 188 for( j = 0; j < (size_t) len; j++ ) 189 TEST_ASSERT( acc[j] != 0 ); 190 191 for( j = len; j < sizeof( buf ); j++ ) 192 TEST_ASSERT( acc[j] == 0 ); 193} 194/* END_CASE */ 195 196/* BEGIN_CASE */ 197void entropy_source_fail( char * path ) 198{ 199 mbedtls_entropy_context ctx; 200 int fail = -1; 201 unsigned char buf[16]; 202 203 mbedtls_entropy_init( &ctx ); 204 205 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, 206 &fail, 16, 207 MBEDTLS_ENTROPY_SOURCE_WEAK ) 208 == 0 ); 209 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 ); 219#else 220 ((void) path); 221#endif 222 223exit: 224 mbedtls_entropy_free( &ctx ); 225} 226/* END_CASE */ 227 228/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */ 229void entropy_threshold( int threshold, int chunk_size, int result ) 230{ 231 mbedtls_entropy_context ctx; 232 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; 233 int ret; 234 235 mbedtls_entropy_init( &ctx ); 236 237 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, 238 &chunk_size, threshold, 239 MBEDTLS_ENTROPY_SOURCE_WEAK ) == 0 ); 240 241 entropy_dummy_calls = 0; 242 ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ); 243 244 if( result >= 0 ) 245 { 246 TEST_ASSERT( ret == 0 ); 247#if defined(MBEDTLS_ENTROPY_NV_SEED) 248 // Two times as much calls due to the NV seed update 249 result *= 2; 250#endif 251 TEST_ASSERT( entropy_dummy_calls == (size_t) result ); 252 } 253 else 254 { 255 TEST_ASSERT( ret == result ); 256 } 257 258exit: 259 mbedtls_entropy_free( &ctx ); 260} 261/* END_CASE */ 262 263/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */ 264void nv_seed_file_create( ) 265{ 266 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 267 268 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 269 270 TEST_ASSERT( write_nv_seed( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 271} 272/* END_CASE */ 273 274/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO:MBEDTLS_PLATFORM_NV_SEED_ALT */ 275void entropy_nv_seed_std_io( ) 276{ 277 unsigned char io_seed[MBEDTLS_ENTROPY_BLOCK_SIZE]; 278 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE]; 279 280 memset( io_seed, 1, MBEDTLS_ENTROPY_BLOCK_SIZE ); 281 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 282 283 mbedtls_platform_set_nv_seed( mbedtls_platform_std_nv_seed_read, 284 mbedtls_platform_std_nv_seed_write ); 285 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 ); 290 291 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 292 293 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 294 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 ); 299 300 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 ); 301} 302/* END_CASE */ 303 304/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PLATFORM_NV_SEED_ALT:MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ 305void entropy_nv_seed( data_t * read_seed ) 306{ 307 mbedtls_sha512_context accumulator; 308 mbedtls_entropy_context ctx; 309 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]; 316 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 ); 323 324 // Set the initial NV seed to read 325 memcpy( buffer_seed, read_seed->x, read_seed->len ); 326 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 ); 329 330 mbedtls_entropy_init( &ctx ); 331 entropy_clear_sources( &ctx ); 332 333 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, mbedtls_nv_seed_poll, NULL, 334 MBEDTLS_ENTROPY_BLOCK_SIZE, 335 MBEDTLS_ENTROPY_SOURCE_STRONG ) == 0 ); 336 337 // Do an entropy run 338 TEST_ASSERT( mbedtls_entropy_func( &ctx, entropy, sizeof( entropy ) ) == 0 ); 339 340 // Determine what should have happened with manual entropy internal logic 341 // Only use the SHA-512 version to check 342 343 // Init accumulator 344 header[1] = MBEDTLS_ENTROPY_BLOCK_SIZE; 345 mbedtls_sha512_starts( &accumulator, 0 ); 346 347 // First run for updating write_seed 348 header[0] = 0; 349 mbedtls_sha512_update( &accumulator, header, 2 ); 350 mbedtls_sha512_update( &accumulator, read_seed->x, read_seed->len ); 351 mbedtls_sha512_finish( &accumulator, buf ); 352 353 memset( &accumulator, 0, sizeof( mbedtls_sha512_context ) ); 354 mbedtls_sha512_starts( &accumulator, 0 ); 355 mbedtls_sha512_update( &accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); 356 357 mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_seed, 0 ); 358 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 ); 363 364 header[0] = 0; 365 mbedtls_sha512_update( &accumulator, header, 2 ); 366 mbedtls_sha512_update( &accumulator, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ); 367 mbedtls_sha512_finish( &accumulator, buf ); 368 369 mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_entropy, 0 ); 370 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 ); 374 375 mbedtls_entropy_free( &ctx ); 376} 377/* END_CASE */ 378 379/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG:MBEDTLS_SELF_TEST */ 380void entropy_selftest( int result ) 381{ 382 TEST_ASSERT( mbedtls_entropy_self_test( 1 ) == result ); 383} 384/* END_CASE */ 385