Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8774 rgimad 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 
43
 
44
#if defined(MBEDTLS_FS_IO)
45
#include 
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 
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 */