Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

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_ENTROPY_NV_SEED)
00046 #include "mbedtls/platform.h"
00047 #endif
00048 
00049 #if defined(MBEDTLS_SELF_TEST)
00050 #if defined(MBEDTLS_PLATFORM_C)
00051 #include "mbedtls/platform.h"
00052 #else
00053 #include <stdio.h>
00054 #define mbedtls_printf     printf
00055 #endif /* MBEDTLS_PLATFORM_C */
00056 #endif /* MBEDTLS_SELF_TEST */
00057 
00058 #if defined(MBEDTLS_HAVEGE_C)
00059 #include "mbedtls/havege.h"
00060 #endif
00061 
00062 /* Implementation that should never be optimized out by the compiler */
00063 static void mbedtls_zeroize( void *v, size_t n ) {
00064     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
00065 }
00066 
00067 #define ENTROPY_MAX_LOOP    256     /**< Maximum amount to loop before error */
00068 
00069 void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
00070 {
00071     ctx->source_count = 0;
00072     memset( ctx->source, 0, sizeof( ctx->source ) );
00073 
00074 #if defined(MBEDTLS_THREADING_C)
00075     mbedtls_mutex_init( &ctx->mutex  );
00076 #endif
00077 
00078     ctx->accumulator_started = 0;
00079 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
00080     mbedtls_sha512_init( &ctx->accumulator );
00081 #else
00082     mbedtls_sha256_init( &ctx->accumulator );
00083 #endif
00084 #if defined(MBEDTLS_HAVEGE_C)
00085     mbedtls_havege_init( &ctx->havege_data );
00086 #endif
00087 
00088     /* Reminder: Update ENTROPY_HAVE_STRONG in the test files
00089      *           when adding more strong entropy sources here. */
00090 
00091 #if defined(MBEDTLS_TEST_NULL_ENTROPY)
00092     mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL,
00093                                 1, MBEDTLS_ENTROPY_SOURCE_STRONG );
00094 #endif
00095 
00096 #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
00097 #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
00098     mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL,
00099                                 MBEDTLS_ENTROPY_MIN_PLATFORM,
00100                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
00101 #endif
00102 #if defined(MBEDTLS_TIMING_C)
00103     mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL,
00104                                 MBEDTLS_ENTROPY_MIN_HARDCLOCK,
00105                                 MBEDTLS_ENTROPY_SOURCE_WEAK );
00106 #endif
00107 #if defined(MBEDTLS_HAVEGE_C)
00108     mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data,
00109                                 MBEDTLS_ENTROPY_MIN_HAVEGE,
00110                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
00111 #endif
00112 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
00113     mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL,
00114                                 MBEDTLS_ENTROPY_MIN_HARDWARE,
00115                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
00116 #endif
00117 #if defined(MBEDTLS_ENTROPY_NV_SEED)
00118     mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL,
00119                                 MBEDTLS_ENTROPY_BLOCK_SIZE,
00120                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
00121     ctx->initial_entropy_run = 0;
00122 #endif
00123 #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
00124 }
00125 
00126 void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
00127 {
00128 #if defined(MBEDTLS_HAVEGE_C)
00129     mbedtls_havege_free( &ctx->havege_data );
00130 #endif
00131 #if defined(MBEDTLS_THREADING_C)
00132     mbedtls_mutex_free( &ctx->mutex  );
00133 #endif
00134 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
00135     mbedtls_sha512_free( &ctx->accumulator );
00136 #else
00137     mbedtls_sha256_free( &ctx->accumulator );
00138 #endif
00139 #if defined(MBEDTLS_ENTROPY_NV_SEED)
00140     ctx->initial_entropy_run = 0;
00141 #endif
00142     ctx->source_count = 0;
00143     mbedtls_zeroize( ctx->source, sizeof( ctx->source ) );
00144     ctx->accumulator_started = 0;
00145 }
00146 
00147 int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
00148                         mbedtls_entropy_f_source_ptr f_source, void *p_source,
00149                         size_t threshold, int strong )
00150 {
00151     int idx, ret = 0;
00152 
00153 #if defined(MBEDTLS_THREADING_C)
00154     if( ( ret = mbedtls_mutex_lock( &ctx->mutex  ) ) != 0 )
00155         return( ret );
00156 #endif
00157 
00158     idx = ctx->source_count;
00159     if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES )
00160     {
00161         ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
00162         goto exit;
00163     }
00164 
00165     ctx->source[idx].f_source  = f_source;
00166     ctx->source[idx].p_source  = p_source;
00167     ctx->source[idx].threshold = threshold;
00168     ctx->source[idx].strong    = strong;
00169 
00170     ctx->source_count++;
00171 
00172 exit:
00173 #if defined(MBEDTLS_THREADING_C)
00174     if( mbedtls_mutex_unlock( &ctx->mutex  ) != 0 )
00175         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00176 #endif
00177 
00178     return( ret );
00179 }
00180 
00181 /*
00182  * Entropy accumulator update
00183  */
00184 static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id,
00185                            const unsigned char *data, size_t len )
00186 {
00187     unsigned char header[2];
00188     unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
00189     size_t use_len = len;
00190     const unsigned char *p = data;
00191     int ret = 0;
00192 
00193     if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE )
00194     {
00195 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
00196         if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 )
00197             goto cleanup;
00198 #else
00199         if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 )
00200             goto cleanup;
00201 #endif
00202         p = tmp;
00203         use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
00204     }
00205 
00206     header[0] = source_id;
00207     header[1] = use_len & 0xFF;
00208 
00209     /*
00210      * Start the accumulator if this has not already happened. Note that
00211      * it is sufficient to start the accumulator here only because all calls to
00212      * gather entropy eventually execute this code.
00213      */
00214 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
00215     if( ctx->accumulator_started == 0 &&
00216         ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
00217         goto cleanup;
00218     else
00219         ctx->accumulator_started = 1;
00220     if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
00221         goto cleanup;
00222     ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len );
00223 #else
00224     if( ctx->accumulator_started == 0 &&
00225         ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
00226         goto cleanup;
00227     else
00228         ctx->accumulator_started = 1;
00229     if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
00230         goto cleanup;
00231     ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len );
00232 #endif
00233 
00234 cleanup:
00235     mbedtls_zeroize( tmp, sizeof( tmp ) );
00236 
00237     return( ret );
00238 }
00239 
00240 int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
00241                            const unsigned char *data, size_t len )
00242 {
00243     int ret;
00244 
00245 #if defined(MBEDTLS_THREADING_C)
00246     if( ( ret = mbedtls_mutex_lock( &ctx->mutex  ) ) != 0 )
00247         return( ret );
00248 #endif
00249 
00250     ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len );
00251 
00252 #if defined(MBEDTLS_THREADING_C)
00253     if( mbedtls_mutex_unlock( &ctx->mutex  ) != 0 )
00254         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00255 #endif
00256 
00257     return( ret );
00258 }
00259 
00260 /*
00261  * Run through the different sources to add entropy to our accumulator
00262  */
00263 static int entropy_gather_internal( mbedtls_entropy_context *ctx )
00264 {
00265     int ret, i, have_one_strong = 0;
00266     unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
00267     size_t olen;
00268 
00269     if( ctx->source_count == 0 )
00270         return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED );
00271 
00272     /*
00273      * Run through our entropy sources
00274      */
00275     for( i = 0; i < ctx->source_count; i++ )
00276     {
00277         if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
00278             have_one_strong = 1;
00279 
00280         olen = 0;
00281         if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
00282                         buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 )
00283         {
00284             goto cleanup;
00285         }
00286 
00287         /*
00288          * Add if we actually gathered something
00289          */
00290         if( olen > 0 )
00291         {
00292             if( ( ret = entropy_update( ctx, (unsigned char) i,
00293                                         buf, olen ) ) != 0 )
00294                 return( ret );
00295             ctx->source[i].size += olen;
00296         }
00297     }
00298 
00299     if( have_one_strong == 0 )
00300         ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
00301 
00302 cleanup:
00303     mbedtls_zeroize( buf, sizeof( buf ) );
00304 
00305     return( ret );
00306 }
00307 
00308 /*
00309  * Thread-safe wrapper for entropy_gather_internal()
00310  */
00311 int mbedtls_entropy_gather( mbedtls_entropy_context *ctx )
00312 {
00313     int ret;
00314 
00315 #if defined(MBEDTLS_THREADING_C)
00316     if( ( ret = mbedtls_mutex_lock( &ctx->mutex  ) ) != 0 )
00317         return( ret );
00318 #endif
00319 
00320     ret = entropy_gather_internal( ctx );
00321 
00322 #if defined(MBEDTLS_THREADING_C)
00323     if( mbedtls_mutex_unlock( &ctx->mutex  ) != 0 )
00324         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00325 #endif
00326 
00327     return( ret );
00328 }
00329 
00330 int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
00331 {
00332     int ret, count = 0, i, done;
00333     mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
00334     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
00335 
00336     if( len > MBEDTLS_ENTROPY_BLOCK_SIZE )
00337         return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
00338 
00339 #if defined(MBEDTLS_ENTROPY_NV_SEED)
00340     /* Update the NV entropy seed before generating any entropy for outside
00341      * use.
00342      */
00343     if( ctx->initial_entropy_run == 0 )
00344     {
00345         ctx->initial_entropy_run = 1;
00346         if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 )
00347             return( ret );
00348     }
00349 #endif
00350 
00351 #if defined(MBEDTLS_THREADING_C)
00352     if( ( ret = mbedtls_mutex_lock( &ctx->mutex  ) ) != 0 )
00353         return( ret );
00354 #endif
00355 
00356     /*
00357      * Always gather extra entropy before a call
00358      */
00359     do
00360     {
00361         if( count++ > ENTROPY_MAX_LOOP )
00362         {
00363             ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
00364             goto exit;
00365         }
00366 
00367         if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
00368             goto exit;
00369 
00370         done = 1;
00371         for( i = 0; i < ctx->source_count; i++ )
00372             if( ctx->source[i].size < ctx->source[i].threshold )
00373                 done = 0;
00374     }
00375     while( ! done );
00376 
00377     memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
00378 
00379 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
00380     /*
00381      * Note that at this stage it is assumed that the accumulator was started
00382      * in a previous call to entropy_update(). If this is not guaranteed, the
00383      * code below will fail.
00384      */
00385     if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 )
00386         goto exit;
00387 
00388     /*
00389      * Reset accumulator and counters and recycle existing entropy
00390      */
00391     mbedtls_sha512_free( &ctx->accumulator );
00392     mbedtls_sha512_init( &ctx->accumulator );
00393     if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
00394         goto exit;
00395     if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf,
00396                                            MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
00397         goto exit;
00398 
00399     /*
00400      * Perform second SHA-512 on entropy
00401      */
00402     if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
00403                                     buf, 0 ) ) != 0 )
00404         goto exit;
00405 #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
00406     if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 )
00407         goto exit;
00408 
00409     /*
00410      * Reset accumulator and counters and recycle existing entropy
00411      */
00412     mbedtls_sha256_free( &ctx->accumulator );
00413     mbedtls_sha256_init( &ctx->accumulator );
00414     if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
00415         goto exit;
00416     if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf,
00417                                            MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
00418         goto exit;
00419 
00420     /*
00421      * Perform second SHA-256 on entropy
00422      */
00423     if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
00424                                     buf, 0 ) ) != 0 )
00425         goto exit;
00426 #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
00427 
00428     for( i = 0; i < ctx->source_count; i++ )
00429         ctx->source[i].size = 0;
00430 
00431     memcpy( output, buf, len );
00432 
00433     ret = 0;
00434 
00435 exit:
00436     mbedtls_zeroize( buf, sizeof( buf ) );
00437 
00438 #if defined(MBEDTLS_THREADING_C)
00439     if( mbedtls_mutex_unlock( &ctx->mutex  ) != 0 )
00440         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00441 #endif
00442 
00443     return( ret );
00444 }
00445 
00446 #if defined(MBEDTLS_ENTROPY_NV_SEED)
00447 int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx )
00448 {
00449     int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
00450     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
00451 
00452     /* Read new seed  and write it to NV */
00453     if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
00454         return( ret );
00455 
00456     if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
00457         return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
00458 
00459     /* Manually update the remaining stream with a separator value to diverge */
00460     memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
00461     ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
00462 
00463     return( ret );
00464 }
00465 #endif /* MBEDTLS_ENTROPY_NV_SEED */
00466 
00467 #if defined(MBEDTLS_FS_IO)
00468 int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
00469 {
00470     int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
00471     FILE *f;
00472     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
00473 
00474     if( ( f = fopen( path, "wb" ) ) == NULL )
00475         return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
00476 
00477     if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
00478         goto exit;
00479 
00480     if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
00481     {
00482         ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
00483         goto exit;
00484     }
00485 
00486     ret = 0;
00487 
00488 exit:
00489     mbedtls_zeroize( buf, sizeof( buf ) );
00490 
00491     fclose( f );
00492     return( ret );
00493 }
00494 
00495 int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path )
00496 {
00497     int ret = 0;
00498     FILE *f;
00499     size_t n;
00500     unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ];
00501 
00502     if( ( f = fopen( path, "rb" ) ) == NULL )
00503         return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
00504 
00505     fseek( f, 0, SEEK_END );
00506     n = (size_t) ftell( f );
00507     fseek( f, 0, SEEK_SET );
00508 
00509     if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE )
00510         n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
00511 
00512     if( fread( buf, 1, n, f ) != n )
00513         ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
00514     else
00515         ret = mbedtls_entropy_update_manual( ctx, buf, n );
00516 
00517     fclose( f );
00518 
00519     mbedtls_zeroize( buf, sizeof( buf ) );
00520 
00521     if( ret != 0 )
00522         return( ret );
00523 
00524     return( mbedtls_entropy_write_seed_file( ctx, path ) );
00525 }
00526 #endif /* MBEDTLS_FS_IO */
00527 
00528 #if defined(MBEDTLS_SELF_TEST)
00529 #if !defined(MBEDTLS_TEST_NULL_ENTROPY)
00530 /*
00531  * Dummy source function
00532  */
00533 static int entropy_dummy_source( void *data, unsigned char *output,
00534                                  size_t len, size_t *olen )
00535 {
00536     ((void) data);
00537 
00538     memset( output, 0x2a, len );
00539     *olen = len;
00540 
00541     return( 0 );
00542 }
00543 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
00544 
00545 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
00546 
00547 static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len )
00548 {
00549     int ret = 0;
00550     size_t entropy_len = 0;
00551     size_t olen = 0;
00552     size_t attempts = buf_len;
00553 
00554     while( attempts > 0 && entropy_len < buf_len )
00555     {
00556         if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len,
00557             buf_len - entropy_len, &olen ) ) != 0 )
00558             return( ret );
00559 
00560         entropy_len += olen;
00561         attempts--;
00562     }
00563 
00564     if( entropy_len < buf_len )
00565     {
00566         ret = 1;
00567     }
00568 
00569     return( ret );
00570 }
00571 
00572 
00573 static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf,
00574                                                         size_t buf_len )
00575 {
00576     unsigned char set= 0xFF;
00577     unsigned char unset = 0x00;
00578     size_t i;
00579 
00580     for( i = 0; i < buf_len; i++ )
00581     {
00582         set &= buf[i];
00583         unset |= buf[i];
00584     }
00585 
00586     return( set == 0xFF || unset == 0x00 );
00587 }
00588 
00589 /*
00590  * A test to ensure hat the entropy sources are functioning correctly
00591  * and there is no obvious failure. The test performs the following checks:
00592  *  - The entropy source is not providing only 0s (all bits unset) or 1s (all
00593  *    bits set).
00594  *  - The entropy source is not providing values in a pattern. Because the
00595  *    hardware could be providing data in an arbitrary length, this check polls
00596  *    the hardware entropy source twice and compares the result to ensure they
00597  *    are not equal.
00598  *  - The error code returned by the entropy source is not an error.
00599  */
00600 int mbedtls_entropy_source_self_test( int verbose )
00601 {
00602     int ret = 0;
00603     unsigned char buf0[2 * sizeof( unsigned long long int )];
00604     unsigned char buf1[2 * sizeof( unsigned long long int )];
00605 
00606     if( verbose != 0 )
00607         mbedtls_printf( "  ENTROPY_BIAS test: " );
00608 
00609     memset( buf0, 0x00, sizeof( buf0 ) );
00610     memset( buf1, 0x00, sizeof( buf1 ) );
00611 
00612     if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 )
00613         goto cleanup;
00614     if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 )
00615         goto cleanup;
00616 
00617     /* Make sure that the returned values are not all 0 or 1 */
00618     if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 )
00619         goto cleanup;
00620     if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 )
00621         goto cleanup;
00622 
00623     /* Make sure that the entropy source is not returning values in a
00624      * pattern */
00625     ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0;
00626 
00627 cleanup:
00628     if( verbose != 0 )
00629     {
00630         if( ret != 0 )
00631             mbedtls_printf( "failed\n" );
00632         else
00633             mbedtls_printf( "passed\n" );
00634 
00635         mbedtls_printf( "\n" );
00636     }
00637 
00638     return( ret != 0 );
00639 }
00640 
00641 #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
00642 
00643 /*
00644  * The actual entropy quality is hard to test, but we can at least
00645  * test that the functions don't cause errors and write the correct
00646  * amount of data to buffers.
00647  */
00648 int mbedtls_entropy_self_test( int verbose )
00649 {
00650     int ret = 1;
00651 #if !defined(MBEDTLS_TEST_NULL_ENTROPY)
00652     mbedtls_entropy_context ctx;
00653     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
00654     unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
00655     size_t i, j;
00656 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
00657 
00658     if( verbose != 0 )
00659         mbedtls_printf( "  ENTROPY test: " );
00660 
00661 #if !defined(MBEDTLS_TEST_NULL_ENTROPY)
00662     mbedtls_entropy_init( &ctx );
00663 
00664     /* First do a gather to make sure we have default sources */
00665     if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 )
00666         goto cleanup;
00667 
00668     ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16,
00669                                       MBEDTLS_ENTROPY_SOURCE_WEAK );
00670     if( ret != 0 )
00671         goto cleanup;
00672 
00673     if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
00674         goto cleanup;
00675 
00676     /*
00677      * To test that mbedtls_entropy_func writes correct number of bytes:
00678      * - use the whole buffer and rely on ASan to detect overruns
00679      * - collect entropy 8 times and OR the result in an accumulator:
00680      *   any byte should then be 0 with probably 2^(-64), so requiring
00681      *   each of the 32 or 64 bytes to be non-zero has a false failure rate
00682      *   of at most 2^(-58) which is acceptable.
00683      */
00684     for( i = 0; i < 8; i++ )
00685     {
00686         if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
00687             goto cleanup;
00688 
00689         for( j = 0; j < sizeof( buf ); j++ )
00690             acc[j] |= buf[j];
00691     }
00692 
00693     for( j = 0; j < sizeof( buf ); j++ )
00694     {
00695         if( acc[j] == 0 )
00696         {
00697             ret = 1;
00698             goto cleanup;
00699         }
00700     }
00701 
00702 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
00703     if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 )
00704         goto cleanup;
00705 #endif
00706 
00707 cleanup:
00708     mbedtls_entropy_free( &ctx );
00709 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
00710 
00711     if( verbose != 0 )
00712     {
00713         if( ret != 0 )
00714             mbedtls_printf( "failed\n" );
00715         else
00716             mbedtls_printf( "passed\n" );
00717 
00718         mbedtls_printf( "\n" );
00719     }
00720 
00721     return( ret != 0 );
00722 }
00723 #endif /* MBEDTLS_SELF_TEST */
00724 
00725 #endif /* MBEDTLS_ENTROPY_C */