Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  Entropy accumulator implementation
  3.  *
  4.  *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
  5.  *  SPDX-License-Identifier: GPL-2.0
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License along
  18.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  19.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  *  This file is part of mbed TLS (https://tls.mbed.org)
  22.  */
  23.  
  24. #if !defined(MBEDTLS_CONFIG_FILE)
  25. #include "mbedtls/config.h"
  26. #else
  27. #include MBEDTLS_CONFIG_FILE
  28. #endif
  29.  
  30. #if defined(MBEDTLS_ENTROPY_C)
  31.  
  32. #if defined(MBEDTLS_TEST_NULL_ENTROPY)
  33. #warning "**** WARNING!  MBEDTLS_TEST_NULL_ENTROPY defined! "
  34. #warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES "
  35. #warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE "
  36. #endif
  37.  
  38. #include "mbedtls/entropy.h"
  39. #include "mbedtls/entropy_poll.h"
  40. #include "mbedtls/platform_util.h"
  41.  
  42. #include <string.h>
  43.  
  44. #if defined(MBEDTLS_FS_IO)
  45. #include <stdio.h>
  46. #endif
  47.  
  48. #if defined(MBEDTLS_ENTROPY_NV_SEED)
  49. #include "mbedtls/platform.h"
  50. #endif
  51.  
  52. #if defined(MBEDTLS_SELF_TEST)
  53. #if defined(MBEDTLS_PLATFORM_C)
  54. #include "mbedtls/platform.h"
  55. #else
  56. #include <stdio.h>
  57. #define mbedtls_printf     printf
  58. #endif /* MBEDTLS_PLATFORM_C */
  59. #endif /* MBEDTLS_SELF_TEST */
  60.  
  61. #if defined(MBEDTLS_HAVEGE_C)
  62. #include "mbedtls/havege.h"
  63. #endif
  64.  
  65. #define ENTROPY_MAX_LOOP    256     /**< Maximum amount to loop before error */
  66.  
  67. void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
  68. {
  69.     ctx->source_count = 0;
  70.     memset( ctx->source, 0, sizeof( ctx->source ) );
  71.  
  72. #if defined(MBEDTLS_THREADING_C)
  73.     mbedtls_mutex_init( &ctx->mutex );
  74. #endif
  75.  
  76.     ctx->accumulator_started = 0;
  77. #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
  78.     mbedtls_sha512_init( &ctx->accumulator );
  79. #else
  80.     mbedtls_sha256_init( &ctx->accumulator );
  81. #endif
  82. #if defined(MBEDTLS_HAVEGE_C)
  83.     mbedtls_havege_init( &ctx->havege_data );
  84. #endif
  85.  
  86.     /* Reminder: Update ENTROPY_HAVE_STRONG in the test files
  87.      *           when adding more strong entropy sources here. */
  88.  
  89.     /* add KolibriOS entropy sources */
  90.  
  91.     mbedtls_entropy_add_source( ctx, mbedtls_sysfn_3_poll, NULL,
  92.                                 4, MBEDTLS_ENTROPY_SOURCE_WEAK );
  93.  
  94.     mbedtls_entropy_add_source( ctx, mbedtls_sysfn_26_9_poll, NULL,
  95.                                 4, MBEDTLS_ENTROPY_SOURCE_WEAK );
  96.  
  97.     mbedtls_entropy_add_source( ctx, mbedtls_sysfn_14_poll, NULL,
  98.                                 4, MBEDTLS_ENTROPY_SOURCE_WEAK );
  99.  
  100.     mbedtls_entropy_add_source( ctx, mbedtls_sysfn_18_4_poll, NULL,
  101.                                 4, MBEDTLS_ENTROPY_SOURCE_STRONG );
  102.  
  103.     mbedtls_entropy_add_source( ctx, mbedtls_sysfn_37_0_poll, NULL,
  104.                                 4, MBEDTLS_ENTROPY_SOURCE_WEAK );
  105.  
  106.     mbedtls_entropy_add_source( ctx, mbedtls_sysfn_66_3_poll, NULL,
  107.                                 4, MBEDTLS_ENTROPY_SOURCE_WEAK );
  108.  
  109.     mbedtls_entropy_add_source( ctx, mbedtls_sysfn_68_0_poll, NULL,
  110.                                 4, MBEDTLS_ENTROPY_SOURCE_STRONG );
  111.  
  112. #if defined(MBEDTLS_TEST_NULL_ENTROPY)
  113.     mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL,
  114.                                 1, MBEDTLS_ENTROPY_SOURCE_STRONG );
  115. #endif
  116.  
  117. #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
  118. #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
  119.     mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL,
  120.                                 MBEDTLS_ENTROPY_MIN_PLATFORM,
  121.                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
  122. #endif
  123. #if defined(MBEDTLS_TIMING_C)
  124.     mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL,
  125.                                 MBEDTLS_ENTROPY_MIN_HARDCLOCK,
  126.                                 MBEDTLS_ENTROPY_SOURCE_WEAK );
  127. #endif
  128. #if defined(MBEDTLS_HAVEGE_C)
  129.     mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data,
  130.                                 MBEDTLS_ENTROPY_MIN_HAVEGE,
  131.                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
  132. #endif
  133. #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
  134.     mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL,
  135.                                 MBEDTLS_ENTROPY_MIN_HARDWARE,
  136.                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
  137. #endif
  138. #if defined(MBEDTLS_ENTROPY_NV_SEED)
  139.     mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL,
  140.                                 MBEDTLS_ENTROPY_BLOCK_SIZE,
  141.                                 MBEDTLS_ENTROPY_SOURCE_STRONG );
  142.     ctx->initial_entropy_run = 0;
  143. #endif
  144. #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
  145. }
  146.  
  147. void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
  148. {
  149. #if defined(MBEDTLS_HAVEGE_C)
  150.     mbedtls_havege_free( &ctx->havege_data );
  151. #endif
  152. #if defined(MBEDTLS_THREADING_C)
  153.     mbedtls_mutex_free( &ctx->mutex );
  154. #endif
  155. #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
  156.     mbedtls_sha512_free( &ctx->accumulator );
  157. #else
  158.     mbedtls_sha256_free( &ctx->accumulator );
  159. #endif
  160. #if defined(MBEDTLS_ENTROPY_NV_SEED)
  161.     ctx->initial_entropy_run = 0;
  162. #endif
  163.     ctx->source_count = 0;
  164.     mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) );
  165.     ctx->accumulator_started = 0;
  166. }
  167.  
  168. int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
  169.                         mbedtls_entropy_f_source_ptr f_source, void *p_source,
  170.                         size_t threshold, int strong )
  171. {
  172.     int idx, ret = 0;
  173.  
  174. #if defined(MBEDTLS_THREADING_C)
  175.     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
  176.         return( ret );
  177. #endif
  178.  
  179.     idx = ctx->source_count;
  180.     if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES )
  181.     {
  182.         ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
  183.         goto exit;
  184.     }
  185.  
  186.     ctx->source[idx].f_source  = f_source;
  187.     ctx->source[idx].p_source  = p_source;
  188.     ctx->source[idx].threshold = threshold;
  189.     ctx->source[idx].strong    = strong;
  190.  
  191.     ctx->source_count++;
  192.  
  193. exit:
  194. #if defined(MBEDTLS_THREADING_C)
  195.     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
  196.         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
  197. #endif
  198.  
  199.     return( ret );
  200. }
  201.  
  202. /*
  203.  * Entropy accumulator update
  204.  */
  205. static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id,
  206.                            const unsigned char *data, size_t len )
  207. {
  208.     unsigned char header[2];
  209.     unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
  210.     size_t use_len = len;
  211.     const unsigned char *p = data;
  212.     int ret = 0;
  213.  
  214.     if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE )
  215.     {
  216. #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
  217.         if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 )
  218.             goto cleanup;
  219. #else
  220.         if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 )
  221.             goto cleanup;
  222. #endif
  223.         p = tmp;
  224.         use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
  225.     }
  226.  
  227.     header[0] = source_id;
  228.     header[1] = use_len & 0xFF;
  229.  
  230.     /*
  231.      * Start the accumulator if this has not already happened. Note that
  232.      * it is sufficient to start the accumulator here only because all calls to
  233.      * gather entropy eventually execute this code.
  234.      */
  235. #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
  236.     if( ctx->accumulator_started == 0 &&
  237.         ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
  238.         goto cleanup;
  239.     else
  240.         ctx->accumulator_started = 1;
  241.     if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
  242.         goto cleanup;
  243.     ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len );
  244. #else
  245.     if( ctx->accumulator_started == 0 &&
  246.         ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
  247.         goto cleanup;
  248.     else
  249.         ctx->accumulator_started = 1;
  250.     if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
  251.         goto cleanup;
  252.     ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len );
  253. #endif
  254.  
  255. cleanup:
  256.     mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
  257.  
  258.     return( ret );
  259. }
  260.  
  261. int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
  262.                            const unsigned char *data, size_t len )
  263. {
  264.     int ret;
  265.  
  266. #if defined(MBEDTLS_THREADING_C)
  267.     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
  268.         return( ret );
  269. #endif
  270.  
  271.     ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len );
  272.  
  273. #if defined(MBEDTLS_THREADING_C)
  274.     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
  275.         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
  276. #endif
  277.  
  278.     return( ret );
  279. }
  280.  
  281. /*
  282.  * Run through the different sources to add entropy to our accumulator
  283.  */
  284. static int entropy_gather_internal( mbedtls_entropy_context *ctx )
  285. {
  286.     int ret, i, have_one_strong = 0;
  287.     unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
  288.     size_t olen;
  289.  
  290.     if( ctx->source_count == 0 )
  291.         return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED );
  292.  
  293.     /*
  294.      * Run through our entropy sources
  295.      */
  296.     for( i = 0; i < ctx->source_count; i++ )
  297.     {
  298.         if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
  299.             have_one_strong = 1;
  300.  
  301.         olen = 0;
  302.         if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
  303.                         buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 )
  304.         {
  305.             goto cleanup;
  306.         }
  307.  
  308.         /*
  309.          * Add if we actually gathered something
  310.          */
  311.         if( olen > 0 )
  312.         {
  313.             if( ( ret = entropy_update( ctx, (unsigned char) i,
  314.                                         buf, olen ) ) != 0 )
  315.                 return( ret );
  316.             ctx->source[i].size += olen;
  317.         }
  318.     }
  319.  
  320.     if( have_one_strong == 0 )
  321.         ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
  322.  
  323. cleanup:
  324.     mbedtls_platform_zeroize( buf, sizeof( buf ) );
  325.  
  326.     return( ret );
  327. }
  328.  
  329. /*
  330.  * Thread-safe wrapper for entropy_gather_internal()
  331.  */
  332. int mbedtls_entropy_gather( mbedtls_entropy_context *ctx )
  333. {
  334.     int ret;
  335.  
  336. #if defined(MBEDTLS_THREADING_C)
  337.     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
  338.         return( ret );
  339. #endif
  340.  
  341.     ret = entropy_gather_internal( ctx );
  342.  
  343. #if defined(MBEDTLS_THREADING_C)
  344.     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
  345.         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
  346. #endif
  347.  
  348.     return( ret );
  349. }
  350.  
  351. int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
  352. {
  353.     int ret, count = 0, i, done;
  354.     mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
  355.     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
  356.  
  357.     if( len > MBEDTLS_ENTROPY_BLOCK_SIZE )
  358.         return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
  359.  
  360. #if defined(MBEDTLS_ENTROPY_NV_SEED)
  361.     /* Update the NV entropy seed before generating any entropy for outside
  362.      * use.
  363.      */
  364.     if( ctx->initial_entropy_run == 0 )
  365.     {
  366.         ctx->initial_entropy_run = 1;
  367.         if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 )
  368.             return( ret );
  369.     }
  370. #endif
  371.  
  372. #if defined(MBEDTLS_THREADING_C)
  373.     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
  374.         return( ret );
  375. #endif
  376.  
  377.     /*
  378.      * Always gather extra entropy before a call
  379.      */
  380.     do
  381.     {
  382.         if( count++ > ENTROPY_MAX_LOOP )
  383.         {
  384.             /*for( i = 0; i < ctx->source_count; i++ ) { // rgimad
  385.                 mbedtls_printf("ctx->source[%d].size = %d\n", i, ctx->source[i].size);
  386.             }*/
  387.             ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
  388.             goto exit;
  389.         }
  390.  
  391.         if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
  392.             goto exit;
  393.  
  394.         done = 1;
  395.         for( i = 0; i < ctx->source_count; i++ )
  396.             if( ctx->source[i].size < ctx->source[i].threshold )
  397.                 done = 0;
  398.     }
  399.     while( ! done );
  400.  
  401.     memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
  402.  
  403. #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
  404.     /*
  405.      * Note that at this stage it is assumed that the accumulator was started
  406.      * in a previous call to entropy_update(). If this is not guaranteed, the
  407.      * code below will fail.
  408.      */
  409.     if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 )
  410.         goto exit;
  411.  
  412.     /*
  413.      * Reset accumulator and counters and recycle existing entropy
  414.      */
  415.     mbedtls_sha512_free( &ctx->accumulator );
  416.     mbedtls_sha512_init( &ctx->accumulator );
  417.     if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
  418.         goto exit;
  419.     if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf,
  420.                                            MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
  421.         goto exit;
  422.  
  423.     /*
  424.      * Perform second SHA-512 on entropy
  425.      */
  426.     if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
  427.                                     buf, 0 ) ) != 0 )
  428.         goto exit;
  429. #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
  430.     if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 )
  431.         goto exit;
  432.  
  433.     /*
  434.      * Reset accumulator and counters and recycle existing entropy
  435.      */
  436.     mbedtls_sha256_free( &ctx->accumulator );
  437.     mbedtls_sha256_init( &ctx->accumulator );
  438.     if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
  439.         goto exit;
  440.     if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf,
  441.                                            MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
  442.         goto exit;
  443.  
  444.     /*
  445.      * Perform second SHA-256 on entropy
  446.      */
  447.     if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
  448.                                     buf, 0 ) ) != 0 )
  449.         goto exit;
  450. #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
  451.  
  452.     for( i = 0; i < ctx->source_count; i++ )
  453.         ctx->source[i].size = 0;
  454.  
  455.     memcpy( output, buf, len );
  456.  
  457.     ret = 0;
  458.  
  459. exit:
  460.     mbedtls_platform_zeroize( buf, sizeof( buf ) );
  461.  
  462. #if defined(MBEDTLS_THREADING_C)
  463.     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
  464.         return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
  465. #endif
  466.  
  467.     return( ret );
  468. }
  469.  
  470. #if defined(MBEDTLS_ENTROPY_NV_SEED)
  471. int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx )
  472. {
  473.     int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
  474.     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
  475.  
  476.     /* Read new seed  and write it to NV */
  477.     if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
  478.         return( ret );
  479.  
  480.     if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
  481.         return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
  482.  
  483.     /* Manually update the remaining stream with a separator value to diverge */
  484.     memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
  485.     ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
  486.  
  487.     return( ret );
  488. }
  489. #endif /* MBEDTLS_ENTROPY_NV_SEED */
  490.  
  491. #if defined(MBEDTLS_FS_IO)
  492. int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
  493. {
  494.     int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
  495.     FILE *f;
  496.     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
  497.  
  498.     if( ( f = fopen( path, "wb" ) ) == NULL )
  499.         return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
  500.  
  501.     if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
  502.         goto exit;
  503.  
  504.     if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
  505.     {
  506.         ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
  507.         goto exit;
  508.     }
  509.  
  510.     ret = 0;
  511.  
  512. exit:
  513.     mbedtls_platform_zeroize( buf, sizeof( buf ) );
  514.  
  515.     fclose( f );
  516.     return( ret );
  517. }
  518.  
  519. int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path )
  520. {
  521.     int ret = 0;
  522.     FILE *f;
  523.     size_t n;
  524.     unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ];
  525.  
  526.     if( ( f = fopen( path, "rb" ) ) == NULL )
  527.         return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
  528.  
  529.     fseek( f, 0, SEEK_END );
  530.     n = (size_t) ftell( f );
  531.     fseek( f, 0, SEEK_SET );
  532.  
  533.     if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE )
  534.         n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
  535.  
  536.     if( fread( buf, 1, n, f ) != n )
  537.         ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
  538.     else
  539.         ret = mbedtls_entropy_update_manual( ctx, buf, n );
  540.  
  541.     fclose( f );
  542.  
  543.     mbedtls_platform_zeroize( buf, sizeof( buf ) );
  544.  
  545.     if( ret != 0 )
  546.         return( ret );
  547.  
  548.     return( mbedtls_entropy_write_seed_file( ctx, path ) );
  549. }
  550. #endif /* MBEDTLS_FS_IO */
  551.  
  552. #if defined(MBEDTLS_SELF_TEST)
  553. #if !defined(MBEDTLS_TEST_NULL_ENTROPY)
  554. /*
  555.  * Dummy source function
  556.  */
  557. static int entropy_dummy_source( void *data, unsigned char *output,
  558.                                  size_t len, size_t *olen )
  559. {
  560.     ((void) data);
  561.  
  562.     memset( output, 0x2a, len );
  563.     *olen = len;
  564.  
  565.     return( 0 );
  566. }
  567. #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
  568.  
  569. #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
  570.  
  571. static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len )
  572. {
  573.     int ret = 0;
  574.     size_t entropy_len = 0;
  575.     size_t olen = 0;
  576.     size_t attempts = buf_len;
  577.  
  578.     while( attempts > 0 && entropy_len < buf_len )
  579.     {
  580.         if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len,
  581.             buf_len - entropy_len, &olen ) ) != 0 )
  582.             return( ret );
  583.  
  584.         entropy_len += olen;
  585.         attempts--;
  586.     }
  587.  
  588.     if( entropy_len < buf_len )
  589.     {
  590.         ret = 1;
  591.     }
  592.  
  593.     return( ret );
  594. }
  595.  
  596.  
  597. static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf,
  598.                                                         size_t buf_len )
  599. {
  600.     unsigned char set= 0xFF;
  601.     unsigned char unset = 0x00;
  602.     size_t i;
  603.  
  604.     for( i = 0; i < buf_len; i++ )
  605.     {
  606.         set &= buf[i];
  607.         unset |= buf[i];
  608.     }
  609.  
  610.     return( set == 0xFF || unset == 0x00 );
  611. }
  612.  
  613. /*
  614.  * A test to ensure hat the entropy sources are functioning correctly
  615.  * and there is no obvious failure. The test performs the following checks:
  616.  *  - The entropy source is not providing only 0s (all bits unset) or 1s (all
  617.  *    bits set).
  618.  *  - The entropy source is not providing values in a pattern. Because the
  619.  *    hardware could be providing data in an arbitrary length, this check polls
  620.  *    the hardware entropy source twice and compares the result to ensure they
  621.  *    are not equal.
  622.  *  - The error code returned by the entropy source is not an error.
  623.  */
  624. int mbedtls_entropy_source_self_test( int verbose )
  625. {
  626.     int ret = 0;
  627.     unsigned char buf0[2 * sizeof( unsigned long long int )];
  628.     unsigned char buf1[2 * sizeof( unsigned long long int )];
  629.  
  630.     if( verbose != 0 )
  631.         mbedtls_printf( "  ENTROPY_BIAS test: " );
  632.  
  633.     memset( buf0, 0x00, sizeof( buf0 ) );
  634.     memset( buf1, 0x00, sizeof( buf1 ) );
  635.  
  636.     if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 )
  637.         goto cleanup;
  638.     if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 )
  639.         goto cleanup;
  640.  
  641.     /* Make sure that the returned values are not all 0 or 1 */
  642.     if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 )
  643.         goto cleanup;
  644.     if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 )
  645.         goto cleanup;
  646.  
  647.     /* Make sure that the entropy source is not returning values in a
  648.      * pattern */
  649.     ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0;
  650.  
  651. cleanup:
  652.     if( verbose != 0 )
  653.     {
  654.         if( ret != 0 )
  655.             mbedtls_printf( "failed\n" );
  656.         else
  657.             mbedtls_printf( "passed\n" );
  658.  
  659.         mbedtls_printf( "\n" );
  660.     }
  661.  
  662.     return( ret != 0 );
  663. }
  664.  
  665. #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
  666.  
  667. /*
  668.  * The actual entropy quality is hard to test, but we can at least
  669.  * test that the functions don't cause errors and write the correct
  670.  * amount of data to buffers.
  671.  */
  672. int mbedtls_entropy_self_test( int verbose )
  673. {
  674.     int ret = 1;
  675. #if !defined(MBEDTLS_TEST_NULL_ENTROPY)
  676.     mbedtls_entropy_context ctx;
  677.     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
  678.     unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
  679.     size_t i, j;
  680. #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
  681.  
  682.     if( verbose != 0 )
  683.         mbedtls_printf( "  ENTROPY test: " );
  684.  
  685. #if !defined(MBEDTLS_TEST_NULL_ENTROPY)
  686.     mbedtls_entropy_init( &ctx );
  687.  
  688.     /* First do a gather to make sure we have default sources */
  689.     if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 )
  690.         goto cleanup;
  691.  
  692.     ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16,
  693.                                       MBEDTLS_ENTROPY_SOURCE_WEAK );
  694.     if( ret != 0 )
  695.         goto cleanup;
  696.  
  697.     if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
  698.         goto cleanup;
  699.  
  700.     /*
  701.      * To test that mbedtls_entropy_func writes correct number of bytes:
  702.      * - use the whole buffer and rely on ASan to detect overruns
  703.      * - collect entropy 8 times and OR the result in an accumulator:
  704.      *   any byte should then be 0 with probably 2^(-64), so requiring
  705.      *   each of the 32 or 64 bytes to be non-zero has a false failure rate
  706.      *   of at most 2^(-58) which is acceptable.
  707.      */
  708.     for( i = 0; i < 8; i++ )
  709.     {
  710.         if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
  711.             goto cleanup;
  712.  
  713.         for( j = 0; j < sizeof( buf ); j++ )
  714.             acc[j] |= buf[j];
  715.     }
  716.  
  717.     for( j = 0; j < sizeof( buf ); j++ )
  718.     {
  719.         if( acc[j] == 0 )
  720.         {
  721.             ret = 1;
  722.             goto cleanup;
  723.         }
  724.     }
  725.  
  726. #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
  727.     if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 )
  728.         goto cleanup;
  729. #endif
  730.  
  731. cleanup:
  732.     mbedtls_entropy_free( &ctx );
  733. #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
  734.  
  735.     if( verbose != 0 )
  736.     {
  737.         if( ret != 0 )
  738.             mbedtls_printf( "failed\n" );
  739.         else
  740.             mbedtls_printf( "passed\n" );
  741.  
  742.         mbedtls_printf( "\n" );
  743.     }
  744.  
  745.     return( ret != 0 );
  746. }
  747. #endif /* MBEDTLS_SELF_TEST */
  748.  
  749. #endif /* MBEDTLS_ENTROPY_C */
  750.