PolarSSL v1.2.9
entropy.c
Go to the documentation of this file.
1 /*
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 
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  sha4_starts( &ctx->accumulator, 0 );
44 #if defined(POLARSSL_HAVEGE_C)
45  havege_init( &ctx->havege_data );
46 #endif
47 
48 #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
49 #if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
52 #endif
53 #if defined(POLARSSL_TIMING_C)
55 #endif
56 #if defined(POLARSSL_HAVEGE_C)
57  entropy_add_source( ctx, havege_poll, &ctx->havege_data,
59 #endif
60 #endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
61 }
62 
64  f_source_ptr f_source, void *p_source,
65  size_t threshold )
66 {
67  int index = ctx->source_count;
68 
69  if( index >= ENTROPY_MAX_SOURCES )
71 
72  ctx->source[index].f_source = f_source;
73  ctx->source[index].p_source = p_source;
74  ctx->source[index].threshold = threshold;
75 
76  ctx->source_count++;
77 
78  return( 0 );
79 }
80 
81 /*
82  * Entropy accumulator update
83  */
84 int 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 
106  return( 0 );
107 }
108 
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  */
119 {
120  int ret, i;
121  unsigned char buf[ENTROPY_MAX_GATHER];
122  size_t olen;
123 
124  if( ctx->source_count == 0 )
126 
127  /*
128  * Run through our entropy sources
129  */
130  for( i = 0; i < ctx->source_count; i++ )
131  {
132  olen = 0;
133  if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
134  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 )
143  {
144  entropy_update( ctx, (unsigned char) i, buf, olen );
145  ctx->source[i].size += olen;
146  }
147  }
148 
149  return( 0 );
150 }
151 
152 int entropy_func( void *data, unsigned char *output, size_t len )
153 {
154  int ret, count = 0, i, reached;
155  entropy_context *ctx = (entropy_context *) data;
156  unsigned char buf[ENTROPY_BLOCK_SIZE];
157 
158  if( len > ENTROPY_BLOCK_SIZE )
160 
161  /*
162  * Always gather extra entropy before a call
163  */
164  do
165  {
166  if( count++ > ENTROPY_MAX_LOOP )
168 
169  if( ( ret = entropy_gather( ctx ) ) != 0 )
170  return( ret );
171 
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++;
177  }
178  while( reached != ctx->source_count );
179 
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  /*
190  * Reset accumulator and counters and recycle existing entropy
191  */
192  memset( &ctx->accumulator, 0, sizeof( sha4_context ) );
193  sha4_starts( &ctx->accumulator, 0 );
195 
196  for( i = 0; i < ctx->source_count; i++ )
197  ctx->source[i].size = 0;
198 
199  memcpy( output, buf, len );
200 
201  return( 0 );
202 }
203 
204 #endif
int entropy_add_source(entropy_context *ctx, f_source_ptr f_source, void *p_source, size_t threshold)
Adds an entropy source to poll.
#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:40
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:84
int source_count
Definition: entropy.h:87
#define ENTROPY_MAX_GATHER
Maximum amount requested from entropy sources.
Definition: entropy.h:45
void * p_source
The callback data pointer.
Definition: entropy.h:75
Platform-specific and custom entropy polling functions.
Entropy accumulator implementation.
#define ENTROPY_SOURCE_MANUAL
Definition: entropy.h:50
source_state source[ENTROPY_MAX_SOURCES]
Definition: entropy.h:88
#define ENTROPY_BLOCK_SIZE
Block size of entropy accumulator (SHA-512)
Definition: entropy.h:48
void sha4_starts(sha4_context *ctx, int is384)
SHA-512 context setup.
#define ENTROPY_MIN_HAVEGE
Minimum for HAVEGE.
Definition: entropy_poll.h:42
size_t size
Amount received.
Definition: entropy.h:76
f_source_ptr f_source
The entropy source callback.
Definition: entropy.h:74
void sha4_update(sha4_context *ctx, const unsigned char *input, size_t ilen)
SHA-512 process buffer.
HAVEGE: HArdware Volatile Entropy Gathering and Expansion.
sha4_context accumulator
Definition: entropy.h:86
int platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen)
Platform-specific entropy poll callback.
#define ENTROPY_MAX_SOURCES
Maximum number of sources supported.
Definition: entropy.h:44
void havege_init(havege_state *hs)
HAVEGE initialization.
void sha4(const unsigned char *input, size_t ilen, unsigned char output[64], int is384)
Output = SHA-512( input buffer )
size_t threshold
Minimum level required before release.
Definition: entropy.h:77
#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED
No sources have been added to poll.
Definition: entropy.h:41
SHA-512 context structure.
Definition: sha4.h:51
void sha4_finish(sha4_context *ctx, unsigned char output[64])
SHA-512 final digest.
#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED
Critical entropy source failure.
Definition: entropy.h:39
int(* f_source_ptr)(void *, unsigned char *, size_t, size_t *)
Entropy poll callback pointer.
Definition: entropy.h:67
int hardclock_poll(void *data, unsigned char *output, size_t len, size_t *olen)
hardclock-based entropy poll callback
int entropy_func(void *data, unsigned char *output, size_t len)
Retrieve entropy from the accumulator (Max ENTROPY_BLOCK_SIZE)