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