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