This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

source: ps/trunk/build/premake/premake5/contrib/mbedtls/library/entropy.c

Last change on this file was 20366, checked in by Itms, 7 years ago

Alpha 12 version of Premake 5, including prebuilt binary for Windows.
Directly taken from https://premake.github.io/.

Refs #3729.

File size: 13.1 KB
Line 
1/*
2 * Entropy accumulator implementation
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
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 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22#if !defined(MBEDTLS_CONFIG_FILE)
23#include "mbedtls/config.h"
24#else
25#include MBEDTLS_CONFIG_FILE
26#endif
27
28#if defined(MBEDTLS_ENTROPY_C)
29
30#include "mbedtls/entropy.h"
31#include "mbedtls/entropy_poll.h"
32
33#include <string.h>
34
35#if defined(MBEDTLS_FS_IO)
36#include <stdio.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#if defined(MBEDTLS_HAVEGE_C)
49#include "mbedtls/havege.h"
50#endif
51
52/* Implementation that should never be optimized out by the compiler */
53static void mbedtls_zeroize( void *v, size_t n ) {
54 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
55}
56
57#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
58
59void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
60{
61 memset( ctx, 0, sizeof(mbedtls_entropy_context) );
62
63#if defined(MBEDTLS_THREADING_C)
64 mbedtls_mutex_init( &ctx->mutex );
65#endif
66
67#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
68 mbedtls_sha512_starts( &ctx->accumulator, 0 );
69#else
70 mbedtls_sha256_starts( &ctx->accumulator, 0 );
71#endif
72#if defined(MBEDTLS_HAVEGE_C)
73 mbedtls_havege_init( &ctx->havege_data );
74#endif
75
76#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
77#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
78 mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL,
79 MBEDTLS_ENTROPY_MIN_PLATFORM,
80 MBEDTLS_ENTROPY_SOURCE_STRONG );
81#endif
82#if defined(MBEDTLS_TIMING_C)
83 mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL,
84 MBEDTLS_ENTROPY_MIN_HARDCLOCK,
85 MBEDTLS_ENTROPY_SOURCE_WEAK );
86#endif
87#if defined(MBEDTLS_HAVEGE_C)
88 mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data,
89 MBEDTLS_ENTROPY_MIN_HAVEGE,
90 MBEDTLS_ENTROPY_SOURCE_STRONG );
91#endif
92#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
93 mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL,
94 MBEDTLS_ENTROPY_MIN_HARDWARE,
95 MBEDTLS_ENTROPY_SOURCE_STRONG );
96#endif
97#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
98}
99
100void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
101{
102#if defined(MBEDTLS_HAVEGE_C)
103 mbedtls_havege_free( &ctx->havege_data );
104#endif
105#if defined(MBEDTLS_THREADING_C)
106 mbedtls_mutex_free( &ctx->mutex );
107#endif
108 mbedtls_zeroize( ctx, sizeof( mbedtls_entropy_context ) );
109}
110
111int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
112 mbedtls_entropy_f_source_ptr f_source, void *p_source,
113 size_t threshold, int strong )
114{
115 int index, ret = 0;
116
117#if defined(MBEDTLS_THREADING_C)
118 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
119 return( ret );
120#endif
121
122 index = ctx->source_count;
123 if( index >= MBEDTLS_ENTROPY_MAX_SOURCES )
124 {
125 ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
126 goto exit;
127 }
128
129 ctx->source[index].f_source = f_source;
130 ctx->source[index].p_source = p_source;
131 ctx->source[index].threshold = threshold;
132 ctx->source[index].strong = strong;
133
134 ctx->source_count++;
135
136exit:
137#if defined(MBEDTLS_THREADING_C)
138 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
139 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
140#endif
141
142 return( ret );
143}
144
145/*
146 * Entropy accumulator update
147 */
148static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id,
149 const unsigned char *data, size_t len )
150{
151 unsigned char header[2];
152 unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
153 size_t use_len = len;
154 const unsigned char *p = data;
155
156 if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE )
157 {
158#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
159 mbedtls_sha512( data, len, tmp, 0 );
160#else
161 mbedtls_sha256( data, len, tmp, 0 );
162#endif
163 p = tmp;
164 use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
165 }
166
167 header[0] = source_id;
168 header[1] = use_len & 0xFF;
169
170#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
171 mbedtls_sha512_update( &ctx->accumulator, header, 2 );
172 mbedtls_sha512_update( &ctx->accumulator, p, use_len );
173#else
174 mbedtls_sha256_update( &ctx->accumulator, header, 2 );
175 mbedtls_sha256_update( &ctx->accumulator, p, use_len );
176#endif
177
178 return( 0 );
179}
180
181int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
182 const unsigned char *data, size_t len )
183{
184 int ret;
185
186#if defined(MBEDTLS_THREADING_C)
187 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
188 return( ret );
189#endif
190
191 ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len );
192
193#if defined(MBEDTLS_THREADING_C)
194 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
195 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
196#endif
197
198 return( ret );
199}
200
201/*
202 * Run through the different sources to add entropy to our accumulator
203 */
204static int entropy_gather_internal( mbedtls_entropy_context *ctx )
205{
206 int ret, i, have_one_strong = 0;
207 unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
208 size_t olen;
209
210 if( ctx->source_count == 0 )
211 return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED );
212
213 /*
214 * Run through our entropy sources
215 */
216 for( i = 0; i < ctx->source_count; i++ )
217 {
218 if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
219 have_one_strong = 1;
220
221 olen = 0;
222 if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
223 buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 )
224 {
225 return( ret );
226 }
227
228 /*
229 * Add if we actually gathered something
230 */
231 if( olen > 0 )
232 {
233 entropy_update( ctx, (unsigned char) i, buf, olen );
234 ctx->source[i].size += olen;
235 }
236 }
237
238 if( have_one_strong == 0 )
239 return( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE );
240
241 return( 0 );
242}
243
244/*
245 * Thread-safe wrapper for entropy_gather_internal()
246 */
247int mbedtls_entropy_gather( mbedtls_entropy_context *ctx )
248{
249 int ret;
250
251#if defined(MBEDTLS_THREADING_C)
252 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
253 return( ret );
254#endif
255
256 ret = entropy_gather_internal( ctx );
257
258#if defined(MBEDTLS_THREADING_C)
259 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
260 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
261#endif
262
263 return( ret );
264}
265
266int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
267{
268 int ret, count = 0, i, done;
269 mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
270 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
271
272 if( len > MBEDTLS_ENTROPY_BLOCK_SIZE )
273 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
274
275#if defined(MBEDTLS_THREADING_C)
276 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
277 return( ret );
278#endif
279
280 /*
281 * Always gather extra entropy before a call
282 */
283 do
284 {
285 if( count++ > ENTROPY_MAX_LOOP )
286 {
287 ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
288 goto exit;
289 }
290
291 if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
292 goto exit;
293
294 done = 1;
295 for( i = 0; i < ctx->source_count; i++ )
296 if( ctx->source[i].size < ctx->source[i].threshold )
297 done = 0;
298 }
299 while( ! done );
300
301 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
302
303#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
304 mbedtls_sha512_finish( &ctx->accumulator, buf );
305
306 /*
307 * Reset accumulator and counters and recycle existing entropy
308 */
309 memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) );
310 mbedtls_sha512_starts( &ctx->accumulator, 0 );
311 mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
312
313 /*
314 * Perform second SHA-512 on entropy
315 */
316 mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 );
317#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
318 mbedtls_sha256_finish( &ctx->accumulator, buf );
319
320 /*
321 * Reset accumulator and counters and recycle existing entropy
322 */
323 memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) );
324 mbedtls_sha256_starts( &ctx->accumulator, 0 );
325 mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
326
327 /*
328 * Perform second SHA-256 on entropy
329 */
330 mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 );
331#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
332
333 for( i = 0; i < ctx->source_count; i++ )
334 ctx->source[i].size = 0;
335
336 memcpy( output, buf, len );
337
338 ret = 0;
339
340exit:
341#if defined(MBEDTLS_THREADING_C)
342 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
343 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
344#endif
345
346 return( ret );
347}
348
349#if defined(MBEDTLS_FS_IO)
350int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
351{
352 int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
353 FILE *f;
354 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
355
356 if( ( f = fopen( path, "wb" ) ) == NULL )
357 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
358
359 if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
360 goto exit;
361
362 if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
363 {
364 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
365 goto exit;
366 }
367
368 ret = 0;
369
370exit:
371 fclose( f );
372 return( ret );
373}
374
375int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path )
376{
377 FILE *f;
378 size_t n;
379 unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ];
380
381 if( ( f = fopen( path, "rb" ) ) == NULL )
382 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
383
384 fseek( f, 0, SEEK_END );
385 n = (size_t) ftell( f );
386 fseek( f, 0, SEEK_SET );
387
388 if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE )
389 n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
390
391 if( fread( buf, 1, n, f ) != n )
392 {
393 fclose( f );
394 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
395 }
396
397 fclose( f );
398
399 mbedtls_entropy_update_manual( ctx, buf, n );
400
401 return( mbedtls_entropy_write_seed_file( ctx, path ) );
402}
403#endif /* MBEDTLS_FS_IO */
404
405#if defined(MBEDTLS_SELF_TEST)
406/*
407 * Dummy source function
408 */
409static int entropy_dummy_source( void *data, unsigned char *output,
410 size_t len, size_t *olen )
411{
412 ((void) data);
413
414 memset( output, 0x2a, len );
415 *olen = len;
416
417 return( 0 );
418}
419
420/*
421 * The actual entropy quality is hard to test, but we can at least
422 * test that the functions don't cause errors and write the correct
423 * amount of data to buffers.
424 */
425int mbedtls_entropy_self_test( int verbose )
426{
427 int ret = 0;
428 mbedtls_entropy_context ctx;
429 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
430 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
431 size_t i, j;
432
433 if( verbose != 0 )
434 mbedtls_printf( " ENTROPY test: " );
435
436 mbedtls_entropy_init( &ctx );
437
438 /* First do a gather to make sure we have default sources */
439 if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 )
440 goto cleanup;
441
442 ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16,
443 MBEDTLS_ENTROPY_SOURCE_WEAK );
444 if( ret != 0 )
445 goto cleanup;
446
447 if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
448 goto cleanup;
449
450 /*
451 * To test that mbedtls_entropy_func writes correct number of bytes:
452 * - use the whole buffer and rely on ASan to detect overruns
453 * - collect entropy 8 times and OR the result in an accumulator:
454 * any byte should then be 0 with probably 2^(-64), so requiring
455 * each of the 32 or 64 bytes to be non-zero has a false failure rate
456 * of at most 2^(-58) which is acceptable.
457 */
458 for( i = 0; i < 8; i++ )
459 {
460 if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
461 goto cleanup;
462
463 for( j = 0; j < sizeof( buf ); j++ )
464 acc[j] |= buf[j];
465 }
466
467 for( j = 0; j < sizeof( buf ); j++ )
468 {
469 if( acc[j] == 0 )
470 {
471 ret = 1;
472 goto cleanup;
473 }
474 }
475
476cleanup:
477 mbedtls_entropy_free( &ctx );
478
479 if( verbose != 0 )
480 {
481 if( ret != 0 )
482 mbedtls_printf( "failed\n" );
483 else
484 mbedtls_printf( "passed\n" );
485
486 mbedtls_printf( "\n" );
487 }
488
489 return( ret != 0 );
490}
491#endif /* MBEDTLS_SELF_TEST */
492
493#endif /* MBEDTLS_ENTROPY_C */
Note: See TracBrowser for help on using the repository browser.