• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* BEGIN_HEADER */
2#include "mbedtls/hmac_drbg.h"
3#include "string.h"
4
5typedef struct
6{
7    unsigned char *p;
8    size_t len;
9} entropy_ctx;
10
11static int mbedtls_test_entropy_func( void *data, unsigned char *buf, size_t len )
12{
13    entropy_ctx *ctx = (entropy_ctx *) data;
14
15    if( len > ctx->len )
16        return( -1 );
17
18    memcpy( buf, ctx->p, len );
19
20    ctx->p += len;
21    ctx->len -= len;
22
23    return( 0 );
24}
25/* END_HEADER */
26
27/* BEGIN_DEPENDENCIES
28 * depends_on:MBEDTLS_HMAC_DRBG_C
29 * END_DEPENDENCIES
30 */
31
32/* BEGIN_CASE */
33void hmac_drbg_entropy_usage( int md_alg )
34{
35    unsigned char out[16];
36    unsigned char buf[1024];
37    const mbedtls_md_info_t *md_info;
38    mbedtls_hmac_drbg_context ctx;
39    entropy_ctx entropy;
40    size_t i, reps = 10;
41    size_t default_entropy_len;
42    size_t expected_consumed_entropy = 0;
43
44    mbedtls_hmac_drbg_init( &ctx );
45    memset( buf, 0, sizeof( buf ) );
46    memset( out, 0, sizeof( out ) );
47
48    entropy.len = sizeof( buf );
49    entropy.p = buf;
50
51    md_info = mbedtls_md_info_from_type( md_alg );
52    TEST_ASSERT( md_info != NULL );
53    if( mbedtls_md_get_size( md_info ) <= 20 )
54        default_entropy_len = 16;
55    else if( mbedtls_md_get_size( md_info ) <= 28 )
56        default_entropy_len = 24;
57    else
58        default_entropy_len = 32;
59
60    /* Set reseed interval before seed */
61    mbedtls_hmac_drbg_set_reseed_interval( &ctx, 2 * reps );
62
63    /* Init must use entropy */
64    TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &entropy,
65                                 NULL, 0 ) == 0 );
66    /* default_entropy_len of entropy, plus half as much for the nonce */
67    expected_consumed_entropy += default_entropy_len * 3 / 2;
68    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
69
70    /* By default, PR is off, and reseed interval was set to
71     * 2 * reps so the next few calls should not use entropy */
72    for( i = 0; i < reps; i++ )
73    {
74        TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 );
75        TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, out, sizeof( out ) - 4,
76                                                buf, 16 ) == 0 );
77    }
78    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
79
80    /* While at it, make sure we didn't write past the requested length */
81    TEST_ASSERT( out[sizeof( out ) - 4] == 0 );
82    TEST_ASSERT( out[sizeof( out ) - 3] == 0 );
83    TEST_ASSERT( out[sizeof( out ) - 2] == 0 );
84    TEST_ASSERT( out[sizeof( out ) - 1] == 0 );
85
86    /* There have been 2 * reps calls to random. The next call should reseed */
87    TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
88    expected_consumed_entropy += default_entropy_len;
89    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
90
91    /* Set reseed interval after seed */
92    mbedtls_hmac_drbg_set_reseed_interval( &ctx, 4 * reps + 1);
93
94    /* The new few calls should not reseed */
95    for( i = 0; i < (2 * reps); i++ )
96    {
97        TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
98        TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, out, sizeof( out ) ,
99                                                buf, 16 ) == 0 );
100    }
101    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
102
103    /* Now enable PR, so the next few calls should all reseed */
104    mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
105    TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
106    expected_consumed_entropy += default_entropy_len;
107    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
108
109    /* Finally, check setting entropy_len */
110    mbedtls_hmac_drbg_set_entropy_len( &ctx, 42 );
111    TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
112    expected_consumed_entropy += 42;
113    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
114
115    mbedtls_hmac_drbg_set_entropy_len( &ctx, 13 );
116    TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
117    expected_consumed_entropy += 13;
118    TEST_EQUAL( sizeof( buf )  - entropy.len, expected_consumed_entropy );
119
120exit:
121    mbedtls_hmac_drbg_free( &ctx );
122}
123/* END_CASE */
124
125/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
126void hmac_drbg_seed_file( int md_alg, char * path, int ret )
127{
128    const mbedtls_md_info_t *md_info;
129    mbedtls_hmac_drbg_context ctx;
130
131    mbedtls_hmac_drbg_init( &ctx );
132
133    md_info = mbedtls_md_info_from_type( md_alg );
134    TEST_ASSERT( md_info != NULL );
135
136    TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info,
137                                         mbedtls_test_rnd_std_rand, NULL,
138                                         NULL, 0 ) == 0 );
139
140    TEST_ASSERT( mbedtls_hmac_drbg_write_seed_file( &ctx, path ) == ret );
141    TEST_ASSERT( mbedtls_hmac_drbg_update_seed_file( &ctx, path ) == ret );
142
143exit:
144    mbedtls_hmac_drbg_free( &ctx );
145}
146/* END_CASE */
147
148/* BEGIN_CASE */
149void hmac_drbg_buf( int md_alg )
150{
151    unsigned char out[16];
152    unsigned char buf[100];
153    const mbedtls_md_info_t *md_info;
154    mbedtls_hmac_drbg_context ctx;
155    size_t i;
156
157    mbedtls_hmac_drbg_init( &ctx );
158    memset( buf, 0, sizeof( buf ) );
159    memset( out, 0, sizeof( out ) );
160
161    md_info = mbedtls_md_info_from_type( md_alg );
162    TEST_ASSERT( md_info != NULL );
163    TEST_ASSERT( mbedtls_hmac_drbg_seed_buf( &ctx, md_info, buf, sizeof( buf ) ) == 0 );
164
165    /* Make sure it never tries to reseed (would segfault otherwise) */
166    mbedtls_hmac_drbg_set_reseed_interval( &ctx, 3 );
167    mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
168
169    for( i = 0; i < 30; i++ )
170        TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
171
172exit:
173    mbedtls_hmac_drbg_free( &ctx );
174}
175/* END_CASE */
176
177/* BEGIN_CASE */
178void hmac_drbg_no_reseed( int md_alg, data_t * entropy,
179                          data_t * custom, data_t * add1,
180                          data_t * add2, data_t * output )
181{
182    unsigned char data[1024];
183    unsigned char my_output[512];
184    entropy_ctx p_entropy;
185    const mbedtls_md_info_t *md_info;
186    mbedtls_hmac_drbg_context ctx;
187
188    mbedtls_hmac_drbg_init( &ctx );
189
190    p_entropy.p = entropy->x;
191    p_entropy.len = entropy->len;
192
193    md_info = mbedtls_md_info_from_type( md_alg );
194    TEST_ASSERT( md_info != NULL );
195
196    /* Test the simplified buffer-based variant */
197    memcpy( data, entropy->x, p_entropy.len );
198    memcpy( data + p_entropy.len, custom->x, custom->len );
199    TEST_ASSERT( mbedtls_hmac_drbg_seed_buf( &ctx, md_info,
200                                     data, p_entropy.len + custom->len ) == 0 );
201    TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len,
202                                            add1->x, add1->len ) == 0 );
203    TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len,
204                                            add2->x, add2->len ) == 0 );
205
206    /* Reset context for second run */
207    mbedtls_hmac_drbg_free( &ctx );
208
209    TEST_ASSERT( memcmp( my_output, output->x, output->len ) == 0 );
210
211    /* And now the normal entropy-based variant */
212    TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &p_entropy,
213                                 custom->x, custom->len ) == 0 );
214    TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len,
215                                            add1->x, add1->len ) == 0 );
216    TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len,
217                                            add2->x, add2->len ) == 0 );
218    TEST_ASSERT( memcmp( my_output, output->x, output->len ) == 0 );
219
220exit:
221    mbedtls_hmac_drbg_free( &ctx );
222}
223/* END_CASE */
224
225/* BEGIN_CASE */
226void hmac_drbg_nopr( int md_alg, data_t * entropy, data_t * custom,
227                     data_t * add1, data_t * add2, data_t * add3,
228                     data_t * output )
229{
230    unsigned char my_output[512];
231    entropy_ctx p_entropy;
232    const mbedtls_md_info_t *md_info;
233    mbedtls_hmac_drbg_context ctx;
234
235    mbedtls_hmac_drbg_init( &ctx );
236
237    p_entropy.p = entropy->x;
238    p_entropy.len = entropy->len;
239
240    md_info = mbedtls_md_info_from_type( md_alg );
241    TEST_ASSERT( md_info != NULL );
242
243    TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &p_entropy,
244                                 custom->x, custom->len ) == 0 );
245    TEST_ASSERT( mbedtls_hmac_drbg_reseed( &ctx, add1->x, add1->len ) == 0 );
246    TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len,
247                                            add2->x, add2->len ) == 0 );
248    TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len,
249                                            add3->x, add3->len ) == 0 );
250
251    TEST_ASSERT( memcmp( my_output, output->x, output->len ) == 0 );
252
253exit:
254    mbedtls_hmac_drbg_free( &ctx );
255}
256/* END_CASE */
257
258/* BEGIN_CASE */
259void hmac_drbg_pr( int md_alg, data_t * entropy, data_t * custom,
260                   data_t * add1, data_t * add2, data_t * output )
261{
262    unsigned char my_output[512];
263    entropy_ctx p_entropy;
264    const mbedtls_md_info_t *md_info;
265    mbedtls_hmac_drbg_context ctx;
266
267    mbedtls_hmac_drbg_init( &ctx );
268
269    p_entropy.p = entropy->x;
270    p_entropy.len = entropy->len;
271
272    md_info = mbedtls_md_info_from_type( md_alg );
273    TEST_ASSERT( md_info != NULL );
274
275    TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &p_entropy,
276                                 custom->x, custom->len ) == 0 );
277    mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
278    TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len,
279                                            add1->x, add1->len ) == 0 );
280    TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len,
281                                            add2->x, add2->len ) == 0 );
282
283    TEST_ASSERT( memcmp( my_output, output->x, output->len ) == 0 );
284
285exit:
286    mbedtls_hmac_drbg_free( &ctx );
287}
288/* END_CASE */
289
290/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
291void hmac_drbg_selftest(  )
292{
293    TEST_ASSERT( mbedtls_hmac_drbg_self_test( 1 ) == 0 );
294}
295/* END_CASE */
296