entropy.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. /*
  2. * Entropy accumulator implementation
  3. *
  4. * Copyright (C) 2006-2014, Brainspark B.V.
  5. *
  6. * This file is part of PolarSSL (http://www.polarssl.org)
  7. * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  8. *
  9. * All rights reserved.
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License along
  22. * with this program; if not, write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  24. */
  25. #if !defined(POLARSSL_CONFIG_FILE)
  26. #include "polarssl/config.h"
  27. #else
  28. #include POLARSSL_CONFIG_FILE
  29. #endif
  30. #if defined(POLARSSL_ENTROPY_C)
  31. #include "polarssl/entropy.h"
  32. #include "polarssl/entropy_poll.h"
  33. #if defined(POLARSSL_FS_IO)
  34. #include <stdio.h>
  35. #endif
  36. #if defined(POLARSSL_HAVEGE_C)
  37. #include "polarssl/havege.h"
  38. #endif
  39. /* Implementation that should never be optimized out by the compiler */
  40. static void polarssl_zeroize( void *v, size_t n ) {
  41. volatile unsigned char *p = v; while( n-- ) *p++ = 0;
  42. }
  43. #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
  44. void entropy_init( entropy_context *ctx )
  45. {
  46. memset( ctx, 0, sizeof(entropy_context) );
  47. #if defined(POLARSSL_THREADING_C)
  48. polarssl_mutex_init( &ctx->mutex );
  49. #endif
  50. #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
  51. sha512_starts( &ctx->accumulator, 0 );
  52. #else
  53. sha256_starts( &ctx->accumulator, 0 );
  54. #endif
  55. #if defined(POLARSSL_HAVEGE_C)
  56. havege_init( &ctx->havege_data );
  57. #endif
  58. #if !defined(POLARSSL_NO_DEFAULT_ENTROPY_SOURCES)
  59. #if !defined(POLARSSL_NO_PLATFORM_ENTROPY)
  60. entropy_add_source( ctx, platform_entropy_poll, NULL,
  61. ENTROPY_MIN_PLATFORM );
  62. #endif
  63. #if defined(POLARSSL_TIMING_C)
  64. entropy_add_source( ctx, hardclock_poll, NULL, ENTROPY_MIN_HARDCLOCK );
  65. #endif
  66. #if defined(POLARSSL_HAVEGE_C)
  67. entropy_add_source( ctx, havege_poll, &ctx->havege_data,
  68. ENTROPY_MIN_HAVEGE );
  69. #endif
  70. #endif /* POLARSSL_NO_DEFAULT_ENTROPY_SOURCES */
  71. }
  72. void entropy_free( entropy_context *ctx )
  73. {
  74. #if defined(POLARSSL_HAVEGE_C)
  75. havege_free( &ctx->havege_data );
  76. #endif
  77. polarssl_zeroize( ctx, sizeof( entropy_context ) );
  78. #if defined(POLARSSL_THREADING_C)
  79. polarssl_mutex_free( &ctx->mutex );
  80. #endif
  81. }
  82. int entropy_add_source( entropy_context *ctx,
  83. f_source_ptr f_source, void *p_source,
  84. size_t threshold )
  85. {
  86. int index, ret = 0;
  87. #if defined(POLARSSL_THREADING_C)
  88. if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
  89. return( ret );
  90. #endif
  91. index = ctx->source_count;
  92. if( index >= ENTROPY_MAX_SOURCES )
  93. {
  94. ret = POLARSSL_ERR_ENTROPY_MAX_SOURCES;
  95. goto exit;
  96. }
  97. ctx->source[index].f_source = f_source;
  98. ctx->source[index].p_source = p_source;
  99. ctx->source[index].threshold = threshold;
  100. ctx->source_count++;
  101. exit:
  102. #if defined(POLARSSL_THREADING_C)
  103. if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
  104. return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
  105. #endif
  106. return( ret );
  107. }
  108. /*
  109. * Entropy accumulator update
  110. */
  111. static int entropy_update( entropy_context *ctx, unsigned char source_id,
  112. const unsigned char *data, size_t len )
  113. {
  114. unsigned char header[2];
  115. unsigned char tmp[ENTROPY_BLOCK_SIZE];
  116. size_t use_len = len;
  117. const unsigned char *p = data;
  118. if( use_len > ENTROPY_BLOCK_SIZE )
  119. {
  120. #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
  121. sha512( data, len, tmp, 0 );
  122. #else
  123. sha256( data, len, tmp, 0 );
  124. #endif
  125. p = tmp;
  126. use_len = ENTROPY_BLOCK_SIZE;
  127. }
  128. header[0] = source_id;
  129. header[1] = use_len & 0xFF;
  130. #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
  131. sha512_update( &ctx->accumulator, header, 2 );
  132. sha512_update( &ctx->accumulator, p, use_len );
  133. #else
  134. sha256_update( &ctx->accumulator, header, 2 );
  135. sha256_update( &ctx->accumulator, p, use_len );
  136. #endif
  137. return( 0 );
  138. }
  139. int entropy_update_manual( entropy_context *ctx,
  140. const unsigned char *data, size_t len )
  141. {
  142. int ret;
  143. #if defined(POLARSSL_THREADING_C)
  144. if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
  145. return( ret );
  146. #endif
  147. ret = entropy_update( ctx, ENTROPY_SOURCE_MANUAL, data, len );
  148. #if defined(POLARSSL_THREADING_C)
  149. if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
  150. return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
  151. #endif
  152. return( ret );
  153. }
  154. /*
  155. * Run through the different sources to add entropy to our accumulator
  156. */
  157. static int entropy_gather_internal( entropy_context *ctx )
  158. {
  159. int ret, i;
  160. unsigned char buf[ENTROPY_MAX_GATHER];
  161. size_t olen;
  162. if( ctx->source_count == 0 )
  163. return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
  164. /*
  165. * Run through our entropy sources
  166. */
  167. for( i = 0; i < ctx->source_count; i++ )
  168. {
  169. olen = 0;
  170. if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
  171. buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
  172. {
  173. return( ret );
  174. }
  175. /*
  176. * Add if we actually gathered something
  177. */
  178. if( olen > 0 )
  179. {
  180. entropy_update( ctx, (unsigned char) i, buf, olen );
  181. ctx->source[i].size += olen;
  182. }
  183. }
  184. return( 0 );
  185. }
  186. /*
  187. * Thread-safe wrapper for entropy_gather_internal()
  188. */
  189. int entropy_gather( entropy_context *ctx )
  190. {
  191. int ret;
  192. #if defined(POLARSSL_THREADING_C)
  193. if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
  194. return( ret );
  195. #endif
  196. ret = entropy_gather_internal( ctx );
  197. #if defined(POLARSSL_THREADING_C)
  198. if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
  199. return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
  200. #endif
  201. return( ret );
  202. }
  203. int entropy_func( void *data, unsigned char *output, size_t len )
  204. {
  205. int ret, count = 0, i, reached;
  206. entropy_context *ctx = (entropy_context *) data;
  207. unsigned char buf[ENTROPY_BLOCK_SIZE];
  208. if( len > ENTROPY_BLOCK_SIZE )
  209. return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED );
  210. #if defined(POLARSSL_THREADING_C)
  211. if( ( ret = polarssl_mutex_lock( &ctx->mutex ) ) != 0 )
  212. return( ret );
  213. #endif
  214. /*
  215. * Always gather extra entropy before a call
  216. */
  217. do
  218. {
  219. if( count++ > ENTROPY_MAX_LOOP )
  220. {
  221. ret = POLARSSL_ERR_ENTROPY_SOURCE_FAILED;
  222. goto exit;
  223. }
  224. if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
  225. goto exit;
  226. reached = 0;
  227. for( i = 0; i < ctx->source_count; i++ )
  228. if( ctx->source[i].size >= ctx->source[i].threshold )
  229. reached++;
  230. }
  231. while( reached != ctx->source_count );
  232. memset( buf, 0, ENTROPY_BLOCK_SIZE );
  233. #if defined(POLARSSL_ENTROPY_SHA512_ACCUMULATOR)
  234. sha512_finish( &ctx->accumulator, buf );
  235. /*
  236. * Reset accumulator and counters and recycle existing entropy
  237. */
  238. memset( &ctx->accumulator, 0, sizeof( sha512_context ) );
  239. sha512_starts( &ctx->accumulator, 0 );
  240. sha512_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
  241. /*
  242. * Perform second SHA-512 on entropy
  243. */
  244. sha512( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
  245. #else /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
  246. sha256_finish( &ctx->accumulator, buf );
  247. /*
  248. * Reset accumulator and counters and recycle existing entropy
  249. */
  250. memset( &ctx->accumulator, 0, sizeof( sha256_context ) );
  251. sha256_starts( &ctx->accumulator, 0 );
  252. sha256_update( &ctx->accumulator, buf, ENTROPY_BLOCK_SIZE );
  253. /*
  254. * Perform second SHA-256 on entropy
  255. */
  256. sha256( buf, ENTROPY_BLOCK_SIZE, buf, 0 );
  257. #endif /* POLARSSL_ENTROPY_SHA512_ACCUMULATOR */
  258. for( i = 0; i < ctx->source_count; i++ )
  259. ctx->source[i].size = 0;
  260. memcpy( output, buf, len );
  261. ret = 0;
  262. exit:
  263. #if defined(POLARSSL_THREADING_C)
  264. if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
  265. return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
  266. #endif
  267. return( ret );
  268. }
  269. #if defined(POLARSSL_FS_IO)
  270. int entropy_write_seed_file( entropy_context *ctx, const char *path )
  271. {
  272. int ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR;
  273. FILE *f;
  274. unsigned char buf[ENTROPY_BLOCK_SIZE];
  275. if( ( f = fopen( path, "wb" ) ) == NULL )
  276. return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
  277. if( ( ret = entropy_func( ctx, buf, ENTROPY_BLOCK_SIZE ) ) != 0 )
  278. goto exit;
  279. if( fwrite( buf, 1, ENTROPY_BLOCK_SIZE, f ) != ENTROPY_BLOCK_SIZE )
  280. {
  281. ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR;
  282. goto exit;
  283. }
  284. ret = 0;
  285. exit:
  286. fclose( f );
  287. return( ret );
  288. }
  289. int entropy_update_seed_file( entropy_context *ctx, const char *path )
  290. {
  291. FILE *f;
  292. size_t n;
  293. unsigned char buf[ ENTROPY_MAX_SEED_SIZE ];
  294. if( ( f = fopen( path, "rb" ) ) == NULL )
  295. return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
  296. fseek( f, 0, SEEK_END );
  297. n = (size_t) ftell( f );
  298. fseek( f, 0, SEEK_SET );
  299. if( n > ENTROPY_MAX_SEED_SIZE )
  300. n = ENTROPY_MAX_SEED_SIZE;
  301. if( fread( buf, 1, n, f ) != n )
  302. {
  303. fclose( f );
  304. return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
  305. }
  306. fclose( f );
  307. entropy_update_manual( ctx, buf, n );
  308. return( entropy_write_seed_file( ctx, path ) );
  309. }
  310. #endif /* POLARSSL_FS_IO */
  311. #if defined(POLARSSL_SELF_TEST)
  312. #if defined(POLARSSL_PLATFORM_C)
  313. #include "polarssl/platform.h"
  314. #else
  315. #include <stdio.h>
  316. #define polarssl_printf printf
  317. #endif
  318. /*
  319. * Dummy source function
  320. */
  321. static int entropy_dummy_source( void *data, unsigned char *output,
  322. size_t len, size_t *olen )
  323. {
  324. ((void) data);
  325. memset( output, 0x2a, len );
  326. *olen = len;
  327. return( 0 );
  328. }
  329. /*
  330. * The actual entropy quality is hard to test, but we can at least
  331. * test that the functions don't cause errors and write the correct
  332. * amount of data to buffers.
  333. */
  334. int entropy_self_test( int verbose )
  335. {
  336. int ret = 0;
  337. entropy_context ctx;
  338. unsigned char buf[ENTROPY_BLOCK_SIZE] = { 0 };
  339. unsigned char acc[ENTROPY_BLOCK_SIZE] = { 0 };
  340. size_t i, j;
  341. if( verbose != 0 )
  342. polarssl_printf( " ENTROPY test: " );
  343. entropy_init( &ctx );
  344. ret = entropy_add_source( &ctx, entropy_dummy_source, NULL, 16 );
  345. if( ret != 0 )
  346. goto cleanup;
  347. if( ( ret = entropy_gather( &ctx ) ) != 0 )
  348. goto cleanup;
  349. if( ( ret = entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
  350. goto cleanup;
  351. /*
  352. * To test that entropy_func writes correct number of bytes:
  353. * - use the whole buffer and rely on ASan to detect overruns
  354. * - collect entropy 8 times and OR the result in an accumulator:
  355. * any byte should then be 0 with probably 2^(-64), so requiring
  356. * each of the 32 or 64 bytes to be non-zero has a false failure rate
  357. * of at most 2^(-58) which is acceptable.
  358. */
  359. for( i = 0; i < 8; i++ )
  360. {
  361. if( ( ret = entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
  362. goto cleanup;
  363. for( j = 0; j < sizeof( buf ); j++ )
  364. acc[j] |= buf[j];
  365. }
  366. for( j = 0; j < sizeof( buf ); j++ )
  367. {
  368. if( acc[j] == 0 )
  369. {
  370. ret = 1;
  371. goto cleanup;
  372. }
  373. }
  374. cleanup:
  375. entropy_free( &ctx );
  376. if( verbose != 0 )
  377. {
  378. if( ret != 0 )
  379. polarssl_printf( "failed\n" );
  380. else
  381. polarssl_printf( "passed\n" );
  382. polarssl_printf( "\n" );
  383. }
  384. return( ret != 0 );
  385. }
  386. #endif /* POLARSSL_SELF_TEST */
  387. #endif /* POLARSSL_ENTROPY_C */