1a8e1175bSopenharmony_ci/* BEGIN_HEADER */
2a8e1175bSopenharmony_ci#include "mbedtls/entropy.h"
3a8e1175bSopenharmony_ci#include "mbedtls/ctr_drbg.h"
4a8e1175bSopenharmony_ci#include "string.h"
5a8e1175bSopenharmony_ci#include "ctr.h"
6a8e1175bSopenharmony_ci
7a8e1175bSopenharmony_ci#if defined(MBEDTLS_THREADING_PTHREAD)
8a8e1175bSopenharmony_ci#include "mbedtls/threading.h"
9a8e1175bSopenharmony_ci#endif
10a8e1175bSopenharmony_ci
11a8e1175bSopenharmony_ci/* Modes for ctr_drbg_validate */
12a8e1175bSopenharmony_cienum reseed_mode {
13a8e1175bSopenharmony_ci    RESEED_NEVER, /* never reseed */
14a8e1175bSopenharmony_ci    RESEED_FIRST, /* instantiate, reseed, generate, generate */
15a8e1175bSopenharmony_ci    RESEED_SECOND, /* instantiate, generate, reseed, generate */
16a8e1175bSopenharmony_ci    RESEED_ALWAYS /* prediction resistance, no explicit reseed */
17a8e1175bSopenharmony_ci};
18a8e1175bSopenharmony_ci
19a8e1175bSopenharmony_cistatic size_t test_offset_idx = 0;
20a8e1175bSopenharmony_cistatic size_t test_max_idx  = 0;
21a8e1175bSopenharmony_cistatic int mbedtls_test_entropy_func(void *data, unsigned char *buf, size_t len)
22a8e1175bSopenharmony_ci{
23a8e1175bSopenharmony_ci    const unsigned char *p = (unsigned char *) data;
24a8e1175bSopenharmony_ci    if (test_offset_idx + len > test_max_idx) {
25a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
26a8e1175bSopenharmony_ci    }
27a8e1175bSopenharmony_ci    memcpy(buf, p + test_offset_idx, len);
28a8e1175bSopenharmony_ci    test_offset_idx += len;
29a8e1175bSopenharmony_ci    return 0;
30a8e1175bSopenharmony_ci}
31a8e1175bSopenharmony_ci
32a8e1175bSopenharmony_cistatic void ctr_drbg_validate_internal(int reseed_mode, data_t *nonce,
33a8e1175bSopenharmony_ci                                       int entropy_len_arg, data_t *entropy,
34a8e1175bSopenharmony_ci                                       data_t *reseed,
35a8e1175bSopenharmony_ci                                       data_t *add1, data_t *add2,
36a8e1175bSopenharmony_ci                                       data_t *result)
37a8e1175bSopenharmony_ci{
38a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_context ctx;
39a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_init(&ctx);
40a8e1175bSopenharmony_ci    unsigned char buf[64];
41a8e1175bSopenharmony_ci
42a8e1175bSopenharmony_ci    size_t entropy_chunk_len = (size_t) entropy_len_arg;
43a8e1175bSopenharmony_ci    TEST_ASSERT(entropy_chunk_len <= sizeof(buf));
44a8e1175bSopenharmony_ci
45a8e1175bSopenharmony_ci    test_offset_idx = 0;
46a8e1175bSopenharmony_ci    test_max_idx = entropy->len;
47a8e1175bSopenharmony_ci
48a8e1175bSopenharmony_ci    /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
49a8e1175bSopenharmony_ci     * where nonce||perso = nonce[nonce->len] */
50a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_set_entropy_len(&ctx, entropy_chunk_len);
51a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_set_nonce_len(&ctx, 0);
52a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_seed(
53a8e1175bSopenharmony_ci                    &ctx,
54a8e1175bSopenharmony_ci                    mbedtls_test_entropy_func, entropy->x,
55a8e1175bSopenharmony_ci                    nonce->x, nonce->len) == 0);
56a8e1175bSopenharmony_ci    if (reseed_mode == RESEED_ALWAYS) {
57a8e1175bSopenharmony_ci        mbedtls_ctr_drbg_set_prediction_resistance(
58a8e1175bSopenharmony_ci            &ctx,
59a8e1175bSopenharmony_ci            MBEDTLS_CTR_DRBG_PR_ON);
60a8e1175bSopenharmony_ci    }
61a8e1175bSopenharmony_ci
62a8e1175bSopenharmony_ci    if (reseed_mode == RESEED_FIRST) {
63a8e1175bSopenharmony_ci        /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
64a8e1175bSopenharmony_ci         *                 reseed[:reseed->len]) */
65a8e1175bSopenharmony_ci        TEST_ASSERT(mbedtls_ctr_drbg_reseed(
66a8e1175bSopenharmony_ci                        &ctx,
67a8e1175bSopenharmony_ci                        reseed->x, reseed->len) == 0);
68a8e1175bSopenharmony_ci    }
69a8e1175bSopenharmony_ci
70a8e1175bSopenharmony_ci    /* CTR_DRBG_Generate(result->len * 8 bits, add1[:add1->len]) -> buf */
71a8e1175bSopenharmony_ci    /* Then reseed if prediction resistance is enabled. */
72a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(
73a8e1175bSopenharmony_ci                    &ctx,
74a8e1175bSopenharmony_ci                    buf, result->len,
75a8e1175bSopenharmony_ci                    add1->x, add1->len) == 0);
76a8e1175bSopenharmony_ci
77a8e1175bSopenharmony_ci
78a8e1175bSopenharmony_ci    if (reseed_mode == RESEED_SECOND) {
79a8e1175bSopenharmony_ci        /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
80a8e1175bSopenharmony_ci         *                 reseed[:reseed->len]) */
81a8e1175bSopenharmony_ci        TEST_ASSERT(mbedtls_ctr_drbg_reseed(
82a8e1175bSopenharmony_ci                        &ctx,
83a8e1175bSopenharmony_ci                        reseed->x, reseed->len) == 0);
84a8e1175bSopenharmony_ci    }
85a8e1175bSopenharmony_ci
86a8e1175bSopenharmony_ci    /* CTR_DRBG_Generate(result->len * 8 bits, add2->x[:add2->len]) -> buf */
87a8e1175bSopenharmony_ci    /* Then reseed if prediction resistance is enabled. */
88a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(
89a8e1175bSopenharmony_ci                    &ctx,
90a8e1175bSopenharmony_ci                    buf, result->len,
91a8e1175bSopenharmony_ci                    add2->x, add2->len) == 0);
92a8e1175bSopenharmony_ci    TEST_ASSERT(memcmp(buf, result->x, result->len) == 0);
93a8e1175bSopenharmony_ci
94a8e1175bSopenharmony_ciexit:
95a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_free(&ctx);
96a8e1175bSopenharmony_ci}
97a8e1175bSopenharmony_ci
98a8e1175bSopenharmony_cistatic const int thread_random_reps = 10;
99a8e1175bSopenharmony_civoid *thread_random_function(void *ctx)
100a8e1175bSopenharmony_ci{
101a8e1175bSopenharmony_ci    unsigned char out[16];
102a8e1175bSopenharmony_ci    memset(out, 0, sizeof(out));
103a8e1175bSopenharmony_ci
104a8e1175bSopenharmony_ci    for (int i = 0; i < thread_random_reps; i++) {
105a8e1175bSopenharmony_ci        TEST_EQUAL(mbedtls_ctr_drbg_random((mbedtls_ctr_drbg_context *) ctx, out, sizeof(out)), 0);
106a8e1175bSopenharmony_ci    }
107a8e1175bSopenharmony_ci
108a8e1175bSopenharmony_ciexit:
109a8e1175bSopenharmony_ci    return NULL;
110a8e1175bSopenharmony_ci}
111a8e1175bSopenharmony_ci/* END_HEADER */
112a8e1175bSopenharmony_ci
113a8e1175bSopenharmony_ci/* BEGIN_DEPENDENCIES
114a8e1175bSopenharmony_ci * depends_on:MBEDTLS_CTR_DRBG_C
115a8e1175bSopenharmony_ci * END_DEPENDENCIES
116a8e1175bSopenharmony_ci */
117a8e1175bSopenharmony_ci
118a8e1175bSopenharmony_ci/* BEGIN_CASE */
119a8e1175bSopenharmony_civoid ctr_drbg_special_behaviours()
120a8e1175bSopenharmony_ci{
121a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_context ctx;
122a8e1175bSopenharmony_ci    unsigned char output[512];
123a8e1175bSopenharmony_ci    unsigned char additional[512];
124a8e1175bSopenharmony_ci
125a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_init(&ctx);
126a8e1175bSopenharmony_ci    memset(output, 0, sizeof(output));
127a8e1175bSopenharmony_ci    memset(additional, 0, sizeof(additional));
128a8e1175bSopenharmony_ci
129a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx,
130a8e1175bSopenharmony_ci                                                 output, MBEDTLS_CTR_DRBG_MAX_REQUEST + 1,
131a8e1175bSopenharmony_ci                                                 additional, 16) ==
132a8e1175bSopenharmony_ci                MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG);
133a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx,
134a8e1175bSopenharmony_ci                                                 output, 16,
135a8e1175bSopenharmony_ci                                                 additional, MBEDTLS_CTR_DRBG_MAX_INPUT + 1) ==
136a8e1175bSopenharmony_ci                MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
137a8e1175bSopenharmony_ci
138a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, additional,
139a8e1175bSopenharmony_ci                                        MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 1) ==
140a8e1175bSopenharmony_ci                MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
141a8e1175bSopenharmony_ci
142a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_set_entropy_len(&ctx, ~0);
143a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, additional,
144a8e1175bSopenharmony_ci                                        MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) ==
145a8e1175bSopenharmony_ci                MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
146a8e1175bSopenharmony_ciexit:
147a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_free(&ctx);
148a8e1175bSopenharmony_ci}
149a8e1175bSopenharmony_ci/* END_CASE */
150a8e1175bSopenharmony_ci
151a8e1175bSopenharmony_ci
152a8e1175bSopenharmony_ci/* BEGIN_CASE */
153a8e1175bSopenharmony_civoid ctr_drbg_validate_no_reseed(data_t *add_init, data_t *entropy,
154a8e1175bSopenharmony_ci                                 data_t *add1, data_t *add2,
155a8e1175bSopenharmony_ci                                 data_t *result_string)
156a8e1175bSopenharmony_ci{
157a8e1175bSopenharmony_ci    data_t empty = { 0, 0 };
158a8e1175bSopenharmony_ci    AES_PSA_INIT();
159a8e1175bSopenharmony_ci    ctr_drbg_validate_internal(RESEED_NEVER, add_init,
160a8e1175bSopenharmony_ci                               entropy->len, entropy,
161a8e1175bSopenharmony_ci                               &empty, add1, add2,
162a8e1175bSopenharmony_ci                               result_string);
163a8e1175bSopenharmony_ci    AES_PSA_DONE();
164a8e1175bSopenharmony_ci    goto exit; // goto is needed to avoid warning ( no test assertions in func)
165a8e1175bSopenharmony_ci}
166a8e1175bSopenharmony_ci/* END_CASE */
167a8e1175bSopenharmony_ci
168a8e1175bSopenharmony_ci/* BEGIN_CASE */
169a8e1175bSopenharmony_civoid ctr_drbg_validate_pr(data_t *add_init, data_t *entropy,
170a8e1175bSopenharmony_ci                          data_t *add1, data_t *add2,
171a8e1175bSopenharmony_ci                          data_t *result_string)
172a8e1175bSopenharmony_ci{
173a8e1175bSopenharmony_ci    data_t empty = { 0, 0 };
174a8e1175bSopenharmony_ci    AES_PSA_INIT();
175a8e1175bSopenharmony_ci    ctr_drbg_validate_internal(RESEED_ALWAYS, add_init,
176a8e1175bSopenharmony_ci                               entropy->len / 3, entropy,
177a8e1175bSopenharmony_ci                               &empty, add1, add2,
178a8e1175bSopenharmony_ci                               result_string);
179a8e1175bSopenharmony_ci    AES_PSA_DONE();
180a8e1175bSopenharmony_ci    goto exit; // goto is needed to avoid warning ( no test assertions in func)
181a8e1175bSopenharmony_ci}
182a8e1175bSopenharmony_ci/* END_CASE */
183a8e1175bSopenharmony_ci
184a8e1175bSopenharmony_ci/* BEGIN_CASE */
185a8e1175bSopenharmony_civoid ctr_drbg_validate_reseed_between(data_t *add_init, data_t *entropy,
186a8e1175bSopenharmony_ci                                      data_t *add1, data_t *add_reseed,
187a8e1175bSopenharmony_ci                                      data_t *add2, data_t *result_string)
188a8e1175bSopenharmony_ci{
189a8e1175bSopenharmony_ci    AES_PSA_INIT();
190a8e1175bSopenharmony_ci    ctr_drbg_validate_internal(RESEED_SECOND, add_init,
191a8e1175bSopenharmony_ci                               entropy->len / 2, entropy,
192a8e1175bSopenharmony_ci                               add_reseed, add1, add2,
193a8e1175bSopenharmony_ci                               result_string);
194a8e1175bSopenharmony_ci    AES_PSA_DONE();
195a8e1175bSopenharmony_ci    goto exit; // goto is needed to avoid warning ( no test assertions in func)
196a8e1175bSopenharmony_ci}
197a8e1175bSopenharmony_ci/* END_CASE */
198a8e1175bSopenharmony_ci
199a8e1175bSopenharmony_ci/* BEGIN_CASE */
200a8e1175bSopenharmony_civoid ctr_drbg_validate_reseed_first(data_t *add_init, data_t *entropy,
201a8e1175bSopenharmony_ci                                    data_t *add1, data_t *add_reseed,
202a8e1175bSopenharmony_ci                                    data_t *add2, data_t *result_string)
203a8e1175bSopenharmony_ci{
204a8e1175bSopenharmony_ci    AES_PSA_INIT();
205a8e1175bSopenharmony_ci    ctr_drbg_validate_internal(RESEED_FIRST, add_init,
206a8e1175bSopenharmony_ci                               entropy->len / 2, entropy,
207a8e1175bSopenharmony_ci                               add_reseed, add1, add2,
208a8e1175bSopenharmony_ci                               result_string);
209a8e1175bSopenharmony_ci    AES_PSA_DONE();
210a8e1175bSopenharmony_ci    goto exit; // goto is needed to avoid warning ( no test assertions in func)
211a8e1175bSopenharmony_ci}
212a8e1175bSopenharmony_ci/* END_CASE */
213a8e1175bSopenharmony_ci
214a8e1175bSopenharmony_ci/* BEGIN_CASE */
215a8e1175bSopenharmony_civoid ctr_drbg_entropy_strength(int expected_bit_strength)
216a8e1175bSopenharmony_ci{
217a8e1175bSopenharmony_ci    unsigned char entropy[/*initial entropy*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN +
218a8e1175bSopenharmony_ci                          /*nonce*/ MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN +
219a8e1175bSopenharmony_ci                          /*reseed*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN];
220a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_context ctx;
221a8e1175bSopenharmony_ci    size_t last_idx;
222a8e1175bSopenharmony_ci    size_t byte_strength = expected_bit_strength / 8;
223a8e1175bSopenharmony_ci
224a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_init(&ctx);
225a8e1175bSopenharmony_ci
226a8e1175bSopenharmony_ci    AES_PSA_INIT();
227a8e1175bSopenharmony_ci    test_offset_idx = 0;
228a8e1175bSopenharmony_ci    test_max_idx = sizeof(entropy);
229a8e1175bSopenharmony_ci    memset(entropy, 0, sizeof(entropy));
230a8e1175bSopenharmony_ci
231a8e1175bSopenharmony_ci    /* The initial seeding must grab at least byte_strength bytes of entropy
232a8e1175bSopenharmony_ci     * for the entropy input and byte_strength/2 bytes for a nonce. */
233a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx,
234a8e1175bSopenharmony_ci                                      mbedtls_test_entropy_func, entropy,
235a8e1175bSopenharmony_ci                                      NULL, 0) == 0);
236a8e1175bSopenharmony_ci    TEST_ASSERT(test_offset_idx >= (byte_strength * 3 + 1) / 2);
237a8e1175bSopenharmony_ci    last_idx = test_offset_idx;
238a8e1175bSopenharmony_ci
239a8e1175bSopenharmony_ci    /* A reseed must grab at least byte_strength bytes of entropy. */
240a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0) == 0);
241a8e1175bSopenharmony_ci    TEST_ASSERT(test_offset_idx - last_idx >= byte_strength);
242a8e1175bSopenharmony_ci
243a8e1175bSopenharmony_ciexit:
244a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_free(&ctx);
245a8e1175bSopenharmony_ci    AES_PSA_DONE();
246a8e1175bSopenharmony_ci}
247a8e1175bSopenharmony_ci/* END_CASE */
248a8e1175bSopenharmony_ci
249a8e1175bSopenharmony_ci/* BEGIN_CASE */
250a8e1175bSopenharmony_civoid ctr_drbg_entropy_usage(int entropy_nonce_len)
251a8e1175bSopenharmony_ci{
252a8e1175bSopenharmony_ci    unsigned char out[16];
253a8e1175bSopenharmony_ci    unsigned char add[16];
254a8e1175bSopenharmony_ci    unsigned char entropy[1024];
255a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_context ctx;
256a8e1175bSopenharmony_ci    size_t i, reps = 10;
257a8e1175bSopenharmony_ci    size_t expected_idx = 0;
258a8e1175bSopenharmony_ci
259a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_init(&ctx);
260a8e1175bSopenharmony_ci
261a8e1175bSopenharmony_ci    AES_PSA_INIT();
262a8e1175bSopenharmony_ci
263a8e1175bSopenharmony_ci    test_offset_idx = 0;
264a8e1175bSopenharmony_ci    test_max_idx = sizeof(entropy);
265a8e1175bSopenharmony_ci    memset(entropy, 0, sizeof(entropy));
266a8e1175bSopenharmony_ci    memset(out, 0, sizeof(out));
267a8e1175bSopenharmony_ci    memset(add, 0, sizeof(add));
268a8e1175bSopenharmony_ci
269a8e1175bSopenharmony_ci    if (entropy_nonce_len >= 0) {
270a8e1175bSopenharmony_ci        TEST_ASSERT(mbedtls_ctr_drbg_set_nonce_len(&ctx, entropy_nonce_len) == 0);
271a8e1175bSopenharmony_ci    }
272a8e1175bSopenharmony_ci
273a8e1175bSopenharmony_ci    /* Set reseed interval before seed */
274a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_set_reseed_interval(&ctx, 2 * reps);
275a8e1175bSopenharmony_ci
276a8e1175bSopenharmony_ci    /* Init must use entropy */
277a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0) == 0);
278a8e1175bSopenharmony_ci    expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
279a8e1175bSopenharmony_ci    if (entropy_nonce_len >= 0) {
280a8e1175bSopenharmony_ci        expected_idx += entropy_nonce_len;
281a8e1175bSopenharmony_ci    } else {
282a8e1175bSopenharmony_ci        expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
283a8e1175bSopenharmony_ci    }
284a8e1175bSopenharmony_ci    TEST_EQUAL(test_offset_idx, expected_idx);
285a8e1175bSopenharmony_ci
286a8e1175bSopenharmony_ci    /* By default, PR is off, and reseed interval was set to
287a8e1175bSopenharmony_ci     * 2 * reps so the next few calls should not use entropy */
288a8e1175bSopenharmony_ci    for (i = 0; i < reps; i++) {
289a8e1175bSopenharmony_ci        TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out) - 4) == 0);
290a8e1175bSopenharmony_ci        TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx, out, sizeof(out) - 4,
291a8e1175bSopenharmony_ci                                                     add, sizeof(add)) == 0);
292a8e1175bSopenharmony_ci    }
293a8e1175bSopenharmony_ci    TEST_EQUAL(test_offset_idx, expected_idx);
294a8e1175bSopenharmony_ci
295a8e1175bSopenharmony_ci    /* While at it, make sure we didn't write past the requested length */
296a8e1175bSopenharmony_ci    TEST_ASSERT(out[sizeof(out) - 4] == 0);
297a8e1175bSopenharmony_ci    TEST_ASSERT(out[sizeof(out) - 3] == 0);
298a8e1175bSopenharmony_ci    TEST_ASSERT(out[sizeof(out) - 2] == 0);
299a8e1175bSopenharmony_ci    TEST_ASSERT(out[sizeof(out) - 1] == 0);
300a8e1175bSopenharmony_ci
301a8e1175bSopenharmony_ci    /* There have been 2 * reps calls to random. The next call should reseed */
302a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
303a8e1175bSopenharmony_ci    expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
304a8e1175bSopenharmony_ci    TEST_EQUAL(test_offset_idx, expected_idx);
305a8e1175bSopenharmony_ci
306a8e1175bSopenharmony_ci    /* Set reseed interval after seed */
307a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_set_reseed_interval(&ctx, 4 * reps + 1);
308a8e1175bSopenharmony_ci
309a8e1175bSopenharmony_ci    /* The next few calls should not reseed */
310a8e1175bSopenharmony_ci    for (i = 0; i < (2 * reps); i++) {
311a8e1175bSopenharmony_ci        TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
312a8e1175bSopenharmony_ci        TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx, out, sizeof(out),
313a8e1175bSopenharmony_ci                                                     add, sizeof(add)) == 0);
314a8e1175bSopenharmony_ci    }
315a8e1175bSopenharmony_ci    TEST_EQUAL(test_offset_idx, expected_idx);
316a8e1175bSopenharmony_ci
317a8e1175bSopenharmony_ci    /* Call update with too much data (sizeof(entropy) > MAX(_SEED)_INPUT).
318a8e1175bSopenharmony_ci     * Make sure it's detected as an error and doesn't cause memory
319a8e1175bSopenharmony_ci     * corruption. */
320a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_update(
321a8e1175bSopenharmony_ci                    &ctx, entropy, sizeof(entropy)) != 0);
322a8e1175bSopenharmony_ci
323a8e1175bSopenharmony_ci    /* Now enable PR, so the next few calls should all reseed */
324a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
325a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
326a8e1175bSopenharmony_ci    expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
327a8e1175bSopenharmony_ci    TEST_EQUAL(test_offset_idx, expected_idx);
328a8e1175bSopenharmony_ci
329a8e1175bSopenharmony_ci    /* Finally, check setting entropy_len */
330a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_set_entropy_len(&ctx, 42);
331a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
332a8e1175bSopenharmony_ci    expected_idx += 42;
333a8e1175bSopenharmony_ci    TEST_EQUAL(test_offset_idx, expected_idx);
334a8e1175bSopenharmony_ci
335a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_set_entropy_len(&ctx, 13);
336a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
337a8e1175bSopenharmony_ci    expected_idx += 13;
338a8e1175bSopenharmony_ci    TEST_EQUAL(test_offset_idx, expected_idx);
339a8e1175bSopenharmony_ci
340a8e1175bSopenharmony_ciexit:
341a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_free(&ctx);
342a8e1175bSopenharmony_ci    AES_PSA_DONE();
343a8e1175bSopenharmony_ci}
344a8e1175bSopenharmony_ci/* END_CASE */
345a8e1175bSopenharmony_ci
346a8e1175bSopenharmony_ci/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD:!MBEDTLS_CTR_DRBG_USE_128_BIT_KEY:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
347a8e1175bSopenharmony_civoid ctr_drbg_threads(data_t *expected_result, int reseed, int arg_thread_count)
348a8e1175bSopenharmony_ci{
349a8e1175bSopenharmony_ci    size_t thread_count = (size_t) arg_thread_count;
350a8e1175bSopenharmony_ci    mbedtls_test_thread_t *threads = NULL;
351a8e1175bSopenharmony_ci
352a8e1175bSopenharmony_ci    unsigned char out[16];
353a8e1175bSopenharmony_ci    unsigned char *entropy = NULL;
354a8e1175bSopenharmony_ci
355a8e1175bSopenharmony_ci    const size_t n_random_calls = thread_count * thread_random_reps + 1;
356a8e1175bSopenharmony_ci
357a8e1175bSopenharmony_ci    /* This is a known-answer test, and although tests use a mock entropy
358a8e1175bSopenharmony_ci     * function the input entropy length will still affect the output.
359a8e1175bSopenharmony_ci     * We therefore need to pick a fixed entropy length, rather than using the
360a8e1175bSopenharmony_ci     * default entropy length (MBEDTLS_CTR_DRBG_ENTROPY_LEN). We've chosen to
361a8e1175bSopenharmony_ci     * use the default value of MBEDTLS_CTR_DRBG_ENTROPY_LEN for SHA-512,
362a8e1175bSopenharmony_ci     * as this was the value used when the expected answers were calculated. */
363a8e1175bSopenharmony_ci    const size_t entropy_len = 48;
364a8e1175bSopenharmony_ci
365a8e1175bSopenharmony_ci    AES_PSA_INIT();
366a8e1175bSopenharmony_ci
367a8e1175bSopenharmony_ci    TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count);
368a8e1175bSopenharmony_ci    memset(out, 0, sizeof(out));
369a8e1175bSopenharmony_ci
370a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_context ctx;
371a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_init(&ctx);
372a8e1175bSopenharmony_ci
373a8e1175bSopenharmony_ci    test_offset_idx = 0;
374a8e1175bSopenharmony_ci
375a8e1175bSopenharmony_ci    /* Need to set a non-default fixed entropy len, to ensure same output across
376a8e1175bSopenharmony_ci     * all configs - see above for details. */
377a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_set_entropy_len(&ctx, entropy_len);
378a8e1175bSopenharmony_ci
379a8e1175bSopenharmony_ci    if (reseed == 0) {
380a8e1175bSopenharmony_ci        mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_OFF);
381a8e1175bSopenharmony_ci        mbedtls_ctr_drbg_set_reseed_interval(&ctx, n_random_calls + 1);
382a8e1175bSopenharmony_ci
383a8e1175bSopenharmony_ci        TEST_CALLOC(entropy, entropy_len + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN);
384a8e1175bSopenharmony_ci        test_max_idx = entropy_len + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
385a8e1175bSopenharmony_ci    } else {
386a8e1175bSopenharmony_ci        const size_t entropy_size = ((n_random_calls + 1) * entropy_len)
387a8e1175bSopenharmony_ci                                    + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
388a8e1175bSopenharmony_ci
389a8e1175bSopenharmony_ci        mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
390a8e1175bSopenharmony_ci
391a8e1175bSopenharmony_ci        TEST_CALLOC(entropy, entropy_size);
392a8e1175bSopenharmony_ci        test_max_idx = entropy_size;
393a8e1175bSopenharmony_ci    }
394a8e1175bSopenharmony_ci
395a8e1175bSopenharmony_ci    TEST_EQUAL(
396a8e1175bSopenharmony_ci        mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0),
397a8e1175bSopenharmony_ci        0);
398a8e1175bSopenharmony_ci
399a8e1175bSopenharmony_ci    for (size_t i = 0; i < thread_count; i++) {
400a8e1175bSopenharmony_ci        TEST_EQUAL(
401a8e1175bSopenharmony_ci            mbedtls_test_thread_create(&threads[i],
402a8e1175bSopenharmony_ci                                       thread_random_function, (void *) &ctx),
403a8e1175bSopenharmony_ci            0);
404a8e1175bSopenharmony_ci    }
405a8e1175bSopenharmony_ci
406a8e1175bSopenharmony_ci    for (size_t i = 0; i < thread_count; i++) {
407a8e1175bSopenharmony_ci        TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
408a8e1175bSopenharmony_ci    }
409a8e1175bSopenharmony_ci
410a8e1175bSopenharmony_ci    /* Take a last output for comparing and thus verifying the DRBG state */
411a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)), 0);
412a8e1175bSopenharmony_ci
413a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(out, sizeof(out), expected_result->x, expected_result->len);
414a8e1175bSopenharmony_ci
415a8e1175bSopenharmony_ciexit:
416a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_free(&ctx);
417a8e1175bSopenharmony_ci    mbedtls_free(entropy);
418a8e1175bSopenharmony_ci    mbedtls_free(threads);
419a8e1175bSopenharmony_ci
420a8e1175bSopenharmony_ci    AES_PSA_DONE();
421a8e1175bSopenharmony_ci}
422a8e1175bSopenharmony_ci/* END_CASE */
423a8e1175bSopenharmony_ci
424a8e1175bSopenharmony_ci/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
425a8e1175bSopenharmony_civoid ctr_drbg_seed_file(char *path, int ret)
426a8e1175bSopenharmony_ci{
427a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_context ctx;
428a8e1175bSopenharmony_ci
429a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_init(&ctx);
430a8e1175bSopenharmony_ci
431a8e1175bSopenharmony_ci    AES_PSA_INIT();
432a8e1175bSopenharmony_ci
433a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_rnd_std_rand,
434a8e1175bSopenharmony_ci                                      NULL, NULL, 0) == 0);
435a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_write_seed_file(&ctx, path) == ret);
436a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_update_seed_file(&ctx, path) == ret);
437a8e1175bSopenharmony_ci
438a8e1175bSopenharmony_ciexit:
439a8e1175bSopenharmony_ci    mbedtls_ctr_drbg_free(&ctx);
440a8e1175bSopenharmony_ci    AES_PSA_DONE();
441a8e1175bSopenharmony_ci}
442a8e1175bSopenharmony_ci/* END_CASE */
443a8e1175bSopenharmony_ci
444a8e1175bSopenharmony_ci/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
445a8e1175bSopenharmony_civoid ctr_drbg_selftest()
446a8e1175bSopenharmony_ci{
447a8e1175bSopenharmony_ci    AES_PSA_INIT();
448a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ctr_drbg_self_test(1) == 0);
449a8e1175bSopenharmony_ci    AES_PSA_DONE();
450a8e1175bSopenharmony_ci}
451a8e1175bSopenharmony_ci/* END_CASE */
452a8e1175bSopenharmony_ci
453a8e1175bSopenharmony_ci/* BEGIN_CASE */
454a8e1175bSopenharmony_civoid ctr_increment_rollover()
455a8e1175bSopenharmony_ci{
456a8e1175bSopenharmony_ci    uint8_t c[16];
457a8e1175bSopenharmony_ci    uint8_t r[16];
458a8e1175bSopenharmony_ci
459a8e1175bSopenharmony_ci    // test all increments from 2^n - 1 to 2^n (i.e. where we roll over into the next bit)
460a8e1175bSopenharmony_ci    for (int n = 0; n <= 128; n++) {
461a8e1175bSopenharmony_ci        memset(c, 0, 16);
462a8e1175bSopenharmony_ci        memset(r, 0, 16);
463a8e1175bSopenharmony_ci
464a8e1175bSopenharmony_ci        // set least significant (highest address) n bits to 1, i.e. generate (2^n - 1)
465a8e1175bSopenharmony_ci        for (int i = 0; i < n; i++) {
466a8e1175bSopenharmony_ci            int bit = i % 8;
467a8e1175bSopenharmony_ci            int byte = (i / 8);
468a8e1175bSopenharmony_ci            c[15 - byte] |= 1 << bit;
469a8e1175bSopenharmony_ci        }
470a8e1175bSopenharmony_ci        // increment to get 2^n
471a8e1175bSopenharmony_ci        mbedtls_ctr_increment_counter(c);
472a8e1175bSopenharmony_ci
473a8e1175bSopenharmony_ci        // now generate a reference result equal to 2^n - i.e. set only bit (n + 1)
474a8e1175bSopenharmony_ci        // if n == 127, this will not set any bits (i.e. wraps to 0).
475a8e1175bSopenharmony_ci        int bit = n % 8;
476a8e1175bSopenharmony_ci        int byte = n / 8;
477a8e1175bSopenharmony_ci        if (byte < 16) {
478a8e1175bSopenharmony_ci            r[15 - byte] = 1 << bit;
479a8e1175bSopenharmony_ci        }
480a8e1175bSopenharmony_ci
481a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(c, 16, r, 16);
482a8e1175bSopenharmony_ci    }
483a8e1175bSopenharmony_ci
484a8e1175bSopenharmony_ci    uint64_t lsb = 10, msb = 20;
485a8e1175bSopenharmony_ci    MBEDTLS_PUT_UINT64_BE(msb, c, 0);
486a8e1175bSopenharmony_ci    MBEDTLS_PUT_UINT64_BE(lsb, c, 8);
487a8e1175bSopenharmony_ci    memcpy(r, c, 16);
488a8e1175bSopenharmony_ci    mbedtls_ctr_increment_counter(c);
489a8e1175bSopenharmony_ci    for (int i = 15; i >= 0; i--) {
490a8e1175bSopenharmony_ci        r[i] += 1;
491a8e1175bSopenharmony_ci        if (r[i] != 0) {
492a8e1175bSopenharmony_ci            break;
493a8e1175bSopenharmony_ci        }
494a8e1175bSopenharmony_ci    }
495a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(c, 16, r, 16);
496a8e1175bSopenharmony_ci}
497a8e1175bSopenharmony_ci/* END_CASE */
498a8e1175bSopenharmony_ci
499a8e1175bSopenharmony_ci/* BEGIN_CASE */
500a8e1175bSopenharmony_civoid ctr_increment(data_t *x)
501a8e1175bSopenharmony_ci{
502a8e1175bSopenharmony_ci    uint8_t c[16];
503a8e1175bSopenharmony_ci    uint8_t r[16];
504a8e1175bSopenharmony_ci
505a8e1175bSopenharmony_ci    // initialise c and r from test argument
506a8e1175bSopenharmony_ci    memset(c, 0, 16);
507a8e1175bSopenharmony_ci    memcpy(c, x->x, x->len);
508a8e1175bSopenharmony_ci    memcpy(r, c, 16);
509a8e1175bSopenharmony_ci
510a8e1175bSopenharmony_ci    // increment c
511a8e1175bSopenharmony_ci    mbedtls_ctr_increment_counter(c);
512a8e1175bSopenharmony_ci    // increment reference
513a8e1175bSopenharmony_ci    for (int i = 15; i >= 0; i--) {
514a8e1175bSopenharmony_ci        r[i] += 1;
515a8e1175bSopenharmony_ci        if (r[i] != 0) {
516a8e1175bSopenharmony_ci            break;
517a8e1175bSopenharmony_ci        }
518a8e1175bSopenharmony_ci    }
519a8e1175bSopenharmony_ci
520a8e1175bSopenharmony_ci    // test that mbedtls_ctr_increment_counter behaviour matches reference
521a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(c, 16, r, 16);
522a8e1175bSopenharmony_ci}
523a8e1175bSopenharmony_ci/* END_CASE */
524