blob: c28438587f838426f261ba9531a99efd9561fe1d [file] [log] [blame]
Paul Bakker33b43f12013-08-20 11:48:36 +02001/* BEGIN_HEADER */
Gilles Peskineef0624f2018-08-03 20:23:09 +02002#include "mbedtls/entropy.h"
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +00003#include "mbedtls/ctr_drbg.h"
Mohammad Azim Khan67735d52017-04-06 11:55:43 +01004#include "string.h"
Rich Evans00ab4702015-02-06 13:43:58 +00005
Gilles Peskinee9a34542019-10-22 20:43:24 +02006/* mbedtls_ctr_drbg_seed() grabs a nonce by default if the entropy
7 * length is smaller than 3/2 times the maximum security strength. */
8#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
9#undef DEFAULT_ENTROPY_NONCE
10#else
11#define DEFAULT_ENTROPY_NONCE
12#endif
13
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +020014/* Modes for ctr_drbg_validate */
15enum reseed_mode
16{
17 RESEED_NEVER, /* never reseed */
18 RESEED_FIRST, /* instantiate, reseed, generate, generate */
19 RESEED_SECOND, /* instantiate, generate, reseed, generate */
20 RESEED_ALWAYS /* prediction resistance, no explicit reseed */
21};
22
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030023static size_t test_offset_idx = 0;
24static size_t test_max_idx = 0;
Reut Caspie278b362017-10-19 08:49:19 +010025static int mbedtls_test_entropy_func( void *data, unsigned char *buf, size_t len )
Paul Bakker0e04d0e2011-11-27 14:46:59 +000026{
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +010027 const unsigned char *p = (unsigned char *) data;
Gilles Peskineef0624f2018-08-03 20:23:09 +020028 if( test_offset_idx + len > test_max_idx )
29 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
Paul Bakker3ddfa662013-11-26 17:45:20 +010030 memcpy( buf, p + test_offset_idx, len );
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +010031 test_offset_idx += len;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000032 return( 0 );
33}
Nir Sonnenschein6275be32018-08-29 10:25:30 +030034
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030035static void ctr_drbg_validate_internal( int reseed_mode, data_t * nonce,
Nir Sonnenschein6275be32018-08-29 10:25:30 +030036 int entropy_len_arg, data_t * entropy,
37 data_t * reseed,
38 data_t * add1, data_t * add2,
39 data_t * result )
40{
41 mbedtls_ctr_drbg_context ctx;
42 unsigned char buf[64];
43
44 size_t entropy_chunk_len = (size_t) entropy_len_arg;
45
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030046 TEST_ASSERT( entropy_chunk_len <= sizeof( buf ) );
47
Nir Sonnenschein6275be32018-08-29 10:25:30 +030048 test_offset_idx = 0;
49 mbedtls_ctr_drbg_init( &ctx );
50
51 test_max_idx = entropy->len;
52
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030053 /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
54 * where nonce||perso = nonce[nonce->len] */
Gilles Peskine50ed86b2019-10-04 12:15:55 +020055 mbedtls_ctr_drbg_set_entropy_len( &ctx, entropy_chunk_len );
Gilles Peskine0ed378a2019-10-22 20:33:56 +020056 mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
Gilles Peskine50ed86b2019-10-04 12:15:55 +020057 TEST_ASSERT( mbedtls_ctr_drbg_seed(
Nir Sonnenschein6275be32018-08-29 10:25:30 +030058 &ctx,
59 mbedtls_test_entropy_func, entropy->x,
Gilles Peskine50ed86b2019-10-04 12:15:55 +020060 nonce->x, nonce->len ) == 0 );
Nir Sonnenschein6275be32018-08-29 10:25:30 +030061 if( reseed_mode == RESEED_ALWAYS )
62 mbedtls_ctr_drbg_set_prediction_resistance(
63 &ctx,
64 MBEDTLS_CTR_DRBG_PR_ON );
65
66 if( reseed_mode == RESEED_FIRST )
67 {
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030068 /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
69 * reseed[:reseed->len]) */
Nir Sonnenschein6275be32018-08-29 10:25:30 +030070 TEST_ASSERT( mbedtls_ctr_drbg_reseed(
71 &ctx,
72 reseed->x, reseed->len ) == 0 );
73 }
74
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030075 /* CTR_DRBG_Generate(result->len * 8 bits, add1[:add1->len]) -> buf */
Nir Sonnenschein6275be32018-08-29 10:25:30 +030076 /* Then reseed if prediction resistance is enabled. */
77 TEST_ASSERT( mbedtls_ctr_drbg_random_with_add(
78 &ctx,
79 buf, result->len,
80 add1->x, add1->len ) == 0 );
81
82
83 if( reseed_mode == RESEED_SECOND )
84 {
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030085 /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
86 * reseed[:reseed->len]) */
Nir Sonnenschein6275be32018-08-29 10:25:30 +030087 TEST_ASSERT( mbedtls_ctr_drbg_reseed(
88 &ctx,
89 reseed->x, reseed->len ) == 0 );
90 }
91
92 /* CTR_DRBG_Generate(result->len * 8 bits, add2->x[:add2->len]) -> buf */
93 /* Then reseed if prediction resistance is enabled. */
94 TEST_ASSERT( mbedtls_ctr_drbg_random_with_add(
95 &ctx,
96 buf, result->len,
97 add2->x, add2->len ) == 0 );
98 TEST_ASSERT( memcmp( buf, result->x, result->len ) == 0 );
99
100exit:
101 mbedtls_ctr_drbg_free( &ctx );
Nir Sonnenschein6275be32018-08-29 10:25:30 +0300102}
103
Paul Bakker33b43f12013-08-20 11:48:36 +0200104/* END_HEADER */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000105
Paul Bakker33b43f12013-08-20 11:48:36 +0200106/* BEGIN_DEPENDENCIES
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107 * depends_on:MBEDTLS_CTR_DRBG_C
Paul Bakker33b43f12013-08-20 11:48:36 +0200108 * END_DEPENDENCIES
109 */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000110
Paul Bakker33b43f12013-08-20 11:48:36 +0200111/* BEGIN_CASE */
Nir Sonnenschein6275be32018-08-29 10:25:30 +0300112void ctr_drbg_special_behaviours( )
Paul Bakker185ccf72016-07-14 13:21:10 +0100113{
114 mbedtls_ctr_drbg_context ctx;
115 unsigned char output[512];
116 unsigned char additional[512];
117
118 mbedtls_ctr_drbg_init( &ctx );
119 memset( output, 0, sizeof( output ) );
120 memset( additional, 0, sizeof( additional ) );
121
122 TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx,
123 output, MBEDTLS_CTR_DRBG_MAX_REQUEST + 1,
124 additional, 16 ) ==
125 MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
126 TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx,
127 output, 16,
128 additional, MBEDTLS_CTR_DRBG_MAX_INPUT + 1 ) ==
129 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
130
131 TEST_ASSERT( mbedtls_ctr_drbg_reseed( &ctx, additional,
132 MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 1 ) ==
133 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000134
135 mbedtls_ctr_drbg_set_entropy_len( &ctx, ~0 );
136 TEST_ASSERT( mbedtls_ctr_drbg_reseed( &ctx, additional,
137 MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) ==
138 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
Paul Bakker185ccf72016-07-14 13:21:10 +0100139exit:
140 mbedtls_ctr_drbg_free( &ctx );
141}
142/* END_CASE */
143
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +0200144
145/* BEGIN_CASE */
Nir Sonnenschein6275be32018-08-29 10:25:30 +0300146void ctr_drbg_validate_no_reseed( data_t * add_init, data_t * entropy,
147 data_t * add1, data_t * add2,
148 data_t * result_string )
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +0200149{
Nir Sonnenscheinacedc912018-08-29 23:57:45 +0300150 data_t empty = { 0, 0 };
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300151 ctr_drbg_validate_internal( RESEED_NEVER, add_init,
152 entropy->len, entropy,
153 &empty, add1, add2,
154 result_string );
155 goto exit; // goto is needed to avoid warning ( no test assertions in func)
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +0200156}
157/* END_CASE */
158
159/* BEGIN_CASE */
Nir Sonnenschein6275be32018-08-29 10:25:30 +0300160void ctr_drbg_validate_pr( data_t * add_init, data_t * entropy,
161 data_t * add1, data_t * add2,
162 data_t * result_string )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000163{
Nir Sonnenscheinacedc912018-08-29 23:57:45 +0300164 data_t empty = { 0, 0 };
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300165 ctr_drbg_validate_internal( RESEED_ALWAYS, add_init,
166 entropy->len / 3, entropy,
167 &empty, add1, add2,
168 result_string );
169 goto exit; // goto is needed to avoid warning ( no test assertions in func)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000170}
Paul Bakker33b43f12013-08-20 11:48:36 +0200171/* END_CASE */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000172
Paul Bakker33b43f12013-08-20 11:48:36 +0200173/* BEGIN_CASE */
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300174void ctr_drbg_validate_reseed_between( data_t * add_init, data_t * entropy,
Azim Khan5fcca462018-06-29 11:05:32 +0100175 data_t * add1, data_t * add_reseed,
Nir Sonnenschein6275be32018-08-29 10:25:30 +0300176 data_t * add2, data_t * result_string )
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000177{
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300178 ctr_drbg_validate_internal( RESEED_SECOND, add_init,
179 entropy->len / 2, entropy,
180 add_reseed, add1, add2,
181 result_string );
182 goto exit; // goto is needed to avoid warning ( no test assertions in func)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000183}
Paul Bakker33b43f12013-08-20 11:48:36 +0200184/* END_CASE */
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100185
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100186/* BEGIN_CASE */
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300187void ctr_drbg_validate_reseed_first( data_t * add_init, data_t * entropy,
188 data_t * add1, data_t * add_reseed,
189 data_t * add2, data_t * result_string )
190{
191 ctr_drbg_validate_internal( RESEED_FIRST, add_init,
192 entropy->len / 2, entropy,
193 add_reseed, add1, add2,
194 result_string );
195 goto exit; // goto is needed to avoid warning ( no test assertions in func)
196}
197/* END_CASE */
198
199
200
201/* BEGIN_CASE */
Gilles Peskinec949de02019-10-22 19:14:26 +0200202void ctr_drbg_entropy_usage( int entropy_nonce_len )
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100203{
204 unsigned char out[16];
205 unsigned char add[16];
206 unsigned char entropy[1024];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 mbedtls_ctr_drbg_context ctx;
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100208 size_t i, reps = 10;
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200209 size_t expected_idx = 0;
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100210
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200211 mbedtls_ctr_drbg_init( &ctx );
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100212 test_offset_idx = 0;
Gilles Peskineef0624f2018-08-03 20:23:09 +0200213 test_max_idx = sizeof( entropy );
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100214 memset( entropy, 0, sizeof( entropy ) );
215 memset( out, 0, sizeof( out ) );
216 memset( add, 0, sizeof( add ) );
217
Gilles Peskinec949de02019-10-22 19:14:26 +0200218 if( entropy_nonce_len >= 0 )
219 TEST_ASSERT( mbedtls_ctr_drbg_set_nonce_len( &ctx, entropy_nonce_len ) == 0 );
220
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100221 /* Init must use entropy */
Reut Caspie278b362017-10-19 08:49:19 +0100222 TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, mbedtls_test_entropy_func, entropy, NULL, 0 ) == 0 );
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200223 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskinec949de02019-10-22 19:14:26 +0200224 if( entropy_nonce_len >= 0 )
225 expected_idx += entropy_nonce_len;
Gilles Peskinee9a34542019-10-22 20:43:24 +0200226 else
227 {
228#if defined(DEFAULT_ENTROPY_NONCE)
229 expected_idx += ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2;
230#endif
231 }
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200232 TEST_EQUAL( test_offset_idx, expected_idx );
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100233
234 /* By default, PR is off and reseed_interval is large,
235 * so the next few calls should not use entropy */
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100236 for( i = 0; i < reps; i++ )
237 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200238 TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 );
239 TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, out, sizeof( out ) - 4,
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100240 add, sizeof( add ) ) == 0 );
241 }
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200242 TEST_EQUAL( test_offset_idx, expected_idx );
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100243
244 /* While at it, make sure we didn't write past the requested length */
245 TEST_ASSERT( out[sizeof( out ) - 4] == 0 );
246 TEST_ASSERT( out[sizeof( out ) - 3] == 0 );
247 TEST_ASSERT( out[sizeof( out ) - 2] == 0 );
248 TEST_ASSERT( out[sizeof( out ) - 1] == 0 );
249
250 /* Set reseed_interval to the number of calls done,
251 * so the next call should reseed */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252 mbedtls_ctr_drbg_set_reseed_interval( &ctx, 2 * reps );
253 TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200254 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
255 TEST_EQUAL( test_offset_idx, expected_idx );
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100256
257 /* The new few calls should not reseed */
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100258 for( i = 0; i < reps / 2; i++ )
259 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260 TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
261 TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, out, sizeof( out ) ,
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100262 add, sizeof( add ) ) == 0 );
263 }
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200264 TEST_EQUAL( test_offset_idx, expected_idx );
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100265
Gilles Peskined9199932018-09-11 16:41:54 +0200266 /* Call update with too much data (sizeof entropy > MAX(_SEED)_INPUT).
267 * Make sure it's detected as an error and doesn't cause memory
268 * corruption. */
269 TEST_ASSERT( mbedtls_ctr_drbg_update_ret(
270 &ctx, entropy, sizeof( entropy ) ) != 0 );
Manuel Pégourié-Gonnardf5f25b32014-11-27 14:04:56 +0100271
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100272 /* Now enable PR, so the next few calls should all reseed */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
274 TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200275 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
276 TEST_EQUAL( test_offset_idx, expected_idx );
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100277
278 /* Finally, check setting entropy_len */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279 mbedtls_ctr_drbg_set_entropy_len( &ctx, 42 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280 TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200281 expected_idx += 42;
282 TEST_EQUAL( test_offset_idx, expected_idx );
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 mbedtls_ctr_drbg_set_entropy_len( &ctx, 13 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200286 expected_idx += 13;
287 TEST_EQUAL( test_offset_idx, expected_idx );
Paul Bakkera317a982014-06-18 16:44:11 +0200288
Paul Bakkerbd51b262014-07-10 15:26:12 +0200289exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290 mbedtls_ctr_drbg_free( &ctx );
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100291}
292/* END_CASE */
293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
Azim Khanf1aaec92017-05-30 14:23:15 +0100295void ctr_drbg_seed_file( char * path, int ret )
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100296{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297 mbedtls_ctr_drbg_context ctx;
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100298
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200299 mbedtls_ctr_drbg_init( &ctx );
300
301 TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, rnd_std_rand, NULL, NULL, 0 ) == 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302 TEST_ASSERT( mbedtls_ctr_drbg_write_seed_file( &ctx, path ) == ret );
303 TEST_ASSERT( mbedtls_ctr_drbg_update_seed_file( &ctx, path ) == ret );
Paul Bakkera317a982014-06-18 16:44:11 +0200304
Paul Bakkerbd51b262014-07-10 15:26:12 +0200305exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 mbedtls_ctr_drbg_free( &ctx );
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100307}
308/* END_CASE */
309
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
Azim Khanf1aaec92017-05-30 14:23:15 +0100311void ctr_drbg_selftest( )
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100312{
Andres AG93012e82016-09-09 09:10:28 +0100313 TEST_ASSERT( mbedtls_ctr_drbg_self_test( 1 ) == 0 );
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100314}
315/* END_CASE */