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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 Jul 12 2022 13:54:18 by
