Coverage Report

Created: 2025-07-01 06:54

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