entropy.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /*
  2. * Entropy accumulator implementation
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  6. */
  7. #include "common.h"
  8. #if defined(MBEDTLS_ENTROPY_C)
  9. #include "mbedtls/entropy.h"
  10. #include "entropy_poll.h"
  11. #include "mbedtls/platform_util.h"
  12. #include "mbedtls/error.h"
  13. #include <string.h>
  14. #if defined(MBEDTLS_FS_IO)
  15. #include <stdio.h>
  16. #endif
  17. #include "mbedtls/platform.h"
  18. #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
  19. void mbedtls_entropy_init(mbedtls_entropy_context *ctx)
  20. {
  21. ctx->source_count = 0;
  22. memset(ctx->source, 0, sizeof(ctx->source));
  23. #if defined(MBEDTLS_THREADING_C)
  24. mbedtls_mutex_init(&ctx->mutex);
  25. #endif
  26. ctx->accumulator_started = 0;
  27. mbedtls_md_init(&ctx->accumulator);
  28. /* Reminder: Update ENTROPY_HAVE_STRONG in the test files
  29. * when adding more strong entropy sources here. */
  30. #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
  31. #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
  32. mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL,
  33. MBEDTLS_ENTROPY_MIN_PLATFORM,
  34. MBEDTLS_ENTROPY_SOURCE_STRONG);
  35. #endif
  36. #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
  37. mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL,
  38. MBEDTLS_ENTROPY_MIN_HARDWARE,
  39. MBEDTLS_ENTROPY_SOURCE_STRONG);
  40. #endif
  41. #if defined(MBEDTLS_ENTROPY_NV_SEED)
  42. mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL,
  43. MBEDTLS_ENTROPY_BLOCK_SIZE,
  44. MBEDTLS_ENTROPY_SOURCE_STRONG);
  45. ctx->initial_entropy_run = 0;
  46. #endif
  47. #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
  48. }
  49. void mbedtls_entropy_free(mbedtls_entropy_context *ctx)
  50. {
  51. if (ctx == NULL) {
  52. return;
  53. }
  54. /* If the context was already free, don't call free() again.
  55. * This is important for mutexes which don't allow double-free. */
  56. if (ctx->accumulator_started == -1) {
  57. return;
  58. }
  59. #if defined(MBEDTLS_THREADING_C)
  60. mbedtls_mutex_free(&ctx->mutex);
  61. #endif
  62. mbedtls_md_free(&ctx->accumulator);
  63. #if defined(MBEDTLS_ENTROPY_NV_SEED)
  64. ctx->initial_entropy_run = 0;
  65. #endif
  66. ctx->source_count = 0;
  67. mbedtls_platform_zeroize(ctx->source, sizeof(ctx->source));
  68. ctx->accumulator_started = -1;
  69. }
  70. int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx,
  71. mbedtls_entropy_f_source_ptr f_source, void *p_source,
  72. size_t threshold, int strong)
  73. {
  74. int idx, ret = 0;
  75. #if defined(MBEDTLS_THREADING_C)
  76. if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
  77. return ret;
  78. }
  79. #endif
  80. idx = ctx->source_count;
  81. if (idx >= MBEDTLS_ENTROPY_MAX_SOURCES) {
  82. ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
  83. goto exit;
  84. }
  85. ctx->source[idx].f_source = f_source;
  86. ctx->source[idx].p_source = p_source;
  87. ctx->source[idx].threshold = threshold;
  88. ctx->source[idx].strong = strong;
  89. ctx->source_count++;
  90. exit:
  91. #if defined(MBEDTLS_THREADING_C)
  92. if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
  93. return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
  94. }
  95. #endif
  96. return ret;
  97. }
  98. /*
  99. * Entropy accumulator update
  100. */
  101. static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id,
  102. const unsigned char *data, size_t len)
  103. {
  104. unsigned char header[2];
  105. unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
  106. size_t use_len = len;
  107. const unsigned char *p = data;
  108. int ret = 0;
  109. if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
  110. if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),
  111. data, len, tmp)) != 0) {
  112. goto cleanup;
  113. }
  114. p = tmp;
  115. use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
  116. }
  117. header[0] = source_id;
  118. header[1] = use_len & 0xFF;
  119. /*
  120. * Start the accumulator if this has not already happened. Note that
  121. * it is sufficient to start the accumulator here only because all calls to
  122. * gather entropy eventually execute this code.
  123. */
  124. if (ctx->accumulator_started == 0) {
  125. ret = mbedtls_md_setup(&ctx->accumulator,
  126. mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);
  127. if (ret != 0) {
  128. goto cleanup;
  129. }
  130. ret = mbedtls_md_starts(&ctx->accumulator);
  131. if (ret != 0) {
  132. goto cleanup;
  133. }
  134. ctx->accumulator_started = 1;
  135. }
  136. if ((ret = mbedtls_md_update(&ctx->accumulator, header, 2)) != 0) {
  137. goto cleanup;
  138. }
  139. ret = mbedtls_md_update(&ctx->accumulator, p, use_len);
  140. cleanup:
  141. mbedtls_platform_zeroize(tmp, sizeof(tmp));
  142. return ret;
  143. }
  144. int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx,
  145. const unsigned char *data, size_t len)
  146. {
  147. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  148. #if defined(MBEDTLS_THREADING_C)
  149. if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
  150. return ret;
  151. }
  152. #endif
  153. ret = entropy_update(ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len);
  154. #if defined(MBEDTLS_THREADING_C)
  155. if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
  156. return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
  157. }
  158. #endif
  159. return ret;
  160. }
  161. /*
  162. * Run through the different sources to add entropy to our accumulator
  163. */
  164. static int entropy_gather_internal(mbedtls_entropy_context *ctx)
  165. {
  166. int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
  167. int i;
  168. int have_one_strong = 0;
  169. unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
  170. size_t olen;
  171. if (ctx->source_count == 0) {
  172. return MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED;
  173. }
  174. /*
  175. * Run through our entropy sources
  176. */
  177. for (i = 0; i < ctx->source_count; i++) {
  178. if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {
  179. have_one_strong = 1;
  180. }
  181. olen = 0;
  182. if ((ret = ctx->source[i].f_source(ctx->source[i].p_source,
  183. buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen)) != 0) {
  184. goto cleanup;
  185. }
  186. /*
  187. * Add if we actually gathered something
  188. */
  189. if (olen > 0) {
  190. if ((ret = entropy_update(ctx, (unsigned char) i,
  191. buf, olen)) != 0) {
  192. return ret;
  193. }
  194. ctx->source[i].size += olen;
  195. }
  196. }
  197. if (have_one_strong == 0) {
  198. ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
  199. }
  200. cleanup:
  201. mbedtls_platform_zeroize(buf, sizeof(buf));
  202. return ret;
  203. }
  204. /*
  205. * Thread-safe wrapper for entropy_gather_internal()
  206. */
  207. int mbedtls_entropy_gather(mbedtls_entropy_context *ctx)
  208. {
  209. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  210. #if defined(MBEDTLS_THREADING_C)
  211. if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
  212. return ret;
  213. }
  214. #endif
  215. ret = entropy_gather_internal(ctx);
  216. #if defined(MBEDTLS_THREADING_C)
  217. if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
  218. return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
  219. }
  220. #endif
  221. return ret;
  222. }
  223. int mbedtls_entropy_func(void *data, unsigned char *output, size_t len)
  224. {
  225. int ret, count = 0, i, thresholds_reached;
  226. size_t strong_size;
  227. mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
  228. unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
  229. if (len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
  230. return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
  231. }
  232. #if defined(MBEDTLS_ENTROPY_NV_SEED)
  233. /* Update the NV entropy seed before generating any entropy for outside
  234. * use.
  235. */
  236. if (ctx->initial_entropy_run == 0) {
  237. ctx->initial_entropy_run = 1;
  238. if ((ret = mbedtls_entropy_update_nv_seed(ctx)) != 0) {
  239. return ret;
  240. }
  241. }
  242. #endif
  243. #if defined(MBEDTLS_THREADING_C)
  244. if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
  245. return ret;
  246. }
  247. #endif
  248. /*
  249. * Always gather extra entropy before a call
  250. */
  251. do {
  252. if (count++ > ENTROPY_MAX_LOOP) {
  253. ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
  254. goto exit;
  255. }
  256. if ((ret = entropy_gather_internal(ctx)) != 0) {
  257. goto exit;
  258. }
  259. thresholds_reached = 1;
  260. strong_size = 0;
  261. for (i = 0; i < ctx->source_count; i++) {
  262. if (ctx->source[i].size < ctx->source[i].threshold) {
  263. thresholds_reached = 0;
  264. }
  265. if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {
  266. strong_size += ctx->source[i].size;
  267. }
  268. }
  269. } while (!thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE);
  270. memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
  271. /*
  272. * Note that at this stage it is assumed that the accumulator was started
  273. * in a previous call to entropy_update(). If this is not guaranteed, the
  274. * code below will fail.
  275. */
  276. if ((ret = mbedtls_md_finish(&ctx->accumulator, buf)) != 0) {
  277. goto exit;
  278. }
  279. /*
  280. * Reset accumulator and counters and recycle existing entropy
  281. */
  282. mbedtls_md_free(&ctx->accumulator);
  283. mbedtls_md_init(&ctx->accumulator);
  284. ret = mbedtls_md_setup(&ctx->accumulator,
  285. mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);
  286. if (ret != 0) {
  287. goto exit;
  288. }
  289. ret = mbedtls_md_starts(&ctx->accumulator);
  290. if (ret != 0) {
  291. goto exit;
  292. }
  293. if ((ret = mbedtls_md_update(&ctx->accumulator, buf,
  294. MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
  295. goto exit;
  296. }
  297. /*
  298. * Perform second hashing on entropy
  299. */
  300. if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),
  301. buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf)) != 0) {
  302. goto exit;
  303. }
  304. for (i = 0; i < ctx->source_count; i++) {
  305. ctx->source[i].size = 0;
  306. }
  307. memcpy(output, buf, len);
  308. ret = 0;
  309. exit:
  310. mbedtls_platform_zeroize(buf, sizeof(buf));
  311. #if defined(MBEDTLS_THREADING_C)
  312. if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
  313. return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
  314. }
  315. #endif
  316. return ret;
  317. }
  318. #if defined(MBEDTLS_ENTROPY_NV_SEED)
  319. int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx)
  320. {
  321. int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
  322. unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
  323. /* Read new seed and write it to NV */
  324. if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
  325. return ret;
  326. }
  327. if (mbedtls_nv_seed_write(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) {
  328. return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
  329. }
  330. /* Manually update the remaining stream with a separator value to diverge */
  331. memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
  332. ret = mbedtls_entropy_update_manual(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE);
  333. return ret;
  334. }
  335. #endif /* MBEDTLS_ENTROPY_NV_SEED */
  336. #if defined(MBEDTLS_FS_IO)
  337. int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path)
  338. {
  339. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  340. FILE *f = NULL;
  341. unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
  342. if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
  343. ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
  344. goto exit;
  345. }
  346. if ((f = fopen(path, "wb")) == NULL) {
  347. ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
  348. goto exit;
  349. }
  350. /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
  351. mbedtls_setbuf(f, NULL);
  352. if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) != MBEDTLS_ENTROPY_BLOCK_SIZE) {
  353. ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
  354. goto exit;
  355. }
  356. ret = 0;
  357. exit:
  358. mbedtls_platform_zeroize(buf, sizeof(buf));
  359. if (f != NULL) {
  360. fclose(f);
  361. }
  362. return ret;
  363. }
  364. int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path)
  365. {
  366. int ret = 0;
  367. FILE *f;
  368. size_t n;
  369. unsigned char buf[MBEDTLS_ENTROPY_MAX_SEED_SIZE];
  370. if ((f = fopen(path, "rb")) == NULL) {
  371. return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
  372. }
  373. /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
  374. mbedtls_setbuf(f, NULL);
  375. fseek(f, 0, SEEK_END);
  376. n = (size_t) ftell(f);
  377. fseek(f, 0, SEEK_SET);
  378. if (n > MBEDTLS_ENTROPY_MAX_SEED_SIZE) {
  379. n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
  380. }
  381. if (fread(buf, 1, n, f) != n) {
  382. ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
  383. } else {
  384. ret = mbedtls_entropy_update_manual(ctx, buf, n);
  385. }
  386. fclose(f);
  387. mbedtls_platform_zeroize(buf, sizeof(buf));
  388. if (ret != 0) {
  389. return ret;
  390. }
  391. return mbedtls_entropy_write_seed_file(ctx, path);
  392. }
  393. #endif /* MBEDTLS_FS_IO */
  394. #if defined(MBEDTLS_SELF_TEST)
  395. /*
  396. * Dummy source function
  397. */
  398. static int entropy_dummy_source(void *data, unsigned char *output,
  399. size_t len, size_t *olen)
  400. {
  401. ((void) data);
  402. memset(output, 0x2a, len);
  403. *olen = len;
  404. return 0;
  405. }
  406. #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
  407. static int mbedtls_entropy_source_self_test_gather(unsigned char *buf, size_t buf_len)
  408. {
  409. int ret = 0;
  410. size_t entropy_len = 0;
  411. size_t olen = 0;
  412. size_t attempts = buf_len;
  413. while (attempts > 0 && entropy_len < buf_len) {
  414. if ((ret = mbedtls_hardware_poll(NULL, buf + entropy_len,
  415. buf_len - entropy_len, &olen)) != 0) {
  416. return ret;
  417. }
  418. entropy_len += olen;
  419. attempts--;
  420. }
  421. if (entropy_len < buf_len) {
  422. ret = 1;
  423. }
  424. return ret;
  425. }
  426. static int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf,
  427. size_t buf_len)
  428. {
  429. unsigned char set = 0xFF;
  430. unsigned char unset = 0x00;
  431. size_t i;
  432. for (i = 0; i < buf_len; i++) {
  433. set &= buf[i];
  434. unset |= buf[i];
  435. }
  436. return set == 0xFF || unset == 0x00;
  437. }
  438. /*
  439. * A test to ensure that the entropy sources are functioning correctly
  440. * and there is no obvious failure. The test performs the following checks:
  441. * - The entropy source is not providing only 0s (all bits unset) or 1s (all
  442. * bits set).
  443. * - The entropy source is not providing values in a pattern. Because the
  444. * hardware could be providing data in an arbitrary length, this check polls
  445. * the hardware entropy source twice and compares the result to ensure they
  446. * are not equal.
  447. * - The error code returned by the entropy source is not an error.
  448. */
  449. int mbedtls_entropy_source_self_test(int verbose)
  450. {
  451. int ret = 0;
  452. unsigned char buf0[2 * sizeof(unsigned long long int)];
  453. unsigned char buf1[2 * sizeof(unsigned long long int)];
  454. if (verbose != 0) {
  455. mbedtls_printf(" ENTROPY_BIAS test: ");
  456. }
  457. memset(buf0, 0x00, sizeof(buf0));
  458. memset(buf1, 0x00, sizeof(buf1));
  459. if ((ret = mbedtls_entropy_source_self_test_gather(buf0, sizeof(buf0))) != 0) {
  460. goto cleanup;
  461. }
  462. if ((ret = mbedtls_entropy_source_self_test_gather(buf1, sizeof(buf1))) != 0) {
  463. goto cleanup;
  464. }
  465. /* Make sure that the returned values are not all 0 or 1 */
  466. if ((ret = mbedtls_entropy_source_self_test_check_bits(buf0, sizeof(buf0))) != 0) {
  467. goto cleanup;
  468. }
  469. if ((ret = mbedtls_entropy_source_self_test_check_bits(buf1, sizeof(buf1))) != 0) {
  470. goto cleanup;
  471. }
  472. /* Make sure that the entropy source is not returning values in a
  473. * pattern */
  474. ret = memcmp(buf0, buf1, sizeof(buf0)) == 0;
  475. cleanup:
  476. if (verbose != 0) {
  477. if (ret != 0) {
  478. mbedtls_printf("failed\n");
  479. } else {
  480. mbedtls_printf("passed\n");
  481. }
  482. mbedtls_printf("\n");
  483. }
  484. return ret != 0;
  485. }
  486. #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
  487. /*
  488. * The actual entropy quality is hard to test, but we can at least
  489. * test that the functions don't cause errors and write the correct
  490. * amount of data to buffers.
  491. */
  492. int mbedtls_entropy_self_test(int verbose)
  493. {
  494. int ret = 1;
  495. mbedtls_entropy_context ctx;
  496. unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
  497. unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
  498. size_t i, j;
  499. if (verbose != 0) {
  500. mbedtls_printf(" ENTROPY test: ");
  501. }
  502. mbedtls_entropy_init(&ctx);
  503. /* First do a gather to make sure we have default sources */
  504. if ((ret = mbedtls_entropy_gather(&ctx)) != 0) {
  505. goto cleanup;
  506. }
  507. ret = mbedtls_entropy_add_source(&ctx, entropy_dummy_source, NULL, 16,
  508. MBEDTLS_ENTROPY_SOURCE_WEAK);
  509. if (ret != 0) {
  510. goto cleanup;
  511. }
  512. if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof(buf))) != 0) {
  513. goto cleanup;
  514. }
  515. /*
  516. * To test that mbedtls_entropy_func writes correct number of bytes:
  517. * - use the whole buffer and rely on ASan to detect overruns
  518. * - collect entropy 8 times and OR the result in an accumulator:
  519. * any byte should then be 0 with probably 2^(-64), so requiring
  520. * each of the 32 or 64 bytes to be non-zero has a false failure rate
  521. * of at most 2^(-58) which is acceptable.
  522. */
  523. for (i = 0; i < 8; i++) {
  524. if ((ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf))) != 0) {
  525. goto cleanup;
  526. }
  527. for (j = 0; j < sizeof(buf); j++) {
  528. acc[j] |= buf[j];
  529. }
  530. }
  531. for (j = 0; j < sizeof(buf); j++) {
  532. if (acc[j] == 0) {
  533. ret = 1;
  534. goto cleanup;
  535. }
  536. }
  537. #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
  538. if ((ret = mbedtls_entropy_source_self_test(0)) != 0) {
  539. goto cleanup;
  540. }
  541. #endif
  542. cleanup:
  543. mbedtls_entropy_free(&ctx);
  544. if (verbose != 0) {
  545. if (ret != 0) {
  546. mbedtls_printf("failed\n");
  547. } else {
  548. mbedtls_printf("passed\n");
  549. }
  550. mbedtls_printf("\n");
  551. }
  552. return ret != 0;
  553. }
  554. #endif /* MBEDTLS_SELF_TEST */
  555. #endif /* MBEDTLS_ENTROPY_C */