Example program to test AES-GCM functionality. Used for a workshop
Embed:
(wiki syntax)
Show/hide line numbers
entropy.c
00001 /* 00002 * Entropy accumulator implementation 00003 * 00004 * Copyright (C) 2006-2014, 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 #if !defined(POLARSSL_CONFIG_FILE) 00027 #include "polarssl/config.h" 00028 #else 00029 #include POLARSSL_CONFIG_FILE 00030 #endif 00031 00032 #if defined(POLARSSL_ENTROPY_C) 00033 00034 #include "polarssl/entropy.h" 00035 #include "polarssl/entropy_poll.h" 00036 00037 #if defined(POLARSSL_FS_IO) 00038 #include <stdio.h> 00039 #endif 00040 00041 #if defined(POLARSSL_HAVEGE_C) 00042 #include "polarssl/havege.h" 00043 #endif 00044 00045 #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ 00046 00047 void entropy_init( entropy_context *ctx ) 00048 { 00049 memset( ctx, 0, sizeof(entropy_context) ); 00050 00051 #if defined(POLARSSL_THREADING_C) 00052 polarssl_mutex_init( &ctx->mutex ); 00053 #endif 00054 00055 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00056 sha512_starts( &ctx->accumulator, 0 ); 00057 #else 00058 sha256_starts( &ctx->accumulator, 0 ); 00059 #endif 00060 #if defined(POLARSSL_HAVEGE_C) 00061 havege_init( &ctx->havege_data ); 00062 #endif 00063 00064 #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES) 00065 #if !defined(POLARSSL_NO_PLATFORM_ENTROPY) 00066 entropy_add_source( ctx, platform_entropy_poll, NULL, 00067 ENTROPY_MIN_PLATFORM ); 00068 #endif 00069 #if defined(POLARSSL_TIMING_C) 00070 entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK ); 00071 #endif 00072 #if defined(POLARSSL_HAVEGE_C) 00073 entropy_add_source( ctx, havege_poll, &ctx->havege_data, 00074 ENTROPY_MIN_HAVEGE ); 00075 #endif 00076 #endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */ 00077 } 00078 00079 void entropy_free( entropy_context *ctx ) 00080 { 00081 ((void) ctx); 00082 #if defined(POLARSSL_THREADING_C) 00083 polarssl_mutex_free( &ctx->mutex ); 00084 #endif 00085 } 00086 00087 int entropy_add_source( entropy_context *ctx, 00088 f_source_ptr f_source, void *p_source, 00089 size_t threshold ) 00090 { 00091 int index, ret = 0; 00092 00093 #if defined(POLARSSL_THREADING_C) 00094 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00095 return( ret ); 00096 #endif 00097 00098 index = ctx->source_count; 00099 if( index >= ENTROPY_MAX_SOURCES ) 00100 { 00101 ret = POLARSSL_ERR_ENTROPY_MAX_SOURCES; 00102 goto exit; 00103 } 00104 00105 ctx->source[index].f_source = f_source; 00106 ctx->source[index].p_source = p_source; 00107 ctx->source[index].threshold = threshold; 00108 00109 ctx->source_count++; 00110 00111 exit: 00112 #if defined(POLARSSL_THREADING_C) 00113 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00114 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00115 #endif 00116 00117 return( ret ); 00118 } 00119 00120 /* 00121 * Entropy accumulator update 00122 */ 00123 static int entropy_update( entropy_context *ctx, unsigned char source_id, 00124 const unsigned char *data, size_t len ) 00125 { 00126 unsigned char header[2]; 00127 unsigned char tmp[ENTROPY_BLOCK_SIZE]; 00128 size_t use_len = len; 00129 const unsigned char *p = data; 00130 00131 if( use_len > ENTROPY_BLOCK_SIZE ) 00132 { 00133 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00134 sha512( data, len, tmp, 0 ); 00135 #else 00136 sha256( data, len, tmp, 0 ); 00137 #endif 00138 p = tmp; 00139 use_len = ENTROPY_BLOCK_SIZE; 00140 } 00141 00142 header[0] = source_id; 00143 header[1] = use_len & 0xFF; 00144 00145 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00146 sha512_update( &ctx->accumulator, header, 2 ); 00147 sha512_update( &ctx->accumulator, p, use_len ); 00148 #else 00149 sha256_update( &ctx->accumulator, header, 2 ); 00150 sha256_update( &ctx->accumulator, p, use_len ); 00151 #endif 00152 00153 return( 0 ); 00154 } 00155 00156 int entropy_update_manual( entropy_context *ctx, 00157 const unsigned char *data, size_t len ) 00158 { 00159 int ret; 00160 00161 #if defined(POLARSSL_THREADING_C) 00162 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00163 return( ret ); 00164 #endif 00165 00166 ret = entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len ); 00167 00168 #if defined(POLARSSL_THREADING_C) 00169 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00170 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00171 #endif 00172 00173 return ( ret ); 00174 } 00175 00176 /* 00177 * Run through the different sources to add entropy to our accumulator 00178 */ 00179 static int entropy_gather_internal( entropy_context *ctx ) 00180 { 00181 int ret, i; 00182 unsigned char buf[ENTROPY_MAX_GATHER]; 00183 size_t olen; 00184 00185 if( ctx->source_count == 0 ) 00186 return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED ); 00187 00188 /* 00189 * Run through our entropy sources 00190 */ 00191 for( i = 0; i < ctx->source_count; i++ ) 00192 { 00193 olen = 0; 00194 if ( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, 00195 buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 ) 00196 { 00197 return( ret ); 00198 } 00199 00200 /* 00201 * Add if we actually gathered something 00202 */ 00203 if( olen > 0 ) 00204 { 00205 entropy_update( ctx, (unsigned char) i, buf, olen ); 00206 ctx->source[i].size += olen; 00207 } 00208 } 00209 00210 return( 0 ); 00211 } 00212 00213 /* 00214 * Thread-safe wrapper for entropy_gather_internal() 00215 */ 00216 int entropy_gather( entropy_context *ctx ) 00217 { 00218 int ret; 00219 00220 #if defined(POLARSSL_THREADING_C) 00221 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00222 return( ret ); 00223 #endif 00224 00225 ret = entropy_gather_internal( ctx ); 00226 00227 #if defined(POLARSSL_THREADING_C) 00228 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00229 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00230 #endif 00231 00232 return( ret ); 00233 } 00234 00235 int entropy_func( void *data, unsigned char *output, size_t len ) 00236 { 00237 int ret, count = 0, i, reached; 00238 entropy_context *ctx = (entropy_context *) data; 00239 unsigned char buf[ENTROPY_BLOCK_SIZE]; 00240 00241 if( len > ENTROPY_BLOCK_SIZE ) 00242 return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); 00243 00244 #if defined(POLARSSL_THREADING_C) 00245 if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 ) 00246 return( ret ); 00247 #endif 00248 00249 /* 00250 * Always gather extra entropy before a call 00251 */ 00252 do 00253 { 00254 if( count++ > ENTROPY_MAX_LOOP ) 00255 { 00256 ret = POLARSSL_ERR_ENTROPY_SOURCE_FAILED; 00257 goto exit; 00258 } 00259 00260 if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) 00261 goto exit; 00262 00263 reached = 0; 00264 00265 for( i = 0; i < ctx->source_count; i++ ) 00266 if( ctx->source[i].size >= ctx->source[i].threshold ) 00267 reached++; 00268 } 00269 while( reached != ctx->source_count ); 00270 00271 memset( buf, 0, ENTROPY_BLOCK_SIZE ); 00272 00273 #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR) 00274 sha512_finish( &ctx->accumulator, buf ); 00275 00276 /* 00277 * Reset accumulator and counters and recycle existing entropy 00278 */ 00279 memset( &ctx->accumulator, 0, sizeof( sha512_context ) ); 00280 sha512_starts( &ctx->accumulator, 0 ); 00281 sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); 00282 00283 /* 00284 * Perform second SHA-512 on entropy 00285 */ 00286 sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); 00287 #else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */ 00288 sha256_finish( &ctx->accumulator, buf ); 00289 00290 /* 00291 * Reset accumulator and counters and recycle existing entropy 00292 */ 00293 memset( &ctx->accumulator, 0, sizeof( sha256_context ) ); 00294 sha256_starts( &ctx->accumulator, 0 ); 00295 sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE ); 00296 00297 /* 00298 * Perform second SHA-256 on entropy 00299 */ 00300 sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 ); 00301 #endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */ 00302 00303 for( i = 0; i < ctx->source_count; i++ ) 00304 ctx->source[i].size = 0; 00305 00306 memcpy( output, buf, len ); 00307 00308 ret = 0; 00309 00310 exit: 00311 #if defined(POLARSSL_THREADING_C) 00312 if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) 00313 return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); 00314 #endif 00315 00316 return( ret ); 00317 } 00318 00319 #if defined(POLARSSL_FS_IO) 00320 int entropy_write_seed_file( entropy_context *ctx, const char *path ) 00321 { 00322 int ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR; 00323 FILE *f; 00324 unsigned char buf[ENTROPY_BLOCK_SIZE]; 00325 00326 if( ( f = fopen( path, "wb" ) ) == NULL ) 00327 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); 00328 00329 if( ( ret = entropy_func( ctx, buf, ENTROPY_BLOCK_SIZE ) ) != 0 ) 00330 goto exit; 00331 00332 if( fwrite( buf, 1, ENTROPY_BLOCK_SIZE, f ) != ENTROPY_BLOCK_SIZE ) 00333 { 00334 ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR; 00335 goto exit; 00336 } 00337 00338 ret = 0; 00339 00340 exit: 00341 fclose( f ); 00342 return( ret ); 00343 } 00344 00345 int entropy_update_seed_file( entropy_context *ctx, const char *path ) 00346 { 00347 FILE *f; 00348 size_t n; 00349 unsigned char buf[ ENTROPY_MAX_SEED_SIZE ]; 00350 00351 if( ( f = fopen( path, "rb" ) ) == NULL ) 00352 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); 00353 00354 fseek( f, 0, SEEK_END ); 00355 n = (size_t) ftell( f ); 00356 fseek( f, 0, SEEK_SET ); 00357 00358 if( n > ENTROPY_MAX_SEED_SIZE ) 00359 n = ENTROPY_MAX_SEED_SIZE; 00360 00361 if( fread( buf, 1, n, f ) != n ) 00362 { 00363 fclose( f ); 00364 return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); 00365 } 00366 00367 fclose( f ); 00368 00369 entropy_update_manual( ctx, buf, n ); 00370 00371 return( entropy_write_seed_file( ctx, path ) ); 00372 } 00373 #endif /* POLARSSL_FS_IO */ 00374 00375 #endif /* POLARSSL_ENTROPY_C */ 00376 00377
Generated on Tue Jul 12 2022 19:40:15 by
1.7.2