00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "polarssl/config.h"
00027
00028 #if defined(POLARSSL_ENTROPY_C)
00029
00030 #include "polarssl/entropy.h"
00031 #include "polarssl/entropy_poll.h"
00032
00033 #if defined(POLARSSL_HAVEGE_C)
00034 #include "polarssl/havege.h"
00035 #endif
00036
00037 #define ENTROPY_MAX_LOOP 256
00039 void entropy_init( entropy_context *ctx )
00040 {
00041 memset( ctx, 0, sizeof(entropy_context) );
00042
00043 #if defined(POLARSSL_THREADING_C)
00044 polarssl_mutex_init( &ctx->mutex );
00045 #endif
00046
00047 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
00048 sha512_starts( &ctx->accumulator, 0 );
00049 #else
00050 sha256_starts( &ctx->accumulator, 0 );
00051 #endif
00052 #if defined(POLARSSL_HAVEGE_C)
00053 havege_init( &ctx->havege_data );
00054 #endif
00055
00056 #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
00057 #if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
00058 entropy_add_source( ctx, platform_entropy_poll, NULL,
00059 ENTROPY_MIN_PLATFORM );
00060 #endif
00061 #if defined(POLARSSL_TIMING_C)
00062 entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
00063 #endif
00064 #if defined(POLARSSL_HAVEGE_C)
00065 entropy_add_source( ctx, havege_poll, &ctx->havege_data,
00066 ENTROPY_MIN_HAVEGE );
00067 #endif
00068 #endif
00069 }
00070
00071 void entropy_free( entropy_context *ctx )
00072 {
00073 ((void) ctx);
00074 #if defined(POLARSSL_THREADING_C)
00075 polarssl_mutex_free( &ctx->mutex );
00076 #endif
00077 }
00078
00079 int entropy_add_source( entropy_context *ctx,
00080 f_source_ptr f_source, void *p_source,
00081 size_t threshold )
00082 {
00083 int index = ctx->source_count;
00084
00085 if( index >= ENTROPY_MAX_SOURCES )
00086 return( POLARSSL_ERR_ENTROPY_MAX_SOURCES );
00087
00088 ctx->source[index].f_source = f_source;
00089 ctx->source[index].p_source = p_source;
00090 ctx->source[index].threshold = threshold;
00091
00092 ctx->source_count++;
00093
00094 return( 0 );
00095 }
00096
00097
00098
00099
00100 static int entropy_update( entropy_context *ctx, unsigned char source_id,
00101 const unsigned char *data, size_t len )
00102 {
00103 unsigned char header[2];
00104 unsigned char tmp[ENTROPY_BLOCK_SIZE];
00105 size_t use_len = len;
00106 const unsigned char *p = data;
00107
00108 if( use_len > ENTROPY_BLOCK_SIZE )
00109 {
00110 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
00111 sha512( data, len, tmp, 0 );
00112 #else
00113 sha256( data, len, tmp, 0 );
00114 #endif
00115 p = tmp;
00116 use_len = ENTROPY_BLOCK_SIZE;
00117 }
00118
00119 header[0] = source_id;
00120 header[1] = use_len & 0xFF;
00121
00122 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
00123 sha512_update( &ctx->accumulator, header, 2 );
00124 sha512_update( &ctx->accumulator, p, use_len );
00125 #else
00126 sha256_update( &ctx->accumulator, header, 2 );
00127 sha256_update( &ctx->accumulator, p, use_len );
00128 #endif
00129
00130 return( 0 );
00131 }
00132
00133 int entropy_update_manual( entropy_context *ctx,
00134 const unsigned char *data, size_t len )
00135 {
00136 return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
00137 }
00138
00139
00140
00141
00142 int entropy_gather( entropy_context *ctx )
00143 {
00144 int ret, i;
00145 unsigned char buf[ENTROPY_MAX_GATHER];
00146 size_t olen;
00147
00148 if( ctx->source_count == 0 )
00149 return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
00150
00151
00152
00153
00154 for( i = 0; i < ctx->source_count; i++ )
00155 {
00156 olen = 0;
00157 if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
00158 buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
00159 {
00160 return( ret );
00161 }
00162
00163
00164
00165
00166 if( olen > 0 )
00167 {
00168 entropy_update( ctx, (unsigned char) i, buf, olen );
00169 ctx->source[i].size += olen;
00170 }
00171 }
00172
00173 return( 0 );
00174 }
00175
00176 int entropy_func( void *data, unsigned char *output, size_t len )
00177 {
00178 int ret, count = 0, i, reached;
00179 entropy_context *ctx = (entropy_context *) data;
00180 unsigned char buf[ENTROPY_BLOCK_SIZE];
00181
00182 if( len > ENTROPY_BLOCK_SIZE )
00183 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
00184
00185 #if defined(POLARSSL_THREADING_C)
00186 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
00187 return( ret );
00188 #endif
00189
00190
00191
00192
00193 do
00194 {
00195 if( count++ > ENTROPY_MAX_LOOP )
00196 {
00197 ret = POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
00198 goto exit;
00199 }
00200
00201 if( ( ret = entropy_gather( ctx ) ) != 0 )
00202 goto exit;
00203
00204 reached = 0;
00205
00206 for( i = 0; i < ctx->source_count; i++ )
00207 if( ctx->source[i].size >= ctx->source[i].threshold )
00208 reached++;
00209 }
00210 while( reached != ctx->source_count );
00211
00212 memset( buf, 0, ENTROPY_BLOCK_SIZE );
00213
00214 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
00215 sha512_finish( &ctx->accumulator, buf );
00216
00217
00218
00219
00220 sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
00221
00222
00223
00224
00225 memset( &ctx->accumulator, 0, sizeof( sha512_context ) );
00226 sha512_starts( &ctx->accumulator, 0 );
00227 sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
00228 #else
00229 sha256_finish( &ctx->accumulator, buf );
00230
00231
00232
00233
00234 sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
00235
00236
00237
00238
00239 memset( &ctx->accumulator, 0, sizeof( sha256_context ) );
00240 sha256_starts( &ctx->accumulator, 0 );
00241 sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
00242 #endif
00243
00244 for( i = 0; i < ctx->source_count; i++ )
00245 ctx->source[i].size = 0;
00246
00247 memcpy( output, buf, len );
00248
00249 ret = 0;
00250
00251 exit:
00252 #if defined(POLARSSL_THREADING_C)
00253 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
00254 return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
00255 #endif
00256
00257 return( ret );
00258 }
00259
00260 #endif