PolarSSL v1.3.1
entropy.c
Go to the documentation of this file.
1 /*
2  * Entropy accumulator implementation
3  *
4  * Copyright (C) 2006-2013, 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 
33 #if defined(POLARSSL_HAVEGE_C)
34 #include "polarssl/havege.h"
35 #endif
36 
37 #define ENTROPY_MAX_LOOP 256
39 void entropy_init( entropy_context *ctx )
40 {
41  memset( ctx, 0, sizeof(entropy_context) );
42 
43 #if defined(POLARSSL_THREADING_C)
44  polarssl_mutex_init( &ctx->mutex );
45 #endif
46 
47 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
48  sha512_starts( &ctx->accumulator, 0 );
49 #else
50  sha256_starts( &ctx->accumulator, 0 );
51 #endif
52 #if defined(POLARSSL_HAVEGE_C)
53  havege_init( &ctx->havege_data );
54 #endif
55 
56 #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
57 #if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
60 #endif
61 #if defined(POLARSSL_TIMING_C)
63 #endif
64 #if defined(POLARSSL_HAVEGE_C)
65  entropy_add_source( ctx, havege_poll, &ctx->havege_data,
67 #endif
68 #endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
69 }
70 
71 void entropy_free( entropy_context *ctx )
72 {
73  ((void) ctx);
74 #if defined(POLARSSL_THREADING_C)
75  polarssl_mutex_free( &ctx->mutex );
76 #endif
77 }
78 
80  f_source_ptr f_source, void *p_source,
81  size_t threshold )
82 {
83  int index = ctx->source_count;
84 
85  if( index >= ENTROPY_MAX_SOURCES )
87 
88  ctx->source[index].f_source = f_source;
89  ctx->source[index].p_source = p_source;
90  ctx->source[index].threshold = threshold;
91 
92  ctx->source_count++;
93 
94  return( 0 );
95 }
96 
97 /*
98  * Entropy accumulator update
99  */
100 static int entropy_update( entropy_context *ctx, unsigned char source_id,
101  const unsigned char *data, size_t len )
102 {
103  unsigned char header[2];
104  unsigned char tmp[ENTROPY_BLOCK_SIZE];
105  size_t use_len = len;
106  const unsigned char *p = data;
107 
108  if( use_len > ENTROPY_BLOCK_SIZE )
109  {
110 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
111  sha512( data, len, tmp, 0 );
112 #else
113  sha256( data, len, tmp, 0 );
114 #endif
115  p = tmp;
116  use_len = ENTROPY_BLOCK_SIZE;
117  }
118 
119  header[0] = source_id;
120  header[1] = use_len & 0xFF;
121 
122 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
123  sha512_update( &ctx->accumulator, header, 2 );
124  sha512_update( &ctx->accumulator, p, use_len );
125 #else
126  sha256_update( &ctx->accumulator, header, 2 );
127  sha256_update( &ctx->accumulator, p, use_len );
128 #endif
129 
130  return( 0 );
131 }
132 
134  const unsigned char *data, size_t len )
135 {
136  return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
137 }
138 
139 /*
140  * Run through the different sources to add entropy to our accumulator
141  */
143 {
144  int ret, i;
145  unsigned char buf[ENTROPY_MAX_GATHER];
146  size_t olen;
147 
148  if( ctx->source_count == 0 )
150 
151  /*
152  * Run through our entropy sources
153  */
154  for( i = 0; i < ctx->source_count; i++ )
155  {
156  olen = 0;
157  if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
158  buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
159  {
160  return( ret );
161  }
162 
163  /*
164  * Add if we actually gathered something
165  */
166  if( olen > 0 )
167  {
168  entropy_update( ctx, (unsigned char) i, buf, olen );
169  ctx->source[i].size += olen;
170  }
171  }
172 
173  return( 0 );
174 }
175 
176 int entropy_func( void *data, unsigned char *output, size_t len )
177 {
178  int ret, count = 0, i, reached;
179  entropy_context *ctx = (entropy_context *) data;
180  unsigned char buf[ENTROPY_BLOCK_SIZE];
181 
182  if( len > ENTROPY_BLOCK_SIZE )
184 
185 #if defined(POLARSSL_THREADING_C)
186  if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
187  return( ret );
188 #endif
189 
190  /*
191  * Always gather extra entropy before a call
192  */
193  do
194  {
195  if( count++ > ENTROPY_MAX_LOOP )
196  {
198  goto exit;
199  }
200 
201  if( ( ret = entropy_gather( ctx ) ) != 0 )
202  goto exit;
203 
204  reached = 0;
205 
206  for( i = 0; i < ctx->source_count; i++ )
207  if( ctx->source[i].size >= ctx->source[i].threshold )
208  reached++;
209  }
210  while( reached != ctx->source_count );
211 
212  memset( buf, 0, ENTROPY_BLOCK_SIZE );
213 
214 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
215  sha512_finish( &ctx->accumulator, buf );
216 
217  /*
218  * Perform second SHA-512 on entropy
219  */
220  sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
221 
222  /*
223  * Reset accumulator and counters and recycle existing entropy
224  */
225  memset( &ctx->accumulator, 0, sizeof( sha512_context ) );
226  sha512_starts( &ctx->accumulator, 0 );
228 #else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
229  sha256_finish( &ctx->accumulator, buf );
230 
231  /*
232  * Perform second SHA-256 on entropy
233  */
234  sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
235 
236  /*
237  * Reset accumulator and counters and recycle existing entropy
238  */
239  memset( &ctx->accumulator, 0, sizeof( sha256_context ) );
240  sha256_starts( &ctx->accumulator, 0 );
242 #endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
243 
244  for( i = 0; i < ctx->source_count; i++ )
245  ctx->source[i].size = 0;
246 
247  memcpy( output, buf, len );
248 
249  ret = 0;
250 
251 exit:
252 #if defined(POLARSSL_THREADING_C)
253  if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
255 #endif
256 
257  return( ret );
258 }
259 
260 #endif
int(* polarssl_mutex_lock)(threading_mutex_t *mutex)
int entropy_add_source(entropy_context *ctx, f_source_ptr f_source, void *p_source, size_t threshold)
Adds an entropy source to poll.
void sha256_update(sha256_context *ctx, const unsigned char *input, size_t ilen)
SHA-256 process buffer.
void sha256(const unsigned char *input, size_t ilen, unsigned char output[32], int is224)
Output = SHA-256( input buffer )
#define ENTROPY_MIN_PLATFORM
Minimum for platform source.
Definition: entropy_poll.h:41
int entropy_update_manual(entropy_context *ctx, const unsigned char *data, size_t len)
Add data to the accumulator manually.
#define POLARSSL_ERR_ENTROPY_MAX_SOURCES
No more sources can be added.
Definition: entropy.h:53
sha512_context accumulator
Definition: entropy.h:104
Configuration options (set of defines)
int entropy_gather(entropy_context *ctx)
Trigger an extra gather poll for the accumulator.
#define ENTROPY_MIN_HARDCLOCK
Minimum for hardclock()
Definition: entropy_poll.h:43
Entropy context structure.
Definition: entropy.h:101
int source_count
Definition: entropy.h:108
#define ENTROPY_MAX_GATHER
Maximum amount requested from entropy sources.
Definition: entropy.h:58
void * p_source
The callback data pointer.
Definition: entropy.h:92
Platform-specific and custom entropy polling functions.
Entropy accumulator implementation.
#define ENTROPY_SOURCE_MANUAL
Definition: entropy.h:67
source_state source[ENTROPY_MAX_SOURCES]
Definition: entropy.h:109
#define ENTROPY_BLOCK_SIZE
Block size of entropy accumulator (SHA-512)
Definition: entropy.h:62
#define ENTROPY_MIN_HAVEGE
Minimum for HAVEGE.
Definition: entropy_poll.h:42
size_t size
Amount received.
Definition: entropy.h:93
f_source_ptr f_source
The entropy source callback.
Definition: entropy.h:91
void sha256_starts(sha256_context *ctx, int is224)
SHA-256 context setup.
SHA-512 context structure.
Definition: sha512.h:55
void sha512_starts(sha512_context *ctx, int is384)
SHA-512 context setup.
void sha512(const unsigned char *input, size_t ilen, unsigned char output[64], int is384)
Output = SHA-512( input buffer )
HAVEGE: HArdware Volatile Entropy Gathering and Expansion.
int platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen)
Platform-specific entropy poll callback.
int(* polarssl_mutex_free)(threading_mutex_t *mutex)
#define ENTROPY_MAX_SOURCES
Maximum number of sources supported.
Definition: entropy.h:57
void sha512_finish(sha512_context *ctx, unsigned char output[64])
SHA-512 final digest.
void havege_init(havege_state *hs)
HAVEGE initialization.
size_t threshold
Minimum level required before release.
Definition: entropy.h:94
int(* polarssl_mutex_unlock)(threading_mutex_t *mutex)
#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED
No sources have been added to poll.
Definition: entropy.h:54
int(* polarssl_mutex_init)(threading_mutex_t *mutex)
#define POLARSSL_ERR_THREADING_MUTEX_ERROR
Locking / unlocking / free failed with error code.
Definition: threading.h:40
void sha256_finish(sha256_context *ctx, unsigned char output[32])
SHA-256 final digest.
SHA-256 context structure.
Definition: sha256.h:54
#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED
Critical entropy source failure.
Definition: entropy.h:52
int(* f_source_ptr)(void *, unsigned char *, size_t, size_t *)
Entropy poll callback pointer.
Definition: entropy.h:84
int hardclock_poll(void *data, unsigned char *output, size_t len, size_t *olen)
hardclock-based entropy poll callback
void sha512_update(sha512_context *ctx, const unsigned char *input, size_t ilen)
SHA-512 process buffer.
int entropy_func(void *data, unsigned char *output, size_t len)
Retrieve entropy from the accumulator (Max ENTROPY_BLOCK_SIZE) (Thread-safe if POLARSSL_THREADING_C i...
void entropy_free(entropy_context *ctx)
Free the data in the context.