blob: 98289266817750e0540da79da6994a2a928ecbca [file] [log] [blame]
Paul Bakker6083fd22011-12-03 21:45:14 +00001/*
2 * Entropy accumulator implementation
3 *
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02004 * Copyright (C) 2006-2013, Brainspark B.V.
Paul Bakker6083fd22011-12-03 21:45:14 +00005 *
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#include "polarssl/config.h"
27
28#if defined(POLARSSL_ENTROPY_C)
29
30#include "polarssl/entropy.h"
31#include "polarssl/entropy_poll.h"
32
Paul Bakker66ff70d2014-03-26 11:54:05 +010033#if defined(POLARSSL_FS_IO)
34#include <stdio.h>
35#endif
36
Paul Bakker28c7e7f2011-12-15 19:49:30 +000037#if defined(POLARSSL_HAVEGE_C)
38#include "polarssl/havege.h"
39#endif
40
Paul Bakker6083fd22011-12-03 21:45:14 +000041#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
42
43void entropy_init( entropy_context *ctx )
44{
45 memset( ctx, 0, sizeof(entropy_context) );
46
Paul Bakkerf4e7dc52013-09-28 15:23:57 +020047#if defined(POLARSSL_THREADING_C)
48 polarssl_mutex_init( &ctx->mutex );
49#endif
50
Paul Bakkerfb08fd22013-08-27 15:06:26 +020051#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
Paul Bakker9e36f042013-06-30 14:34:05 +020052 sha512_starts( &ctx->accumulator, 0 );
Paul Bakkerfb08fd22013-08-27 15:06:26 +020053#else
54 sha256_starts( &ctx->accumulator, 0 );
55#endif
Paul Bakker43655f42011-12-15 20:11:16 +000056#if defined(POLARSSL_HAVEGE_C)
57 havege_init( &ctx->havege_data );
58#endif
Paul Bakker6083fd22011-12-03 21:45:14 +000059
Paul Bakker43655f42011-12-15 20:11:16 +000060#if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
Paul Bakker6083fd22011-12-03 21:45:14 +000061#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000062 entropy_add_source( ctx, platform_entropy_poll, NULL,
63 ENTROPY_MIN_PLATFORM );
Paul Bakker6083fd22011-12-03 21:45:14 +000064#endif
65#if defined(POLARSSL_TIMING_C)
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000066 entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
Paul Bakker6083fd22011-12-03 21:45:14 +000067#endif
Paul Bakker28c7e7f2011-12-15 19:49:30 +000068#if defined(POLARSSL_HAVEGE_C)
Paul Bakker28c7e7f2011-12-15 19:49:30 +000069 entropy_add_source( ctx, havege_poll, &ctx->havege_data,
70 ENTROPY_MIN_HAVEGE );
71#endif
Paul Bakker43655f42011-12-15 20:11:16 +000072#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
Paul Bakker6083fd22011-12-03 21:45:14 +000073}
74
Paul Bakker1ffefac2013-09-28 15:23:03 +020075void entropy_free( entropy_context *ctx )
76{
77 ((void) ctx);
Paul Bakkerf4e7dc52013-09-28 15:23:57 +020078#if defined(POLARSSL_THREADING_C)
79 polarssl_mutex_free( &ctx->mutex );
80#endif
Paul Bakker1ffefac2013-09-28 15:23:03 +020081}
82
Paul Bakker6083fd22011-12-03 21:45:14 +000083int entropy_add_source( entropy_context *ctx,
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000084 f_source_ptr f_source, void *p_source,
85 size_t threshold )
Paul Bakker6083fd22011-12-03 21:45:14 +000086{
Paul Bakker47703a02014-02-06 15:01:20 +010087 int index, ret = 0;
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000088
Paul Bakker47703a02014-02-06 15:01:20 +010089#if defined(POLARSSL_THREADING_C)
90 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
91 return( ret );
92#endif
93
94 index = ctx->source_count;
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000095 if( index >= ENTROPY_MAX_SOURCES )
Paul Bakker47703a02014-02-06 15:01:20 +010096 {
97 ret = POLARSSL_ERR_ENTROPY_MAX_SOURCES;
98 goto exit;
99 }
Paul Bakker6083fd22011-12-03 21:45:14 +0000100
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000101 ctx->source[index].f_source = f_source;
102 ctx->source[index].p_source = p_source;
103 ctx->source[index].threshold = threshold;
Paul Bakker6083fd22011-12-03 21:45:14 +0000104
105 ctx->source_count++;
106
Paul Bakker47703a02014-02-06 15:01:20 +0100107exit:
108#if defined(POLARSSL_THREADING_C)
109 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
110 return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
111#endif
112
113 return( ret );
Paul Bakker6083fd22011-12-03 21:45:14 +0000114}
115
116/*
117 * Entropy accumulator update
118 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200119static int entropy_update( entropy_context *ctx, unsigned char source_id,
120 const unsigned char *data, size_t len )
Paul Bakker6083fd22011-12-03 21:45:14 +0000121{
122 unsigned char header[2];
123 unsigned char tmp[ENTROPY_BLOCK_SIZE];
124 size_t use_len = len;
125 const unsigned char *p = data;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200126
Paul Bakker6083fd22011-12-03 21:45:14 +0000127 if( use_len > ENTROPY_BLOCK_SIZE )
128 {
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200129#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
Paul Bakker9e36f042013-06-30 14:34:05 +0200130 sha512( data, len, tmp, 0 );
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200131#else
132 sha256( data, len, tmp, 0 );
133#endif
Paul Bakker6083fd22011-12-03 21:45:14 +0000134 p = tmp;
135 use_len = ENTROPY_BLOCK_SIZE;
136 }
137
138 header[0] = source_id;
139 header[1] = use_len & 0xFF;
140
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200141#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
Paul Bakker9e36f042013-06-30 14:34:05 +0200142 sha512_update( &ctx->accumulator, header, 2 );
143 sha512_update( &ctx->accumulator, p, use_len );
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200144#else
145 sha256_update( &ctx->accumulator, header, 2 );
146 sha256_update( &ctx->accumulator, p, use_len );
147#endif
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200148
Paul Bakker6083fd22011-12-03 21:45:14 +0000149 return( 0 );
150}
151
152int entropy_update_manual( entropy_context *ctx,
153 const unsigned char *data, size_t len )
154{
Paul Bakker47703a02014-02-06 15:01:20 +0100155 int ret;
156
157#if defined(POLARSSL_THREADING_C)
158 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
159 return( ret );
160#endif
161
162 ret = entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
163
164#if defined(POLARSSL_THREADING_C)
165 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
166 return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
167#endif
168
169 return ( ret );
Paul Bakker6083fd22011-12-03 21:45:14 +0000170}
171
172/*
173 * Run through the different sources to add entropy to our accumulator
174 */
Paul Bakker47703a02014-02-06 15:01:20 +0100175static int entropy_gather_internal( entropy_context *ctx )
Paul Bakker6083fd22011-12-03 21:45:14 +0000176{
177 int ret, i;
178 unsigned char buf[ENTROPY_MAX_GATHER];
179 size_t olen;
Paul Bakker47703a02014-02-06 15:01:20 +0100180
Paul Bakker43655f42011-12-15 20:11:16 +0000181 if( ctx->source_count == 0 )
182 return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
183
Paul Bakker6083fd22011-12-03 21:45:14 +0000184 /*
185 * Run through our entropy sources
186 */
187 for( i = 0; i < ctx->source_count; i++ )
188 {
189 olen = 0;
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000190 if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
Paul Bakker6083fd22011-12-03 21:45:14 +0000191 buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
192 {
193 return( ret );
194 }
195
196 /*
197 * Add if we actually gathered something
198 */
199 if( olen > 0 )
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000200 {
Paul Bakker6083fd22011-12-03 21:45:14 +0000201 entropy_update( ctx, (unsigned char) i, buf, olen );
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000202 ctx->source[i].size += olen;
203 }
Paul Bakker6083fd22011-12-03 21:45:14 +0000204 }
205
206 return( 0 );
207}
208
Paul Bakker47703a02014-02-06 15:01:20 +0100209/*
210 * Thread-safe wrapper for entropy_gather_internal()
211 */
212int entropy_gather( entropy_context *ctx )
213{
214 int ret;
215
216#if defined(POLARSSL_THREADING_C)
217 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
218 return( ret );
219#endif
220
221 ret = entropy_gather_internal( ctx );
222
223#if defined(POLARSSL_THREADING_C)
224 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
225 return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
226#endif
227
228 return ( ret );
229}
230
Paul Bakker6083fd22011-12-03 21:45:14 +0000231int entropy_func( void *data, unsigned char *output, size_t len )
232{
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000233 int ret, count = 0, i, reached;
Paul Bakker6083fd22011-12-03 21:45:14 +0000234 entropy_context *ctx = (entropy_context *) data;
235 unsigned char buf[ENTROPY_BLOCK_SIZE];
236
237 if( len > ENTROPY_BLOCK_SIZE )
238 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
239
Paul Bakkerf4e7dc52013-09-28 15:23:57 +0200240#if defined(POLARSSL_THREADING_C)
241 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
242 return( ret );
243#endif
244
Paul Bakker6083fd22011-12-03 21:45:14 +0000245 /*
246 * Always gather extra entropy before a call
247 */
248 do
249 {
250 if( count++ > ENTROPY_MAX_LOOP )
Paul Bakkerf4e7dc52013-09-28 15:23:57 +0200251 {
252 ret = POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
253 goto exit;
254 }
Paul Bakker6083fd22011-12-03 21:45:14 +0000255
Paul Bakker47703a02014-02-06 15:01:20 +0100256 if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
Paul Bakkerf4e7dc52013-09-28 15:23:57 +0200257 goto exit;
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000258
259 reached = 0;
260
261 for( i = 0; i < ctx->source_count; i++ )
262 if( ctx->source[i].size >= ctx->source[i].threshold )
263 reached++;
Paul Bakker6083fd22011-12-03 21:45:14 +0000264 }
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000265 while( reached != ctx->source_count );
Paul Bakker6083fd22011-12-03 21:45:14 +0000266
267 memset( buf, 0, ENTROPY_BLOCK_SIZE );
268
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200269#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
Paul Bakker9e36f042013-06-30 14:34:05 +0200270 sha512_finish( &ctx->accumulator, buf );
271
Paul Bakker6083fd22011-12-03 21:45:14 +0000272 /*
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000273 * Reset accumulator and counters and recycle existing entropy
Paul Bakker6083fd22011-12-03 21:45:14 +0000274 */
Paul Bakker9e36f042013-06-30 14:34:05 +0200275 memset( &ctx->accumulator, 0, sizeof( sha512_context ) );
276 sha512_starts( &ctx->accumulator, 0 );
277 sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200278
279 /*
Paul Bakkerb13d3ff2014-03-26 12:51:25 +0100280 * Perform second SHA-512 on entropy
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200281 */
Paul Bakkerb13d3ff2014-03-26 12:51:25 +0100282 sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
283#else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
284 sha256_finish( &ctx->accumulator, buf );
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200285
286 /*
287 * Reset accumulator and counters and recycle existing entropy
288 */
289 memset( &ctx->accumulator, 0, sizeof( sha256_context ) );
290 sha256_starts( &ctx->accumulator, 0 );
291 sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
Paul Bakkerb13d3ff2014-03-26 12:51:25 +0100292
293 /*
294 * Perform second SHA-256 on entropy
295 */
296 sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200297#endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000298
299 for( i = 0; i < ctx->source_count; i++ )
300 ctx->source[i].size = 0;
Paul Bakker6083fd22011-12-03 21:45:14 +0000301
302 memcpy( output, buf, len );
303
Paul Bakkerf4e7dc52013-09-28 15:23:57 +0200304 ret = 0;
305
306exit:
307#if defined(POLARSSL_THREADING_C)
308 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
309 return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
310#endif
311
312 return( ret );
Paul Bakker6083fd22011-12-03 21:45:14 +0000313}
314
Paul Bakker66ff70d2014-03-26 11:54:05 +0100315#if defined(POLARSSL_FS_IO)
316int entropy_write_seed_file( entropy_context *ctx, const char *path )
317{
318 int ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR;
319 FILE *f;
320 unsigned char buf[ENTROPY_BLOCK_SIZE];
321
322 if( ( f = fopen( path, "wb" ) ) == NULL )
323 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
324
325 if( ( ret = entropy_func( ctx, buf, ENTROPY_BLOCK_SIZE ) ) != 0 )
326 goto exit;
327
328 if( fwrite( buf, 1, ENTROPY_BLOCK_SIZE, f ) != ENTROPY_BLOCK_SIZE )
329 {
330 ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR;
331 goto exit;
332 }
333
334 ret = 0;
335
336exit:
337 fclose( f );
338 return( ret );
339}
340
341int entropy_update_seed_file( entropy_context *ctx, const char *path )
342{
343 FILE *f;
344 size_t n;
345 unsigned char buf[ ENTROPY_MAX_SEED_SIZE ];
346
347 if( ( f = fopen( path, "rb" ) ) == NULL )
348 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
349
350 fseek( f, 0, SEEK_END );
351 n = (size_t) ftell( f );
352 fseek( f, 0, SEEK_SET );
353
354 if( n > ENTROPY_MAX_SEED_SIZE )
355 n = ENTROPY_MAX_SEED_SIZE;
356
357 if( fread( buf, 1, n, f ) != n )
358 {
359 fclose( f );
360 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
361 }
362
363 fclose( f );
364
365 entropy_update_manual( ctx, buf, n );
366
367 return( entropy_write_seed_file( ctx, path ) );
368}
369#endif /* POLARSSL_FS_IO */
370
Paul Bakker6083fd22011-12-03 21:45:14 +0000371#endif