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