initial commit; it works
[psslcertgen.git] / src / libpolarssl / entropy.c
blobd99623af75531a2ef2f920a00b3607a3404dc72b
1 /*
2 * Entropy accumulator implementation
4 * Copyright (C) 2006-2011, Brainspark B.V.
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
9 * All rights reserved.
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 #include "config.h"
28 #if defined(POLARSSL_ENTROPY_C)
30 #include "entropy.h"
31 #include "entropy_poll.h"
33 #if defined(POLARSSL_HAVEGE_C)
34 #include "havege.h"
35 #endif
37 #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
39 void entropy_init( entropy_context *ctx )
41 memset( ctx, 0, sizeof(entropy_context) );
43 sha4_starts( &ctx->accumulator, 0 );
44 #if defined(POLARSSL_HAVEGE_C)
45 havege_init( &ctx->havege_data );
46 #endif
48 #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
49 #if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
50 entropy_add_source( ctx, platform_entropy_poll, NULL,
51 ENTROPY_MIN_PLATFORM );
52 #endif
53 #if defined(POLARSSL_TIMING_C)
54 entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
55 #endif
56 #if defined(POLARSSL_HAVEGE_C)
57 entropy_add_source( ctx, havege_poll, &ctx->havege_data,
58 ENTROPY_MIN_HAVEGE );
59 #endif
60 #endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
63 int entropy_add_source( entropy_context *ctx,
64 f_source_ptr f_source, void *p_source,
65 size_t threshold )
67 int index = ctx->source_count;
69 if( index >= ENTROPY_MAX_SOURCES )
70 return( POLARSSL_ERR_ENTROPY_MAX_SOURCES );
72 ctx->source[index].f_source = f_source;
73 ctx->source[index].p_source = p_source;
74 ctx->source[index].threshold = threshold;
76 ctx->source_count++;
78 return( 0 );
82 * Entropy accumulator update
84 int entropy_update( entropy_context *ctx, unsigned char source_id,
85 const unsigned char *data, size_t len )
87 unsigned char header[2];
88 unsigned char tmp[ENTROPY_BLOCK_SIZE];
89 size_t use_len = len;
90 const unsigned char *p = data;
92 if( use_len > ENTROPY_BLOCK_SIZE )
94 sha4( data, len, tmp, 0 );
96 p = tmp;
97 use_len = ENTROPY_BLOCK_SIZE;
100 header[0] = source_id;
101 header[1] = use_len & 0xFF;
103 sha4_update( &ctx->accumulator, header, 2 );
104 sha4_update( &ctx->accumulator, p, use_len );
106 return( 0 );
109 int entropy_update_manual( entropy_context *ctx,
110 const unsigned char *data, size_t len )
112 return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
116 * Run through the different sources to add entropy to our accumulator
118 int entropy_gather( entropy_context *ctx )
120 int ret, i;
121 unsigned char buf[ENTROPY_MAX_GATHER];
122 size_t olen;
124 if( ctx->source_count == 0 )
125 return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
128 * Run through our entropy sources
130 for( i = 0; i < ctx->source_count; i++ )
132 olen = 0;
133 if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
134 buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
136 return( ret );
140 * Add if we actually gathered something
142 if( olen > 0 )
144 entropy_update( ctx, (unsigned char) i, buf, olen );
145 ctx->source[i].size += olen;
149 return( 0 );
152 int entropy_func( void *data, unsigned char *output, size_t len )
154 int ret, count = 0, i, reached;
155 entropy_context *ctx = (entropy_context *) data;
156 unsigned char buf[ENTROPY_BLOCK_SIZE];
158 if( len > ENTROPY_BLOCK_SIZE )
159 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
162 * Always gather extra entropy before a call
166 if( count++ > ENTROPY_MAX_LOOP )
167 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
169 if( ( ret = entropy_gather( ctx ) ) != 0 )
170 return( ret );
172 reached = 0;
174 for( i = 0; i < ctx->source_count; i++ )
175 if( ctx->source[i].size >= ctx->source[i].threshold )
176 reached++;
178 while( reached != ctx->source_count );
180 memset( buf, 0, ENTROPY_BLOCK_SIZE );
182 sha4_finish( &ctx->accumulator, buf );
185 * Perform second SHA-512 on entropy
187 sha4( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
190 * Reset accumulator and counters and recycle existing entropy
192 memset( &ctx->accumulator, 0, sizeof( sha4_context ) );
193 sha4_starts( &ctx->accumulator, 0 );
194 sha4_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
196 for( i = 0; i < ctx->source_count; i++ )
197 ctx->source[i].size = 0;
199 memcpy( output, buf, len );
201 return( 0 );
204 #endif