blob: ebace08812c76cdc4de6fe4ddc539b3e3f655b75 [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 );
44
45#if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000046 entropy_add_source( ctx, platform_entropy_poll, NULL,
47 ENTROPY_MIN_PLATFORM );
Paul Bakker6083fd22011-12-03 21:45:14 +000048#endif
49#if defined(POLARSSL_TIMING_C)
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000050 entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
Paul Bakker6083fd22011-12-03 21:45:14 +000051#endif
Paul Bakker28c7e7f2011-12-15 19:49:30 +000052#if defined(POLARSSL_HAVEGE_C)
53 havege_init( &ctx->havege_data );
54 entropy_add_source( ctx, havege_poll, &ctx->havege_data,
55 ENTROPY_MIN_HAVEGE );
56#endif
Paul Bakker6083fd22011-12-03 21:45:14 +000057}
58
59int entropy_add_source( entropy_context *ctx,
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000060 f_source_ptr f_source, void *p_source,
61 size_t threshold )
Paul Bakker6083fd22011-12-03 21:45:14 +000062{
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000063 int index = ctx->source_count;
64
65 if( index >= ENTROPY_MAX_SOURCES )
Paul Bakker6083fd22011-12-03 21:45:14 +000066 return( POLARSSL_ERR_ENTROPY_MAX_SOURCES );
67
Paul Bakkerbd4a9d02011-12-10 17:02:19 +000068 ctx->source[index].f_source = f_source;
69 ctx->source[index].p_source = p_source;
70 ctx->source[index].threshold = threshold;
Paul Bakker6083fd22011-12-03 21:45:14 +000071
72 ctx->source_count++;
73
74 return( 0 );
75}
76
77/*
78 * Entropy accumulator update
79 */
80int entropy_update( entropy_context *ctx, unsigned char source_id,
81 const unsigned char *data, size_t len )
82{
83 unsigned char header[2];
84 unsigned char tmp[ENTROPY_BLOCK_SIZE];
85 size_t use_len = len;
86 const unsigned char *p = data;
87
88 if( use_len > ENTROPY_BLOCK_SIZE )
89 {
90 sha4( data, len, tmp, 0 );
91
92 p = tmp;
93 use_len = ENTROPY_BLOCK_SIZE;
94 }
95
96 header[0] = source_id;
97 header[1] = use_len & 0xFF;
98
99 sha4_update( &ctx->accumulator, header, 2 );
100 sha4_update( &ctx->accumulator, p, use_len );
101
Paul Bakker6083fd22011-12-03 21:45:14 +0000102 return( 0 );
103}
104
105int entropy_update_manual( entropy_context *ctx,
106 const unsigned char *data, size_t len )
107{
108 return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
109}
110
111/*
112 * Run through the different sources to add entropy to our accumulator
113 */
114int entropy_gather( entropy_context *ctx )
115{
116 int ret, i;
117 unsigned char buf[ENTROPY_MAX_GATHER];
118 size_t olen;
119
120 /*
121 * Run through our entropy sources
122 */
123 for( i = 0; i < ctx->source_count; i++ )
124 {
125 olen = 0;
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000126 if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
Paul Bakker6083fd22011-12-03 21:45:14 +0000127 buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
128 {
129 return( ret );
130 }
131
132 /*
133 * Add if we actually gathered something
134 */
135 if( olen > 0 )
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000136 {
Paul Bakker6083fd22011-12-03 21:45:14 +0000137 entropy_update( ctx, (unsigned char) i, buf, olen );
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000138 ctx->source[i].size += olen;
139 }
Paul Bakker6083fd22011-12-03 21:45:14 +0000140 }
141
142 return( 0 );
143}
144
145int entropy_func( void *data, unsigned char *output, size_t len )
146{
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000147 int ret, count = 0, i, reached;
Paul Bakker6083fd22011-12-03 21:45:14 +0000148 entropy_context *ctx = (entropy_context *) data;
149 unsigned char buf[ENTROPY_BLOCK_SIZE];
150
151 if( len > ENTROPY_BLOCK_SIZE )
152 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
153
154 /*
155 * Always gather extra entropy before a call
156 */
157 do
158 {
159 if( count++ > ENTROPY_MAX_LOOP )
160 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
161
162 if( ( ret = entropy_gather( ctx ) ) != 0 )
163 return( ret );
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000164
165 reached = 0;
166
167 for( i = 0; i < ctx->source_count; i++ )
168 if( ctx->source[i].size >= ctx->source[i].threshold )
169 reached++;
Paul Bakker6083fd22011-12-03 21:45:14 +0000170 }
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000171 while( reached != ctx->source_count );
Paul Bakker6083fd22011-12-03 21:45:14 +0000172
173 memset( buf, 0, ENTROPY_BLOCK_SIZE );
174
175 sha4_finish( &ctx->accumulator, buf );
176
177 /*
178 * Perform second SHA-512 on entropy
179 */
180 sha4( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
181
182 /*
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000183 * Reset accumulator and counters and recycle existing entropy
Paul Bakker6083fd22011-12-03 21:45:14 +0000184 */
185 memset( &ctx->accumulator, 0, sizeof( sha4_context ) );
186 sha4_starts( &ctx->accumulator, 0 );
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000187 sha4_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
188
189 for( i = 0; i < ctx->source_count; i++ )
190 ctx->source[i].size = 0;
Paul Bakker6083fd22011-12-03 21:45:14 +0000191
192 memcpy( output, buf, len );
193
194 return( 0 );
195}
196
197#endif