joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

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-2016, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 
00022 #if !defined(MBEDTLS_CONFIG_FILE)
00023 #include "mbedtls/config.h"
00024 #else
00025 #include MBEDTLS_CONFIG_FILE
00026 #endif
00027 
00028 #if defined(MBEDTLS_ENTROPY_C)
00029 
00030 #if defined(MBEDTLS_TEST_NULL_ENTROPY)
00031 #warning "**** WARNING!  MBEDTLS_TEST_NULL_ENTROPY defined! "
00032 #warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES "
00033 #warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE "
00034 #endif
00035 
00036 #include "mbedtls/entropy.h"
00037 #include "mbedtls/entropy_poll.h"
00038 
00039 #include <string.h>
00040 
00041 #if defined(MBEDTLS_FS_IO)
00042 #include <stdio.h>
00043 #endif
00044 
00045 #if defined(MBEDTLS_SELF_TEST)
00046 #if defined(MBEDTLS_PLATFORM_C)
00047 #include "mbedtls/platform.h"
00048 #else
00049 #include <stdio.h>
00050 #define mbedtls_printf     printf
00051 #endif /* MBEDTLS_PLATFORM_C */
00052 #endif /* MBEDTLS_SELF_TEST */
00053 
00054 #if defined(MBEDTLS_HAVEGE_C)
00055 #include "mbedtls/havege.h"
00056 #endif
00057 
00058 /* Implementation that should never be optimized out by the compiler */
00059 static void mbedtls_zeroize( void *v, size_t n ) {
00060     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
00061 }
00062 
00063 #define ENTROPY_MAX_LOOP    256     /**< Maximum amount to loop before error */
00064 
00065 void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
00066 {
00067     memset( ctx, 0, sizeof(mbedtls_entropy_context) );
00068 
00069 #if defined(MBEDTLS_THREADING_C)
00070     mbedtls_mutex_init( &ctx->mutex  );
00071 #endif
00072 
00073 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
00074     mbedtls_sha512_starts( &ctx->accumulator, 0 );
00075 #else
00076     mbedtls_sha256_starts( &ctx->accumulator, 0 );
00077 #endif
00078 #if defined(MBEDTLS_HAVEGE_C)
00079     mbedtls_havege_init( &ctx->havege_data );
00080 #endif
00081 
00082 #if defined(MBEDTLS_TEST_NULL_ENTROPY)
00083     mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL,
00084                                 1, MBEDTLS_ENTROPY_SOURCE_STRONG );
00085 #endif
00086 
00087 #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
00088 #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
00089     mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL,
00090                                 MBEDTLS_ENTROPY_MIN_PLATFORM,
00091                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
00092 #endif
00093 #if defined(MBEDTLS_TIMING_C)
00094     mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL,
00095                                 MBEDTLS_ENTROPY_MIN_HARDCLOCK,
00096                                 MBEDTLS_ENTROPY_SOURCE_WEAK );
00097 #endif
00098 #if defined(MBEDTLS_HAVEGE_C)
00099     mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data,
00100                                 MBEDTLS_ENTROPY_MIN_HAVEGE,
00101                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
00102 #endif
00103 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
00104     mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL,
00105                                 MBEDTLS_ENTROPY_MIN_HARDWARE,
00106                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
00107 #endif
00108 #if defined(MBEDTLS_ENTROPY_NV_SEED)
00109     mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL,
00110                                 MBEDTLS_ENTROPY_BLOCK_SIZE,
00111                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
00112 #endif
00113 #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
00114 }
00115 
00116 void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
00117 {
00118 #if defined(MBEDTLS_HAVEGE_C)
00119     mbedtls_havege_free( &ctx->havege_data );
00120 #endif
00121 #if defined(MBEDTLS_THREADING_C)
00122     mbedtls_mutex_free( &ctx->mutex  );
00123 #endif
00124     mbedtls_zeroize( ctx, sizeof( mbedtls_entropy_context ) );
00125 }
00126 
00127 int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
00128                         mbedtls_entropy_f_source_ptr f_source, void *p_source,
00129                         size_t threshold, int strong )
00130 {
00131     int index, ret = 0;
00132 
00133 #if defined(MBEDTLS_THREADING_C)
00134     if( ( ret = mbedtls_mutex_lock( &ctx->mutex  ) ) != 0 )
00135         return( ret );
00136 #endif
00137 
00138     index = ctx->source_count;
00139     if( index >= MBEDTLS_ENTROPY_MAX_SOURCES )
00140     {
00141         ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
00142         goto exit;
00143     }
00144 
00145     ctx->source[index].f_source  = f_source;
00146     ctx->source[index].p_source  = p_source;
00147     ctx->source[index].threshold = threshold;
00148     ctx->source[index].strong    = strong;
00149 
00150     ctx->source_count++;
00151 
00152 exit:
00153 #if defined(MBEDTLS_THREADING_C)
00154     if( mbedtls_mutex_unlock( &ctx->mutex  ) != 0 )
00155         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00156 #endif
00157 
00158     return( ret );
00159 }
00160 
00161 /*
00162  * Entropy accumulator update
00163  */
00164 static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id,
00165                            const unsigned char *data, size_t len )
00166 {
00167     unsigned char header[2];
00168     unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
00169     size_t use_len = len;
00170     const unsigned char *p = data;
00171 
00172     if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE )
00173     {
00174 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
00175         mbedtls_sha512( data, len, tmp, 0 );
00176 #else
00177         mbedtls_sha256( data, len, tmp, 0 );
00178 #endif
00179         p = tmp;
00180         use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
00181     }
00182 
00183     header[0] = source_id;
00184     header[1] = use_len & 0xFF;
00185 
00186 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
00187     mbedtls_sha512_update( &ctx->accumulator, header, 2 );
00188     mbedtls_sha512_update( &ctx->accumulator, p, use_len );
00189 #else
00190     mbedtls_sha256_update( &ctx->accumulator, header, 2 );
00191     mbedtls_sha256_update( &ctx->accumulator, p, use_len );
00192 #endif
00193 
00194     return( 0 );
00195 }
00196 
00197 int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
00198                            const unsigned char *data, size_t len )
00199 {
00200     int ret;
00201 
00202 #if defined(MBEDTLS_THREADING_C)
00203     if( ( ret = mbedtls_mutex_lock( &ctx->mutex  ) ) != 0 )
00204         return( ret );
00205 #endif
00206 
00207     ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len );
00208 
00209 #if defined(MBEDTLS_THREADING_C)
00210     if( mbedtls_mutex_unlock( &ctx->mutex  ) != 0 )
00211         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00212 #endif
00213 
00214     return( ret );
00215 }
00216 
00217 /*
00218  * Run through the different sources to add entropy to our accumulator
00219  */
00220 static int entropy_gather_internal( mbedtls_entropy_context *ctx )
00221 {
00222     int ret, i, have_one_strong = 0;
00223     unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
00224     size_t olen;
00225 
00226     if( ctx->source_count == 0 )
00227         return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED );
00228 
00229     /*
00230      * Run through our entropy sources
00231      */
00232     for( i = 0; i < ctx->source_count; i++ )
00233     {
00234         if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
00235             have_one_strong = 1;
00236 
00237         olen = 0;
00238         if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
00239                         buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 )
00240         {
00241             return( ret );
00242         }
00243 
00244         /*
00245          * Add if we actually gathered something
00246          */
00247         if( olen > 0 )
00248         {
00249             entropy_update( ctx, (unsigned char) i, buf, olen );
00250             ctx->source[i].size += olen;
00251         }
00252     }
00253 
00254     if( have_one_strong == 0 )
00255         return( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE );
00256 
00257     return( 0 );
00258 }
00259 
00260 /*
00261  * Thread-safe wrapper for entropy_gather_internal()
00262  */
00263 int mbedtls_entropy_gather( mbedtls_entropy_context *ctx )
00264 {
00265     int ret;
00266 
00267 #if defined(MBEDTLS_THREADING_C)
00268     if( ( ret = mbedtls_mutex_lock( &ctx->mutex  ) ) != 0 )
00269         return( ret );
00270 #endif
00271 
00272     ret = entropy_gather_internal( ctx );
00273 
00274 #if defined(MBEDTLS_THREADING_C)
00275     if( mbedtls_mutex_unlock( &ctx->mutex  ) != 0 )
00276         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00277 #endif
00278 
00279     return( ret );
00280 }
00281 
00282 int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
00283 {
00284     int ret, count = 0, i, done;
00285     mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
00286     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
00287 
00288     if( len > MBEDTLS_ENTROPY_BLOCK_SIZE )
00289         return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
00290 
00291 #if defined(MBEDTLS_ENTROPY_NV_SEED)
00292     /* Update the NV entropy seed before generating any entropy for outside
00293      * use.
00294      */
00295     if( ctx->initial_entropy_run == 0 )
00296     {
00297         ctx->initial_entropy_run = 1;
00298         if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 )
00299             return( ret );
00300     }
00301 #endif
00302 
00303 #if defined(MBEDTLS_THREADING_C)
00304     if( ( ret = mbedtls_mutex_lock( &ctx->mutex  ) ) != 0 )
00305         return( ret );
00306 #endif
00307 
00308     /*
00309      * Always gather extra entropy before a call
00310      */
00311     do
00312     {
00313         if( count++ > ENTROPY_MAX_LOOP )
00314         {
00315             ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
00316             goto exit;
00317         }
00318 
00319         if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
00320             goto exit;
00321 
00322         done = 1;
00323         for( i = 0; i < ctx->source_count; i++ )
00324             if( ctx->source[i].size < ctx->source[i].threshold )
00325                 done = 0;
00326     }
00327     while( ! done );
00328 
00329     memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
00330 
00331 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
00332     mbedtls_sha512_finish( &ctx->accumulator, buf );
00333 
00334     /*
00335      * Reset accumulator and counters and recycle existing entropy
00336      */
00337     memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) );
00338     mbedtls_sha512_starts( &ctx->accumulator, 0 );
00339     mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
00340 
00341     /*
00342      * Perform second SHA-512 on entropy
00343      */
00344     mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 );
00345 #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
00346     mbedtls_sha256_finish( &ctx->accumulator, buf );
00347 
00348     /*
00349      * Reset accumulator and counters and recycle existing entropy
00350      */
00351     memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) );
00352     mbedtls_sha256_starts( &ctx->accumulator, 0 );
00353     mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
00354 
00355     /*
00356      * Perform second SHA-256 on entropy
00357      */
00358     mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 );
00359 #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
00360 
00361     for( i = 0; i < ctx->source_count; i++ )
00362         ctx->source[i].size = 0;
00363 
00364     memcpy( output, buf, len );
00365 
00366     ret = 0;
00367 
00368 exit:
00369 #if defined(MBEDTLS_THREADING_C)
00370     if( mbedtls_mutex_unlock( &ctx->mutex  ) != 0 )
00371         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00372 #endif
00373 
00374     return( ret );
00375 }
00376 
00377 #if defined(MBEDTLS_ENTROPY_NV_SEED)
00378 int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx )
00379 {
00380     int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
00381     unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ];
00382 
00383     /* Read new seed  and write it to NV */
00384     if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
00385         return( ret );
00386 
00387     if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
00388         return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
00389 
00390     /* Manually update the remaining stream with a separator value to diverge */
00391     memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
00392     mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
00393 
00394     return( 0 );
00395 }
00396 #endif /* MBEDTLS_ENTROPY_NV_SEED */
00397 
00398 #if defined(MBEDTLS_FS_IO)
00399 int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
00400 {
00401     int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
00402     FILE *f;
00403     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
00404 
00405     if( ( f = fopen( path, "wb" ) ) == NULL )
00406         return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
00407 
00408     if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
00409         goto exit;
00410 
00411     if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
00412     {
00413         ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
00414         goto exit;
00415     }
00416 
00417     ret = 0;
00418 
00419 exit:
00420     fclose( f );
00421     return( ret );
00422 }
00423 
00424 int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path )
00425 {
00426     FILE *f;
00427     size_t n;
00428     unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ];
00429 
00430     if( ( f = fopen( path, "rb" ) ) == NULL )
00431         return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
00432 
00433     fseek( f, 0, SEEK_END );
00434     n = (size_t) ftell( f );
00435     fseek( f, 0, SEEK_SET );
00436 
00437     if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE )
00438         n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
00439 
00440     if( fread( buf, 1, n, f ) != n )
00441     {
00442         fclose( f );
00443         return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
00444     }
00445 
00446     fclose( f );
00447 
00448     mbedtls_entropy_update_manual( ctx, buf, n );
00449 
00450     return( mbedtls_entropy_write_seed_file( ctx, path ) );
00451 }
00452 #endif /* MBEDTLS_FS_IO */
00453 
00454 #if defined(MBEDTLS_SELF_TEST)
00455 /*
00456  * Dummy source function
00457  */
00458 static int entropy_dummy_source( void *data, unsigned char *output,
00459                                  size_t len, size_t *olen )
00460 {
00461     ((void) data);
00462 
00463     memset( output, 0x2a, len );
00464     *olen = len;
00465 
00466     return( 0 );
00467 }
00468 
00469 /*
00470  * The actual entropy quality is hard to test, but we can at least
00471  * test that the functions don't cause errors and write the correct
00472  * amount of data to buffers.
00473  */
00474 int mbedtls_entropy_self_test( int verbose )
00475 {
00476     int ret = 0;
00477     mbedtls_entropy_context ctx;
00478     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
00479     unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
00480     size_t i, j;
00481 
00482     if( verbose != 0 )
00483         mbedtls_printf( "  ENTROPY test: " );
00484 
00485     mbedtls_entropy_init( &ctx );
00486 
00487     /* First do a gather to make sure we have default sources */
00488     if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 )
00489         goto cleanup;
00490 
00491     ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16,
00492                                       MBEDTLS_ENTROPY_SOURCE_WEAK );
00493     if( ret != 0 )
00494         goto cleanup;
00495 
00496     if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
00497         goto cleanup;
00498 
00499     /*
00500      * To test that mbedtls_entropy_func writes correct number of bytes:
00501      * - use the whole buffer and rely on ASan to detect overruns
00502      * - collect entropy 8 times and OR the result in an accumulator:
00503      *   any byte should then be 0 with probably 2^(-64), so requiring
00504      *   each of the 32 or 64 bytes to be non-zero has a false failure rate
00505      *   of at most 2^(-58) which is acceptable.
00506      */
00507     for( i = 0; i < 8; i++ )
00508     {
00509         if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
00510             goto cleanup;
00511 
00512         for( j = 0; j < sizeof( buf ); j++ )
00513             acc[j] |= buf[j];
00514     }
00515 
00516     for( j = 0; j < sizeof( buf ); j++ )
00517     {
00518         if( acc[j] == 0 )
00519         {
00520             ret = 1;
00521             goto cleanup;
00522         }
00523     }
00524 
00525 cleanup:
00526     mbedtls_entropy_free( &ctx );
00527 
00528     if( verbose != 0 )
00529     {
00530         if( ret != 0 )
00531             mbedtls_printf( "failed\n" );
00532         else
00533             mbedtls_printf( "passed\n" );
00534 
00535         mbedtls_printf( "\n" );
00536     }
00537 
00538     return( ret != 0 );
00539 }
00540 #endif /* MBEDTLS_SELF_TEST */
00541 
00542 #endif /* MBEDTLS_ENTROPY_C */