blob: 9662454721cb8b9cdd353d296c802fd26c3769cd [file] [log] [blame]
Paul Bakker6083fd22011-12-03 21:45:14 +00001/*
2 * Entropy accumulator implementation
3 *
4 * Copyright (C) 2006-2011, 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#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
43 sha4_starts( &ctx->accumulator, 0 );
Paul Bakker43655f42011-12-15 20:11:16 +000044#if defined(POLARSSL_HAVEGE_C)
45 havege_init( &ctx->havege_data );
46#endif
Paul Bakker6083fd22011-12-03 21:45:14 +000047
Paul Bakker43655f42011-12-15 20:11:16 +000048#if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
Paul Bakker6083fd22011-12-03 21:45:14 +000049#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000050 entropy_add_source( ctx, platform_entropy_poll, NULL,
51 ENTROPY_MIN_PLATFORM );
Paul Bakker6083fd22011-12-03 21:45:14 +000052#endif
53#if defined(POLARSSL_TIMING_C)
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000054 entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
Paul Bakker6083fd22011-12-03 21:45:14 +000055#endif
Paul Bakker28c7e7f2011-12-15 19:49:30 +000056#if defined(POLARSSL_HAVEGE_C)
Paul Bakker28c7e7f2011-12-15 19:49:30 +000057 entropy_add_source( ctx, havege_poll, &ctx->havege_data,
58 ENTROPY_MIN_HAVEGE );
59#endif
Paul Bakker43655f42011-12-15 20:11:16 +000060#endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
Paul Bakker6083fd22011-12-03 21:45:14 +000061}
62
63int entropy_add_source( entropy_context *ctx,
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000064 f_source_ptr f_source, void *p_source,
65 size_t threshold )
Paul Bakker6083fd22011-12-03 21:45:14 +000066{
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000067 int index = ctx->source_count;
68
69 if( index >= ENTROPY_MAX_SOURCES )
Paul Bakker6083fd22011-12-03 21:45:14 +000070 return( POLARSSL_ERR_ENTROPY_MAX_SOURCES );
71
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000072 ctx->source[index].f_source = f_source;
73 ctx->source[index].p_source = p_source;
74 ctx->source[index].threshold = threshold;
Paul Bakker6083fd22011-12-03 21:45:14 +000075
76 ctx->source_count++;
77
78 return( 0 );
79}
80
81/*
82 * Entropy accumulator update
83 */
84int entropy_update( entropy_context *ctx, unsigned char source_id,
85 const unsigned char *data, size_t len )
86{
87 unsigned char header[2];
88 unsigned char tmp[ENTROPY_BLOCK_SIZE];
89 size_t use_len = len;
90 const unsigned char *p = data;
91
92 if( use_len > ENTROPY_BLOCK_SIZE )
93 {
94 sha4( data, len, tmp, 0 );
95
96 p = tmp;
97 use_len = ENTROPY_BLOCK_SIZE;
98 }
99
100 header[0] = source_id;
101 header[1] = use_len & 0xFF;
102
103 sha4_update( &ctx->accumulator, header, 2 );
104 sha4_update( &ctx->accumulator, p, use_len );
105
Paul Bakker6083fd22011-12-03 21:45:14 +0000106 return( 0 );
107}
108
109int entropy_update_manual( entropy_context *ctx,
110 const unsigned char *data, size_t len )
111{
112 return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
113}
114
115/*
116 * Run through the different sources to add entropy to our accumulator
117 */
118int entropy_gather( entropy_context *ctx )
119{
120 int ret, i;
121 unsigned char buf[ENTROPY_MAX_GATHER];
122 size_t olen;
123
Paul Bakker43655f42011-12-15 20:11:16 +0000124 if( ctx->source_count == 0 )
125 return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
126
Paul Bakker6083fd22011-12-03 21:45:14 +0000127 /*
128 * Run through our entropy sources
129 */
130 for( i = 0; i < ctx->source_count; i++ )
131 {
132 olen = 0;
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000133 if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
Paul Bakker6083fd22011-12-03 21:45:14 +0000134 buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
135 {
136 return( ret );
137 }
138
139 /*
140 * Add if we actually gathered something
141 */
142 if( olen > 0 )
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000143 {
Paul Bakker6083fd22011-12-03 21:45:14 +0000144 entropy_update( ctx, (unsigned char) i, buf, olen );
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000145 ctx->source[i].size += olen;
146 }
Paul Bakker6083fd22011-12-03 21:45:14 +0000147 }
148
149 return( 0 );
150}
151
152int entropy_func( void *data, unsigned char *output, size_t len )
153{
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000154 int ret, count = 0, i, reached;
Paul Bakker6083fd22011-12-03 21:45:14 +0000155 entropy_context *ctx = (entropy_context *) data;
156 unsigned char buf[ENTROPY_BLOCK_SIZE];
157
158 if( len > ENTROPY_BLOCK_SIZE )
159 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
160
161 /*
162 * Always gather extra entropy before a call
163 */
164 do
165 {
166 if( count++ > ENTROPY_MAX_LOOP )
167 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
168
169 if( ( ret = entropy_gather( ctx ) ) != 0 )
170 return( ret );
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000171
172 reached = 0;
173
174 for( i = 0; i < ctx->source_count; i++ )
175 if( ctx->source[i].size >= ctx->source[i].threshold )
176 reached++;
Paul Bakker6083fd22011-12-03 21:45:14 +0000177 }
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000178 while( reached != ctx->source_count );
Paul Bakker6083fd22011-12-03 21:45:14 +0000179
180 memset( buf, 0, ENTROPY_BLOCK_SIZE );
181
182 sha4_finish( &ctx->accumulator, buf );
183
184 /*
185 * Perform second SHA-512 on entropy
186 */
187 sha4( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
188
189 /*
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000190 * Reset accumulator and counters and recycle existing entropy
Paul Bakker6083fd22011-12-03 21:45:14 +0000191 */
192 memset( &ctx->accumulator, 0, sizeof( sha4_context ) );
193 sha4_starts( &ctx->accumulator, 0 );
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000194 sha4_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
195
196 for( i = 0; i < ctx->source_count; i++ )
197 ctx->source[i].size = 0;
Paul Bakker6083fd22011-12-03 21:45:14 +0000198
199 memcpy( output, buf, len );
200
201 return( 0 );
202}
203
204#endif