Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbedtls by
entropy.c
00001 /* 00002 * Entropy accumulator implementation 00003 * 00004 * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 00022 #if !defined(MBEDTLS_CONFIG_FILE) 00023 #include "mbedtls/config.h" 00024 #else 00025 #include MBEDTLS_CONFIG_FILE 00026 #endif 00027 00028 #if defined(MBEDTLS_ENTROPY_C) 00029 00030 #if defined(MBEDTLS_TEST_NULL_ENTROPY) 00031 #warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " 00032 #warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " 00033 #warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " 00034 #endif 00035 00036 #include "mbedtls/entropy.h" 00037 #include "mbedtls/entropy_poll.h" 00038 00039 #include <string.h> 00040 00041 #if defined(MBEDTLS_FS_IO) 00042 #include <stdio.h> 00043 #endif 00044 00045 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00046 #include "mbedtls/platform.h" 00047 #endif 00048 00049 #if defined(MBEDTLS_SELF_TEST) 00050 #if defined(MBEDTLS_PLATFORM_C) 00051 #include "mbedtls/platform.h" 00052 #else 00053 #include <stdio.h> 00054 #define mbedtls_printf printf 00055 #endif /* MBEDTLS_PLATFORM_C */ 00056 #endif /* MBEDTLS_SELF_TEST */ 00057 00058 #if defined(MBEDTLS_HAVEGE_C) 00059 #include "mbedtls/havege.h" 00060 #endif 00061 00062 /* Implementation that should never be optimized out by the compiler */ 00063 static void mbedtls_zeroize( void *v, size_t n ) { 00064 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 00065 } 00066 00067 #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ 00068 00069 void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) 00070 { 00071 memset( ctx, 0, sizeof(mbedtls_entropy_context) ); 00072 00073 #if defined(MBEDTLS_THREADING_C) 00074 mbedtls_mutex_init( &ctx->mutex ); 00075 #endif 00076 00077 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00078 mbedtls_sha512_starts( &ctx->accumulator, 0 ); 00079 #else 00080 mbedtls_sha256_starts( &ctx->accumulator, 0 ); 00081 #endif 00082 #if defined(MBEDTLS_HAVEGE_C) 00083 mbedtls_havege_init( &ctx->havege_data ); 00084 #endif 00085 00086 #if defined(MBEDTLS_TEST_NULL_ENTROPY) 00087 mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, 00088 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); 00089 #endif 00090 00091 #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) 00092 #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) 00093 mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, 00094 MBEDTLS_ENTROPY_MIN_PLATFORM, 00095 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00096 #endif 00097 #if defined(MBEDTLS_TIMING_C) 00098 mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, 00099 MBEDTLS_ENTROPY_MIN_HARDCLOCK, 00100 MBEDTLS_ENTROPY_SOURCE_WEAK ); 00101 #endif 00102 #if defined(MBEDTLS_HAVEGE_C) 00103 mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, 00104 MBEDTLS_ENTROPY_MIN_HAVEGE, 00105 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00106 #endif 00107 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) 00108 mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, 00109 MBEDTLS_ENTROPY_MIN_HARDWARE, 00110 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00111 #endif 00112 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00113 mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, 00114 MBEDTLS_ENTROPY_BLOCK_SIZE, 00115 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00116 #endif 00117 #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ 00118 } 00119 00120 void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) 00121 { 00122 #if defined(MBEDTLS_HAVEGE_C) 00123 mbedtls_havege_free( &ctx->havege_data ); 00124 #endif 00125 #if defined(MBEDTLS_THREADING_C) 00126 mbedtls_mutex_free( &ctx->mutex ); 00127 #endif 00128 mbedtls_zeroize( ctx, sizeof( mbedtls_entropy_context ) ); 00129 } 00130 00131 int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, 00132 mbedtls_entropy_f_source_ptr f_source, void *p_source, 00133 size_t threshold, int strong ) 00134 { 00135 int idx, ret = 0; 00136 00137 #if defined(MBEDTLS_THREADING_C) 00138 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00139 return( ret ); 00140 #endif 00141 00142 idx = ctx->source_count; 00143 if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) 00144 { 00145 ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; 00146 goto exit; 00147 } 00148 00149 ctx->source[idx].f_source = f_source; 00150 ctx->source[idx].p_source = p_source; 00151 ctx->source[idx].threshold = threshold; 00152 ctx->source[idx].strong = strong; 00153 00154 ctx->source_count++; 00155 00156 exit: 00157 #if defined(MBEDTLS_THREADING_C) 00158 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00159 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00160 #endif 00161 00162 return( ret ); 00163 } 00164 00165 /* 00166 * Entropy accumulator update 00167 */ 00168 static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, 00169 const unsigned char *data, size_t len ) 00170 { 00171 unsigned char header[2]; 00172 unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; 00173 size_t use_len = len; 00174 const unsigned char *p = data; 00175 00176 if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) 00177 { 00178 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00179 mbedtls_sha512( data, len, tmp, 0 ); 00180 #else 00181 mbedtls_sha256( data, len, tmp, 0 ); 00182 #endif 00183 p = tmp; 00184 use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; 00185 } 00186 00187 header[0] = source_id; 00188 header[1] = use_len & 0xFF; 00189 00190 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00191 mbedtls_sha512_update( &ctx->accumulator, header, 2 ); 00192 mbedtls_sha512_update( &ctx->accumulator, p, use_len ); 00193 #else 00194 mbedtls_sha256_update( &ctx->accumulator, header, 2 ); 00195 mbedtls_sha256_update( &ctx->accumulator, p, use_len ); 00196 #endif 00197 00198 return( 0 ); 00199 } 00200 00201 int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, 00202 const unsigned char *data, size_t len ) 00203 { 00204 int ret; 00205 00206 #if defined(MBEDTLS_THREADING_C) 00207 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00208 return( ret ); 00209 #endif 00210 00211 ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); 00212 00213 #if defined(MBEDTLS_THREADING_C) 00214 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00215 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00216 #endif 00217 00218 return( ret ); 00219 } 00220 00221 /* 00222 * Run through the different sources to add entropy to our accumulator 00223 */ 00224 static int entropy_gather_internal( mbedtls_entropy_context *ctx ) 00225 { 00226 int ret, i, have_one_strong = 0; 00227 unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; 00228 size_t olen; 00229 00230 if( ctx->source_count == 0 ) 00231 return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); 00232 00233 /* 00234 * Run through our entropy sources 00235 */ 00236 for( i = 0; i < ctx->source_count; i++ ) 00237 { 00238 if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) 00239 have_one_strong = 1; 00240 00241 olen = 0; 00242 if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, 00243 buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) 00244 { 00245 return( ret ); 00246 } 00247 00248 /* 00249 * Add if we actually gathered something 00250 */ 00251 if( olen > 0 ) 00252 { 00253 entropy_update( ctx, (unsigned char) i, buf, olen ); 00254 ctx->source[i].size += olen; 00255 } 00256 } 00257 00258 if( have_one_strong == 0 ) 00259 return( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE ); 00260 00261 return( 0 ); 00262 } 00263 00264 /* 00265 * Thread-safe wrapper for entropy_gather_internal() 00266 */ 00267 int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) 00268 { 00269 int ret; 00270 00271 #if defined(MBEDTLS_THREADING_C) 00272 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00273 return( ret ); 00274 #endif 00275 00276 ret = entropy_gather_internal( ctx ); 00277 00278 #if defined(MBEDTLS_THREADING_C) 00279 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00280 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00281 #endif 00282 00283 return( ret ); 00284 } 00285 00286 int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) 00287 { 00288 int ret, count = 0, i, done; 00289 mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; 00290 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 00291 00292 if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) 00293 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 00294 00295 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00296 /* Update the NV entropy seed before generating any entropy for outside 00297 * use. 00298 */ 00299 if( ctx->initial_entropy_run == 0 ) 00300 { 00301 ctx->initial_entropy_run = 1; 00302 if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) 00303 return( ret ); 00304 } 00305 #endif 00306 00307 #if defined(MBEDTLS_THREADING_C) 00308 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00309 return( ret ); 00310 #endif 00311 00312 /* 00313 * Always gather extra entropy before a call 00314 */ 00315 do 00316 { 00317 if( count++ > ENTROPY_MAX_LOOP ) 00318 { 00319 ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; 00320 goto exit; 00321 } 00322 00323 if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) 00324 goto exit; 00325 00326 done = 1; 00327 for( i = 0; i < ctx->source_count; i++ ) 00328 if( ctx->source[i].size < ctx->source[i].threshold ) 00329 done = 0; 00330 } 00331 while( ! done ); 00332 00333 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00334 00335 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00336 mbedtls_sha512_finish( &ctx->accumulator, buf ); 00337 00338 /* 00339 * Reset accumulator and counters and recycle existing entropy 00340 */ 00341 memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) ); 00342 mbedtls_sha512_starts( &ctx->accumulator, 0 ); 00343 mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00344 00345 /* 00346 * Perform second SHA-512 on entropy 00347 */ 00348 mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); 00349 #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ 00350 mbedtls_sha256_finish( &ctx->accumulator, buf ); 00351 00352 /* 00353 * Reset accumulator and counters and recycle existing entropy 00354 */ 00355 memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) ); 00356 mbedtls_sha256_starts( &ctx->accumulator, 0 ); 00357 mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00358 00359 /* 00360 * Perform second SHA-256 on entropy 00361 */ 00362 mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); 00363 #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ 00364 00365 for( i = 0; i < ctx->source_count; i++ ) 00366 ctx->source[i].size = 0; 00367 00368 memcpy( output, buf, len ); 00369 00370 ret = 0; 00371 00372 exit: 00373 #if defined(MBEDTLS_THREADING_C) 00374 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00375 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00376 #endif 00377 00378 return( ret ); 00379 } 00380 00381 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00382 int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) 00383 { 00384 int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 00385 unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; 00386 00387 /* Read new seed and write it to NV */ 00388 if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) 00389 return( ret ); 00390 00391 if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) 00392 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); 00393 00394 /* Manually update the remaining stream with a separator value to diverge */ 00395 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00396 mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00397 00398 return( 0 ); 00399 } 00400 #endif /* MBEDTLS_ENTROPY_NV_SEED */ 00401 00402 #if defined(MBEDTLS_FS_IO) 00403 int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) 00404 { 00405 int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 00406 FILE *f; 00407 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 00408 00409 if( ( f = fopen( path, "wb" ) ) == NULL ) 00410 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); 00411 00412 if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) 00413 goto exit; 00414 00415 if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) 00416 { 00417 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 00418 goto exit; 00419 } 00420 00421 ret = 0; 00422 00423 exit: 00424 fclose( f ); 00425 return( ret ); 00426 } 00427 00428 int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) 00429 { 00430 FILE *f; 00431 size_t n; 00432 unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; 00433 00434 if( ( f = fopen( path, "rb" ) ) == NULL ) 00435 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); 00436 00437 fseek( f, 0, SEEK_END ); 00438 n = (size_t) ftell( f ); 00439 fseek( f, 0, SEEK_SET ); 00440 00441 if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) 00442 n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; 00443 00444 if( fread( buf, 1, n, f ) != n ) 00445 { 00446 fclose( f ); 00447 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); 00448 } 00449 00450 fclose( f ); 00451 00452 mbedtls_entropy_update_manual( ctx, buf, n ); 00453 00454 return( mbedtls_entropy_write_seed_file( ctx, path ) ); 00455 } 00456 #endif /* MBEDTLS_FS_IO */ 00457 00458 #if defined(MBEDTLS_SELF_TEST) 00459 #if !defined(MBEDTLS_TEST_NULL_ENTROPY) 00460 /* 00461 * Dummy source function 00462 */ 00463 static int entropy_dummy_source( void *data, unsigned char *output, 00464 size_t len, size_t *olen ) 00465 { 00466 ((void) data); 00467 00468 memset( output, 0x2a, len ); 00469 *olen = len; 00470 00471 return( 0 ); 00472 } 00473 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */ 00474 00475 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) 00476 00477 static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) 00478 { 00479 int ret = 0; 00480 size_t entropy_len = 0; 00481 size_t olen = 0; 00482 size_t attempts = buf_len; 00483 00484 while( attempts > 0 && entropy_len < buf_len ) 00485 { 00486 if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, 00487 buf_len - entropy_len, &olen ) ) != 0 ) 00488 return( ret ); 00489 00490 entropy_len += olen; 00491 attempts--; 00492 } 00493 00494 if( entropy_len < buf_len ) 00495 { 00496 ret = 1; 00497 } 00498 00499 return( ret ); 00500 } 00501 00502 00503 static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, 00504 size_t buf_len ) 00505 { 00506 unsigned char set= 0xFF; 00507 unsigned char unset = 0x00; 00508 size_t i; 00509 00510 for( i = 0; i < buf_len; i++ ) 00511 { 00512 set &= buf[i]; 00513 unset |= buf[i]; 00514 } 00515 00516 return( set == 0xFF || unset == 0x00 ); 00517 } 00518 00519 /* 00520 * A test to ensure hat the entropy sources are functioning correctly 00521 * and there is no obvious failure. The test performs the following checks: 00522 * - The entropy source is not providing only 0s (all bits unset) or 1s (all 00523 * bits set). 00524 * - The entropy source is not providing values in a pattern. Because the 00525 * hardware could be providing data in an arbitrary length, this check polls 00526 * the hardware entropy source twice and compares the result to ensure they 00527 * are not equal. 00528 * - The error code returned by the entropy source is not an error. 00529 */ 00530 int mbedtls_entropy_source_self_test( int verbose ) 00531 { 00532 int ret = 0; 00533 unsigned char buf0[2 * sizeof( unsigned long long int )]; 00534 unsigned char buf1[2 * sizeof( unsigned long long int )]; 00535 00536 if( verbose != 0 ) 00537 mbedtls_printf( " ENTROPY_BIAS test: " ); 00538 00539 memset( buf0, 0x00, sizeof( buf0 ) ); 00540 memset( buf1, 0x00, sizeof( buf1 ) ); 00541 00542 if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) 00543 goto cleanup; 00544 if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) 00545 goto cleanup; 00546 00547 /* Make sure that the returned values are not all 0 or 1 */ 00548 if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) 00549 goto cleanup; 00550 if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) 00551 goto cleanup; 00552 00553 /* Make sure that the entropy source is not returning values in a 00554 * pattern */ 00555 ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; 00556 00557 cleanup: 00558 if( verbose != 0 ) 00559 { 00560 if( ret != 0 ) 00561 mbedtls_printf( "failed\n" ); 00562 else 00563 mbedtls_printf( "passed\n" ); 00564 00565 mbedtls_printf( "\n" ); 00566 } 00567 00568 return( ret != 0 ); 00569 } 00570 00571 #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ 00572 00573 /* 00574 * The actual entropy quality is hard to test, but we can at least 00575 * test that the functions don't cause errors and write the correct 00576 * amount of data to buffers. 00577 */ 00578 int mbedtls_entropy_self_test( int verbose ) 00579 { 00580 int ret = 1; 00581 #if !defined(MBEDTLS_TEST_NULL_ENTROPY) 00582 mbedtls_entropy_context ctx; 00583 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; 00584 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; 00585 size_t i, j; 00586 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */ 00587 00588 if( verbose != 0 ) 00589 mbedtls_printf( " ENTROPY test: " ); 00590 00591 #if !defined(MBEDTLS_TEST_NULL_ENTROPY) 00592 mbedtls_entropy_init( &ctx ); 00593 00594 /* First do a gather to make sure we have default sources */ 00595 if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) 00596 goto cleanup; 00597 00598 ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, 00599 MBEDTLS_ENTROPY_SOURCE_WEAK ); 00600 if( ret != 0 ) 00601 goto cleanup; 00602 00603 if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) 00604 goto cleanup; 00605 00606 /* 00607 * To test that mbedtls_entropy_func writes correct number of bytes: 00608 * - use the whole buffer and rely on ASan to detect overruns 00609 * - collect entropy 8 times and OR the result in an accumulator: 00610 * any byte should then be 0 with probably 2^(-64), so requiring 00611 * each of the 32 or 64 bytes to be non-zero has a false failure rate 00612 * of at most 2^(-58) which is acceptable. 00613 */ 00614 for( i = 0; i < 8; i++ ) 00615 { 00616 if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) 00617 goto cleanup; 00618 00619 for( j = 0; j < sizeof( buf ); j++ ) 00620 acc[j] |= buf[j]; 00621 } 00622 00623 for( j = 0; j < sizeof( buf ); j++ ) 00624 { 00625 if( acc[j] == 0 ) 00626 { 00627 ret = 1; 00628 goto cleanup; 00629 } 00630 } 00631 00632 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) 00633 if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) 00634 goto cleanup; 00635 #endif 00636 00637 cleanup: 00638 mbedtls_entropy_free( &ctx ); 00639 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */ 00640 00641 if( verbose != 0 ) 00642 { 00643 if( ret != 0 ) 00644 mbedtls_printf( "failed\n" ); 00645 else 00646 mbedtls_printf( "passed\n" ); 00647 00648 mbedtls_printf( "\n" ); 00649 } 00650 00651 return( ret != 0 ); 00652 } 00653 #endif /* MBEDTLS_SELF_TEST */ 00654 00655 #endif /* MBEDTLS_ENTROPY_C */
Generated on Tue Jul 12 2022 17:25:41 by
