mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:137634ff4186 1 /*
ansond 0:137634ff4186 2 * Entropy accumulator implementation
ansond 0:137634ff4186 3 *
ansond 0:137634ff4186 4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
ansond 0:137634ff4186 5 *
ansond 0:137634ff4186 6 * This file is part of mbed TLS (https://tls.mbed.org)
ansond 0:137634ff4186 7 *
ansond 0:137634ff4186 8 * This program is free software; you can redistribute it and/or modify
ansond 0:137634ff4186 9 * it under the terms of the GNU General Public License as published by
ansond 0:137634ff4186 10 * the Free Software Foundation; either version 2 of the License, or
ansond 0:137634ff4186 11 * (at your option) any later version.
ansond 0:137634ff4186 12 *
ansond 0:137634ff4186 13 * This program is distributed in the hope that it will be useful,
ansond 0:137634ff4186 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ansond 0:137634ff4186 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ansond 0:137634ff4186 16 * GNU General Public License for more details.
ansond 0:137634ff4186 17 *
ansond 0:137634ff4186 18 * You should have received a copy of the GNU General Public License along
ansond 0:137634ff4186 19 * with this program; if not, write to the Free Software Foundation, Inc.,
ansond 0:137634ff4186 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ansond 0:137634ff4186 21 */
ansond 0:137634ff4186 22
ansond 0:137634ff4186 23 #if !defined(POLARSSL_CONFIG_FILE)
ansond 0:137634ff4186 24 #include "polarssl/config.h"
ansond 0:137634ff4186 25 #else
ansond 0:137634ff4186 26 #include POLARSSL_CONFIG_FILE
ansond 0:137634ff4186 27 #endif
ansond 0:137634ff4186 28
ansond 0:137634ff4186 29 #if defined(POLARSSL_ENTROPY_C)
ansond 0:137634ff4186 30
ansond 0:137634ff4186 31 #include "polarssl/entropy.h"
ansond 0:137634ff4186 32 #include "polarssl/entropy_poll.h"
ansond 0:137634ff4186 33
ansond 0:137634ff4186 34 #include <string.h>
ansond 0:137634ff4186 35
ansond 0:137634ff4186 36 #if defined(POLARSSL_FS_IO)
ansond 0:137634ff4186 37 #include <stdio.h>
ansond 0:137634ff4186 38 #endif
ansond 0:137634ff4186 39
ansond 0:137634ff4186 40 #if defined(POLARSSL_SELF_TEST)
ansond 0:137634ff4186 41 #if defined(POLARSSL_PLATFORM_C)
ansond 0:137634ff4186 42 #include "polarssl/platform.h"
ansond 0:137634ff4186 43 #else
ansond 0:137634ff4186 44 #include <stdio.h>
ansond 0:137634ff4186 45 #define polarssl_printf printf
ansond 0:137634ff4186 46 #endif /* POLARSSL_PLATFORM_C */
ansond 0:137634ff4186 47 #endif /* POLARSSL_SELF_TEST */
ansond 0:137634ff4186 48
ansond 0:137634ff4186 49 #if defined(POLARSSL_HAVEGE_C)
ansond 0:137634ff4186 50 #include "polarssl/havege.h"
ansond 0:137634ff4186 51 #endif
ansond 0:137634ff4186 52
ansond 0:137634ff4186 53 /* Implementation that should never be optimized out by the compiler */
ansond 0:137634ff4186 54 static void polarssl_zeroize( void *v, size_t n ) {
ansond 0:137634ff4186 55 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
ansond 0:137634ff4186 56 }
ansond 0:137634ff4186 57
ansond 0:137634ff4186 58 #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
ansond 0:137634ff4186 59
ansond 0:137634ff4186 60 void entropy_init( entropy_context *ctx )
ansond 0:137634ff4186 61 {
ansond 0:137634ff4186 62 memset( ctx, 0, sizeof(entropy_context) );
ansond 0:137634ff4186 63
ansond 0:137634ff4186 64 #if defined(POLARSSL_THREADING_C)
ansond 0:137634ff4186 65 polarssl_mutex_init( &ctx->mutex );
ansond 0:137634ff4186 66 #endif
ansond 0:137634ff4186 67
ansond 0:137634ff4186 68 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
ansond 0:137634ff4186 69 sha512_starts( &ctx->accumulator, 0 );
ansond 0:137634ff4186 70 #else
ansond 0:137634ff4186 71 sha256_starts( &ctx->accumulator, 0 );
ansond 0:137634ff4186 72 #endif
ansond 0:137634ff4186 73 #if defined(POLARSSL_HAVEGE_C)
ansond 0:137634ff4186 74 havege_init( &ctx->havege_data );
ansond 0:137634ff4186 75 #endif
ansond 0:137634ff4186 76
ansond 0:137634ff4186 77 #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
ansond 0:137634ff4186 78 #if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
ansond 0:137634ff4186 79 entropy_add_source( ctx, platform_entropy_poll, NULL,
ansond 0:137634ff4186 80 ENTROPY_MIN_PLATFORM );
ansond 0:137634ff4186 81 #endif
ansond 0:137634ff4186 82 #if defined(POLARSSL_TIMING_C)
ansond 0:137634ff4186 83 entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
ansond 0:137634ff4186 84 #endif
ansond 0:137634ff4186 85 #if defined(POLARSSL_HAVEGE_C)
ansond 0:137634ff4186 86 entropy_add_source( ctx, havege_poll, &ctx->havege_data,
ansond 0:137634ff4186 87 ENTROPY_MIN_HAVEGE );
ansond 0:137634ff4186 88 #endif
ansond 0:137634ff4186 89 #endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
ansond 0:137634ff4186 90 }
ansond 0:137634ff4186 91
ansond 0:137634ff4186 92 void entropy_free( entropy_context *ctx )
ansond 0:137634ff4186 93 {
ansond 0:137634ff4186 94 #if defined(POLARSSL_HAVEGE_C)
ansond 0:137634ff4186 95 havege_free( &ctx->havege_data );
ansond 0:137634ff4186 96 #endif
ansond 0:137634ff4186 97 #if defined(POLARSSL_THREADING_C)
ansond 0:137634ff4186 98 polarssl_mutex_free( &ctx->mutex );
ansond 0:137634ff4186 99 #endif
ansond 0:137634ff4186 100 polarssl_zeroize( ctx, sizeof( entropy_context ) );
ansond 0:137634ff4186 101 }
ansond 0:137634ff4186 102
ansond 0:137634ff4186 103 int entropy_add_source( entropy_context *ctx,
ansond 0:137634ff4186 104 f_source_ptr f_source, void *p_source,
ansond 0:137634ff4186 105 size_t threshold )
ansond 0:137634ff4186 106 {
ansond 0:137634ff4186 107 int index, ret = 0;
ansond 0:137634ff4186 108
ansond 0:137634ff4186 109 #if defined(POLARSSL_THREADING_C)
ansond 0:137634ff4186 110 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
ansond 0:137634ff4186 111 return( ret );
ansond 0:137634ff4186 112 #endif
ansond 0:137634ff4186 113
ansond 0:137634ff4186 114 index = ctx->source_count;
ansond 0:137634ff4186 115 if( index >= ENTROPY_MAX_SOURCES )
ansond 0:137634ff4186 116 {
ansond 0:137634ff4186 117 ret = POLARSSL_ERR_ENTROPY_MAX_SOURCES;
ansond 0:137634ff4186 118 goto exit;
ansond 0:137634ff4186 119 }
ansond 0:137634ff4186 120
ansond 0:137634ff4186 121 ctx->source[index].f_source = f_source;
ansond 0:137634ff4186 122 ctx->source[index].p_source = p_source;
ansond 0:137634ff4186 123 ctx->source[index].threshold = threshold;
ansond 0:137634ff4186 124
ansond 0:137634ff4186 125 ctx->source_count++;
ansond 0:137634ff4186 126
ansond 0:137634ff4186 127 exit:
ansond 0:137634ff4186 128 #if defined(POLARSSL_THREADING_C)
ansond 0:137634ff4186 129 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
ansond 0:137634ff4186 130 return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
ansond 0:137634ff4186 131 #endif
ansond 0:137634ff4186 132
ansond 0:137634ff4186 133 return( ret );
ansond 0:137634ff4186 134 }
ansond 0:137634ff4186 135
ansond 0:137634ff4186 136 /*
ansond 0:137634ff4186 137 * Entropy accumulator update
ansond 0:137634ff4186 138 */
ansond 0:137634ff4186 139 static int entropy_update( entropy_context *ctx, unsigned char source_id,
ansond 0:137634ff4186 140 const unsigned char *data, size_t len )
ansond 0:137634ff4186 141 {
ansond 0:137634ff4186 142 unsigned char header[2];
ansond 0:137634ff4186 143 unsigned char tmp[ENTROPY_BLOCK_SIZE];
ansond 0:137634ff4186 144 size_t use_len = len;
ansond 0:137634ff4186 145 const unsigned char *p = data;
ansond 0:137634ff4186 146
ansond 0:137634ff4186 147 if( use_len > ENTROPY_BLOCK_SIZE )
ansond 0:137634ff4186 148 {
ansond 0:137634ff4186 149 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
ansond 0:137634ff4186 150 sha512( data, len, tmp, 0 );
ansond 0:137634ff4186 151 #else
ansond 0:137634ff4186 152 sha256( data, len, tmp, 0 );
ansond 0:137634ff4186 153 #endif
ansond 0:137634ff4186 154 p = tmp;
ansond 0:137634ff4186 155 use_len = ENTROPY_BLOCK_SIZE;
ansond 0:137634ff4186 156 }
ansond 0:137634ff4186 157
ansond 0:137634ff4186 158 header[0] = source_id;
ansond 0:137634ff4186 159 header[1] = use_len & 0xFF;
ansond 0:137634ff4186 160
ansond 0:137634ff4186 161 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
ansond 0:137634ff4186 162 sha512_update( &ctx->accumulator, header, 2 );
ansond 0:137634ff4186 163 sha512_update( &ctx->accumulator, p, use_len );
ansond 0:137634ff4186 164 #else
ansond 0:137634ff4186 165 sha256_update( &ctx->accumulator, header, 2 );
ansond 0:137634ff4186 166 sha256_update( &ctx->accumulator, p, use_len );
ansond 0:137634ff4186 167 #endif
ansond 0:137634ff4186 168
ansond 0:137634ff4186 169 return( 0 );
ansond 0:137634ff4186 170 }
ansond 0:137634ff4186 171
ansond 0:137634ff4186 172 int entropy_update_manual( entropy_context *ctx,
ansond 0:137634ff4186 173 const unsigned char *data, size_t len )
ansond 0:137634ff4186 174 {
ansond 0:137634ff4186 175 int ret;
ansond 0:137634ff4186 176
ansond 0:137634ff4186 177 #if defined(POLARSSL_THREADING_C)
ansond 0:137634ff4186 178 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
ansond 0:137634ff4186 179 return( ret );
ansond 0:137634ff4186 180 #endif
ansond 0:137634ff4186 181
ansond 0:137634ff4186 182 ret = entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
ansond 0:137634ff4186 183
ansond 0:137634ff4186 184 #if defined(POLARSSL_THREADING_C)
ansond 0:137634ff4186 185 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
ansond 0:137634ff4186 186 return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
ansond 0:137634ff4186 187 #endif
ansond 0:137634ff4186 188
ansond 0:137634ff4186 189 return( ret );
ansond 0:137634ff4186 190 }
ansond 0:137634ff4186 191
ansond 0:137634ff4186 192 /*
ansond 0:137634ff4186 193 * Run through the different sources to add entropy to our accumulator
ansond 0:137634ff4186 194 */
ansond 0:137634ff4186 195 static int entropy_gather_internal( entropy_context *ctx )
ansond 0:137634ff4186 196 {
ansond 0:137634ff4186 197 int ret, i;
ansond 0:137634ff4186 198 unsigned char buf[ENTROPY_MAX_GATHER];
ansond 0:137634ff4186 199 size_t olen;
ansond 0:137634ff4186 200
ansond 0:137634ff4186 201 if( ctx->source_count == 0 )
ansond 0:137634ff4186 202 return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
ansond 0:137634ff4186 203
ansond 0:137634ff4186 204 /*
ansond 0:137634ff4186 205 * Run through our entropy sources
ansond 0:137634ff4186 206 */
ansond 0:137634ff4186 207 for( i = 0; i < ctx->source_count; i++ )
ansond 0:137634ff4186 208 {
ansond 0:137634ff4186 209 olen = 0;
ansond 0:137634ff4186 210 if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
ansond 0:137634ff4186 211 buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
ansond 0:137634ff4186 212 {
ansond 0:137634ff4186 213 return( ret );
ansond 0:137634ff4186 214 }
ansond 0:137634ff4186 215
ansond 0:137634ff4186 216 /*
ansond 0:137634ff4186 217 * Add if we actually gathered something
ansond 0:137634ff4186 218 */
ansond 0:137634ff4186 219 if( olen > 0 )
ansond 0:137634ff4186 220 {
ansond 0:137634ff4186 221 entropy_update( ctx, (unsigned char) i, buf, olen );
ansond 0:137634ff4186 222 ctx->source[i].size += olen;
ansond 0:137634ff4186 223 }
ansond 0:137634ff4186 224 }
ansond 0:137634ff4186 225
ansond 0:137634ff4186 226 return( 0 );
ansond 0:137634ff4186 227 }
ansond 0:137634ff4186 228
ansond 0:137634ff4186 229 /*
ansond 0:137634ff4186 230 * Thread-safe wrapper for entropy_gather_internal()
ansond 0:137634ff4186 231 */
ansond 0:137634ff4186 232 int entropy_gather( entropy_context *ctx )
ansond 0:137634ff4186 233 {
ansond 0:137634ff4186 234 int ret;
ansond 0:137634ff4186 235
ansond 0:137634ff4186 236 #if defined(POLARSSL_THREADING_C)
ansond 0:137634ff4186 237 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
ansond 0:137634ff4186 238 return( ret );
ansond 0:137634ff4186 239 #endif
ansond 0:137634ff4186 240
ansond 0:137634ff4186 241 ret = entropy_gather_internal( ctx );
ansond 0:137634ff4186 242
ansond 0:137634ff4186 243 #if defined(POLARSSL_THREADING_C)
ansond 0:137634ff4186 244 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
ansond 0:137634ff4186 245 return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
ansond 0:137634ff4186 246 #endif
ansond 0:137634ff4186 247
ansond 0:137634ff4186 248 return( ret );
ansond 0:137634ff4186 249 }
ansond 0:137634ff4186 250
ansond 0:137634ff4186 251 int entropy_func( void *data, unsigned char *output, size_t len )
ansond 0:137634ff4186 252 {
ansond 0:137634ff4186 253 int ret, count = 0, i, reached;
ansond 0:137634ff4186 254 entropy_context *ctx = (entropy_context *) data;
ansond 0:137634ff4186 255 unsigned char buf[ENTROPY_BLOCK_SIZE];
ansond 0:137634ff4186 256
ansond 0:137634ff4186 257 if( len > ENTROPY_BLOCK_SIZE )
ansond 0:137634ff4186 258 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
ansond 0:137634ff4186 259
ansond 0:137634ff4186 260 #if defined(POLARSSL_THREADING_C)
ansond 0:137634ff4186 261 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
ansond 0:137634ff4186 262 return( ret );
ansond 0:137634ff4186 263 #endif
ansond 0:137634ff4186 264
ansond 0:137634ff4186 265 /*
ansond 0:137634ff4186 266 * Always gather extra entropy before a call
ansond 0:137634ff4186 267 */
ansond 0:137634ff4186 268 do
ansond 0:137634ff4186 269 {
ansond 0:137634ff4186 270 if( count++ > ENTROPY_MAX_LOOP )
ansond 0:137634ff4186 271 {
ansond 0:137634ff4186 272 ret = POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
ansond 0:137634ff4186 273 goto exit;
ansond 0:137634ff4186 274 }
ansond 0:137634ff4186 275
ansond 0:137634ff4186 276 if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
ansond 0:137634ff4186 277 goto exit;
ansond 0:137634ff4186 278
ansond 0:137634ff4186 279 reached = 0;
ansond 0:137634ff4186 280
ansond 0:137634ff4186 281 for( i = 0; i < ctx->source_count; i++ )
ansond 0:137634ff4186 282 if( ctx->source[i].size >= ctx->source[i].threshold )
ansond 0:137634ff4186 283 reached++;
ansond 0:137634ff4186 284 }
ansond 0:137634ff4186 285 while( reached != ctx->source_count );
ansond 0:137634ff4186 286
ansond 0:137634ff4186 287 memset( buf, 0, ENTROPY_BLOCK_SIZE );
ansond 0:137634ff4186 288
ansond 0:137634ff4186 289 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
ansond 0:137634ff4186 290 sha512_finish( &ctx->accumulator, buf );
ansond 0:137634ff4186 291
ansond 0:137634ff4186 292 /*
ansond 0:137634ff4186 293 * Reset accumulator and counters and recycle existing entropy
ansond 0:137634ff4186 294 */
ansond 0:137634ff4186 295 memset( &ctx->accumulator, 0, sizeof( sha512_context ) );
ansond 0:137634ff4186 296 sha512_starts( &ctx->accumulator, 0 );
ansond 0:137634ff4186 297 sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
ansond 0:137634ff4186 298
ansond 0:137634ff4186 299 /*
ansond 0:137634ff4186 300 * Perform second SHA-512 on entropy
ansond 0:137634ff4186 301 */
ansond 0:137634ff4186 302 sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
ansond 0:137634ff4186 303 #else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
ansond 0:137634ff4186 304 sha256_finish( &ctx->accumulator, buf );
ansond 0:137634ff4186 305
ansond 0:137634ff4186 306 /*
ansond 0:137634ff4186 307 * Reset accumulator and counters and recycle existing entropy
ansond 0:137634ff4186 308 */
ansond 0:137634ff4186 309 memset( &ctx->accumulator, 0, sizeof( sha256_context ) );
ansond 0:137634ff4186 310 sha256_starts( &ctx->accumulator, 0 );
ansond 0:137634ff4186 311 sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
ansond 0:137634ff4186 312
ansond 0:137634ff4186 313 /*
ansond 0:137634ff4186 314 * Perform second SHA-256 on entropy
ansond 0:137634ff4186 315 */
ansond 0:137634ff4186 316 sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
ansond 0:137634ff4186 317 #endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
ansond 0:137634ff4186 318
ansond 0:137634ff4186 319 for( i = 0; i < ctx->source_count; i++ )
ansond 0:137634ff4186 320 ctx->source[i].size = 0;
ansond 0:137634ff4186 321
ansond 0:137634ff4186 322 memcpy( output, buf, len );
ansond 0:137634ff4186 323
ansond 0:137634ff4186 324 ret = 0;
ansond 0:137634ff4186 325
ansond 0:137634ff4186 326 exit:
ansond 0:137634ff4186 327 #if defined(POLARSSL_THREADING_C)
ansond 0:137634ff4186 328 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
ansond 0:137634ff4186 329 return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
ansond 0:137634ff4186 330 #endif
ansond 0:137634ff4186 331
ansond 0:137634ff4186 332 return( ret );
ansond 0:137634ff4186 333 }
ansond 0:137634ff4186 334
ansond 0:137634ff4186 335 #if defined(POLARSSL_FS_IO)
ansond 0:137634ff4186 336 int entropy_write_seed_file( entropy_context *ctx, const char *path )
ansond 0:137634ff4186 337 {
ansond 0:137634ff4186 338 int ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR;
ansond 0:137634ff4186 339 FILE *f;
ansond 0:137634ff4186 340 unsigned char buf[ENTROPY_BLOCK_SIZE];
ansond 0:137634ff4186 341
ansond 0:137634ff4186 342 if( ( f = fopen( path, "wb" ) ) == NULL )
ansond 0:137634ff4186 343 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
ansond 0:137634ff4186 344
ansond 0:137634ff4186 345 if( ( ret = entropy_func( ctx, buf, ENTROPY_BLOCK_SIZE ) ) != 0 )
ansond 0:137634ff4186 346 goto exit;
ansond 0:137634ff4186 347
ansond 0:137634ff4186 348 if( fwrite( buf, 1, ENTROPY_BLOCK_SIZE, f ) != ENTROPY_BLOCK_SIZE )
ansond 0:137634ff4186 349 {
ansond 0:137634ff4186 350 ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR;
ansond 0:137634ff4186 351 goto exit;
ansond 0:137634ff4186 352 }
ansond 0:137634ff4186 353
ansond 0:137634ff4186 354 ret = 0;
ansond 0:137634ff4186 355
ansond 0:137634ff4186 356 exit:
ansond 0:137634ff4186 357 fclose( f );
ansond 0:137634ff4186 358 return( ret );
ansond 0:137634ff4186 359 }
ansond 0:137634ff4186 360
ansond 0:137634ff4186 361 int entropy_update_seed_file( entropy_context *ctx, const char *path )
ansond 0:137634ff4186 362 {
ansond 0:137634ff4186 363 FILE *f;
ansond 0:137634ff4186 364 size_t n;
ansond 0:137634ff4186 365 unsigned char buf[ ENTROPY_MAX_SEED_SIZE ];
ansond 0:137634ff4186 366
ansond 0:137634ff4186 367 if( ( f = fopen( path, "rb" ) ) == NULL )
ansond 0:137634ff4186 368 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
ansond 0:137634ff4186 369
ansond 0:137634ff4186 370 fseek( f, 0, SEEK_END );
ansond 0:137634ff4186 371 n = (size_t) ftell( f );
ansond 0:137634ff4186 372 fseek( f, 0, SEEK_SET );
ansond 0:137634ff4186 373
ansond 0:137634ff4186 374 if( n > ENTROPY_MAX_SEED_SIZE )
ansond 0:137634ff4186 375 n = ENTROPY_MAX_SEED_SIZE;
ansond 0:137634ff4186 376
ansond 0:137634ff4186 377 if( fread( buf, 1, n, f ) != n )
ansond 0:137634ff4186 378 {
ansond 0:137634ff4186 379 fclose( f );
ansond 0:137634ff4186 380 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
ansond 0:137634ff4186 381 }
ansond 0:137634ff4186 382
ansond 0:137634ff4186 383 fclose( f );
ansond 0:137634ff4186 384
ansond 0:137634ff4186 385 entropy_update_manual( ctx, buf, n );
ansond 0:137634ff4186 386
ansond 0:137634ff4186 387 return( entropy_write_seed_file( ctx, path ) );
ansond 0:137634ff4186 388 }
ansond 0:137634ff4186 389 #endif /* POLARSSL_FS_IO */
ansond 0:137634ff4186 390
ansond 0:137634ff4186 391 #if defined(POLARSSL_SELF_TEST)
ansond 0:137634ff4186 392 /*
ansond 0:137634ff4186 393 * Dummy source function
ansond 0:137634ff4186 394 */
ansond 0:137634ff4186 395 static int entropy_dummy_source( void *data, unsigned char *output,
ansond 0:137634ff4186 396 size_t len, size_t *olen )
ansond 0:137634ff4186 397 {
ansond 0:137634ff4186 398 ((void) data);
ansond 0:137634ff4186 399
ansond 0:137634ff4186 400 memset( output, 0x2a, len );
ansond 0:137634ff4186 401 *olen = len;
ansond 0:137634ff4186 402
ansond 0:137634ff4186 403 return( 0 );
ansond 0:137634ff4186 404 }
ansond 0:137634ff4186 405
ansond 0:137634ff4186 406 /*
ansond 0:137634ff4186 407 * The actual entropy quality is hard to test, but we can at least
ansond 0:137634ff4186 408 * test that the functions don't cause errors and write the correct
ansond 0:137634ff4186 409 * amount of data to buffers.
ansond 0:137634ff4186 410 */
ansond 0:137634ff4186 411 int entropy_self_test( int verbose )
ansond 0:137634ff4186 412 {
ansond 0:137634ff4186 413 int ret = 0;
ansond 0:137634ff4186 414 entropy_context ctx;
ansond 0:137634ff4186 415 unsigned char buf[ENTROPY_BLOCK_SIZE] = { 0 };
ansond 0:137634ff4186 416 unsigned char acc[ENTROPY_BLOCK_SIZE] = { 0 };
ansond 0:137634ff4186 417 size_t i, j;
ansond 0:137634ff4186 418
ansond 0:137634ff4186 419 if( verbose != 0 )
ansond 0:137634ff4186 420 polarssl_printf( " ENTROPY test: " );
ansond 0:137634ff4186 421
ansond 0:137634ff4186 422 entropy_init( &ctx );
ansond 0:137634ff4186 423
ansond 0:137634ff4186 424 ret = entropy_add_source( &ctx, entropy_dummy_source, NULL, 16 );
ansond 0:137634ff4186 425 if( ret != 0 )
ansond 0:137634ff4186 426 goto cleanup;
ansond 0:137634ff4186 427
ansond 0:137634ff4186 428 if( ( ret = entropy_gather( &ctx ) ) != 0 )
ansond 0:137634ff4186 429 goto cleanup;
ansond 0:137634ff4186 430
ansond 0:137634ff4186 431 if( ( ret = entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
ansond 0:137634ff4186 432 goto cleanup;
ansond 0:137634ff4186 433
ansond 0:137634ff4186 434 /*
ansond 0:137634ff4186 435 * To test that entropy_func writes correct number of bytes:
ansond 0:137634ff4186 436 * - use the whole buffer and rely on ASan to detect overruns
ansond 0:137634ff4186 437 * - collect entropy 8 times and OR the result in an accumulator:
ansond 0:137634ff4186 438 * any byte should then be 0 with probably 2^(-64), so requiring
ansond 0:137634ff4186 439 * each of the 32 or 64 bytes to be non-zero has a false failure rate
ansond 0:137634ff4186 440 * of at most 2^(-58) which is acceptable.
ansond 0:137634ff4186 441 */
ansond 0:137634ff4186 442 for( i = 0; i < 8; i++ )
ansond 0:137634ff4186 443 {
ansond 0:137634ff4186 444 if( ( ret = entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
ansond 0:137634ff4186 445 goto cleanup;
ansond 0:137634ff4186 446
ansond 0:137634ff4186 447 for( j = 0; j < sizeof( buf ); j++ )
ansond 0:137634ff4186 448 acc[j] |= buf[j];
ansond 0:137634ff4186 449 }
ansond 0:137634ff4186 450
ansond 0:137634ff4186 451 for( j = 0; j < sizeof( buf ); j++ )
ansond 0:137634ff4186 452 {
ansond 0:137634ff4186 453 if( acc[j] == 0 )
ansond 0:137634ff4186 454 {
ansond 0:137634ff4186 455 ret = 1;
ansond 0:137634ff4186 456 goto cleanup;
ansond 0:137634ff4186 457 }
ansond 0:137634ff4186 458 }
ansond 0:137634ff4186 459
ansond 0:137634ff4186 460 cleanup:
ansond 0:137634ff4186 461 entropy_free( &ctx );
ansond 0:137634ff4186 462
ansond 0:137634ff4186 463 if( verbose != 0 )
ansond 0:137634ff4186 464 {
ansond 0:137634ff4186 465 if( ret != 0 )
ansond 0:137634ff4186 466 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 467 else
ansond 0:137634ff4186 468 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 469
ansond 0:137634ff4186 470 polarssl_printf( "\n" );
ansond 0:137634ff4186 471 }
ansond 0:137634ff4186 472
ansond 0:137634ff4186 473 return( ret != 0 );
ansond 0:137634ff4186 474 }
ansond 0:137634ff4186 475 #endif /* POLARSSL_SELF_TEST */
ansond 0:137634ff4186 476
ansond 0:137634ff4186 477 #endif /* POLARSSL_ENTROPY_C */
ansond 0:137634ff4186 478