Example program to test AES-GCM functionality. Used for a workshop

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers entropy.c Source File

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