PolarSSL v1.1.4
|
00001 /* 00002 * Entropy accumulator implementation 00003 * 00004 * Copyright (C) 2006-2011, Brainspark B.V. 00005 * 00006 * This file is part of PolarSSL (http://www.polarssl.org) 00007 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> 00008 * 00009 * All rights reserved. 00010 * 00011 * This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License along 00022 * with this program; if not, write to the Free Software Foundation, Inc., 00023 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00024 */ 00025 00026 #include "polarssl/config.h" 00027 00028 #if defined(POLARSSL_ENTROPY_C) 00029 00030 #include "polarssl/entropy.h" 00031 #include "polarssl/entropy_poll.h" 00032 00033 #if defined(POLARSSL_HAVEGE_C) 00034 #include "polarssl/havege.h" 00035 #endif 00036 00037 #define ENTROPY_MAX_LOOP 256 00039 void entropy_init( entropy_context *ctx ) 00040 { 00041 memset( ctx, 0, sizeof(entropy_context) ); 00042 00043 sha4_starts( &ctx->accumulator, 0 ); 00044 #if defined(POLARSSL_HAVEGE_C) 00045 havege_init( &ctx->havege_data ); 00046 #endif 00047 00048 #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES) 00049 #if !defined(POLARSSL_NO_PLATFORM_ENTROPY) 00050 entropy_add_source( ctx, platform_entropy_poll, NULL, 00051 ENTROPY_MIN_PLATFORM ); 00052 #endif 00053 #if defined(POLARSSL_TIMING_C) 00054 entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK ); 00055 #endif 00056 #if defined(POLARSSL_HAVEGE_C) 00057 entropy_add_source( ctx, havege_poll, &ctx->havege_data, 00058 ENTROPY_MIN_HAVEGE ); 00059 #endif 00060 #endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */ 00061 } 00062 00063 int entropy_add_source( entropy_context *ctx, 00064 f_source_ptr f_source, void *p_source, 00065 size_t threshold ) 00066 { 00067 int index = ctx->source_count; 00068 00069 if( index >= ENTROPY_MAX_SOURCES ) 00070 return( POLARSSL_ERR_ENTROPY_MAX_SOURCES ); 00071 00072 ctx->source[index].f_source = f_source; 00073 ctx->source[index].p_source = p_source; 00074 ctx->source[index].threshold = threshold; 00075 00076 ctx->source_count++; 00077 00078 return( 0 ); 00079 } 00080 00081 /* 00082 * Entropy accumulator update 00083 */ 00084 int entropy_update( entropy_context *ctx, unsigned char source_id, 00085 const unsigned char *data, size_t len ) 00086 { 00087 unsigned char header[2]; 00088 unsigned char tmp[ENTROPY_BLOCK_SIZE]; 00089 size_t use_len = len; 00090 const unsigned char *p = data; 00091 00092 if( use_len > ENTROPY_BLOCK_SIZE ) 00093 { 00094 sha4( data, len, tmp, 0 ); 00095 00096 p = tmp; 00097 use_len = ENTROPY_BLOCK_SIZE; 00098 } 00099 00100 header[0] = source_id; 00101 header[1] = use_len & 0xFF; 00102 00103 sha4_update( &ctx->accumulator, header, 2 ); 00104 sha4_update( &ctx->accumulator, p, use_len ); 00105 00106 return( 0 ); 00107 } 00108 00109 int entropy_update_manual( entropy_context *ctx, 00110 const unsigned char *data, size_t len ) 00111 { 00112 return entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len ); 00113 } 00114 00115 /* 00116 * Run through the different sources to add entropy to our accumulator 00117 */ 00118 int entropy_gather( entropy_context *ctx ) 00119 { 00120 int ret, i; 00121 unsigned char buf[ENTROPY_MAX_GATHER]; 00122 size_t olen; 00123 00124 if( ctx->source_count == 0 ) 00125 return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED ); 00126 00127 /* 00128 * Run through our entropy sources 00129 */ 00130 for( i = 0; i < ctx->source_count; i++ ) 00131 { 00132 olen = 0; 00133 if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, 00134 buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 ) 00135 { 00136 return( ret ); 00137 } 00138 00139 /* 00140 * Add if we actually gathered something 00141 */ 00142 if( olen > 0 ) 00143 { 00144 entropy_update( ctx, (unsigned char) i, buf, olen ); 00145 ctx->source[i].size += olen; 00146 } 00147 } 00148 00149 return( 0 ); 00150 } 00151 00152 int entropy_func( void *data, unsigned char *output, size_t len ) 00153 { 00154 int ret, count = 0, i, reached; 00155 entropy_context *ctx = (entropy_context *) data; 00156 unsigned char buf[ENTROPY_BLOCK_SIZE]; 00157 00158 if( len > ENTROPY_BLOCK_SIZE ) 00159 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); 00160 00161 /* 00162 * Always gather extra entropy before a call 00163 */ 00164 do 00165 { 00166 if( count++ > ENTROPY_MAX_LOOP ) 00167 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); 00168 00169 if( ( ret = entropy_gather( ctx ) ) != 0 ) 00170 return( ret ); 00171 00172 reached = 0; 00173 00174 for( i = 0; i < ctx->source_count; i++ ) 00175 if( ctx->source[i].size >= ctx->source[i].threshold ) 00176 reached++; 00177 } 00178 while( reached != ctx->source_count ); 00179 00180 memset( buf, 0, ENTROPY_BLOCK_SIZE ); 00181 00182 sha4_finish( &ctx->accumulator, buf ); 00183 00184 /* 00185 * Perform second SHA-512 on entropy 00186 */ 00187 sha4( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); 00188 00189 /* 00190 * Reset accumulator and counters and recycle existing entropy 00191 */ 00192 memset( &ctx->accumulator, 0, sizeof( sha4_context ) ); 00193 sha4_starts( &ctx->accumulator, 0 ); 00194 sha4_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); 00195 00196 for( i = 0; i < ctx->source_count; i++ ) 00197 ctx->source[i].size = 0; 00198 00199 memcpy( output, buf, len ); 00200 00201 return( 0 ); 00202 } 00203 00204 #endif