• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* BEGIN_HEADER */
2#include "mbedtls/hmac_drbg.h"
3#include "string.h"
4
5typedef struct {
6    unsigned char *p;
7    size_t len;
8} entropy_ctx;
9
10static int mbedtls_test_entropy_func(void *data, unsigned char *buf, size_t len)
11{
12    entropy_ctx *ctx = (entropy_ctx *) data;
13
14    if (len > ctx->len) {
15        return -1;
16    }
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
61    /* Set reseed interval before seed */
62    mbedtls_hmac_drbg_set_reseed_interval(&ctx, 2 * reps);
63
64    /* Init must use entropy */
65    TEST_ASSERT(mbedtls_hmac_drbg_seed(&ctx, md_info, mbedtls_test_entropy_func, &entropy,
66                                       NULL, 0) == 0);
67    /* default_entropy_len of entropy, plus half as much for the nonce */
68    expected_consumed_entropy += default_entropy_len * 3 / 2;
69    TEST_EQUAL(sizeof(buf)  - entropy.len, expected_consumed_entropy);
70
71    /* By default, PR is off, and reseed interval was set to
72     * 2 * reps so the next few calls should not use entropy */
73    for (i = 0; i < reps; i++) {
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        TEST_ASSERT(mbedtls_hmac_drbg_random(&ctx, out, sizeof(out)) == 0);
97        TEST_ASSERT(mbedtls_hmac_drbg_random_with_add(&ctx, out, sizeof(out),
98                                                      buf, 16) == 0);
99    }
100    TEST_EQUAL(sizeof(buf)  - entropy.len, expected_consumed_entropy);
101
102    /* Now enable PR, so the next few calls should all reseed */
103    mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON);
104    TEST_ASSERT(mbedtls_hmac_drbg_random(&ctx, out, sizeof(out)) == 0);
105    expected_consumed_entropy += default_entropy_len;
106    TEST_EQUAL(sizeof(buf)  - entropy.len, expected_consumed_entropy);
107
108    /* Finally, check setting entropy_len */
109    mbedtls_hmac_drbg_set_entropy_len(&ctx, 42);
110    TEST_ASSERT(mbedtls_hmac_drbg_random(&ctx, out, sizeof(out)) == 0);
111    expected_consumed_entropy += 42;
112    TEST_EQUAL(sizeof(buf)  - entropy.len, expected_consumed_entropy);
113
114    mbedtls_hmac_drbg_set_entropy_len(&ctx, 13);
115    TEST_ASSERT(mbedtls_hmac_drbg_random(&ctx, out, sizeof(out)) == 0);
116    expected_consumed_entropy += 13;
117    TEST_EQUAL(sizeof(buf)  - entropy.len, expected_consumed_entropy);
118
119exit:
120    mbedtls_hmac_drbg_free(&ctx);
121}
122/* END_CASE */
123
124/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
125void hmac_drbg_seed_file(int md_alg, char *path, int ret)
126{
127    const mbedtls_md_info_t *md_info;
128    mbedtls_hmac_drbg_context ctx;
129
130    mbedtls_hmac_drbg_init(&ctx);
131
132    md_info = mbedtls_md_info_from_type(md_alg);
133    TEST_ASSERT(md_info != NULL);
134
135    TEST_ASSERT(mbedtls_hmac_drbg_seed(&ctx, md_info,
136                                       mbedtls_test_rnd_std_rand, NULL,
137                                       NULL, 0) == 0);
138
139    TEST_ASSERT(mbedtls_hmac_drbg_write_seed_file(&ctx, path) == ret);
140    TEST_ASSERT(mbedtls_hmac_drbg_update_seed_file(&ctx, path) == ret);
141
142exit:
143    mbedtls_hmac_drbg_free(&ctx);
144}
145/* END_CASE */
146
147/* BEGIN_CASE */
148void hmac_drbg_buf(int md_alg)
149{
150    unsigned char out[16];
151    unsigned char buf[100];
152    const mbedtls_md_info_t *md_info;
153    mbedtls_hmac_drbg_context ctx;
154    size_t i;
155
156    mbedtls_hmac_drbg_init(&ctx);
157    memset(buf, 0, sizeof(buf));
158    memset(out, 0, sizeof(out));
159
160    md_info = mbedtls_md_info_from_type(md_alg);
161    TEST_ASSERT(md_info != NULL);
162    TEST_ASSERT(mbedtls_hmac_drbg_seed_buf(&ctx, md_info, buf, sizeof(buf)) == 0);
163
164    /* Make sure it never tries to reseed (would segfault otherwise) */
165    mbedtls_hmac_drbg_set_reseed_interval(&ctx, 3);
166    mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON);
167
168    for (i = 0; i < 30; i++) {
169        TEST_ASSERT(mbedtls_hmac_drbg_random(&ctx, out, sizeof(out)) == 0);
170    }
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