blob: 7983c767ee0f5903fc6704e39c14c93f942caa0a [file] [log] [blame]
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +02001/* BEGIN_HEADER */
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +00002#include "mbedtls/entropy.h"
Paul Bakkerffbfb4c2016-06-01 15:36:18 +01003#include "mbedtls/entropy_poll.h"
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +02004
5/*
6 * Number of calls made to entropy_dummy_source()
7 */
8static size_t entropy_dummy_calls;
9
10/*
11 * Dummy entropy source
12 *
13 * If data is NULL, write exactly the requested length.
14 * Otherwise, write the length indicated by data or error if negative
15 */
16static int entropy_dummy_source( void *data, unsigned char *output,
17 size_t len, size_t *olen )
18{
19 entropy_dummy_calls++;
20
21 if( data == NULL )
22 *olen = len;
23 else
24 {
25 int *d = (int *) data;
26
27 if( *d < 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +020029 else
30 *olen = *d;
31 }
32
33 memset( output, 0x2a, *olen );
34
35 return( 0 );
36}
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010037
Paul Bakker4a6c6fc2016-06-01 16:34:25 +010038#if defined(MBEDTLS_ENTROPY_NV_SEED)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010039/*
40 * Ability to clear entropy sources to allow testing with just predefined
41 * entropy sources. This function or tests depending on it might break if there
42 * are internal changes to how entropy sources are registered.
43 *
44 * To be called immediately after mbedtls_entropy_init().
45 *
46 * Just resetting the counter. New sources will overwrite existing ones.
47 * This might break memory checks in the future if sources need 'free-ing' then
48 * as well.
49 */
50static void entropy_clear_sources( mbedtls_entropy_context *ctx )
51{
52 ctx->source_count = 0;
53}
54
55/*
56 * NV seed read/write functions that use a buffer instead of a file
57 */
58static unsigned char buffer_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
59
60static int buffer_nv_seed_read( unsigned char *buf, size_t buf_len )
61{
62 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
63 return( -1 );
64
65 memcpy( buf, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
66 return( 0 );
67}
68
69static int buffer_nv_seed_write( unsigned char *buf, size_t buf_len )
70{
71 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
72 return( -1 );
73
74 memcpy( buffer_seed, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
75 return( 0 );
76}
77
78/*
79 * NV seed read/write helpers that fill the base seedfile
80 */
81static int write_nv_seed( unsigned char *buf, size_t buf_len )
82{
83 FILE *f;
84
85 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
86 return( -1 );
87
88 if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL )
89 return( -1 );
90
91 if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) !=
92 MBEDTLS_ENTROPY_BLOCK_SIZE )
93 return( -1 );
94
95 fclose( f );
96
97 return( 0 );
98}
99
100static int read_nv_seed( unsigned char *buf, size_t buf_len )
101{
102 FILE *f;
103
104 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
105 return( -1 );
106
107 if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL )
108 return( -1 );
109
110 if( fread( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) !=
111 MBEDTLS_ENTROPY_BLOCK_SIZE )
112 return( -1 );
113
114 fclose( f );
115
116 return( 0 );
117}
Paul Bakker4a6c6fc2016-06-01 16:34:25 +0100118#endif /* MBEDTLS_ENTROPY_NV_SEED */
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200119/* END_HEADER */
120
121/* BEGIN_DEPENDENCIES
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122 * depends_on:MBEDTLS_ENTROPY_C
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200123 * END_DEPENDENCIES
124 */
125
Simon Butcherb7f45c52016-09-15 18:42:26 +0100126/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200127void entropy_seed_file( char *path, int ret )
128{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 mbedtls_entropy_context ctx;
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200130
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 mbedtls_entropy_init( &ctx );
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, path ) == ret );
134 TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, path ) == ret );
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200135
Paul Bakkerbd51b262014-07-10 15:26:12 +0200136exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_entropy_free( &ctx );
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200138}
139/* END_CASE */
140
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200141/* BEGIN_CASE */
142void entropy_too_many_sources( )
143{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200144 mbedtls_entropy_context ctx;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200145 size_t i;
146
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147 mbedtls_entropy_init( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200148
149 /*
150 * It's hard to tell precisely when the error will occur,
151 * since we don't know how many sources were automatically added.
152 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 for( i = 0; i < MBEDTLS_ENTROPY_MAX_SOURCES; i++ )
Manuel Pégourié-Gonnard7580ba42015-06-19 10:26:32 +0200154 (void) mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL,
155 16, MBEDTLS_ENTROPY_SOURCE_WEAK );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200156
Manuel Pégourié-Gonnard7580ba42015-06-19 10:26:32 +0200157 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL,
158 16, MBEDTLS_ENTROPY_SOURCE_WEAK )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 == MBEDTLS_ERR_ENTROPY_MAX_SOURCES );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200160
Paul Bakkerbd51b262014-07-10 15:26:12 +0200161exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 mbedtls_entropy_free( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200163}
164/* END_CASE */
165
Hanno Becker47deec42017-07-24 12:27:09 +0100166/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_HAVE_STRONG */
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200167void entropy_func_len( int len, int ret )
168{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 mbedtls_entropy_context ctx;
170 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 };
171 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200172 size_t i, j;
173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 mbedtls_entropy_init( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200175
176 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 * See comments in mbedtls_entropy_self_test()
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200178 */
179 for( i = 0; i < 8; i++ )
180 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 TEST_ASSERT( mbedtls_entropy_func( &ctx, buf, len ) == ret );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200182 for( j = 0; j < sizeof( buf ); j++ )
183 acc[j] |= buf[j];
184 }
185
186 if( ret == 0 )
187 for( j = 0; j < (size_t) len; j++ )
188 TEST_ASSERT( acc[j] != 0 );
189
190 for( j = len; j < sizeof( buf ); j++ )
191 TEST_ASSERT( acc[j] == 0 );
192}
193/* END_CASE */
194
195/* BEGIN_CASE */
196void entropy_source_fail( char *path )
197{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 mbedtls_entropy_context ctx;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200199 int fail = -1;
200 unsigned char buf[16];
201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202 mbedtls_entropy_init( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200203
Manuel Pégourié-Gonnard7580ba42015-06-19 10:26:32 +0200204 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
205 &fail, 16,
206 MBEDTLS_ENTROPY_SOURCE_WEAK )
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200207 == 0 );
208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 TEST_ASSERT( mbedtls_entropy_func( &ctx, buf, sizeof( buf ) )
210 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
211 TEST_ASSERT( mbedtls_entropy_gather( &ctx )
212 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
Simon Butcherb7f45c52016-09-15 18:42:26 +0100213#if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_NV_SEED)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, path )
215 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
216 TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, path )
217 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200218#else
219 ((void) path);
220#endif
221
Paul Bakkerbd51b262014-07-10 15:26:12 +0200222exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 mbedtls_entropy_free( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200224}
225/* END_CASE */
226
Hanno Becker47deec42017-07-24 12:27:09 +0100227/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_HAVE_STRONG */
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200228void entropy_threshold( int threshold, int chunk_size, int result )
229{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230 mbedtls_entropy_context ctx;
231 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200232 int ret;
233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 mbedtls_entropy_init( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200235
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
Manuel Pégourié-Gonnard7580ba42015-06-19 10:26:32 +0200237 &chunk_size, threshold,
238 MBEDTLS_ENTROPY_SOURCE_WEAK ) == 0 );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200239
240 entropy_dummy_calls = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200242
243 if( result >= 0 )
244 {
245 TEST_ASSERT( ret == 0 );
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100246#if defined(MBEDTLS_ENTROPY_NV_SEED)
247 // Two times as much calls due to the NV seed update
248 result *= 2;
249#endif
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200250 TEST_ASSERT( entropy_dummy_calls == (size_t) result );
251 }
252 else
253 {
254 TEST_ASSERT( ret == result );
255 }
256
Paul Bakkerbd51b262014-07-10 15:26:12 +0200257exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258 mbedtls_entropy_free( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200259}
260/* END_CASE */
261
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100262/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
263void nv_seed_file_create()
264{
265 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
266
267 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
268
269 TEST_ASSERT( write_nv_seed( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
270}
271/* END_CASE */
272
Paul Bakkerb598c292016-06-01 16:57:11 +0100273/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO:MBEDTLS_PLATFORM_NV_SEED_ALT */
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100274void entropy_nv_seed_std_io()
275{
276 unsigned char io_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
277 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
278
279 memset( io_seed, 1, MBEDTLS_ENTROPY_BLOCK_SIZE );
280 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
281
282 mbedtls_platform_set_nv_seed( mbedtls_platform_std_nv_seed_read,
283 mbedtls_platform_std_nv_seed_write );
284
285 /* Check if platform NV read and write manipulate the same data */
286 TEST_ASSERT( write_nv_seed( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
287 TEST_ASSERT( mbedtls_nv_seed_read( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) ==
288 MBEDTLS_ENTROPY_BLOCK_SIZE );
289
290 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
291
292 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
293
294 /* Check if platform NV write and raw read manipulate the same data */
295 TEST_ASSERT( mbedtls_nv_seed_write( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) ==
296 MBEDTLS_ENTROPY_BLOCK_SIZE );
297 TEST_ASSERT( read_nv_seed( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
298
299 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
300}
301/* END_CASE */
302
Paul Bakkerc5687622016-06-07 11:06:09 +0100303/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PLATFORM_NV_SEED_ALT:MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100304void entropy_nv_seed( char *read_seed_str )
305{
306 mbedtls_sha512_context accumulator;
307 mbedtls_entropy_context ctx;
308
309 unsigned char header[2];
310 unsigned char entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
311 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
312 unsigned char empty[MBEDTLS_ENTROPY_BLOCK_SIZE];
313 unsigned char read_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
314 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
315 unsigned char check_entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
316
317 memset( entropy, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
318 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
319 memset( buffer_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
320 memset( empty, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
321 memset( check_seed, 2, MBEDTLS_ENTROPY_BLOCK_SIZE );
322 memset( check_entropy, 3, MBEDTLS_ENTROPY_BLOCK_SIZE );
323
324 // Set the initial NV seed to read
325 unhexify( read_seed, read_seed_str );
326 memcpy( buffer_seed, read_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
327
328 // Make sure we read/write NV seed from our buffers
329 mbedtls_platform_set_nv_seed( buffer_nv_seed_read, buffer_nv_seed_write );
330
331 mbedtls_entropy_init( &ctx );
332 entropy_clear_sources( &ctx );
333
334 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, mbedtls_nv_seed_poll, NULL,
335 MBEDTLS_ENTROPY_BLOCK_SIZE,
336 MBEDTLS_ENTROPY_SOURCE_STRONG ) == 0 );
337
338 // Do an entropy run
339 TEST_ASSERT( mbedtls_entropy_func( &ctx, entropy, sizeof( entropy ) ) == 0 );
340
341 // Determine what should have happened with manual entropy internal logic
342 // Only use the SHA-512 version to check
343
344 // Init accumulator
345 header[1] = MBEDTLS_ENTROPY_BLOCK_SIZE;
346 mbedtls_sha512_starts( &accumulator, 0 );
347
348 // First run for updating write_seed
349 header[0] = 0;
350 mbedtls_sha512_update( &accumulator, header, 2 );
351 mbedtls_sha512_update( &accumulator, read_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
352 mbedtls_sha512_finish( &accumulator, buf );
353
354 memset( &accumulator, 0, sizeof( mbedtls_sha512_context ) );
355 mbedtls_sha512_starts( &accumulator, 0 );
356 mbedtls_sha512_update( &accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
357
358 mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_seed, 0 );
359
360 // Second run for actual entropy (triggers mbedtls_entropy_update_nv_seed)
361 header[0] = MBEDTLS_ENTROPY_SOURCE_MANUAL;
362 mbedtls_sha512_update( &accumulator, header, 2 );
363 mbedtls_sha512_update( &accumulator, empty, MBEDTLS_ENTROPY_BLOCK_SIZE );
364
365 header[0] = 0;
366 mbedtls_sha512_update( &accumulator, header, 2 );
367 mbedtls_sha512_update( &accumulator, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
368 mbedtls_sha512_finish( &accumulator, buf );
369
370 mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_entropy, 0 );
371
372 // Check result of both NV file and entropy received with the manual calculations
373 TEST_ASSERT( memcmp( check_seed, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
374 TEST_ASSERT( memcmp( check_entropy, entropy, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
375
376 mbedtls_entropy_free( &ctx );
377}
378/* END_CASE */
379
Hanno Becker47deec42017-07-24 12:27:09 +0100380/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_HAVE_STRONG:MBEDTLS_SELF_TEST */
Simon Butcherb7f45c52016-09-15 18:42:26 +0100381void entropy_selftest( int result )
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200382{
Andres AG93012e82016-09-09 09:10:28 +0100383 TEST_ASSERT( mbedtls_entropy_self_test( 1 ) == result );
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200384}
385/* END_CASE */