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.
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 #include "mbedtls/platform_util.h" 00039 00040 #include <string.h> 00041 00042 #if defined(MBEDTLS_FS_IO) 00043 #include <stdio.h> 00044 #endif 00045 00046 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00047 #include "mbedtls/platform.h" 00048 #endif 00049 00050 #if defined(MBEDTLS_SELF_TEST) 00051 #if defined(MBEDTLS_PLATFORM_C) 00052 #include "mbedtls/platform.h" 00053 #else 00054 #include <stdio.h> 00055 #define mbedtls_printf printf 00056 #endif /* MBEDTLS_PLATFORM_C */ 00057 #endif /* MBEDTLS_SELF_TEST */ 00058 00059 #if defined(MBEDTLS_HAVEGE_C) 00060 #include "mbedtls/havege.h" 00061 #endif 00062 00063 #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ 00064 00065 void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) 00066 { 00067 ctx->source_count = 0; 00068 memset( ctx->source, 0, sizeof( ctx->source ) ); 00069 00070 #if defined(MBEDTLS_THREADING_C) 00071 mbedtls_mutex_init( &ctx->mutex ); 00072 #endif 00073 00074 ctx->accumulator_started = 0; 00075 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00076 mbedtls_sha512_init( &ctx->accumulator ); 00077 #else 00078 mbedtls_sha256_init( &ctx->accumulator ); 00079 #endif 00080 #if defined(MBEDTLS_HAVEGE_C) 00081 mbedtls_havege_init( &ctx->havege_data ); 00082 #endif 00083 00084 /* Reminder: Update ENTROPY_HAVE_STRONG in the test files 00085 * when adding more strong entropy sources here. */ 00086 00087 #if defined(MBEDTLS_TEST_NULL_ENTROPY) 00088 mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, 00089 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); 00090 #endif 00091 00092 #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) 00093 #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) 00094 mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, 00095 MBEDTLS_ENTROPY_MIN_PLATFORM, 00096 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00097 #endif 00098 #if defined(MBEDTLS_TIMING_C) 00099 mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, 00100 MBEDTLS_ENTROPY_MIN_HARDCLOCK, 00101 MBEDTLS_ENTROPY_SOURCE_WEAK ); 00102 #endif 00103 #if defined(MBEDTLS_HAVEGE_C) 00104 mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, 00105 MBEDTLS_ENTROPY_MIN_HAVEGE, 00106 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00107 #endif 00108 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) 00109 mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, 00110 MBEDTLS_ENTROPY_MIN_HARDWARE, 00111 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00112 #endif 00113 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00114 mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, 00115 MBEDTLS_ENTROPY_BLOCK_SIZE, 00116 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00117 ctx->initial_entropy_run = 0; 00118 #endif 00119 #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ 00120 } 00121 00122 void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) 00123 { 00124 #if defined(MBEDTLS_HAVEGE_C) 00125 mbedtls_havege_free( &ctx->havege_data ); 00126 #endif 00127 #if defined(MBEDTLS_THREADING_C) 00128 mbedtls_mutex_free( &ctx->mutex ); 00129 #endif 00130 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00131 mbedtls_sha512_free( &ctx->accumulator ); 00132 #else 00133 mbedtls_sha256_free( &ctx->accumulator ); 00134 #endif 00135 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00136 ctx->initial_entropy_run = 0; 00137 #endif 00138 ctx->source_count = 0; 00139 mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) ); 00140 ctx->accumulator_started = 0; 00141 } 00142 00143 int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, 00144 mbedtls_entropy_f_source_ptr f_source, void *p_source, 00145 size_t threshold, int strong ) 00146 { 00147 int idx, ret = 0; 00148 00149 #if defined(MBEDTLS_THREADING_C) 00150 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00151 return( ret ); 00152 #endif 00153 00154 idx = ctx->source_count; 00155 if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) 00156 { 00157 ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; 00158 goto exit; 00159 } 00160 00161 ctx->source[idx].f_source = f_source; 00162 ctx->source[idx].p_source = p_source; 00163 ctx->source[idx].threshold = threshold; 00164 ctx->source[idx].strong = strong; 00165 00166 ctx->source_count++; 00167 00168 exit: 00169 #if defined(MBEDTLS_THREADING_C) 00170 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00171 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00172 #endif 00173 00174 return( ret ); 00175 } 00176 00177 /* 00178 * Entropy accumulator update 00179 */ 00180 static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, 00181 const unsigned char *data, size_t len ) 00182 { 00183 unsigned char header[2]; 00184 unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; 00185 size_t use_len = len; 00186 const unsigned char *p = data; 00187 int ret = 0; 00188 00189 if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) 00190 { 00191 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00192 if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 ) 00193 goto cleanup; 00194 #else 00195 if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 ) 00196 goto cleanup; 00197 #endif 00198 p = tmp; 00199 use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; 00200 } 00201 00202 header[0] = source_id; 00203 header[1] = use_len & 0xFF; 00204 00205 /* 00206 * Start the accumulator if this has not already happened. Note that 00207 * it is sufficient to start the accumulator here only because all calls to 00208 * gather entropy eventually execute this code. 00209 */ 00210 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00211 if( ctx->accumulator_started == 0 && 00212 ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) 00213 goto cleanup; 00214 else 00215 ctx->accumulator_started = 1; 00216 if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) 00217 goto cleanup; 00218 ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len ); 00219 #else 00220 if( ctx->accumulator_started == 0 && 00221 ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) 00222 goto cleanup; 00223 else 00224 ctx->accumulator_started = 1; 00225 if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) 00226 goto cleanup; 00227 ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len ); 00228 #endif 00229 00230 cleanup: 00231 mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 00232 00233 return( ret ); 00234 } 00235 00236 int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, 00237 const unsigned char *data, size_t len ) 00238 { 00239 int ret; 00240 00241 #if defined(MBEDTLS_THREADING_C) 00242 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00243 return( ret ); 00244 #endif 00245 00246 ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); 00247 00248 #if defined(MBEDTLS_THREADING_C) 00249 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00250 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00251 #endif 00252 00253 return( ret ); 00254 } 00255 00256 /* 00257 * Run through the different sources to add entropy to our accumulator 00258 */ 00259 static int entropy_gather_internal( mbedtls_entropy_context *ctx ) 00260 { 00261 int ret, i, have_one_strong = 0; 00262 unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; 00263 size_t olen; 00264 00265 if( ctx->source_count == 0 ) 00266 return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); 00267 00268 /* 00269 * Run through our entropy sources 00270 */ 00271 for( i = 0; i < ctx->source_count; i++ ) 00272 { 00273 if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) 00274 have_one_strong = 1; 00275 00276 olen = 0; 00277 if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, 00278 buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) 00279 { 00280 goto cleanup; 00281 } 00282 00283 /* 00284 * Add if we actually gathered something 00285 */ 00286 if( olen > 0 ) 00287 { 00288 if( ( ret = entropy_update( ctx, (unsigned char) i, 00289 buf, olen ) ) != 0 ) 00290 return( ret ); 00291 ctx->source[i].size += olen; 00292 } 00293 } 00294 00295 if( have_one_strong == 0 ) 00296 ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; 00297 00298 cleanup: 00299 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 00300 00301 return( ret ); 00302 } 00303 00304 /* 00305 * Thread-safe wrapper for entropy_gather_internal() 00306 */ 00307 int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) 00308 { 00309 int ret; 00310 00311 #if defined(MBEDTLS_THREADING_C) 00312 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00313 return( ret ); 00314 #endif 00315 00316 ret = entropy_gather_internal( ctx ); 00317 00318 #if defined(MBEDTLS_THREADING_C) 00319 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00320 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00321 #endif 00322 00323 return( ret ); 00324 } 00325 00326 int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) 00327 { 00328 int ret, count = 0, i, done; 00329 mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; 00330 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 00331 00332 if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) 00333 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 00334 00335 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00336 /* Update the NV entropy seed before generating any entropy for outside 00337 * use. 00338 */ 00339 if( ctx->initial_entropy_run == 0 ) 00340 { 00341 ctx->initial_entropy_run = 1; 00342 if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) 00343 return( ret ); 00344 } 00345 #endif 00346 00347 #if defined(MBEDTLS_THREADING_C) 00348 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00349 return( ret ); 00350 #endif 00351 00352 /* 00353 * Always gather extra entropy before a call 00354 */ 00355 do 00356 { 00357 if( count++ > ENTROPY_MAX_LOOP ) 00358 { 00359 ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; 00360 goto exit; 00361 } 00362 00363 if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) 00364 goto exit; 00365 00366 done = 1; 00367 for( i = 0; i < ctx->source_count; i++ ) 00368 if( ctx->source[i].size < ctx->source[i].threshold ) 00369 done = 0; 00370 } 00371 while( ! done ); 00372 00373 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00374 00375 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00376 /* 00377 * Note that at this stage it is assumed that the accumulator was started 00378 * in a previous call to entropy_update(). If this is not guaranteed, the 00379 * code below will fail. 00380 */ 00381 if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 ) 00382 goto exit; 00383 00384 /* 00385 * Reset accumulator and counters and recycle existing entropy 00386 */ 00387 mbedtls_sha512_free( &ctx->accumulator ); 00388 mbedtls_sha512_init( &ctx->accumulator ); 00389 if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) 00390 goto exit; 00391 if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf, 00392 MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) 00393 goto exit; 00394 00395 /* 00396 * Perform second SHA-512 on entropy 00397 */ 00398 if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, 00399 buf, 0 ) ) != 0 ) 00400 goto exit; 00401 #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ 00402 if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 ) 00403 goto exit; 00404 00405 /* 00406 * Reset accumulator and counters and recycle existing entropy 00407 */ 00408 mbedtls_sha256_free( &ctx->accumulator ); 00409 mbedtls_sha256_init( &ctx->accumulator ); 00410 if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) 00411 goto exit; 00412 if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf, 00413 MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) 00414 goto exit; 00415 00416 /* 00417 * Perform second SHA-256 on entropy 00418 */ 00419 if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, 00420 buf, 0 ) ) != 0 ) 00421 goto exit; 00422 #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ 00423 00424 for( i = 0; i < ctx->source_count; i++ ) 00425 ctx->source[i].size = 0; 00426 00427 memcpy( output, buf, len ); 00428 00429 ret = 0; 00430 00431 exit: 00432 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 00433 00434 #if defined(MBEDTLS_THREADING_C) 00435 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00436 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00437 #endif 00438 00439 return( ret ); 00440 } 00441 00442 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00443 int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) 00444 { 00445 int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 00446 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 00447 00448 /* Read new seed and write it to NV */ 00449 if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) 00450 return( ret ); 00451 00452 if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) 00453 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); 00454 00455 /* Manually update the remaining stream with a separator value to diverge */ 00456 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00457 ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00458 00459 return( ret ); 00460 } 00461 #endif /* MBEDTLS_ENTROPY_NV_SEED */ 00462 00463 #if defined(MBEDTLS_FS_IO) 00464 int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) 00465 { 00466 int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 00467 FILE *f; 00468 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 00469 00470 if( ( f = fopen( path, "wb" ) ) == NULL ) 00471 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); 00472 00473 if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) 00474 goto exit; 00475 00476 if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) 00477 { 00478 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 00479 goto exit; 00480 } 00481 00482 ret = 0; 00483 00484 exit: 00485 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 00486 00487 fclose( f ); 00488 return( ret ); 00489 } 00490 00491 int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) 00492 { 00493 int ret = 0; 00494 FILE *f; 00495 size_t n; 00496 unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; 00497 00498 if( ( f = fopen( path, "rb" ) ) == NULL ) 00499 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); 00500 00501 fseek( f, 0, SEEK_END ); 00502 n = (size_t) ftell( f ); 00503 fseek( f, 0, SEEK_SET ); 00504 00505 if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) 00506 n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; 00507 00508 if( fread( buf, 1, n, f ) != n ) 00509 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 00510 else 00511 ret = mbedtls_entropy_update_manual( ctx, buf, n ); 00512 00513 fclose( f ); 00514 00515 mbedtls_platform_zeroize( buf, sizeof( buf ) ); 00516 00517 if( ret != 0 ) 00518 return( ret ); 00519 00520 return( mbedtls_entropy_write_seed_file( ctx, path ) ); 00521 } 00522 #endif /* MBEDTLS_FS_IO */ 00523 00524 #if defined(MBEDTLS_SELF_TEST) 00525 #if !defined(MBEDTLS_TEST_NULL_ENTROPY) 00526 /* 00527 * Dummy source function 00528 */ 00529 static int entropy_dummy_source( void *data, unsigned char *output, 00530 size_t len, size_t *olen ) 00531 { 00532 ((void) data); 00533 00534 memset( output, 0x2a, len ); 00535 *olen = len; 00536 00537 return( 0 ); 00538 } 00539 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */ 00540 00541 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) 00542 00543 static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) 00544 { 00545 int ret = 0; 00546 size_t entropy_len = 0; 00547 size_t olen = 0; 00548 size_t attempts = buf_len; 00549 00550 while( attempts > 0 && entropy_len < buf_len ) 00551 { 00552 if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, 00553 buf_len - entropy_len, &olen ) ) != 0 ) 00554 return( ret ); 00555 00556 entropy_len += olen; 00557 attempts--; 00558 } 00559 00560 if( entropy_len < buf_len ) 00561 { 00562 ret = 1; 00563 } 00564 00565 return( ret ); 00566 } 00567 00568 00569 static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, 00570 size_t buf_len ) 00571 { 00572 unsigned char set= 0xFF; 00573 unsigned char unset = 0x00; 00574 size_t i; 00575 00576 for( i = 0; i < buf_len; i++ ) 00577 { 00578 set &= buf[i]; 00579 unset |= buf[i]; 00580 } 00581 00582 return( set == 0xFF || unset == 0x00 ); 00583 } 00584 00585 /* 00586 * A test to ensure hat the entropy sources are functioning correctly 00587 * and there is no obvious failure. The test performs the following checks: 00588 * - The entropy source is not providing only 0s (all bits unset) or 1s (all 00589 * bits set). 00590 * - The entropy source is not providing values in a pattern. Because the 00591 * hardware could be providing data in an arbitrary length, this check polls 00592 * the hardware entropy source twice and compares the result to ensure they 00593 * are not equal. 00594 * - The error code returned by the entropy source is not an error. 00595 */ 00596 int mbedtls_entropy_source_self_test( int verbose ) 00597 { 00598 int ret = 0; 00599 unsigned char buf0[2 * sizeof( unsigned long long int )]; 00600 unsigned char buf1[2 * sizeof( unsigned long long int )]; 00601 00602 if( verbose != 0 ) 00603 mbedtls_printf( " ENTROPY_BIAS test: " ); 00604 00605 memset( buf0, 0x00, sizeof( buf0 ) ); 00606 memset( buf1, 0x00, sizeof( buf1 ) ); 00607 00608 if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) 00609 goto cleanup; 00610 if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) 00611 goto cleanup; 00612 00613 /* Make sure that the returned values are not all 0 or 1 */ 00614 if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) 00615 goto cleanup; 00616 if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) 00617 goto cleanup; 00618 00619 /* Make sure that the entropy source is not returning values in a 00620 * pattern */ 00621 ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; 00622 00623 cleanup: 00624 if( verbose != 0 ) 00625 { 00626 if( ret != 0 ) 00627 mbedtls_printf( "failed\n" ); 00628 else 00629 mbedtls_printf( "passed\n" ); 00630 00631 mbedtls_printf( "\n" ); 00632 } 00633 00634 return( ret != 0 ); 00635 } 00636 00637 #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ 00638 00639 /* 00640 * The actual entropy quality is hard to test, but we can at least 00641 * test that the functions don't cause errors and write the correct 00642 * amount of data to buffers. 00643 */ 00644 int mbedtls_entropy_self_test( int verbose ) 00645 { 00646 int ret = 1; 00647 #if !defined(MBEDTLS_TEST_NULL_ENTROPY) 00648 mbedtls_entropy_context ctx; 00649 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; 00650 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; 00651 size_t i, j; 00652 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */ 00653 00654 if( verbose != 0 ) 00655 mbedtls_printf( " ENTROPY test: " ); 00656 00657 #if !defined(MBEDTLS_TEST_NULL_ENTROPY) 00658 mbedtls_entropy_init( &ctx ); 00659 00660 /* First do a gather to make sure we have default sources */ 00661 if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) 00662 goto cleanup; 00663 00664 ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, 00665 MBEDTLS_ENTROPY_SOURCE_WEAK ); 00666 if( ret != 0 ) 00667 goto cleanup; 00668 00669 if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) 00670 goto cleanup; 00671 00672 /* 00673 * To test that mbedtls_entropy_func writes correct number of bytes: 00674 * - use the whole buffer and rely on ASan to detect overruns 00675 * - collect entropy 8 times and OR the result in an accumulator: 00676 * any byte should then be 0 with probably 2^(-64), so requiring 00677 * each of the 32 or 64 bytes to be non-zero has a false failure rate 00678 * of at most 2^(-58) which is acceptable. 00679 */ 00680 for( i = 0; i < 8; i++ ) 00681 { 00682 if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) 00683 goto cleanup; 00684 00685 for( j = 0; j < sizeof( buf ); j++ ) 00686 acc[j] |= buf[j]; 00687 } 00688 00689 for( j = 0; j < sizeof( buf ); j++ ) 00690 { 00691 if( acc[j] == 0 ) 00692 { 00693 ret = 1; 00694 goto cleanup; 00695 } 00696 } 00697 00698 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) 00699 if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) 00700 goto cleanup; 00701 #endif 00702 00703 cleanup: 00704 mbedtls_entropy_free( &ctx ); 00705 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */ 00706 00707 if( verbose != 0 ) 00708 { 00709 if( ret != 0 ) 00710 mbedtls_printf( "failed\n" ); 00711 else 00712 mbedtls_printf( "passed\n" ); 00713 00714 mbedtls_printf( "\n" ); 00715 } 00716 00717 return( ret != 0 ); 00718 } 00719 #endif /* MBEDTLS_SELF_TEST */ 00720 00721 #endif /* MBEDTLS_ENTROPY_C */
Generated on Tue Aug 9 2022 00:37:06 by
1.7.2