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