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