blob: 999b5f66708d8acdb0142c5bdf00060e30bf4571 [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
38/*
39 * Ability to clear entropy sources to allow testing with just predefined
40 * entropy sources. This function or tests depending on it might break if there
41 * are internal changes to how entropy sources are registered.
42 *
43 * To be called immediately after mbedtls_entropy_init().
44 *
45 * Just resetting the counter. New sources will overwrite existing ones.
46 * This might break memory checks in the future if sources need 'free-ing' then
47 * as well.
48 */
49static void entropy_clear_sources( mbedtls_entropy_context *ctx )
50{
51 ctx->source_count = 0;
52}
53
54/*
55 * NV seed read/write functions that use a buffer instead of a file
56 */
57static unsigned char buffer_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
58
59static int buffer_nv_seed_read( unsigned char *buf, size_t buf_len )
60{
61 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
62 return( -1 );
63
64 memcpy( buf, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
65 return( 0 );
66}
67
68static int buffer_nv_seed_write( unsigned char *buf, size_t buf_len )
69{
70 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
71 return( -1 );
72
73 memcpy( buffer_seed, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
74 return( 0 );
75}
76
77/*
78 * NV seed read/write helpers that fill the base seedfile
79 */
80static int write_nv_seed( unsigned char *buf, size_t buf_len )
81{
82 FILE *f;
83
84 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
85 return( -1 );
86
87 if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL )
88 return( -1 );
89
90 if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) !=
91 MBEDTLS_ENTROPY_BLOCK_SIZE )
92 return( -1 );
93
94 fclose( f );
95
96 return( 0 );
97}
98
99static int read_nv_seed( unsigned char *buf, size_t buf_len )
100{
101 FILE *f;
102
103 if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
104 return( -1 );
105
106 if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL )
107 return( -1 );
108
109 if( fread( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) !=
110 MBEDTLS_ENTROPY_BLOCK_SIZE )
111 return( -1 );
112
113 fclose( f );
114
115 return( 0 );
116}
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200117/* END_HEADER */
118
119/* BEGIN_DEPENDENCIES
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 * depends_on:MBEDTLS_ENTROPY_C
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200121 * END_DEPENDENCIES
122 */
123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200125void entropy_seed_file( char *path, int ret )
126{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 mbedtls_entropy_context ctx;
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 mbedtls_entropy_init( &ctx );
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200130
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, path ) == ret );
132 TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, path ) == ret );
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200133
Paul Bakkerbd51b262014-07-10 15:26:12 +0200134exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_entropy_free( &ctx );
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200136}
137/* END_CASE */
138
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200139/* BEGIN_CASE */
140void entropy_too_many_sources( )
141{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142 mbedtls_entropy_context ctx;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200143 size_t i;
144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 mbedtls_entropy_init( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200146
147 /*
148 * It's hard to tell precisely when the error will occur,
149 * since we don't know how many sources were automatically added.
150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151 for( i = 0; i < MBEDTLS_ENTROPY_MAX_SOURCES; i++ )
Manuel Pégourié-Gonnard7580ba42015-06-19 10:26:32 +0200152 (void) mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL,
153 16, MBEDTLS_ENTROPY_SOURCE_WEAK );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200154
Manuel Pégourié-Gonnard7580ba42015-06-19 10:26:32 +0200155 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL,
156 16, MBEDTLS_ENTROPY_SOURCE_WEAK )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 == MBEDTLS_ERR_ENTROPY_MAX_SOURCES );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200158
Paul Bakkerbd51b262014-07-10 15:26:12 +0200159exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 mbedtls_entropy_free( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200161}
162/* END_CASE */
163
164/* BEGIN_CASE */
165void entropy_func_len( int len, int ret )
166{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 mbedtls_entropy_context ctx;
168 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 };
169 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200170 size_t i, j;
171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 mbedtls_entropy_init( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200173
174 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 * See comments in mbedtls_entropy_self_test()
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200176 */
177 for( i = 0; i < 8; i++ )
178 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 TEST_ASSERT( mbedtls_entropy_func( &ctx, buf, len ) == ret );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200180 for( j = 0; j < sizeof( buf ); j++ )
181 acc[j] |= buf[j];
182 }
183
184 if( ret == 0 )
185 for( j = 0; j < (size_t) len; j++ )
186 TEST_ASSERT( acc[j] != 0 );
187
188 for( j = len; j < sizeof( buf ); j++ )
189 TEST_ASSERT( acc[j] == 0 );
190}
191/* END_CASE */
192
193/* BEGIN_CASE */
194void entropy_source_fail( char *path )
195{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 mbedtls_entropy_context ctx;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200197 int fail = -1;
198 unsigned char buf[16];
199
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200200 mbedtls_entropy_init( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200201
Manuel Pégourié-Gonnard7580ba42015-06-19 10:26:32 +0200202 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
203 &fail, 16,
204 MBEDTLS_ENTROPY_SOURCE_WEAK )
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200205 == 0 );
206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 TEST_ASSERT( mbedtls_entropy_func( &ctx, buf, sizeof( buf ) )
208 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
209 TEST_ASSERT( mbedtls_entropy_gather( &ctx )
210 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
211#if defined(MBEDTLS_FS_IO)
212 TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, path )
213 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
214 TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, path )
215 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200216#else
217 ((void) path);
218#endif
219
Paul Bakkerbd51b262014-07-10 15:26:12 +0200220exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221 mbedtls_entropy_free( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200222}
223/* END_CASE */
224
225/* BEGIN_CASE */
226void entropy_threshold( int threshold, int chunk_size, int result )
227{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 mbedtls_entropy_context ctx;
229 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200230 int ret;
231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232 mbedtls_entropy_init( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, entropy_dummy_source,
Manuel Pégourié-Gonnard7580ba42015-06-19 10:26:32 +0200235 &chunk_size, threshold,
236 MBEDTLS_ENTROPY_SOURCE_WEAK ) == 0 );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200237
238 entropy_dummy_calls = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200240
241 if( result >= 0 )
242 {
243 TEST_ASSERT( ret == 0 );
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100244#if defined(MBEDTLS_ENTROPY_NV_SEED)
245 // Two times as much calls due to the NV seed update
246 result *= 2;
247#endif
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200248 TEST_ASSERT( entropy_dummy_calls == (size_t) result );
249 }
250 else
251 {
252 TEST_ASSERT( ret == result );
253 }
254
Paul Bakkerbd51b262014-07-10 15:26:12 +0200255exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 mbedtls_entropy_free( &ctx );
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200257}
258/* END_CASE */
259
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100260/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
261void nv_seed_file_create()
262{
263 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
264
265 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
266
267 TEST_ASSERT( write_nv_seed( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
268}
269/* END_CASE */
270
271/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
272void entropy_nv_seed_std_io()
273{
274 unsigned char io_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
275 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
276
277 memset( io_seed, 1, MBEDTLS_ENTROPY_BLOCK_SIZE );
278 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
279
280 mbedtls_platform_set_nv_seed( mbedtls_platform_std_nv_seed_read,
281 mbedtls_platform_std_nv_seed_write );
282
283 /* Check if platform NV read and write manipulate the same data */
284 TEST_ASSERT( write_nv_seed( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
285 TEST_ASSERT( mbedtls_nv_seed_read( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) ==
286 MBEDTLS_ENTROPY_BLOCK_SIZE );
287
288 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
289
290 memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
291
292 /* Check if platform NV write and raw read manipulate the same data */
293 TEST_ASSERT( mbedtls_nv_seed_write( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) ==
294 MBEDTLS_ENTROPY_BLOCK_SIZE );
295 TEST_ASSERT( read_nv_seed( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
296
297 TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
298}
299/* END_CASE */
300
301/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PLATFORM_NV_SEED_ALT:MBEDTLS_SHA512_C */
302void entropy_nv_seed( char *read_seed_str )
303{
304 mbedtls_sha512_context accumulator;
305 mbedtls_entropy_context ctx;
306
307 unsigned char header[2];
308 unsigned char entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
309 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
310 unsigned char empty[MBEDTLS_ENTROPY_BLOCK_SIZE];
311 unsigned char read_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
312 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
313 unsigned char check_entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
314
315 memset( entropy, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
316 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
317 memset( buffer_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
318 memset( empty, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
319 memset( check_seed, 2, MBEDTLS_ENTROPY_BLOCK_SIZE );
320 memset( check_entropy, 3, MBEDTLS_ENTROPY_BLOCK_SIZE );
321
322 // Set the initial NV seed to read
323 unhexify( read_seed, read_seed_str );
324 memcpy( buffer_seed, read_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
325
326 // Make sure we read/write NV seed from our buffers
327 mbedtls_platform_set_nv_seed( buffer_nv_seed_read, buffer_nv_seed_write );
328
329 mbedtls_entropy_init( &ctx );
330 entropy_clear_sources( &ctx );
331
332 TEST_ASSERT( mbedtls_entropy_add_source( &ctx, mbedtls_nv_seed_poll, NULL,
333 MBEDTLS_ENTROPY_BLOCK_SIZE,
334 MBEDTLS_ENTROPY_SOURCE_STRONG ) == 0 );
335
336 // Do an entropy run
337 TEST_ASSERT( mbedtls_entropy_func( &ctx, entropy, sizeof( entropy ) ) == 0 );
338
339 // Determine what should have happened with manual entropy internal logic
340 // Only use the SHA-512 version to check
341
342 // Init accumulator
343 header[1] = MBEDTLS_ENTROPY_BLOCK_SIZE;
344 mbedtls_sha512_starts( &accumulator, 0 );
345
346 // First run for updating write_seed
347 header[0] = 0;
348 mbedtls_sha512_update( &accumulator, header, 2 );
349 mbedtls_sha512_update( &accumulator, read_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
350 mbedtls_sha512_finish( &accumulator, buf );
351
352 memset( &accumulator, 0, sizeof( mbedtls_sha512_context ) );
353 mbedtls_sha512_starts( &accumulator, 0 );
354 mbedtls_sha512_update( &accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
355
356 mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_seed, 0 );
357
358 // Second run for actual entropy (triggers mbedtls_entropy_update_nv_seed)
359 header[0] = MBEDTLS_ENTROPY_SOURCE_MANUAL;
360 mbedtls_sha512_update( &accumulator, header, 2 );
361 mbedtls_sha512_update( &accumulator, empty, MBEDTLS_ENTROPY_BLOCK_SIZE );
362
363 header[0] = 0;
364 mbedtls_sha512_update( &accumulator, header, 2 );
365 mbedtls_sha512_update( &accumulator, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
366 mbedtls_sha512_finish( &accumulator, buf );
367
368 mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_entropy, 0 );
369
370 // Check result of both NV file and entropy received with the manual calculations
371 TEST_ASSERT( memcmp( check_seed, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
372 TEST_ASSERT( memcmp( check_entropy, entropy, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
373
374 mbedtls_entropy_free( &ctx );
375}
376/* END_CASE */
377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200379void entropy_selftest( )
380{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381 TEST_ASSERT( mbedtls_entropy_self_test( 0 ) == 0 );
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200382}
383/* END_CASE */