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