2 * Entropy accumulator implementation
4 * Copyright (C) 2006-2014, Brainspark B.V.
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
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.
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.
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.
26 #if !defined(POLARSSL_CONFIG_FILE)
29 #include POLARSSL_CONFIG_FILE
32 #if defined(POLARSSL_ENTROPY_C)
35 #include "entropy_poll.h"
37 #if defined(POLARSSL_FS_IO)
41 #if defined(POLARSSL_HAVEGE_C)
45 #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
47 void entropy_init( entropy_context
*ctx
)
49 memset( ctx
, 0, sizeof(entropy_context
) );
51 #if defined(POLARSSL_THREADING_C)
52 polarssl_mutex_init( &ctx
->mutex
);
55 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
56 sha512_starts( &ctx
->accumulator
, 0 );
58 sha256_starts( &ctx
->accumulator
, 0 );
60 #if defined(POLARSSL_HAVEGE_C)
61 havege_init( &ctx
->havege_data
);
64 #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
65 #if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
66 entropy_add_source( ctx
, platform_entropy_poll
, NULL
,
67 ENTROPY_MIN_PLATFORM
);
69 #if defined(POLARSSL_TIMING_C)
70 entropy_add_source( ctx
, hardclock_poll
, NULL
, ENTROPY_MIN_HARDCLOCK
);
72 #if defined(POLARSSL_HAVEGE_C)
73 entropy_add_source( ctx
, havege_poll
, &ctx
->havege_data
,
76 #endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
79 void entropy_free( entropy_context
*ctx
)
82 #if defined(POLARSSL_THREADING_C)
83 polarssl_mutex_free( &ctx
->mutex
);
87 int entropy_add_source( entropy_context
*ctx
,
88 f_source_ptr f_source
, void *p_source
,
93 #if defined(POLARSSL_THREADING_C)
94 if( ( ret
= polarssl_mutex_lock( &ctx
->mutex
) ) != 0 )
98 index
= ctx
->source_count
;
99 if( index
>= ENTROPY_MAX_SOURCES
)
101 ret
= POLARSSL_ERR_ENTROPY_MAX_SOURCES
;
105 ctx
->source
[index
].f_source
= f_source
;
106 ctx
->source
[index
].p_source
= p_source
;
107 ctx
->source
[index
].threshold
= threshold
;
112 #if defined(POLARSSL_THREADING_C)
113 if( polarssl_mutex_unlock( &ctx
->mutex
) != 0 )
114 return( POLARSSL_ERR_THREADING_MUTEX_ERROR
);
121 * Entropy accumulator update
123 static int entropy_update( entropy_context
*ctx
, unsigned char source_id
,
124 const unsigned char *data
, size_t len
)
126 unsigned char header
[2];
127 unsigned char tmp
[ENTROPY_BLOCK_SIZE
];
128 size_t use_len
= len
;
129 const unsigned char *p
= data
;
131 if( use_len
> ENTROPY_BLOCK_SIZE
)
133 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
134 sha512( data
, len
, tmp
, 0 );
136 sha256( data
, len
, tmp
, 0 );
139 use_len
= ENTROPY_BLOCK_SIZE
;
142 header
[0] = source_id
;
143 header
[1] = use_len
& 0xFF;
145 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
146 sha512_update( &ctx
->accumulator
, header
, 2 );
147 sha512_update( &ctx
->accumulator
, p
, use_len
);
149 sha256_update( &ctx
->accumulator
, header
, 2 );
150 sha256_update( &ctx
->accumulator
, p
, use_len
);
156 int entropy_update_manual( entropy_context
*ctx
,
157 const unsigned char *data
, size_t len
)
161 #if defined(POLARSSL_THREADING_C)
162 if( ( ret
= polarssl_mutex_lock( &ctx
->mutex
) ) != 0 )
166 ret
= entropy_update( ctx
, ENTROPY_SOURCE_MANUAL
, data
, len
);
168 #if defined(POLARSSL_THREADING_C)
169 if( polarssl_mutex_unlock( &ctx
->mutex
) != 0 )
170 return( POLARSSL_ERR_THREADING_MUTEX_ERROR
);
177 * Run through the different sources to add entropy to our accumulator
179 static int entropy_gather_internal( entropy_context
*ctx
)
182 unsigned char buf
[ENTROPY_MAX_GATHER
];
185 if( ctx
->source_count
== 0 )
186 return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED
);
189 * Run through our entropy sources
191 for( i
= 0; i
< ctx
->source_count
; i
++ )
194 if ( ( ret
= ctx
->source
[i
].f_source( ctx
->source
[i
].p_source
,
195 buf
, ENTROPY_MAX_GATHER
, &olen
) ) != 0 )
201 * Add if we actually gathered something
205 entropy_update( ctx
, (unsigned char) i
, buf
, olen
);
206 ctx
->source
[i
].size
+= olen
;
214 * Thread-safe wrapper for entropy_gather_internal()
216 int entropy_gather( entropy_context
*ctx
)
220 #if defined(POLARSSL_THREADING_C)
221 if( ( ret
= polarssl_mutex_lock( &ctx
->mutex
) ) != 0 )
225 ret
= entropy_gather_internal( ctx
);
227 #if defined(POLARSSL_THREADING_C)
228 if( polarssl_mutex_unlock( &ctx
->mutex
) != 0 )
229 return( POLARSSL_ERR_THREADING_MUTEX_ERROR
);
235 int entropy_func( void *data
, unsigned char *output
, size_t len
)
237 int ret
, count
= 0, i
, reached
;
238 entropy_context
*ctx
= (entropy_context
*) data
;
239 unsigned char buf
[ENTROPY_BLOCK_SIZE
];
241 if( len
> ENTROPY_BLOCK_SIZE
)
242 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED
);
244 #if defined(POLARSSL_THREADING_C)
245 if( ( ret
= polarssl_mutex_lock( &ctx
->mutex
) ) != 0 )
250 * Always gather extra entropy before a call
254 if( count
++ > ENTROPY_MAX_LOOP
)
256 ret
= POLARSSL_ERR_ENTROPY_SOURCE_FAILED
;
260 if( ( ret
= entropy_gather_internal( ctx
) ) != 0 )
265 for( i
= 0; i
< ctx
->source_count
; i
++ )
266 if( ctx
->source
[i
].size
>= ctx
->source
[i
].threshold
)
269 while( reached
!= ctx
->source_count
);
271 memset( buf
, 0, ENTROPY_BLOCK_SIZE
);
273 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
274 sha512_finish( &ctx
->accumulator
, buf
);
277 * Reset accumulator and counters and recycle existing entropy
279 memset( &ctx
->accumulator
, 0, sizeof( sha512_context
) );
280 sha512_starts( &ctx
->accumulator
, 0 );
281 sha512_update( &ctx
->accumulator
, buf
, ENTROPY_BLOCK_SIZE
);
284 * Perform second SHA-512 on entropy
286 sha512( buf
, ENTROPY_BLOCK_SIZE
, buf
, 0 );
287 #else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
288 sha256_finish( &ctx
->accumulator
, buf
);
291 * Reset accumulator and counters and recycle existing entropy
293 memset( &ctx
->accumulator
, 0, sizeof( sha256_context
) );
294 sha256_starts( &ctx
->accumulator
, 0 );
295 sha256_update( &ctx
->accumulator
, buf
, ENTROPY_BLOCK_SIZE
);
298 * Perform second SHA-256 on entropy
300 sha256( buf
, ENTROPY_BLOCK_SIZE
, buf
, 0 );
301 #endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
303 for( i
= 0; i
< ctx
->source_count
; i
++ )
304 ctx
->source
[i
].size
= 0;
306 memcpy( output
, buf
, len
);
311 #if defined(POLARSSL_THREADING_C)
312 if( polarssl_mutex_unlock( &ctx
->mutex
) != 0 )
313 return( POLARSSL_ERR_THREADING_MUTEX_ERROR
);
319 #if defined(POLARSSL_FS_IO)
320 int entropy_write_seed_file( entropy_context
*ctx
, const char *path
)
322 int ret
= POLARSSL_ERR_ENTROPY_FILE_IO_ERROR
;
324 unsigned char buf
[ENTROPY_BLOCK_SIZE
];
326 if( ( f
= fopen( path
, "wb" ) ) == NULL
)
327 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR
);
329 if( ( ret
= entropy_func( ctx
, buf
, ENTROPY_BLOCK_SIZE
) ) != 0 )
332 if( fwrite( buf
, 1, ENTROPY_BLOCK_SIZE
, f
) != ENTROPY_BLOCK_SIZE
)
334 ret
= POLARSSL_ERR_ENTROPY_FILE_IO_ERROR
;
345 int entropy_update_seed_file( entropy_context
*ctx
, const char *path
)
349 unsigned char buf
[ ENTROPY_MAX_SEED_SIZE
];
351 if( ( f
= fopen( path
, "rb" ) ) == NULL
)
352 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR
);
354 fseek( f
, 0, SEEK_END
);
355 n
= (size_t) ftell( f
);
356 fseek( f
, 0, SEEK_SET
);
358 if( n
> ENTROPY_MAX_SEED_SIZE
)
359 n
= ENTROPY_MAX_SEED_SIZE
;
361 if( fread( buf
, 1, n
, f
) != n
)
364 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR
);
369 entropy_update_manual( ctx
, buf
, n
);
371 return( entropy_write_seed_file( ctx
, path
) );
373 #endif /* POLARSSL_FS_IO */
375 #endif /* POLARSSL_ENTROPY_C */