blob: d43f9833c11526e8e3b919c5d286338a4baa7758 [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 Bakker28c7e7f2011-12-15 19:49:30 +000033#if defined(POLARSSL_HAVEGE_C)
34#include "polarssl/havege.h"
35#endif
36
Paul Bakker6083fd22011-12-03 21:45:14 +000037#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
38
39void entropy_init( entropy_context *ctx )
40{
41 memset( ctx, 0, sizeof(entropy_context) );
42
Paul Bakkerfb08fd22013-08-27 15:06:26 +020043#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
Paul Bakker9e36f042013-06-30 14:34:05 +020044 sha512_starts( &ctx->accumulator, 0 );
Paul Bakkerfb08fd22013-08-27 15:06:26 +020045#else
46 sha256_starts( &ctx->accumulator, 0 );
47#endif
Paul Bakker43655f42011-12-15 20:11:16 +000048#if defined(POLARSSL_HAVEGE_C)
49 havege_init( &ctx->havege_data );
50#endif
Paul Bakker6083fd22011-12-03 21:45:14 +000051
Paul Bakker43655f42011-12-15 20:11:16 +000052#if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
Paul Bakker6083fd22011-12-03 21:45:14 +000053#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000054 entropy_add_source( ctx, platform_entropy_poll, NULL,
55 ENTROPY_MIN_PLATFORM );
Paul Bakker6083fd22011-12-03 21:45:14 +000056#endif
57#if defined(POLARSSL_TIMING_C)
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000058 entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
Paul Bakker6083fd22011-12-03 21:45:14 +000059#endif
Paul Bakker28c7e7f2011-12-15 19:49:30 +000060#if defined(POLARSSL_HAVEGE_C)
Paul Bakker28c7e7f2011-12-15 19:49:30 +000061 entropy_add_source( ctx, havege_poll, &ctx->havege_data,
62 ENTROPY_MIN_HAVEGE );
63#endif
Paul Bakker43655f42011-12-15 20:11:16 +000064#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
Paul Bakker6083fd22011-12-03 21:45:14 +000065}
66
Paul Bakker1ffefac2013-09-28 15:23:03 +020067void entropy_free( entropy_context *ctx )
68{
69 ((void) ctx);
70}
71
Paul Bakker6083fd22011-12-03 21:45:14 +000072int entropy_add_source( entropy_context *ctx,
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000073 f_source_ptr f_source, void *p_source,
74 size_t threshold )
Paul Bakker6083fd22011-12-03 21:45:14 +000075{
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000076 int index = ctx->source_count;
77
78 if( index >= ENTROPY_MAX_SOURCES )
Paul Bakker6083fd22011-12-03 21:45:14 +000079 return( POLARSSL_ERR_ENTROPY_MAX_SOURCES );
80
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000081 ctx->source[index].f_source = f_source;
82 ctx->source[index].p_source = p_source;
83 ctx->source[index].threshold = threshold;
Paul Bakker6083fd22011-12-03 21:45:14 +000084
85 ctx->source_count++;
86
87 return( 0 );
88}
89
90/*
91 * Entropy accumulator update
92 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +020093static int entropy_update( entropy_context *ctx, unsigned char source_id,
94 const unsigned char *data, size_t len )
Paul Bakker6083fd22011-12-03 21:45:14 +000095{
96 unsigned char header[2];
97 unsigned char tmp[ENTROPY_BLOCK_SIZE];
98 size_t use_len = len;
99 const unsigned char *p = data;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200100
Paul Bakker6083fd22011-12-03 21:45:14 +0000101 if( use_len > ENTROPY_BLOCK_SIZE )
102 {
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200103#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
Paul Bakker9e36f042013-06-30 14:34:05 +0200104 sha512( data, len, tmp, 0 );
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200105#else
106 sha256( data, len, tmp, 0 );
107#endif
Paul Bakker6083fd22011-12-03 21:45:14 +0000108 p = tmp;
109 use_len = ENTROPY_BLOCK_SIZE;
110 }
111
112 header[0] = source_id;
113 header[1] = use_len & 0xFF;
114
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200115#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
Paul Bakker9e36f042013-06-30 14:34:05 +0200116 sha512_update( &ctx->accumulator, header, 2 );
117 sha512_update( &ctx->accumulator, p, use_len );
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200118#else
119 sha256_update( &ctx->accumulator, header, 2 );
120 sha256_update( &ctx->accumulator, p, use_len );
121#endif
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200122
Paul Bakker6083fd22011-12-03 21:45:14 +0000123 return( 0 );
124}
125
126int entropy_update_manual( entropy_context *ctx,
127 const unsigned char *data, size_t len )
128{
129 return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
130}
131
132/*
133 * Run through the different sources to add entropy to our accumulator
134 */
135int entropy_gather( entropy_context *ctx )
136{
137 int ret, i;
138 unsigned char buf[ENTROPY_MAX_GATHER];
139 size_t olen;
140
Paul Bakker43655f42011-12-15 20:11:16 +0000141 if( ctx->source_count == 0 )
142 return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
143
Paul Bakker6083fd22011-12-03 21:45:14 +0000144 /*
145 * Run through our entropy sources
146 */
147 for( i = 0; i < ctx->source_count; i++ )
148 {
149 olen = 0;
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000150 if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
Paul Bakker6083fd22011-12-03 21:45:14 +0000151 buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
152 {
153 return( ret );
154 }
155
156 /*
157 * Add if we actually gathered something
158 */
159 if( olen > 0 )
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000160 {
Paul Bakker6083fd22011-12-03 21:45:14 +0000161 entropy_update( ctx, (unsigned char) i, buf, olen );
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000162 ctx->source[i].size += olen;
163 }
Paul Bakker6083fd22011-12-03 21:45:14 +0000164 }
165
166 return( 0 );
167}
168
169int entropy_func( void *data, unsigned char *output, size_t len )
170{
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000171 int ret, count = 0, i, reached;
Paul Bakker6083fd22011-12-03 21:45:14 +0000172 entropy_context *ctx = (entropy_context *) data;
173 unsigned char buf[ENTROPY_BLOCK_SIZE];
174
175 if( len > ENTROPY_BLOCK_SIZE )
176 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
177
178 /*
179 * Always gather extra entropy before a call
180 */
181 do
182 {
183 if( count++ > ENTROPY_MAX_LOOP )
184 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
185
186 if( ( ret = entropy_gather( ctx ) ) != 0 )
187 return( ret );
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000188
189 reached = 0;
190
191 for( i = 0; i < ctx->source_count; i++ )
192 if( ctx->source[i].size >= ctx->source[i].threshold )
193 reached++;
Paul Bakker6083fd22011-12-03 21:45:14 +0000194 }
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000195 while( reached != ctx->source_count );
Paul Bakker6083fd22011-12-03 21:45:14 +0000196
197 memset( buf, 0, ENTROPY_BLOCK_SIZE );
198
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200199#if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
Paul Bakker9e36f042013-06-30 14:34:05 +0200200 sha512_finish( &ctx->accumulator, buf );
201
Paul Bakker6083fd22011-12-03 21:45:14 +0000202 /*
203 * Perform second SHA-512 on entropy
204 */
Paul Bakker9e36f042013-06-30 14:34:05 +0200205 sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
Paul Bakker6083fd22011-12-03 21:45:14 +0000206
207 /*
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000208 * Reset accumulator and counters and recycle existing entropy
Paul Bakker6083fd22011-12-03 21:45:14 +0000209 */
Paul Bakker9e36f042013-06-30 14:34:05 +0200210 memset( &ctx->accumulator, 0, sizeof( sha512_context ) );
211 sha512_starts( &ctx->accumulator, 0 );
212 sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200213#else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
214 sha256_finish( &ctx->accumulator, buf );
215
216 /*
217 * Perform second SHA-256 on entropy
218 */
219 sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
220
221 /*
222 * Reset accumulator and counters and recycle existing entropy
223 */
224 memset( &ctx->accumulator, 0, sizeof( sha256_context ) );
225 sha256_starts( &ctx->accumulator, 0 );
226 sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
227#endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000228
229 for( i = 0; i < ctx->source_count; i++ )
230 ctx->source[i].size = 0;
Paul Bakker6083fd22011-12-03 21:45:14 +0000231
232 memcpy( output, buf, len );
233
234 return( 0 );
235}
236
237#endif