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-2014, Brainspark B.V. 00005 * 00006 * This file is part of PolarSSL (http://www.polarssl.org) 00007 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> 00008 * 00009 * All rights reserved. 00010 * 00011 * This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License along 00022 * with this program; if not, write to the Free Software Foundation, Inc., 00023 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00024 */ 00025 00026 #if !defined(POLARSSL_CONFIG_FILE) 00027 #include "polarssl/config.h" 00028 #else 00029 #include POLARSSL_CONFIG_FILE 00030 #endif 00031 00032 #if defined(POLARSSL_ENTROPY_C) 00033 00034 #include "polarssl/entropy.h" 00035 #include "polarssl/entropy_poll.h" 00036 00037 #if defined(POLARSSL_FS_IO) 00038 #include <stdio.h> 00039 #endif 00040 00041 #if defined(POLARSSL_HAVEGE_C) 00042 #include "polarssl/havege.h" 00043 #endif 00044 00045 #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ 00046 00047 void entropy_init( entropy_context *ctx ) 00048 { 00049 memset( ctx, 0, sizeof(entropy_context) ); 00050 00051 #if defined(POLARSSL_THREADING_C) 00052 polarssl_mutex_init( &ctx->mutex ); 00053 #endif 00054 00055 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00056 sha512_starts( &ctx->accumulator, 0 ); 00057 #else 00058 sha256_starts( &ctx->accumulator, 0 ); 00059 #endif 00060 #if defined(POLARSSL_HAVEGE_C) 00061 havege_init( &ctx->havege_data ); 00062 #endif 00063 00064 #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES) 00065 #if !defined(POLARSSL_NO_PLATFORM_ENTROPY) 00066 entropy_add_source( ctx, platform_entropy_poll, NULL, 00067 ENTROPY_MIN_PLATFORM ); 00068 #endif 00069 #if defined(POLARSSL_TIMING_C) 00070 entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK ); 00071 #endif 00072 #if defined(POLARSSL_HAVEGE_C) 00073 entropy_add_source( ctx, havege_poll, &ctx->havege_data, 00074 ENTROPY_MIN_HAVEGE ); 00075 #endif 00076 #endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */ 00077 } 00078 00079 void entropy_free( entropy_context *ctx ) 00080 { 00081 ((void) ctx); 00082 #if defined(POLARSSL_THREADING_C) 00083 polarssl_mutex_free( &ctx->mutex ); 00084 #endif 00085 } 00086 00087 int entropy_add_source( entropy_context *ctx, 00088 f_source_ptr f_source, void *p_source, 00089 size_t threshold ) 00090 { 00091 int index, ret = 0; 00092 00093 #if defined(POLARSSL_THREADING_C) 00094 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00095 return( ret ); 00096 #endif 00097 00098 index = ctx->source_count; 00099 if( index >= ENTROPY_MAX_SOURCES ) 00100 { 00101 ret = POLARSSL_ERR_ENTROPY_MAX_SOURCES; 00102 goto exit; 00103 } 00104 00105 ctx->source[index].f_source = f_source; 00106 ctx->source[index].p_source = p_source; 00107 ctx->source[index].threshold = threshold; 00108 00109 ctx->source_count++; 00110 00111 exit: 00112 #if defined(POLARSSL_THREADING_C) 00113 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00114 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00115 #endif 00116 00117 return( ret ); 00118 } 00119 00120 /* 00121 * Entropy accumulator update 00122 */ 00123 static int entropy_update( entropy_context *ctx, unsigned char source_id, 00124 const unsigned char *data, size_t len ) 00125 { 00126 unsigned char header[2]; 00127 unsigned char tmp[ENTROPY_BLOCK_SIZE]; 00128 size_t use_len = len; 00129 const unsigned char *p = data; 00130 00131 if( use_len > ENTROPY_BLOCK_SIZE ) 00132 { 00133 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00134 sha512( data, len, tmp, 0 ); 00135 #else 00136 sha256( data, len, tmp, 0 ); 00137 #endif 00138 p = tmp; 00139 use_len = ENTROPY_BLOCK_SIZE; 00140 } 00141 00142 header[0] = source_id; 00143 header[1] = use_len & 0xFF; 00144 00145 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00146 sha512_update( &ctx->accumulator, header, 2 ); 00147 sha512_update( &ctx->accumulator, p, use_len ); 00148 #else 00149 sha256_update( &ctx->accumulator, header, 2 ); 00150 sha256_update( &ctx->accumulator, p, use_len ); 00151 #endif 00152 00153 return( 0 ); 00154 } 00155 00156 int entropy_update_manual( entropy_context *ctx, 00157 const unsigned char *data, size_t len ) 00158 { 00159 int ret; 00160 00161 #if defined(POLARSSL_THREADING_C) 00162 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00163 return( ret ); 00164 #endif 00165 00166 ret = entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len ); 00167 00168 #if defined(POLARSSL_THREADING_C) 00169 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00170 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00171 #endif 00172 00173 return ( ret ); 00174 } 00175 00176 /* 00177 * Run through the different sources to add entropy to our accumulator 00178 */ 00179 static int entropy_gather_internal( entropy_context *ctx ) 00180 { 00181 int ret, i; 00182 unsigned char buf[ENTROPY_MAX_GATHER]; 00183 size_t olen; 00184 00185 if( ctx->source_count == 0 ) 00186 return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED ); 00187 00188 /* 00189 * Run through our entropy sources 00190 */ 00191 for( i = 0; i < ctx->source_count; i++ ) 00192 { 00193 olen = 0; 00194 if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, 00195 buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 ) 00196 { 00197 return( ret ); 00198 } 00199 00200 /* 00201 * Add if we actually gathered something 00202 */ 00203 if( olen > 0 ) 00204 { 00205 entropy_update( ctx, (unsigned char) i, buf, olen ); 00206 ctx->source[i].size += olen; 00207 } 00208 } 00209 00210 return( 0 ); 00211 } 00212 00213 /* 00214 * Thread-safe wrapper for entropy_gather_internal() 00215 */ 00216 int entropy_gather( entropy_context *ctx ) 00217 { 00218 int ret; 00219 00220 #if defined(POLARSSL_THREADING_C) 00221 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00222 return( ret ); 00223 #endif 00224 00225 ret = entropy_gather_internal( ctx ); 00226 00227 #if defined(POLARSSL_THREADING_C) 00228 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00229 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00230 #endif 00231 00232 return( ret ); 00233 } 00234 00235 int entropy_func( void *data, unsigned char *output, size_t len ) 00236 { 00237 int ret, count = 0, i, reached; 00238 entropy_context *ctx = (entropy_context *) data; 00239 unsigned char buf[ENTROPY_BLOCK_SIZE]; 00240 00241 if( len > ENTROPY_BLOCK_SIZE ) 00242 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); 00243 00244 #if defined(POLARSSL_THREADING_C) 00245 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00246 return( ret ); 00247 #endif 00248 00249 /* 00250 * Always gather extra entropy before a call 00251 */ 00252 do 00253 { 00254 if( count++ > ENTROPY_MAX_LOOP ) 00255 { 00256 ret = POLARSSL_ERR_ENTROPY_SOURCE_FAILED; 00257 goto exit; 00258 } 00259 00260 if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) 00261 goto exit; 00262 00263 reached = 0; 00264 00265 for( i = 0; i < ctx->source_count; i++ ) 00266 if( ctx->source[i].size >= ctx->source[i].threshold ) 00267 reached++; 00268 } 00269 while( reached != ctx->source_count ); 00270 00271 memset( buf, 0, ENTROPY_BLOCK_SIZE ); 00272 00273 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00274 sha512_finish( &ctx->accumulator, buf ); 00275 00276 /* 00277 * Reset accumulator and counters and recycle existing entropy 00278 */ 00279 memset( &ctx->accumulator, 0, sizeof( sha512_context ) ); 00280 sha512_starts( &ctx->accumulator, 0 ); 00281 sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); 00282 00283 /* 00284 * Perform second SHA-512 on entropy 00285 */ 00286 sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); 00287 #else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */ 00288 sha256_finish( &ctx->accumulator, buf ); 00289 00290 /* 00291 * Reset accumulator and counters and recycle existing entropy 00292 */ 00293 memset( &ctx->accumulator, 0, sizeof( sha256_context ) ); 00294 sha256_starts( &ctx->accumulator, 0 ); 00295 sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); 00296 00297 /* 00298 * Perform second SHA-256 on entropy 00299 */ 00300 sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); 00301 #endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */ 00302 00303 for( i = 0; i < ctx->source_count; i++ ) 00304 ctx->source[i].size = 0; 00305 00306 memcpy( output, buf, len ); 00307 00308 ret = 0; 00309 00310 exit: 00311 #if defined(POLARSSL_THREADING_C) 00312 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00313 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00314 #endif 00315 00316 return( ret ); 00317 } 00318 00319 #if defined(POLARSSL_FS_IO) 00320 int entropy_write_seed_file( entropy_context *ctx, const char *path ) 00321 { 00322 int ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR; 00323 FILE *f; 00324 unsigned char buf[ENTROPY_BLOCK_SIZE]; 00325 00326 if( ( f = fopen( path, "wb" ) ) == NULL ) 00327 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); 00328 00329 if( ( ret = entropy_func( ctx, buf, ENTROPY_BLOCK_SIZE ) ) != 0 ) 00330 goto exit; 00331 00332 if( fwrite( buf, 1, ENTROPY_BLOCK_SIZE, f ) != ENTROPY_BLOCK_SIZE ) 00333 { 00334 ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR; 00335 goto exit; 00336 } 00337 00338 ret = 0; 00339 00340 exit: 00341 fclose( f ); 00342 return( ret ); 00343 } 00344 00345 int entropy_update_seed_file( entropy_context *ctx, const char *path ) 00346 { 00347 FILE *f; 00348 size_t n; 00349 unsigned char buf[ ENTROPY_MAX_SEED_SIZE ]; 00350 00351 if( ( f = fopen( path, "rb" ) ) == NULL ) 00352 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); 00353 00354 fseek( f, 0, SEEK_END ); 00355 n = (size_t) ftell( f ); 00356 fseek( f, 0, SEEK_SET ); 00357 00358 if( n > ENTROPY_MAX_SEED_SIZE ) 00359 n = ENTROPY_MAX_SEED_SIZE; 00360 00361 if( fread( buf, 1, n, f ) != n ) 00362 { 00363 fclose( f ); 00364 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); 00365 } 00366 00367 fclose( f ); 00368 00369 entropy_update_manual( ctx, buf, n ); 00370 00371 return( entropy_write_seed_file( ctx, path ) ); 00372 } 00373 #endif /* POLARSSL_FS_IO */ 00374 00375 #endif /* POLARSSL_ENTROPY_C */ 00376 00377
Generated on Tue Jul 12 2022 19:40:15 by
1.7.2