blob: 329c222cf9f1d61181651b3b85ba931c99958069 [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
Paul Elliott20b2efa2023-11-21 14:46:51 +00006#if defined(MBEDTLS_THREADING_PTHREAD)
7#include "mbedtls/threading.h"
8#endif
9
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +020010/* Modes for ctr_drbg_validate */
Gilles Peskine449bd832023-01-11 14:50:10 +010011enum reseed_mode {
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +020012 RESEED_NEVER, /* never reseed */
13 RESEED_FIRST, /* instantiate, reseed, generate, generate */
14 RESEED_SECOND, /* instantiate, generate, reseed, generate */
15 RESEED_ALWAYS /* prediction resistance, no explicit reseed */
16};
17
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030018static size_t test_offset_idx = 0;
19static size_t test_max_idx = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +010020static int mbedtls_test_entropy_func(void *data, unsigned char *buf, size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000021{
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +010022 const unsigned char *p = (unsigned char *) data;
Gilles Peskine449bd832023-01-11 14:50:10 +010023 if (test_offset_idx + len > test_max_idx) {
24 return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
25 }
26 memcpy(buf, p + test_offset_idx, len);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +010027 test_offset_idx += len;
Gilles Peskine449bd832023-01-11 14:50:10 +010028 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000029}
Nir Sonnenschein6275be32018-08-29 10:25:30 +030030
Gilles Peskine449bd832023-01-11 14:50:10 +010031static void ctr_drbg_validate_internal(int reseed_mode, data_t *nonce,
32 int entropy_len_arg, data_t *entropy,
33 data_t *reseed,
34 data_t *add1, data_t *add2,
35 data_t *result)
Nir Sonnenschein6275be32018-08-29 10:25:30 +030036{
37 mbedtls_ctr_drbg_context ctx;
Gilles Peskine21e46b32023-10-17 16:35:20 +020038 mbedtls_ctr_drbg_init(&ctx);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030039 unsigned char buf[64];
40
41 size_t entropy_chunk_len = (size_t) entropy_len_arg;
Gilles Peskine449bd832023-01-11 14:50:10 +010042 TEST_ASSERT(entropy_chunk_len <= sizeof(buf));
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030043
Nir Sonnenschein6275be32018-08-29 10:25:30 +030044 test_offset_idx = 0;
Nir Sonnenschein6275be32018-08-29 10:25:30 +030045 test_max_idx = entropy->len;
46
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030047 /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
48 * where nonce||perso = nonce[nonce->len] */
Gilles Peskine449bd832023-01-11 14:50:10 +010049 mbedtls_ctr_drbg_set_entropy_len(&ctx, entropy_chunk_len);
50 mbedtls_ctr_drbg_set_nonce_len(&ctx, 0);
51 TEST_ASSERT(mbedtls_ctr_drbg_seed(
52 &ctx,
53 mbedtls_test_entropy_func, entropy->x,
54 nonce->x, nonce->len) == 0);
55 if (reseed_mode == RESEED_ALWAYS) {
Nir Sonnenschein6275be32018-08-29 10:25:30 +030056 mbedtls_ctr_drbg_set_prediction_resistance(
57 &ctx,
Gilles Peskine449bd832023-01-11 14:50:10 +010058 MBEDTLS_CTR_DRBG_PR_ON);
59 }
Nir Sonnenschein6275be32018-08-29 10:25:30 +030060
Gilles Peskine449bd832023-01-11 14:50:10 +010061 if (reseed_mode == RESEED_FIRST) {
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030062 /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
63 * reseed[:reseed->len]) */
Gilles Peskine449bd832023-01-11 14:50:10 +010064 TEST_ASSERT(mbedtls_ctr_drbg_reseed(
65 &ctx,
66 reseed->x, reseed->len) == 0);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030067 }
68
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030069 /* CTR_DRBG_Generate(result->len * 8 bits, add1[:add1->len]) -> buf */
Nir Sonnenschein6275be32018-08-29 10:25:30 +030070 /* Then reseed if prediction resistance is enabled. */
Gilles Peskine449bd832023-01-11 14:50:10 +010071 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(
72 &ctx,
73 buf, result->len,
74 add1->x, add1->len) == 0);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030075
76
Gilles Peskine449bd832023-01-11 14:50:10 +010077 if (reseed_mode == RESEED_SECOND) {
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030078 /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
79 * reseed[:reseed->len]) */
Gilles Peskine449bd832023-01-11 14:50:10 +010080 TEST_ASSERT(mbedtls_ctr_drbg_reseed(
81 &ctx,
82 reseed->x, reseed->len) == 0);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030083 }
84
85 /* CTR_DRBG_Generate(result->len * 8 bits, add2->x[:add2->len]) -> buf */
86 /* Then reseed if prediction resistance is enabled. */
Gilles Peskine449bd832023-01-11 14:50:10 +010087 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(
88 &ctx,
89 buf, result->len,
90 add2->x, add2->len) == 0);
91 TEST_ASSERT(memcmp(buf, result->x, result->len) == 0);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030092
93exit:
Gilles Peskine449bd832023-01-11 14:50:10 +010094 mbedtls_ctr_drbg_free(&ctx);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030095}
96
Janos Follatha16ee6b2023-10-04 19:05:26 +010097static const int thread_random_reps = 10;
Paul Elliott6a997c92023-11-30 14:47:17 +000098void *thread_random_function(void *ctx)
Janos Follatha16ee6b2023-10-04 19:05:26 +010099{
100 unsigned char out[16];
101 memset(out, 0, sizeof(out));
102
Paul Elliott6a997c92023-11-30 14:47:17 +0000103 for (int i = 0; i < thread_random_reps; i++) {
104 TEST_EQUAL(mbedtls_ctr_drbg_random((mbedtls_ctr_drbg_context *) ctx, out, sizeof(out)), 0);
Janos Follatha16ee6b2023-10-04 19:05:26 +0100105 }
106
107exit:
108 return NULL;
109}
Paul Bakker33b43f12013-08-20 11:48:36 +0200110/* END_HEADER */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000111
Paul Bakker33b43f12013-08-20 11:48:36 +0200112/* BEGIN_DEPENDENCIES
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113 * depends_on:MBEDTLS_CTR_DRBG_C
Paul Bakker33b43f12013-08-20 11:48:36 +0200114 * END_DEPENDENCIES
115 */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000116
Paul Bakker33b43f12013-08-20 11:48:36 +0200117/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100118void ctr_drbg_special_behaviours()
Paul Bakker185ccf72016-07-14 13:21:10 +0100119{
120 mbedtls_ctr_drbg_context ctx;
121 unsigned char output[512];
122 unsigned char additional[512];
123
Gilles Peskine449bd832023-01-11 14:50:10 +0100124 mbedtls_ctr_drbg_init(&ctx);
125 memset(output, 0, sizeof(output));
126 memset(additional, 0, sizeof(additional));
Paul Bakker185ccf72016-07-14 13:21:10 +0100127
Gilles Peskine449bd832023-01-11 14:50:10 +0100128 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx,
129 output, MBEDTLS_CTR_DRBG_MAX_REQUEST + 1,
130 additional, 16) ==
131 MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG);
132 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx,
133 output, 16,
134 additional, MBEDTLS_CTR_DRBG_MAX_INPUT + 1) ==
135 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
Paul Bakker185ccf72016-07-14 13:21:10 +0100136
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, additional,
138 MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 1) ==
139 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000140
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 mbedtls_ctr_drbg_set_entropy_len(&ctx, ~0);
142 TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, additional,
143 MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) ==
144 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
Paul Bakker185ccf72016-07-14 13:21:10 +0100145exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100146 mbedtls_ctr_drbg_free(&ctx);
Paul Bakker185ccf72016-07-14 13:21:10 +0100147}
148/* END_CASE */
149
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +0200150
151/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100152void ctr_drbg_validate_no_reseed(data_t *add_init, data_t *entropy,
153 data_t *add1, data_t *add2,
154 data_t *result_string)
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +0200155{
Nir Sonnenscheinacedc912018-08-29 23:57:45 +0300156 data_t empty = { 0, 0 };
Valerio Settidc32ac22023-11-13 10:27:56 +0100157 AES_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100158 ctr_drbg_validate_internal(RESEED_NEVER, add_init,
159 entropy->len, entropy,
160 &empty, add1, add2,
161 result_string);
Valerio Settidc32ac22023-11-13 10:27:56 +0100162 AES_PSA_DONE();
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300163 goto exit; // goto is needed to avoid warning ( no test assertions in func)
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +0200164}
165/* END_CASE */
166
167/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100168void ctr_drbg_validate_pr(data_t *add_init, data_t *entropy,
169 data_t *add1, data_t *add2,
170 data_t *result_string)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000171{
Nir Sonnenscheinacedc912018-08-29 23:57:45 +0300172 data_t empty = { 0, 0 };
Valerio Settidc32ac22023-11-13 10:27:56 +0100173 AES_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 ctr_drbg_validate_internal(RESEED_ALWAYS, add_init,
175 entropy->len / 3, entropy,
176 &empty, add1, add2,
177 result_string);
Valerio Settidc32ac22023-11-13 10:27:56 +0100178 AES_PSA_DONE();
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300179 goto exit; // goto is needed to avoid warning ( no test assertions in func)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000180}
Paul Bakker33b43f12013-08-20 11:48:36 +0200181/* END_CASE */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182
Paul Bakker33b43f12013-08-20 11:48:36 +0200183/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100184void ctr_drbg_validate_reseed_between(data_t *add_init, data_t *entropy,
185 data_t *add1, data_t *add_reseed,
186 data_t *add2, data_t *result_string)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000187{
Valerio Settidc32ac22023-11-13 10:27:56 +0100188 AES_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100189 ctr_drbg_validate_internal(RESEED_SECOND, add_init,
190 entropy->len / 2, entropy,
191 add_reseed, add1, add2,
192 result_string);
Valerio Settidc32ac22023-11-13 10:27:56 +0100193 AES_PSA_DONE();
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300194 goto exit; // goto is needed to avoid warning ( no test assertions in func)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000195}
Paul Bakker33b43f12013-08-20 11:48:36 +0200196/* END_CASE */
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100197
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100198/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100199void ctr_drbg_validate_reseed_first(data_t *add_init, data_t *entropy,
200 data_t *add1, data_t *add_reseed,
201 data_t *add2, data_t *result_string)
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300202{
Valerio Settidc32ac22023-11-13 10:27:56 +0100203 AES_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 ctr_drbg_validate_internal(RESEED_FIRST, add_init,
205 entropy->len / 2, entropy,
206 add_reseed, add1, add2,
207 result_string);
Valerio Settidc32ac22023-11-13 10:27:56 +0100208 AES_PSA_DONE();
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300209 goto exit; // goto is needed to avoid warning ( no test assertions in func)
210}
211/* END_CASE */
212
Gilles Peskine69971662019-10-23 19:39:36 +0200213/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100214void ctr_drbg_entropy_strength(int expected_bit_strength)
Gilles Peskine69971662019-10-23 19:39:36 +0200215{
216 unsigned char entropy[/*initial entropy*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN +
Gilles Peskine449bd832023-01-11 14:50:10 +0100217 /*nonce*/ MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN +
218 /*reseed*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN];
Gilles Peskine69971662019-10-23 19:39:36 +0200219 mbedtls_ctr_drbg_context ctx;
220 size_t last_idx;
221 size_t byte_strength = expected_bit_strength / 8;
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300222
Gilles Peskine449bd832023-01-11 14:50:10 +0100223 mbedtls_ctr_drbg_init(&ctx);
Valerio Settidc32ac22023-11-13 10:27:56 +0100224
225 AES_PSA_INIT();
Gilles Peskine69971662019-10-23 19:39:36 +0200226 test_offset_idx = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100227 test_max_idx = sizeof(entropy);
228 memset(entropy, 0, sizeof(entropy));
Gilles Peskine69971662019-10-23 19:39:36 +0200229
230 /* The initial seeding must grab at least byte_strength bytes of entropy
231 * for the entropy input and byte_strength/2 bytes for a nonce. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx,
233 mbedtls_test_entropy_func, entropy,
234 NULL, 0) == 0);
235 TEST_ASSERT(test_offset_idx >= (byte_strength * 3 + 1) / 2);
Gilles Peskine69971662019-10-23 19:39:36 +0200236 last_idx = test_offset_idx;
237
238 /* A reseed must grab at least byte_strength bytes of entropy. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100239 TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0) == 0);
240 TEST_ASSERT(test_offset_idx - last_idx >= byte_strength);
Gilles Peskine69971662019-10-23 19:39:36 +0200241
242exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 mbedtls_ctr_drbg_free(&ctx);
Valerio Settidc32ac22023-11-13 10:27:56 +0100244 AES_PSA_DONE();
Gilles Peskine69971662019-10-23 19:39:36 +0200245}
246/* END_CASE */
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300247
248/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100249void ctr_drbg_entropy_usage(int entropy_nonce_len)
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100250{
251 unsigned char out[16];
252 unsigned char add[16];
253 unsigned char entropy[1024];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 mbedtls_ctr_drbg_context ctx;
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100255 size_t i, reps = 10;
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200256 size_t expected_idx = 0;
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100257
Gilles Peskine449bd832023-01-11 14:50:10 +0100258 mbedtls_ctr_drbg_init(&ctx);
Valerio Settidc32ac22023-11-13 10:27:56 +0100259
260 AES_PSA_INIT();
261
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100262 test_offset_idx = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100263 test_max_idx = sizeof(entropy);
264 memset(entropy, 0, sizeof(entropy));
265 memset(out, 0, sizeof(out));
266 memset(add, 0, sizeof(add));
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100267
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 if (entropy_nonce_len >= 0) {
269 TEST_ASSERT(mbedtls_ctr_drbg_set_nonce_len(&ctx, entropy_nonce_len) == 0);
270 }
Gilles Peskinec949de02019-10-22 19:14:26 +0200271
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800272 /* Set reseed interval before seed */
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 mbedtls_ctr_drbg_set_reseed_interval(&ctx, 2 * reps);
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800274
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100275 /* Init must use entropy */
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0) == 0);
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200277 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100278 if (entropy_nonce_len >= 0) {
Gilles Peskinec949de02019-10-22 19:14:26 +0200279 expected_idx += entropy_nonce_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 } else {
Gilles Peskine69971662019-10-23 19:39:36 +0200281 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 }
283 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100284
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800285 /* By default, PR is off, and reseed interval was set to
286 * 2 * reps so the next few calls should not use entropy */
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 for (i = 0; i < reps; i++) {
288 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out) - 4) == 0);
289 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx, out, sizeof(out) - 4,
290 add, sizeof(add)) == 0);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100291 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100292 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100293
294 /* While at it, make sure we didn't write past the requested length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 TEST_ASSERT(out[sizeof(out) - 4] == 0);
296 TEST_ASSERT(out[sizeof(out) - 3] == 0);
297 TEST_ASSERT(out[sizeof(out) - 2] == 0);
298 TEST_ASSERT(out[sizeof(out) - 1] == 0);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100299
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800300 /* There have been 2 * reps calls to random. The next call should reseed */
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200302 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100304
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800305 /* Set reseed interval after seed */
Gilles Peskine449bd832023-01-11 14:50:10 +0100306 mbedtls_ctr_drbg_set_reseed_interval(&ctx, 4 * reps + 1);
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800307
308 /* The next few calls should not reseed */
Gilles Peskine449bd832023-01-11 14:50:10 +0100309 for (i = 0; i < (2 * reps); i++) {
310 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
311 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx, out, sizeof(out),
312 add, sizeof(add)) == 0);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100313 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100315
Dave Rodgman6dd757a2023-02-02 12:40:50 +0000316 /* Call update with too much data (sizeof(entropy) > MAX(_SEED)_INPUT).
Gilles Peskined9199932018-09-11 16:41:54 +0200317 * Make sure it's detected as an error and doesn't cause memory
318 * corruption. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100319 TEST_ASSERT(mbedtls_ctr_drbg_update(
320 &ctx, entropy, sizeof(entropy)) != 0);
Manuel Pégourié-Gonnardf5f25b32014-11-27 14:04:56 +0100321
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100322 /* Now enable PR, so the next few calls should all reseed */
Gilles Peskine449bd832023-01-11 14:50:10 +0100323 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
324 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200325 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100327
328 /* Finally, check setting entropy_len */
Gilles Peskine449bd832023-01-11 14:50:10 +0100329 mbedtls_ctr_drbg_set_entropy_len(&ctx, 42);
330 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200331 expected_idx += 42;
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100333
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 mbedtls_ctr_drbg_set_entropy_len(&ctx, 13);
335 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200336 expected_idx += 13;
Gilles Peskine449bd832023-01-11 14:50:10 +0100337 TEST_EQUAL(test_offset_idx, expected_idx);
Paul Bakkera317a982014-06-18 16:44:11 +0200338
Paul Bakkerbd51b262014-07-10 15:26:12 +0200339exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 mbedtls_ctr_drbg_free(&ctx);
Valerio Settidc32ac22023-11-13 10:27:56 +0100341 AES_PSA_DONE();
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100342}
343/* END_CASE */
344
Janos Follatha16ee6b2023-10-04 19:05:26 +0100345/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD */
Paul Elliottbda25dd2023-11-21 17:07:40 +0000346void ctr_drbg_threads(data_t *expected_result, int reseed)
Janos Follatha16ee6b2023-10-04 19:05:26 +0100347{
348#define THREAD_CNT 5
349 pthread_t threads[THREAD_CNT];
350
351 unsigned char out[16];
Paul Elliottbda25dd2023-11-21 17:07:40 +0000352 unsigned char *entropy = NULL;
353
354 const size_t n_random_calls = THREAD_CNT * thread_random_reps + 1;
355
Janos Follatha16ee6b2023-10-04 19:05:26 +0100356 memset(out, 0, sizeof(out));
357
Janos Follatha16ee6b2023-10-04 19:05:26 +0100358 mbedtls_ctr_drbg_context ctx;
359 mbedtls_ctr_drbg_init(&ctx);
360
Paul Elliottbda25dd2023-11-21 17:07:40 +0000361 test_offset_idx = 0;
Janos Follatha16ee6b2023-10-04 19:05:26 +0100362
Paul Elliottbda25dd2023-11-21 17:07:40 +0000363 if (reseed == 0) {
364 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_OFF);
365 mbedtls_ctr_drbg_set_reseed_interval(&ctx, n_random_calls + 1);
366
Paul Elliottfed410f2023-11-30 20:40:55 +0000367 TEST_CALLOC(entropy, MBEDTLS_CTR_DRBG_ENTROPY_LEN + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN);
368 test_max_idx = MBEDTLS_CTR_DRBG_ENTROPY_LEN + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
Paul Elliottbda25dd2023-11-21 17:07:40 +0000369 } else {
Paul Elliottfed410f2023-11-30 20:40:55 +0000370 const size_t entropy_size = ((n_random_calls + 1) * MBEDTLS_CTR_DRBG_ENTROPY_LEN)
371 + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
Paul Elliottbda25dd2023-11-21 17:07:40 +0000372
373 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
374
375 TEST_CALLOC(entropy, entropy_size);
376 test_max_idx = entropy_size;
377 }
Janos Follatha16ee6b2023-10-04 19:05:26 +0100378
379 TEST_EQUAL(
380 mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0),
381 0);
382
383 for (size_t i = 0; i < THREAD_CNT; i++) {
384 TEST_EQUAL(
385 pthread_create(&threads[i], NULL,
Paul Elliott6a997c92023-11-30 14:47:17 +0000386 thread_random_function, (void *) &ctx),
Janos Follatha16ee6b2023-10-04 19:05:26 +0100387 0);
388 }
389
390 for (size_t i = 0; i < THREAD_CNT; i++) {
391 TEST_EQUAL(pthread_join(threads[i], NULL), 0);
392 }
393
394 /* Take a last output for comparing and thus verifying the DRBG state */
395 TEST_EQUAL(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)), 0);
396
397 TEST_MEMORY_COMPARE(out, sizeof(out), expected_result->x, expected_result->len);
398
399exit:
400 mbedtls_ctr_drbg_free(&ctx);
Paul Elliottbda25dd2023-11-21 17:07:40 +0000401 mbedtls_free(entropy);
Janos Follatha16ee6b2023-10-04 19:05:26 +0100402}
403#undef THREAD_CNT
404/* END_CASE */
405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
Gilles Peskine449bd832023-01-11 14:50:10 +0100407void ctr_drbg_seed_file(char *path, int ret)
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100408{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 mbedtls_ctr_drbg_context ctx;
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100410
Gilles Peskine449bd832023-01-11 14:50:10 +0100411 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200412
Valerio Settidc32ac22023-11-13 10:27:56 +0100413 AES_PSA_INIT();
414
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_rnd_std_rand,
416 NULL, NULL, 0) == 0);
417 TEST_ASSERT(mbedtls_ctr_drbg_write_seed_file(&ctx, path) == ret);
418 TEST_ASSERT(mbedtls_ctr_drbg_update_seed_file(&ctx, path) == ret);
Paul Bakkera317a982014-06-18 16:44:11 +0200419
Paul Bakkerbd51b262014-07-10 15:26:12 +0200420exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100421 mbedtls_ctr_drbg_free(&ctx);
Valerio Settidc32ac22023-11-13 10:27:56 +0100422 AES_PSA_DONE();
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100423}
424/* END_CASE */
425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
Gilles Peskine449bd832023-01-11 14:50:10 +0100427void ctr_drbg_selftest()
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100428{
Valerio Settidc32ac22023-11-13 10:27:56 +0100429 AES_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 TEST_ASSERT(mbedtls_ctr_drbg_self_test(1) == 0);
Valerio Settidc32ac22023-11-13 10:27:56 +0100431 AES_PSA_DONE();
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100432}
433/* END_CASE */