mbed TLS library
Dependents: HTTPClient-SSL WS_SERVER
entropy.c
00001 /* 00002 * Entropy accumulator implementation 00003 * 00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved 00005 * 00006 * This file is part of mbed TLS (https://tls.mbed.org) 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License along 00019 * with this program; if not, write to the Free Software Foundation, Inc., 00020 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00021 */ 00022 00023 #if !defined(POLARSSL_CONFIG_FILE) 00024 #include "polarssl/config.h" 00025 #else 00026 #include POLARSSL_CONFIG_FILE 00027 #endif 00028 00029 #if defined(POLARSSL_ENTROPY_C) 00030 00031 #include "polarssl/entropy.h" 00032 #include "polarssl/entropy_poll.h" 00033 00034 #include <string.h> 00035 00036 #if defined(POLARSSL_FS_IO) 00037 #include <stdio.h> 00038 #endif 00039 00040 #if defined(POLARSSL_SELF_TEST) 00041 #if defined(POLARSSL_PLATFORM_C) 00042 #include "polarssl/platform.h" 00043 #else 00044 #include <stdio.h> 00045 #define polarssl_printf printf 00046 #endif /* POLARSSL_PLATFORM_C */ 00047 #endif /* POLARSSL_SELF_TEST */ 00048 00049 #if defined(POLARSSL_HAVEGE_C) 00050 #include "polarssl/havege.h" 00051 #endif 00052 00053 /* Implementation that should never be optimized out by the compiler */ 00054 static void polarssl_zeroize( void *v, size_t n ) { 00055 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 00056 } 00057 00058 #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ 00059 00060 void entropy_init( entropy_context *ctx ) 00061 { 00062 memset( ctx, 0, sizeof(entropy_context) ); 00063 00064 #if defined(POLARSSL_THREADING_C) 00065 polarssl_mutex_init( &ctx->mutex ); 00066 #endif 00067 00068 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00069 sha512_starts( &ctx->accumulator, 0 ); 00070 #else 00071 sha256_starts( &ctx->accumulator, 0 ); 00072 #endif 00073 #if defined(POLARSSL_HAVEGE_C) 00074 havege_init( &ctx->havege_data ); 00075 #endif 00076 00077 #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES) 00078 #if !defined(POLARSSL_NO_PLATFORM_ENTROPY) 00079 entropy_add_source( ctx, platform_entropy_poll, NULL, 00080 ENTROPY_MIN_PLATFORM ); 00081 #endif 00082 #if defined(POLARSSL_TIMING_C) 00083 entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK ); 00084 #endif 00085 #if defined(POLARSSL_HAVEGE_C) 00086 entropy_add_source( ctx, havege_poll, &ctx->havege_data, 00087 ENTROPY_MIN_HAVEGE ); 00088 #endif 00089 #endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */ 00090 } 00091 00092 void entropy_free( entropy_context *ctx ) 00093 { 00094 #if defined(POLARSSL_HAVEGE_C) 00095 havege_free( &ctx->havege_data ); 00096 #endif 00097 #if defined(POLARSSL_THREADING_C) 00098 polarssl_mutex_free( &ctx->mutex ); 00099 #endif 00100 polarssl_zeroize( ctx, sizeof( entropy_context ) ); 00101 } 00102 00103 int entropy_add_source( entropy_context *ctx, 00104 f_source_ptr f_source, void *p_source, 00105 size_t threshold ) 00106 { 00107 int index, ret = 0; 00108 00109 #if defined(POLARSSL_THREADING_C) 00110 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00111 return( ret ); 00112 #endif 00113 00114 index = ctx->source_count; 00115 if( index >= ENTROPY_MAX_SOURCES ) 00116 { 00117 ret = POLARSSL_ERR_ENTROPY_MAX_SOURCES; 00118 goto exit; 00119 } 00120 00121 ctx->source[index].f_source = f_source; 00122 ctx->source[index].p_source = p_source; 00123 ctx->source[index].threshold = threshold; 00124 00125 ctx->source_count++; 00126 00127 exit: 00128 #if defined(POLARSSL_THREADING_C) 00129 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00130 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00131 #endif 00132 00133 return( ret ); 00134 } 00135 00136 /* 00137 * Entropy accumulator update 00138 */ 00139 static int entropy_update( entropy_context *ctx, unsigned char source_id, 00140 const unsigned char *data, size_t len ) 00141 { 00142 unsigned char header[2]; 00143 unsigned char tmp[ENTROPY_BLOCK_SIZE]; 00144 size_t use_len = len; 00145 const unsigned char *p = data; 00146 00147 if( use_len > ENTROPY_BLOCK_SIZE ) 00148 { 00149 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00150 sha512( data, len, tmp, 0 ); 00151 #else 00152 sha256( data, len, tmp, 0 ); 00153 #endif 00154 p = tmp; 00155 use_len = ENTROPY_BLOCK_SIZE; 00156 } 00157 00158 header[0] = source_id; 00159 header[1] = use_len & 0xFF; 00160 00161 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00162 sha512_update( &ctx->accumulator, header, 2 ); 00163 sha512_update( &ctx->accumulator, p, use_len ); 00164 #else 00165 sha256_update( &ctx->accumulator, header, 2 ); 00166 sha256_update( &ctx->accumulator, p, use_len ); 00167 #endif 00168 00169 return( 0 ); 00170 } 00171 00172 int entropy_update_manual( entropy_context *ctx, 00173 const unsigned char *data, size_t len ) 00174 { 00175 int ret; 00176 00177 #if defined(POLARSSL_THREADING_C) 00178 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00179 return( ret ); 00180 #endif 00181 00182 ret = entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len ); 00183 00184 #if defined(POLARSSL_THREADING_C) 00185 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00186 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00187 #endif 00188 00189 return( ret ); 00190 } 00191 00192 /* 00193 * Run through the different sources to add entropy to our accumulator 00194 */ 00195 static int entropy_gather_internal( entropy_context *ctx ) 00196 { 00197 int ret, i; 00198 unsigned char buf[ENTROPY_MAX_GATHER]; 00199 size_t olen; 00200 00201 if( ctx->source_count == 0 ) 00202 return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED ); 00203 00204 /* 00205 * Run through our entropy sources 00206 */ 00207 for( i = 0; i < ctx->source_count; i++ ) 00208 { 00209 olen = 0; 00210 if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, 00211 buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 ) 00212 { 00213 return( ret ); 00214 } 00215 00216 /* 00217 * Add if we actually gathered something 00218 */ 00219 if( olen > 0 ) 00220 { 00221 entropy_update( ctx, (unsigned char) i, buf, olen ); 00222 ctx->source[i].size += olen; 00223 } 00224 } 00225 00226 return( 0 ); 00227 } 00228 00229 /* 00230 * Thread-safe wrapper for entropy_gather_internal() 00231 */ 00232 int entropy_gather( entropy_context *ctx ) 00233 { 00234 int ret; 00235 00236 #if defined(POLARSSL_THREADING_C) 00237 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00238 return( ret ); 00239 #endif 00240 00241 ret = entropy_gather_internal( ctx ); 00242 00243 #if defined(POLARSSL_THREADING_C) 00244 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00245 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00246 #endif 00247 00248 return( ret ); 00249 } 00250 00251 int entropy_func( void *data, unsigned char *output, size_t len ) 00252 { 00253 int ret, count = 0, i, reached; 00254 entropy_context *ctx = (entropy_context *) data; 00255 unsigned char buf[ENTROPY_BLOCK_SIZE]; 00256 00257 if( len > ENTROPY_BLOCK_SIZE ) 00258 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); 00259 00260 #if defined(POLARSSL_THREADING_C) 00261 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00262 return( ret ); 00263 #endif 00264 00265 /* 00266 * Always gather extra entropy before a call 00267 */ 00268 do 00269 { 00270 if( count++ > ENTROPY_MAX_LOOP ) 00271 { 00272 ret = POLARSSL_ERR_ENTROPY_SOURCE_FAILED; 00273 goto exit; 00274 } 00275 00276 if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) 00277 goto exit; 00278 00279 reached = 0; 00280 00281 for( i = 0; i < ctx->source_count; i++ ) 00282 if( ctx->source[i].size >= ctx->source[i].threshold ) 00283 reached++; 00284 } 00285 while( reached != ctx->source_count ); 00286 00287 memset( buf, 0, ENTROPY_BLOCK_SIZE ); 00288 00289 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00290 sha512_finish( &ctx->accumulator, buf ); 00291 00292 /* 00293 * Reset accumulator and counters and recycle existing entropy 00294 */ 00295 memset( &ctx->accumulator, 0, sizeof( sha512_context ) ); 00296 sha512_starts( &ctx->accumulator, 0 ); 00297 sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); 00298 00299 /* 00300 * Perform second SHA-512 on entropy 00301 */ 00302 sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); 00303 #else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */ 00304 sha256_finish( &ctx->accumulator, buf ); 00305 00306 /* 00307 * Reset accumulator and counters and recycle existing entropy 00308 */ 00309 memset( &ctx->accumulator, 0, sizeof( sha256_context ) ); 00310 sha256_starts( &ctx->accumulator, 0 ); 00311 sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); 00312 00313 /* 00314 * Perform second SHA-256 on entropy 00315 */ 00316 sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); 00317 #endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */ 00318 00319 for( i = 0; i < ctx->source_count; i++ ) 00320 ctx->source[i].size = 0; 00321 00322 memcpy( output, buf, len ); 00323 00324 ret = 0; 00325 00326 exit: 00327 #if defined(POLARSSL_THREADING_C) 00328 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00329 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00330 #endif 00331 00332 return( ret ); 00333 } 00334 00335 #if defined(POLARSSL_FS_IO) 00336 int entropy_write_seed_file( entropy_context *ctx, const char *path ) 00337 { 00338 int ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR; 00339 FILE *f; 00340 unsigned char buf[ENTROPY_BLOCK_SIZE]; 00341 00342 if( ( f = fopen( path, "wb" ) ) == NULL ) 00343 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); 00344 00345 if( ( ret = entropy_func( ctx, buf, ENTROPY_BLOCK_SIZE ) ) != 0 ) 00346 goto exit; 00347 00348 if( fwrite( buf, 1, ENTROPY_BLOCK_SIZE, f ) != ENTROPY_BLOCK_SIZE ) 00349 { 00350 ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR; 00351 goto exit; 00352 } 00353 00354 ret = 0; 00355 00356 exit: 00357 fclose( f ); 00358 return( ret ); 00359 } 00360 00361 int entropy_update_seed_file( entropy_context *ctx, const char *path ) 00362 { 00363 FILE *f; 00364 size_t n; 00365 unsigned char buf[ ENTROPY_MAX_SEED_SIZE ]; 00366 00367 if( ( f = fopen( path, "rb" ) ) == NULL ) 00368 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); 00369 00370 fseek( f, 0, SEEK_END ); 00371 n = (size_t) ftell( f ); 00372 fseek( f, 0, SEEK_SET ); 00373 00374 if( n > ENTROPY_MAX_SEED_SIZE ) 00375 n = ENTROPY_MAX_SEED_SIZE; 00376 00377 if( fread( buf, 1, n, f ) != n ) 00378 { 00379 fclose( f ); 00380 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); 00381 } 00382 00383 fclose( f ); 00384 00385 entropy_update_manual( ctx, buf, n ); 00386 00387 return( entropy_write_seed_file( ctx, path ) ); 00388 } 00389 #endif /* POLARSSL_FS_IO */ 00390 00391 #if defined(POLARSSL_SELF_TEST) 00392 /* 00393 * Dummy source function 00394 */ 00395 static int entropy_dummy_source( void *data, unsigned char *output, 00396 size_t len, size_t *olen ) 00397 { 00398 ((void) data); 00399 00400 memset( output, 0x2a, len ); 00401 *olen = len; 00402 00403 return( 0 ); 00404 } 00405 00406 /* 00407 * The actual entropy quality is hard to test, but we can at least 00408 * test that the functions don't cause errors and write the correct 00409 * amount of data to buffers. 00410 */ 00411 int entropy_self_test( int verbose ) 00412 { 00413 int ret = 0; 00414 entropy_context ctx; 00415 unsigned char buf[ENTROPY_BLOCK_SIZE] = { 0 }; 00416 unsigned char acc[ENTROPY_BLOCK_SIZE] = { 0 }; 00417 size_t i, j; 00418 00419 if( verbose != 0 ) 00420 polarssl_printf( " ENTROPY test: " ); 00421 00422 entropy_init( &ctx ); 00423 00424 ret = entropy_add_source( &ctx, entropy_dummy_source, NULL, 16 ); 00425 if( ret != 0 ) 00426 goto cleanup; 00427 00428 if( ( ret = entropy_gather( &ctx ) ) != 0 ) 00429 goto cleanup; 00430 00431 if( ( ret = entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) 00432 goto cleanup; 00433 00434 /* 00435 * To test that entropy_func writes correct number of bytes: 00436 * - use the whole buffer and rely on ASan to detect overruns 00437 * - collect entropy 8 times and OR the result in an accumulator: 00438 * any byte should then be 0 with probably 2^(-64), so requiring 00439 * each of the 32 or 64 bytes to be non-zero has a false failure rate 00440 * of at most 2^(-58) which is acceptable. 00441 */ 00442 for( i = 0; i < 8; i++ ) 00443 { 00444 if( ( ret = entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) 00445 goto cleanup; 00446 00447 for( j = 0; j < sizeof( buf ); j++ ) 00448 acc[j] |= buf[j]; 00449 } 00450 00451 for( j = 0; j < sizeof( buf ); j++ ) 00452 { 00453 if( acc[j] == 0 ) 00454 { 00455 ret = 1; 00456 goto cleanup; 00457 } 00458 } 00459 00460 cleanup: 00461 entropy_free( &ctx ); 00462 00463 if( verbose != 0 ) 00464 { 00465 if( ret != 0 ) 00466 polarssl_printf( "failed\n" ); 00467 else 00468 polarssl_printf( "passed\n" ); 00469 00470 polarssl_printf( "\n" ); 00471 } 00472 00473 return( ret != 0 ); 00474 } 00475 #endif /* POLARSSL_SELF_TEST */ 00476 00477 #endif /* POLARSSL_ENTROPY_C */ 00478
Generated on Tue Jul 12 2022 13:50:37 by 1.7.2