2 * Entropy accumulator implementation
4 * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * This file is part of mbed TLS (https://tls.mbed.org)
22 #if !defined(MBEDTLS_CONFIG_FILE)
23 #include "mbedtls/config.h"
25 #include MBEDTLS_CONFIG_FILE
28 #if defined(MBEDTLS_ENTROPY_C)
30 #if defined(MBEDTLS_TEST_NULL_ENTROPY)
31 #warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! "
32 #warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES "
33 #warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE "
36 #include "mbedtls/entropy.h"
37 #include "mbedtls/entropy_poll.h"
41 #if defined(MBEDTLS_FS_IO)
45 #if defined(MBEDTLS_SELF_TEST)
46 #if defined(MBEDTLS_PLATFORM_C)
47 #include "mbedtls/platform.h"
50 #define mbedtls_printf printf
51 #endif /* MBEDTLS_PLATFORM_C */
52 #endif /* MBEDTLS_SELF_TEST */
54 #if defined(MBEDTLS_HAVEGE_C)
55 #include "mbedtls/havege.h"
58 /* Implementation that should never be optimized out by the compiler */
59 static void mbedtls_zeroize( void *v
, size_t n
) {
60 volatile unsigned char *p
= v
; while( n
-- ) *p
++ = 0;
63 #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
65 void mbedtls_entropy_init( mbedtls_entropy_context
*ctx
)
67 memset( ctx
, 0, sizeof(mbedtls_entropy_context
) );
69 #if defined(MBEDTLS_THREADING_C)
70 mbedtls_mutex_init( &ctx
->mutex
);
73 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
74 mbedtls_sha512_starts( &ctx
->accumulator
, 0 );
76 mbedtls_sha256_starts( &ctx
->accumulator
, 0 );
78 #if defined(MBEDTLS_HAVEGE_C)
79 mbedtls_havege_init( &ctx
->havege_data
);
82 #if defined(MBEDTLS_TEST_NULL_ENTROPY)
83 mbedtls_entropy_add_source( ctx
, mbedtls_null_entropy_poll
, NULL
,
84 1, MBEDTLS_ENTROPY_SOURCE_STRONG
);
87 #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
88 #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
89 mbedtls_entropy_add_source( ctx
, mbedtls_platform_entropy_poll
, NULL
,
90 MBEDTLS_ENTROPY_MIN_PLATFORM
,
91 MBEDTLS_ENTROPY_SOURCE_STRONG
);
93 #if defined(MBEDTLS_TIMING_C)
94 mbedtls_entropy_add_source( ctx
, mbedtls_hardclock_poll
, NULL
,
95 MBEDTLS_ENTROPY_MIN_HARDCLOCK
,
96 MBEDTLS_ENTROPY_SOURCE_WEAK
);
98 #if defined(MBEDTLS_HAVEGE_C)
99 mbedtls_entropy_add_source( ctx
, mbedtls_havege_poll
, &ctx
->havege_data
,
100 MBEDTLS_ENTROPY_MIN_HAVEGE
,
101 MBEDTLS_ENTROPY_SOURCE_STRONG
);
103 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
104 mbedtls_entropy_add_source( ctx
, mbedtls_hardware_poll
, NULL
,
105 MBEDTLS_ENTROPY_MIN_HARDWARE
,
106 MBEDTLS_ENTROPY_SOURCE_STRONG
);
108 #if defined(MBEDTLS_ENTROPY_NV_SEED)
109 mbedtls_entropy_add_source( ctx
, mbedtls_nv_seed_poll
, NULL
,
110 MBEDTLS_ENTROPY_BLOCK_SIZE
,
111 MBEDTLS_ENTROPY_SOURCE_STRONG
);
113 #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
116 void mbedtls_entropy_free( mbedtls_entropy_context
*ctx
)
118 #if defined(MBEDTLS_HAVEGE_C)
119 mbedtls_havege_free( &ctx
->havege_data
);
121 #if defined(MBEDTLS_THREADING_C)
122 mbedtls_mutex_free( &ctx
->mutex
);
124 mbedtls_zeroize( ctx
, sizeof( mbedtls_entropy_context
) );
127 int mbedtls_entropy_add_source( mbedtls_entropy_context
*ctx
,
128 mbedtls_entropy_f_source_ptr f_source
, void *p_source
,
129 size_t threshold
, int strong
)
133 #if defined(MBEDTLS_THREADING_C)
134 if( ( ret
= mbedtls_mutex_lock( &ctx
->mutex
) ) != 0 )
138 index
= ctx
->source_count
;
139 if( index
>= MBEDTLS_ENTROPY_MAX_SOURCES
)
141 ret
= MBEDTLS_ERR_ENTROPY_MAX_SOURCES
;
145 ctx
->source
[index
].f_source
= f_source
;
146 ctx
->source
[index
].p_source
= p_source
;
147 ctx
->source
[index
].threshold
= threshold
;
148 ctx
->source
[index
].strong
= strong
;
153 #if defined(MBEDTLS_THREADING_C)
154 if( mbedtls_mutex_unlock( &ctx
->mutex
) != 0 )
155 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR
);
162 * Entropy accumulator update
164 static int entropy_update( mbedtls_entropy_context
*ctx
, unsigned char source_id
,
165 const unsigned char *data
, size_t len
)
167 unsigned char header
[2];
168 unsigned char tmp
[MBEDTLS_ENTROPY_BLOCK_SIZE
];
169 size_t use_len
= len
;
170 const unsigned char *p
= data
;
172 if( use_len
> MBEDTLS_ENTROPY_BLOCK_SIZE
)
174 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
175 mbedtls_sha512( data
, len
, tmp
, 0 );
177 mbedtls_sha256( data
, len
, tmp
, 0 );
180 use_len
= MBEDTLS_ENTROPY_BLOCK_SIZE
;
183 header
[0] = source_id
;
184 header
[1] = use_len
& 0xFF;
186 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
187 mbedtls_sha512_update( &ctx
->accumulator
, header
, 2 );
188 mbedtls_sha512_update( &ctx
->accumulator
, p
, use_len
);
190 mbedtls_sha256_update( &ctx
->accumulator
, header
, 2 );
191 mbedtls_sha256_update( &ctx
->accumulator
, p
, use_len
);
197 int mbedtls_entropy_update_manual( mbedtls_entropy_context
*ctx
,
198 const unsigned char *data
, size_t len
)
202 #if defined(MBEDTLS_THREADING_C)
203 if( ( ret
= mbedtls_mutex_lock( &ctx
->mutex
) ) != 0 )
207 ret
= entropy_update( ctx
, MBEDTLS_ENTROPY_SOURCE_MANUAL
, data
, len
);
209 #if defined(MBEDTLS_THREADING_C)
210 if( mbedtls_mutex_unlock( &ctx
->mutex
) != 0 )
211 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR
);
218 * Run through the different sources to add entropy to our accumulator
220 static int entropy_gather_internal( mbedtls_entropy_context
*ctx
)
222 int ret
, i
, have_one_strong
= 0;
223 unsigned char buf
[MBEDTLS_ENTROPY_MAX_GATHER
];
226 if( ctx
->source_count
== 0 )
227 return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED
);
230 * Run through our entropy sources
232 for( i
= 0; i
< ctx
->source_count
; i
++ )
234 if( ctx
->source
[i
].strong
== MBEDTLS_ENTROPY_SOURCE_STRONG
)
238 if( ( ret
= ctx
->source
[i
].f_source( ctx
->source
[i
].p_source
,
239 buf
, MBEDTLS_ENTROPY_MAX_GATHER
, &olen
) ) != 0 )
245 * Add if we actually gathered something
249 entropy_update( ctx
, (unsigned char) i
, buf
, olen
);
250 ctx
->source
[i
].size
+= olen
;
254 if( have_one_strong
== 0 )
255 return( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE
);
261 * Thread-safe wrapper for entropy_gather_internal()
263 int mbedtls_entropy_gather( mbedtls_entropy_context
*ctx
)
267 #if defined(MBEDTLS_THREADING_C)
268 if( ( ret
= mbedtls_mutex_lock( &ctx
->mutex
) ) != 0 )
272 ret
= entropy_gather_internal( ctx
);
274 #if defined(MBEDTLS_THREADING_C)
275 if( mbedtls_mutex_unlock( &ctx
->mutex
) != 0 )
276 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR
);
282 int mbedtls_entropy_func( void *data
, unsigned char *output
, size_t len
)
284 int ret
, count
= 0, i
, done
;
285 mbedtls_entropy_context
*ctx
= (mbedtls_entropy_context
*) data
;
286 unsigned char buf
[MBEDTLS_ENTROPY_BLOCK_SIZE
];
288 if( len
> MBEDTLS_ENTROPY_BLOCK_SIZE
)
289 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
);
291 #if defined(MBEDTLS_ENTROPY_NV_SEED)
292 /* Update the NV entropy seed before generating any entropy for outside
295 if( ctx
->initial_entropy_run
== 0 )
297 ctx
->initial_entropy_run
= 1;
298 if( ( ret
= mbedtls_entropy_update_nv_seed( ctx
) ) != 0 )
303 #if defined(MBEDTLS_THREADING_C)
304 if( ( ret
= mbedtls_mutex_lock( &ctx
->mutex
) ) != 0 )
309 * Always gather extra entropy before a call
313 if( count
++ > ENTROPY_MAX_LOOP
)
315 ret
= MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
;
319 if( ( ret
= entropy_gather_internal( ctx
) ) != 0 )
323 for( i
= 0; i
< ctx
->source_count
; i
++ )
324 if( ctx
->source
[i
].size
< ctx
->source
[i
].threshold
)
329 memset( buf
, 0, MBEDTLS_ENTROPY_BLOCK_SIZE
);
331 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
332 mbedtls_sha512_finish( &ctx
->accumulator
, buf
);
335 * Reset accumulator and counters and recycle existing entropy
337 memset( &ctx
->accumulator
, 0, sizeof( mbedtls_sha512_context
) );
338 mbedtls_sha512_starts( &ctx
->accumulator
, 0 );
339 mbedtls_sha512_update( &ctx
->accumulator
, buf
, MBEDTLS_ENTROPY_BLOCK_SIZE
);
342 * Perform second SHA-512 on entropy
344 mbedtls_sha512( buf
, MBEDTLS_ENTROPY_BLOCK_SIZE
, buf
, 0 );
345 #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
346 mbedtls_sha256_finish( &ctx
->accumulator
, buf
);
349 * Reset accumulator and counters and recycle existing entropy
351 memset( &ctx
->accumulator
, 0, sizeof( mbedtls_sha256_context
) );
352 mbedtls_sha256_starts( &ctx
->accumulator
, 0 );
353 mbedtls_sha256_update( &ctx
->accumulator
, buf
, MBEDTLS_ENTROPY_BLOCK_SIZE
);
356 * Perform second SHA-256 on entropy
358 mbedtls_sha256( buf
, MBEDTLS_ENTROPY_BLOCK_SIZE
, buf
, 0 );
359 #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
361 for( i
= 0; i
< ctx
->source_count
; i
++ )
362 ctx
->source
[i
].size
= 0;
364 memcpy( output
, buf
, len
);
369 #if defined(MBEDTLS_THREADING_C)
370 if( mbedtls_mutex_unlock( &ctx
->mutex
) != 0 )
371 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR
);
377 #if defined(MBEDTLS_ENTROPY_NV_SEED)
378 int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context
*ctx
)
380 int ret
= MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR
;
381 unsigned char buf
[ MBEDTLS_ENTROPY_MAX_SEED_SIZE
];
383 /* Read new seed and write it to NV */
384 if( ( ret
= mbedtls_entropy_func( ctx
, buf
, MBEDTLS_ENTROPY_BLOCK_SIZE
) ) != 0 )
387 if( mbedtls_nv_seed_write( buf
, MBEDTLS_ENTROPY_BLOCK_SIZE
) < 0 )
388 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR
);
390 /* Manually update the remaining stream with a separator value to diverge */
391 memset( buf
, 0, MBEDTLS_ENTROPY_BLOCK_SIZE
);
392 mbedtls_entropy_update_manual( ctx
, buf
, MBEDTLS_ENTROPY_BLOCK_SIZE
);
396 #endif /* MBEDTLS_ENTROPY_NV_SEED */
398 #if defined(MBEDTLS_FS_IO)
399 int mbedtls_entropy_write_seed_file( mbedtls_entropy_context
*ctx
, const char *path
)
401 int ret
= MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR
;
403 unsigned char buf
[MBEDTLS_ENTROPY_BLOCK_SIZE
];
405 if( ( f
= fopen( path
, "wb" ) ) == NULL
)
406 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR
);
408 if( ( ret
= mbedtls_entropy_func( ctx
, buf
, MBEDTLS_ENTROPY_BLOCK_SIZE
) ) != 0 )
411 if( fwrite( buf
, 1, MBEDTLS_ENTROPY_BLOCK_SIZE
, f
) != MBEDTLS_ENTROPY_BLOCK_SIZE
)
413 ret
= MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR
;
424 int mbedtls_entropy_update_seed_file( mbedtls_entropy_context
*ctx
, const char *path
)
428 unsigned char buf
[ MBEDTLS_ENTROPY_MAX_SEED_SIZE
];
430 if( ( f
= fopen( path
, "rb" ) ) == NULL
)
431 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR
);
433 fseek( f
, 0, SEEK_END
);
434 n
= (size_t) ftell( f
);
435 fseek( f
, 0, SEEK_SET
);
437 if( n
> MBEDTLS_ENTROPY_MAX_SEED_SIZE
)
438 n
= MBEDTLS_ENTROPY_MAX_SEED_SIZE
;
440 if( fread( buf
, 1, n
, f
) != n
)
443 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR
);
448 mbedtls_entropy_update_manual( ctx
, buf
, n
);
450 return( mbedtls_entropy_write_seed_file( ctx
, path
) );
452 #endif /* MBEDTLS_FS_IO */
454 #if defined(MBEDTLS_SELF_TEST)
456 * Dummy source function
458 static int entropy_dummy_source( void *data
, unsigned char *output
,
459 size_t len
, size_t *olen
)
463 memset( output
, 0x2a, len
);
470 * The actual entropy quality is hard to test, but we can at least
471 * test that the functions don't cause errors and write the correct
472 * amount of data to buffers.
474 int mbedtls_entropy_self_test( int verbose
)
477 mbedtls_entropy_context ctx
;
478 unsigned char buf
[MBEDTLS_ENTROPY_BLOCK_SIZE
] = { 0 };
479 unsigned char acc
[MBEDTLS_ENTROPY_BLOCK_SIZE
] = { 0 };
483 mbedtls_printf( " ENTROPY test: " );
485 mbedtls_entropy_init( &ctx
);
487 /* First do a gather to make sure we have default sources */
488 if( ( ret
= mbedtls_entropy_gather( &ctx
) ) != 0 )
491 ret
= mbedtls_entropy_add_source( &ctx
, entropy_dummy_source
, NULL
, 16,
492 MBEDTLS_ENTROPY_SOURCE_WEAK
);
496 if( ( ret
= mbedtls_entropy_update_manual( &ctx
, buf
, sizeof buf
) ) != 0 )
500 * To test that mbedtls_entropy_func writes correct number of bytes:
501 * - use the whole buffer and rely on ASan to detect overruns
502 * - collect entropy 8 times and OR the result in an accumulator:
503 * any byte should then be 0 with probably 2^(-64), so requiring
504 * each of the 32 or 64 bytes to be non-zero has a false failure rate
505 * of at most 2^(-58) which is acceptable.
507 for( i
= 0; i
< 8; i
++ )
509 if( ( ret
= mbedtls_entropy_func( &ctx
, buf
, sizeof( buf
) ) ) != 0 )
512 for( j
= 0; j
< sizeof( buf
); j
++ )
516 for( j
= 0; j
< sizeof( buf
); j
++ )
526 mbedtls_entropy_free( &ctx
);
531 mbedtls_printf( "failed\n" );
533 mbedtls_printf( "passed\n" );
535 mbedtls_printf( "\n" );
540 #endif /* MBEDTLS_SELF_TEST */
542 #endif /* MBEDTLS_ENTROPY_C */