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