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_SELF_TEST) 00046 #if defined(MBEDTLS_PLATFORM_C) 00047 #include "mbedtls/platform.h" 00048 #else 00049 #include <stdio.h> 00050 #define mbedtls_printf printf 00051 #endif /* MBEDTLS_PLATFORM_C */ 00052 #endif /* MBEDTLS_SELF_TEST */ 00053 00054 #if defined(MBEDTLS_HAVEGE_C) 00055 #include "mbedtls/havege.h" 00056 #endif 00057 00058 /* Implementation that should never be optimized out by the compiler */ 00059 static void mbedtls_zeroize( void *v, size_t n ) { 00060 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 00061 } 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 memset( ctx, 0, sizeof(mbedtls_entropy_context) ); 00068 00069 #if defined(MBEDTLS_THREADING_C) 00070 mbedtls_mutex_init( &ctx->mutex ); 00071 #endif 00072 00073 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00074 mbedtls_sha512_starts( &ctx->accumulator, 0 ); 00075 #else 00076 mbedtls_sha256_starts( &ctx->accumulator, 0 ); 00077 #endif 00078 #if defined(MBEDTLS_HAVEGE_C) 00079 mbedtls_havege_init( &ctx->havege_data ); 00080 #endif 00081 00082 #if defined(MBEDTLS_TEST_NULL_ENTROPY) 00083 mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, 00084 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); 00085 #endif 00086 00087 #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) 00088 #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) 00089 mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, 00090 MBEDTLS_ENTROPY_MIN_PLATFORM, 00091 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00092 #endif 00093 #if defined(MBEDTLS_TIMING_C) 00094 mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, 00095 MBEDTLS_ENTROPY_MIN_HARDCLOCK, 00096 MBEDTLS_ENTROPY_SOURCE_WEAK ); 00097 #endif 00098 #if defined(MBEDTLS_HAVEGE_C) 00099 mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, 00100 MBEDTLS_ENTROPY_MIN_HAVEGE, 00101 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00102 #endif 00103 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) 00104 mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, 00105 MBEDTLS_ENTROPY_MIN_HARDWARE, 00106 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00107 #endif 00108 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00109 mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, 00110 MBEDTLS_ENTROPY_BLOCK_SIZE, 00111 MBEDTLS_ENTROPY_SOURCE_STRONG ); 00112 #endif 00113 #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ 00114 } 00115 00116 void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) 00117 { 00118 #if defined(MBEDTLS_HAVEGE_C) 00119 mbedtls_havege_free( &ctx->havege_data ); 00120 #endif 00121 #if defined(MBEDTLS_THREADING_C) 00122 mbedtls_mutex_free( &ctx->mutex ); 00123 #endif 00124 mbedtls_zeroize( ctx, sizeof( mbedtls_entropy_context ) ); 00125 } 00126 00127 int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, 00128 mbedtls_entropy_f_source_ptr f_source, void *p_source, 00129 size_t threshold, int strong ) 00130 { 00131 int index, ret = 0; 00132 00133 #if defined(MBEDTLS_THREADING_C) 00134 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00135 return( ret ); 00136 #endif 00137 00138 index = ctx->source_count; 00139 if( index >= MBEDTLS_ENTROPY_MAX_SOURCES ) 00140 { 00141 ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; 00142 goto exit; 00143 } 00144 00145 ctx->source[index].f_source = f_source; 00146 ctx->source[index].p_source = p_source; 00147 ctx->source[index].threshold = threshold; 00148 ctx->source[index].strong = strong; 00149 00150 ctx->source_count++; 00151 00152 exit: 00153 #if defined(MBEDTLS_THREADING_C) 00154 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00155 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00156 #endif 00157 00158 return( ret ); 00159 } 00160 00161 /* 00162 * Entropy accumulator update 00163 */ 00164 static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, 00165 const unsigned char *data, size_t len ) 00166 { 00167 unsigned char header[2]; 00168 unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; 00169 size_t use_len = len; 00170 const unsigned char *p = data; 00171 00172 if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) 00173 { 00174 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00175 mbedtls_sha512( data, len, tmp, 0 ); 00176 #else 00177 mbedtls_sha256( data, len, tmp, 0 ); 00178 #endif 00179 p = tmp; 00180 use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; 00181 } 00182 00183 header[0] = source_id; 00184 header[1] = use_len & 0xFF; 00185 00186 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00187 mbedtls_sha512_update( &ctx->accumulator, header, 2 ); 00188 mbedtls_sha512_update( &ctx->accumulator, p, use_len ); 00189 #else 00190 mbedtls_sha256_update( &ctx->accumulator, header, 2 ); 00191 mbedtls_sha256_update( &ctx->accumulator, p, use_len ); 00192 #endif 00193 00194 return( 0 ); 00195 } 00196 00197 int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, 00198 const unsigned char *data, size_t len ) 00199 { 00200 int ret; 00201 00202 #if defined(MBEDTLS_THREADING_C) 00203 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00204 return( ret ); 00205 #endif 00206 00207 ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); 00208 00209 #if defined(MBEDTLS_THREADING_C) 00210 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00211 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00212 #endif 00213 00214 return( ret ); 00215 } 00216 00217 /* 00218 * Run through the different sources to add entropy to our accumulator 00219 */ 00220 static int entropy_gather_internal( mbedtls_entropy_context *ctx ) 00221 { 00222 int ret, i, have_one_strong = 0; 00223 unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; 00224 size_t olen; 00225 00226 if( ctx->source_count == 0 ) 00227 return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); 00228 00229 /* 00230 * Run through our entropy sources 00231 */ 00232 for( i = 0; i < ctx->source_count; i++ ) 00233 { 00234 if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) 00235 have_one_strong = 1; 00236 00237 olen = 0; 00238 if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, 00239 buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) 00240 { 00241 return( ret ); 00242 } 00243 00244 /* 00245 * Add if we actually gathered something 00246 */ 00247 if( olen > 0 ) 00248 { 00249 entropy_update( ctx, (unsigned char) i, buf, olen ); 00250 ctx->source[i].size += olen; 00251 } 00252 } 00253 00254 if( have_one_strong == 0 ) 00255 return( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE ); 00256 00257 return( 0 ); 00258 } 00259 00260 /* 00261 * Thread-safe wrapper for entropy_gather_internal() 00262 */ 00263 int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) 00264 { 00265 int ret; 00266 00267 #if defined(MBEDTLS_THREADING_C) 00268 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00269 return( ret ); 00270 #endif 00271 00272 ret = entropy_gather_internal( ctx ); 00273 00274 #if defined(MBEDTLS_THREADING_C) 00275 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00276 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00277 #endif 00278 00279 return( ret ); 00280 } 00281 00282 int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) 00283 { 00284 int ret, count = 0, i, done; 00285 mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; 00286 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 00287 00288 if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) 00289 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 00290 00291 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00292 /* Update the NV entropy seed before generating any entropy for outside 00293 * use. 00294 */ 00295 if( ctx->initial_entropy_run == 0 ) 00296 { 00297 ctx->initial_entropy_run = 1; 00298 if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) 00299 return( ret ); 00300 } 00301 #endif 00302 00303 #if defined(MBEDTLS_THREADING_C) 00304 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 00305 return( ret ); 00306 #endif 00307 00308 /* 00309 * Always gather extra entropy before a call 00310 */ 00311 do 00312 { 00313 if( count++ > ENTROPY_MAX_LOOP ) 00314 { 00315 ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; 00316 goto exit; 00317 } 00318 00319 if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) 00320 goto exit; 00321 00322 done = 1; 00323 for( i = 0; i < ctx->source_count; i++ ) 00324 if( ctx->source[i].size < ctx->source[i].threshold ) 00325 done = 0; 00326 } 00327 while( ! done ); 00328 00329 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00330 00331 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 00332 mbedtls_sha512_finish( &ctx->accumulator, buf ); 00333 00334 /* 00335 * Reset accumulator and counters and recycle existing entropy 00336 */ 00337 memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) ); 00338 mbedtls_sha512_starts( &ctx->accumulator, 0 ); 00339 mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00340 00341 /* 00342 * Perform second SHA-512 on entropy 00343 */ 00344 mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); 00345 #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ 00346 mbedtls_sha256_finish( &ctx->accumulator, buf ); 00347 00348 /* 00349 * Reset accumulator and counters and recycle existing entropy 00350 */ 00351 memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) ); 00352 mbedtls_sha256_starts( &ctx->accumulator, 0 ); 00353 mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00354 00355 /* 00356 * Perform second SHA-256 on entropy 00357 */ 00358 mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); 00359 #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ 00360 00361 for( i = 0; i < ctx->source_count; i++ ) 00362 ctx->source[i].size = 0; 00363 00364 memcpy( output, buf, len ); 00365 00366 ret = 0; 00367 00368 exit: 00369 #if defined(MBEDTLS_THREADING_C) 00370 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 00371 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 00372 #endif 00373 00374 return( ret ); 00375 } 00376 00377 #if defined(MBEDTLS_ENTROPY_NV_SEED) 00378 int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) 00379 { 00380 int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 00381 unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; 00382 00383 /* Read new seed and write it to NV */ 00384 if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) 00385 return( ret ); 00386 00387 if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) 00388 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); 00389 00390 /* Manually update the remaining stream with a separator value to diverge */ 00391 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00392 mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); 00393 00394 return( 0 ); 00395 } 00396 #endif /* MBEDTLS_ENTROPY_NV_SEED */ 00397 00398 #if defined(MBEDTLS_FS_IO) 00399 int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) 00400 { 00401 int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 00402 FILE *f; 00403 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; 00404 00405 if( ( f = fopen( path, "wb" ) ) == NULL ) 00406 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); 00407 00408 if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) 00409 goto exit; 00410 00411 if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) 00412 { 00413 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; 00414 goto exit; 00415 } 00416 00417 ret = 0; 00418 00419 exit: 00420 fclose( f ); 00421 return( ret ); 00422 } 00423 00424 int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) 00425 { 00426 FILE *f; 00427 size_t n; 00428 unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; 00429 00430 if( ( f = fopen( path, "rb" ) ) == NULL ) 00431 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); 00432 00433 fseek( f, 0, SEEK_END ); 00434 n = (size_t) ftell( f ); 00435 fseek( f, 0, SEEK_SET ); 00436 00437 if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) 00438 n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; 00439 00440 if( fread( buf, 1, n, f ) != n ) 00441 { 00442 fclose( f ); 00443 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); 00444 } 00445 00446 fclose( f ); 00447 00448 mbedtls_entropy_update_manual( ctx, buf, n ); 00449 00450 return( mbedtls_entropy_write_seed_file( ctx, path ) ); 00451 } 00452 #endif /* MBEDTLS_FS_IO */ 00453 00454 #if defined(MBEDTLS_SELF_TEST) 00455 /* 00456 * Dummy source function 00457 */ 00458 static int entropy_dummy_source( void *data, unsigned char *output, 00459 size_t len, size_t *olen ) 00460 { 00461 ((void) data); 00462 00463 memset( output, 0x2a, len ); 00464 *olen = len; 00465 00466 return( 0 ); 00467 } 00468 00469 /* 00470 * The actual entropy quality is hard to test, but we can at least 00471 * test that the functions don't cause errors and write the correct 00472 * amount of data to buffers. 00473 */ 00474 int mbedtls_entropy_self_test( int verbose ) 00475 { 00476 int ret = 0; 00477 mbedtls_entropy_context ctx; 00478 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; 00479 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; 00480 size_t i, j; 00481 00482 if( verbose != 0 ) 00483 mbedtls_printf( " ENTROPY test: " ); 00484 00485 mbedtls_entropy_init( &ctx ); 00486 00487 /* First do a gather to make sure we have default sources */ 00488 if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) 00489 goto cleanup; 00490 00491 ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, 00492 MBEDTLS_ENTROPY_SOURCE_WEAK ); 00493 if( ret != 0 ) 00494 goto cleanup; 00495 00496 if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) 00497 goto cleanup; 00498 00499 /* 00500 * To test that mbedtls_entropy_func writes correct number of bytes: 00501 * - use the whole buffer and rely on ASan to detect overruns 00502 * - collect entropy 8 times and OR the result in an accumulator: 00503 * any byte should then be 0 with probably 2^(-64), so requiring 00504 * each of the 32 or 64 bytes to be non-zero has a false failure rate 00505 * of at most 2^(-58) which is acceptable. 00506 */ 00507 for( i = 0; i < 8; i++ ) 00508 { 00509 if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) 00510 goto cleanup; 00511 00512 for( j = 0; j < sizeof( buf ); j++ ) 00513 acc[j] |= buf[j]; 00514 } 00515 00516 for( j = 0; j < sizeof( buf ); j++ ) 00517 { 00518 if( acc[j] == 0 ) 00519 { 00520 ret = 1; 00521 goto cleanup; 00522 } 00523 } 00524 00525 cleanup: 00526 mbedtls_entropy_free( &ctx ); 00527 00528 if( verbose != 0 ) 00529 { 00530 if( ret != 0 ) 00531 mbedtls_printf( "failed\n" ); 00532 else 00533 mbedtls_printf( "passed\n" ); 00534 00535 mbedtls_printf( "\n" ); 00536 } 00537 00538 return( ret != 0 ); 00539 } 00540 #endif /* MBEDTLS_SELF_TEST */ 00541 00542 #endif /* MBEDTLS_ENTROPY_C */
Generated on Tue Jul 12 2022 13:04:58 by
 1.7.2
 1.7.2