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