blob: 78a63ea626ecc3f6ad93dfb9c543914a5a65df53 [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"
Dave Rodgmanae730342024-01-13 17:31:13 +00005#include "ctr.h"
Rich Evans00ab4702015-02-06 13:43:58 +00006
Paul Elliott20b2efa2023-11-21 14:46:51 +00007#if defined(MBEDTLS_THREADING_PTHREAD)
8#include "mbedtls/threading.h"
9#endif
10
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +020011/* Modes for ctr_drbg_validate */
Gilles Peskine449bd832023-01-11 14:50:10 +010012enum reseed_mode {
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +020013 RESEED_NEVER, /* never reseed */
14 RESEED_FIRST, /* instantiate, reseed, generate, generate */
15 RESEED_SECOND, /* instantiate, generate, reseed, generate */
16 RESEED_ALWAYS /* prediction resistance, no explicit reseed */
17};
18
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030019static size_t test_offset_idx = 0;
20static size_t test_max_idx = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +010021static int mbedtls_test_entropy_func(void *data, unsigned char *buf, size_t len)
Paul Bakker0e04d0e2011-11-27 14:46:59 +000022{
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +010023 const unsigned char *p = (unsigned char *) data;
Gilles Peskine449bd832023-01-11 14:50:10 +010024 if (test_offset_idx + len > test_max_idx) {
25 return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
26 }
27 memcpy(buf, p + test_offset_idx, len);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +010028 test_offset_idx += len;
Gilles Peskine449bd832023-01-11 14:50:10 +010029 return 0;
Paul Bakker0e04d0e2011-11-27 14:46:59 +000030}
Nir Sonnenschein6275be32018-08-29 10:25:30 +030031
Gilles Peskine449bd832023-01-11 14:50:10 +010032static void ctr_drbg_validate_internal(int reseed_mode, data_t *nonce,
33 int entropy_len_arg, data_t *entropy,
34 data_t *reseed,
35 data_t *add1, data_t *add2,
36 data_t *result)
Nir Sonnenschein6275be32018-08-29 10:25:30 +030037{
38 mbedtls_ctr_drbg_context ctx;
Gilles Peskine21e46b32023-10-17 16:35:20 +020039 mbedtls_ctr_drbg_init(&ctx);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030040 unsigned char buf[64];
41
42 size_t entropy_chunk_len = (size_t) entropy_len_arg;
Gilles Peskine449bd832023-01-11 14:50:10 +010043 TEST_ASSERT(entropy_chunk_len <= sizeof(buf));
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030044
Nir Sonnenschein6275be32018-08-29 10:25:30 +030045 test_offset_idx = 0;
Nir Sonnenschein6275be32018-08-29 10:25:30 +030046 test_max_idx = entropy->len;
47
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030048 /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
49 * where nonce||perso = nonce[nonce->len] */
Gilles Peskine449bd832023-01-11 14:50:10 +010050 mbedtls_ctr_drbg_set_entropy_len(&ctx, entropy_chunk_len);
51 mbedtls_ctr_drbg_set_nonce_len(&ctx, 0);
52 TEST_ASSERT(mbedtls_ctr_drbg_seed(
53 &ctx,
54 mbedtls_test_entropy_func, entropy->x,
55 nonce->x, nonce->len) == 0);
56 if (reseed_mode == RESEED_ALWAYS) {
Nir Sonnenschein6275be32018-08-29 10:25:30 +030057 mbedtls_ctr_drbg_set_prediction_resistance(
58 &ctx,
Gilles Peskine449bd832023-01-11 14:50:10 +010059 MBEDTLS_CTR_DRBG_PR_ON);
60 }
Nir Sonnenschein6275be32018-08-29 10:25:30 +030061
Gilles Peskine449bd832023-01-11 14:50:10 +010062 if (reseed_mode == RESEED_FIRST) {
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030063 /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
64 * reseed[:reseed->len]) */
Gilles Peskine449bd832023-01-11 14:50:10 +010065 TEST_ASSERT(mbedtls_ctr_drbg_reseed(
66 &ctx,
67 reseed->x, reseed->len) == 0);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030068 }
69
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030070 /* CTR_DRBG_Generate(result->len * 8 bits, add1[:add1->len]) -> buf */
Nir Sonnenschein6275be32018-08-29 10:25:30 +030071 /* Then reseed if prediction resistance is enabled. */
Gilles Peskine449bd832023-01-11 14:50:10 +010072 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(
73 &ctx,
74 buf, result->len,
75 add1->x, add1->len) == 0);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030076
77
Gilles Peskine449bd832023-01-11 14:50:10 +010078 if (reseed_mode == RESEED_SECOND) {
Nir Sonnenschein85fcb582018-08-29 23:38:57 +030079 /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
80 * reseed[:reseed->len]) */
Gilles Peskine449bd832023-01-11 14:50:10 +010081 TEST_ASSERT(mbedtls_ctr_drbg_reseed(
82 &ctx,
83 reseed->x, reseed->len) == 0);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030084 }
85
86 /* CTR_DRBG_Generate(result->len * 8 bits, add2->x[:add2->len]) -> buf */
87 /* Then reseed if prediction resistance is enabled. */
Gilles Peskine449bd832023-01-11 14:50:10 +010088 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(
89 &ctx,
90 buf, result->len,
91 add2->x, add2->len) == 0);
92 TEST_ASSERT(memcmp(buf, result->x, result->len) == 0);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030093
94exit:
Gilles Peskine449bd832023-01-11 14:50:10 +010095 mbedtls_ctr_drbg_free(&ctx);
Nir Sonnenschein6275be32018-08-29 10:25:30 +030096}
97
Janos Follatha16ee6b2023-10-04 19:05:26 +010098static const int thread_random_reps = 10;
Michael Schusterb1e33fb2024-06-04 02:30:22 +020099void *thread_random_function(void *ctx); /* only used conditionally in ctr_drbg_threads */
Paul Elliott6a997c92023-11-30 14:47:17 +0000100void *thread_random_function(void *ctx)
Janos Follatha16ee6b2023-10-04 19:05:26 +0100101{
102 unsigned char out[16];
103 memset(out, 0, sizeof(out));
104
Paul Elliott6a997c92023-11-30 14:47:17 +0000105 for (int i = 0; i < thread_random_reps; i++) {
106 TEST_EQUAL(mbedtls_ctr_drbg_random((mbedtls_ctr_drbg_context *) ctx, out, sizeof(out)), 0);
Janos Follatha16ee6b2023-10-04 19:05:26 +0100107 }
108
109exit:
110 return NULL;
111}
Paul Bakker33b43f12013-08-20 11:48:36 +0200112/* END_HEADER */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000113
Paul Bakker33b43f12013-08-20 11:48:36 +0200114/* BEGIN_DEPENDENCIES
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115 * depends_on:MBEDTLS_CTR_DRBG_C
Paul Bakker33b43f12013-08-20 11:48:36 +0200116 * END_DEPENDENCIES
117 */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000118
Paul Bakker33b43f12013-08-20 11:48:36 +0200119/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100120void ctr_drbg_special_behaviours()
Paul Bakker185ccf72016-07-14 13:21:10 +0100121{
122 mbedtls_ctr_drbg_context ctx;
123 unsigned char output[512];
124 unsigned char additional[512];
125
Gilles Peskine449bd832023-01-11 14:50:10 +0100126 mbedtls_ctr_drbg_init(&ctx);
127 memset(output, 0, sizeof(output));
128 memset(additional, 0, sizeof(additional));
Paul Bakker185ccf72016-07-14 13:21:10 +0100129
Gilles Peskine449bd832023-01-11 14:50:10 +0100130 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx,
131 output, MBEDTLS_CTR_DRBG_MAX_REQUEST + 1,
132 additional, 16) ==
133 MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG);
134 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx,
135 output, 16,
136 additional, MBEDTLS_CTR_DRBG_MAX_INPUT + 1) ==
137 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
Paul Bakker185ccf72016-07-14 13:21:10 +0100138
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, additional,
140 MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 1) ==
141 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
Andres Amaya Garcia6a543362017-01-17 23:04:22 +0000142
Gilles Peskine449bd832023-01-11 14:50:10 +0100143 mbedtls_ctr_drbg_set_entropy_len(&ctx, ~0);
144 TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, additional,
145 MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) ==
146 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
Paul Bakker185ccf72016-07-14 13:21:10 +0100147exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100148 mbedtls_ctr_drbg_free(&ctx);
Paul Bakker185ccf72016-07-14 13:21:10 +0100149}
150/* END_CASE */
151
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +0200152
153/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100154void ctr_drbg_validate_no_reseed(data_t *add_init, data_t *entropy,
155 data_t *add1, data_t *add2,
156 data_t *result_string)
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +0200157{
Nir Sonnenscheinacedc912018-08-29 23:57:45 +0300158 data_t empty = { 0, 0 };
Valerio Settidc32ac22023-11-13 10:27:56 +0100159 AES_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100160 ctr_drbg_validate_internal(RESEED_NEVER, add_init,
161 entropy->len, entropy,
162 &empty, add1, add2,
163 result_string);
Valerio Settidc32ac22023-11-13 10:27:56 +0100164 AES_PSA_DONE();
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300165 goto exit; // goto is needed to avoid warning ( no test assertions in func)
Gilles Peskine5ef5a9a2018-08-03 20:27:50 +0200166}
167/* END_CASE */
168
169/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100170void ctr_drbg_validate_pr(data_t *add_init, data_t *entropy,
171 data_t *add1, data_t *add2,
172 data_t *result_string)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000173{
Nir Sonnenscheinacedc912018-08-29 23:57:45 +0300174 data_t empty = { 0, 0 };
Valerio Settidc32ac22023-11-13 10:27:56 +0100175 AES_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 ctr_drbg_validate_internal(RESEED_ALWAYS, add_init,
177 entropy->len / 3, entropy,
178 &empty, add1, add2,
179 result_string);
Valerio Settidc32ac22023-11-13 10:27:56 +0100180 AES_PSA_DONE();
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300181 goto exit; // goto is needed to avoid warning ( no test assertions in func)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000182}
Paul Bakker33b43f12013-08-20 11:48:36 +0200183/* END_CASE */
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000184
Paul Bakker33b43f12013-08-20 11:48:36 +0200185/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100186void ctr_drbg_validate_reseed_between(data_t *add_init, data_t *entropy,
187 data_t *add1, data_t *add_reseed,
188 data_t *add2, data_t *result_string)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000189{
Valerio Settidc32ac22023-11-13 10:27:56 +0100190 AES_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 ctr_drbg_validate_internal(RESEED_SECOND, add_init,
192 entropy->len / 2, entropy,
193 add_reseed, add1, add2,
194 result_string);
Valerio Settidc32ac22023-11-13 10:27:56 +0100195 AES_PSA_DONE();
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300196 goto exit; // goto is needed to avoid warning ( no test assertions in func)
Paul Bakker0e04d0e2011-11-27 14:46:59 +0000197}
Paul Bakker33b43f12013-08-20 11:48:36 +0200198/* END_CASE */
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100199
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100200/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100201void ctr_drbg_validate_reseed_first(data_t *add_init, data_t *entropy,
202 data_t *add1, data_t *add_reseed,
203 data_t *add2, data_t *result_string)
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300204{
Valerio Settidc32ac22023-11-13 10:27:56 +0100205 AES_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 ctr_drbg_validate_internal(RESEED_FIRST, add_init,
207 entropy->len / 2, entropy,
208 add_reseed, add1, add2,
209 result_string);
Valerio Settidc32ac22023-11-13 10:27:56 +0100210 AES_PSA_DONE();
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300211 goto exit; // goto is needed to avoid warning ( no test assertions in func)
212}
213/* END_CASE */
214
Gilles Peskine69971662019-10-23 19:39:36 +0200215/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100216void ctr_drbg_entropy_strength(int expected_bit_strength)
Gilles Peskine69971662019-10-23 19:39:36 +0200217{
218 unsigned char entropy[/*initial entropy*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN +
Gilles Peskine449bd832023-01-11 14:50:10 +0100219 /*nonce*/ MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN +
220 /*reseed*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN];
Gilles Peskine69971662019-10-23 19:39:36 +0200221 mbedtls_ctr_drbg_context ctx;
222 size_t last_idx;
223 size_t byte_strength = expected_bit_strength / 8;
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300224
Gilles Peskine449bd832023-01-11 14:50:10 +0100225 mbedtls_ctr_drbg_init(&ctx);
Valerio Settidc32ac22023-11-13 10:27:56 +0100226
227 AES_PSA_INIT();
Gilles Peskine69971662019-10-23 19:39:36 +0200228 test_offset_idx = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 test_max_idx = sizeof(entropy);
230 memset(entropy, 0, sizeof(entropy));
Gilles Peskine69971662019-10-23 19:39:36 +0200231
232 /* The initial seeding must grab at least byte_strength bytes of entropy
233 * for the entropy input and byte_strength/2 bytes for a nonce. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100234 TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx,
235 mbedtls_test_entropy_func, entropy,
236 NULL, 0) == 0);
237 TEST_ASSERT(test_offset_idx >= (byte_strength * 3 + 1) / 2);
Gilles Peskine69971662019-10-23 19:39:36 +0200238 last_idx = test_offset_idx;
239
240 /* A reseed must grab at least byte_strength bytes of entropy. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0) == 0);
242 TEST_ASSERT(test_offset_idx - last_idx >= byte_strength);
Gilles Peskine69971662019-10-23 19:39:36 +0200243
244exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100245 mbedtls_ctr_drbg_free(&ctx);
Valerio Settidc32ac22023-11-13 10:27:56 +0100246 AES_PSA_DONE();
Gilles Peskine69971662019-10-23 19:39:36 +0200247}
248/* END_CASE */
Nir Sonnenschein85fcb582018-08-29 23:38:57 +0300249
250/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100251void ctr_drbg_entropy_usage(int entropy_nonce_len)
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100252{
253 unsigned char out[16];
254 unsigned char add[16];
255 unsigned char entropy[1024];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 mbedtls_ctr_drbg_context ctx;
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100257 size_t i, reps = 10;
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200258 size_t expected_idx = 0;
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100259
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 mbedtls_ctr_drbg_init(&ctx);
Valerio Settidc32ac22023-11-13 10:27:56 +0100261
262 AES_PSA_INIT();
263
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100264 test_offset_idx = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100265 test_max_idx = sizeof(entropy);
266 memset(entropy, 0, sizeof(entropy));
267 memset(out, 0, sizeof(out));
268 memset(add, 0, sizeof(add));
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100269
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 if (entropy_nonce_len >= 0) {
271 TEST_ASSERT(mbedtls_ctr_drbg_set_nonce_len(&ctx, entropy_nonce_len) == 0);
272 }
Gilles Peskinec949de02019-10-22 19:14:26 +0200273
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800274 /* Set reseed interval before seed */
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 mbedtls_ctr_drbg_set_reseed_interval(&ctx, 2 * reps);
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800276
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100277 /* Init must use entropy */
Gilles Peskine449bd832023-01-11 14:50:10 +0100278 TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0) == 0);
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200279 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 if (entropy_nonce_len >= 0) {
Gilles Peskinec949de02019-10-22 19:14:26 +0200281 expected_idx += entropy_nonce_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 } else {
Gilles Peskine69971662019-10-23 19:39:36 +0200283 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 }
285 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100286
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800287 /* By default, PR is off, and reseed interval was set to
288 * 2 * reps so the next few calls should not use entropy */
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 for (i = 0; i < reps; i++) {
290 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out) - 4) == 0);
291 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx, out, sizeof(out) - 4,
292 add, sizeof(add)) == 0);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100293 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100295
296 /* While at it, make sure we didn't write past the requested length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100297 TEST_ASSERT(out[sizeof(out) - 4] == 0);
298 TEST_ASSERT(out[sizeof(out) - 3] == 0);
299 TEST_ASSERT(out[sizeof(out) - 2] == 0);
300 TEST_ASSERT(out[sizeof(out) - 1] == 0);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100301
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800302 /* There have been 2 * reps calls to random. The next call should reseed */
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200304 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100305 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100306
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800307 /* Set reseed interval after seed */
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 mbedtls_ctr_drbg_set_reseed_interval(&ctx, 4 * reps + 1);
Gavin Acquroff6aceb512020-03-01 17:06:11 -0800309
310 /* The next few calls should not reseed */
Gilles Peskine449bd832023-01-11 14:50:10 +0100311 for (i = 0; i < (2 * reps); i++) {
312 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
313 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx, out, sizeof(out),
314 add, sizeof(add)) == 0);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100315 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100316 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100317
Dave Rodgman6dd757a2023-02-02 12:40:50 +0000318 /* Call update with too much data (sizeof(entropy) > MAX(_SEED)_INPUT).
Gilles Peskined9199932018-09-11 16:41:54 +0200319 * Make sure it's detected as an error and doesn't cause memory
320 * corruption. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100321 TEST_ASSERT(mbedtls_ctr_drbg_update(
322 &ctx, entropy, sizeof(entropy)) != 0);
Manuel Pégourié-Gonnardf5f25b32014-11-27 14:04:56 +0100323
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100324 /* Now enable PR, so the next few calls should all reseed */
Gilles Peskine449bd832023-01-11 14:50:10 +0100325 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
326 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200327 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100329
330 /* Finally, check setting entropy_len */
Gilles Peskine449bd832023-01-11 14:50:10 +0100331 mbedtls_ctr_drbg_set_entropy_len(&ctx, 42);
332 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200333 expected_idx += 42;
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 TEST_EQUAL(test_offset_idx, expected_idx);
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100335
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 mbedtls_ctr_drbg_set_entropy_len(&ctx, 13);
337 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
Gilles Peskine58b56ce2019-10-22 19:10:01 +0200338 expected_idx += 13;
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 TEST_EQUAL(test_offset_idx, expected_idx);
Paul Bakkera317a982014-06-18 16:44:11 +0200340
Paul Bakkerbd51b262014-07-10 15:26:12 +0200341exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100342 mbedtls_ctr_drbg_free(&ctx);
Valerio Settidc32ac22023-11-13 10:27:56 +0100343 AES_PSA_DONE();
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100344}
345/* END_CASE */
346
Paul Elliott445af3c2023-12-11 18:05:32 +0000347/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD:!MBEDTLS_CTR_DRBG_USE_128_BIT_KEY:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
Paul Elliottbb0e48f2023-12-01 18:05:19 +0000348void ctr_drbg_threads(data_t *expected_result, int reseed, int arg_thread_count)
Janos Follatha16ee6b2023-10-04 19:05:26 +0100349{
Paul Elliottbb0e48f2023-12-01 18:05:19 +0000350 size_t thread_count = (size_t) arg_thread_count;
Paul Elliott3dce2322023-12-08 21:13:42 +0000351 mbedtls_test_thread_t *threads = NULL;
Janos Follatha16ee6b2023-10-04 19:05:26 +0100352
353 unsigned char out[16];
Paul Elliottbda25dd2023-11-21 17:07:40 +0000354 unsigned char *entropy = NULL;
355
Paul Elliottbb0e48f2023-12-01 18:05:19 +0000356 const size_t n_random_calls = thread_count * thread_random_reps + 1;
Paul Elliottbda25dd2023-11-21 17:07:40 +0000357
Paul Elliottbda577b2024-02-06 17:49:20 +0000358 /* This is a known-answer test, and although tests use a mock entropy
359 * function the input entropy length will still affect the output.
360 * We therefore need to pick a fixed entropy length, rather than using the
361 * default entropy length (MBEDTLS_CTR_DRBG_ENTROPY_LEN). We've chosen to
362 * use the default value of MBEDTLS_CTR_DRBG_ENTROPY_LEN for SHA-512,
363 * as this was the value used when the expected answers were calculated. */
Paul Elliott40f0ec22023-12-11 17:40:54 +0000364 const size_t entropy_len = 48;
365
Janos Follatha16ee6b2023-10-04 19:05:26 +0100366 mbedtls_ctr_drbg_context ctx;
367 mbedtls_ctr_drbg_init(&ctx);
368
Paul Elliott31e7c1f2024-10-25 12:27:36 +0100369 AES_PSA_INIT();
370
Paul Elliott29fe76b2024-10-24 14:27:26 +0100371 TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count);
372 memset(out, 0, sizeof(out));
373
Paul Elliottbda25dd2023-11-21 17:07:40 +0000374 test_offset_idx = 0;
Janos Follatha16ee6b2023-10-04 19:05:26 +0100375
Paul Elliottbda577b2024-02-06 17:49:20 +0000376 /* Need to set a non-default fixed entropy len, to ensure same output across
377 * all configs - see above for details. */
Paul Elliott40f0ec22023-12-11 17:40:54 +0000378 mbedtls_ctr_drbg_set_entropy_len(&ctx, entropy_len);
379
Paul Elliottbda25dd2023-11-21 17:07:40 +0000380 if (reseed == 0) {
381 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_OFF);
382 mbedtls_ctr_drbg_set_reseed_interval(&ctx, n_random_calls + 1);
383
Paul Elliott40f0ec22023-12-11 17:40:54 +0000384 TEST_CALLOC(entropy, entropy_len + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN);
385 test_max_idx = entropy_len + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
Paul Elliottbda25dd2023-11-21 17:07:40 +0000386 } else {
Paul Elliott40f0ec22023-12-11 17:40:54 +0000387 const size_t entropy_size = ((n_random_calls + 1) * entropy_len)
Paul Elliottfed410f2023-11-30 20:40:55 +0000388 + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
Paul Elliottbda25dd2023-11-21 17:07:40 +0000389
390 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
391
392 TEST_CALLOC(entropy, entropy_size);
393 test_max_idx = entropy_size;
394 }
Janos Follatha16ee6b2023-10-04 19:05:26 +0100395
396 TEST_EQUAL(
397 mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0),
398 0);
399
Paul Elliottbb0e48f2023-12-01 18:05:19 +0000400 for (size_t i = 0; i < thread_count; i++) {
Janos Follatha16ee6b2023-10-04 19:05:26 +0100401 TEST_EQUAL(
Paul Elliott3dce2322023-12-08 21:13:42 +0000402 mbedtls_test_thread_create(&threads[i],
403 thread_random_function, (void *) &ctx),
Janos Follatha16ee6b2023-10-04 19:05:26 +0100404 0);
405 }
406
Paul Elliottbb0e48f2023-12-01 18:05:19 +0000407 for (size_t i = 0; i < thread_count; i++) {
Paul Elliott3dce2322023-12-08 21:13:42 +0000408 TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
Janos Follatha16ee6b2023-10-04 19:05:26 +0100409 }
410
411 /* Take a last output for comparing and thus verifying the DRBG state */
412 TEST_EQUAL(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)), 0);
413
414 TEST_MEMORY_COMPARE(out, sizeof(out), expected_result->x, expected_result->len);
415
416exit:
417 mbedtls_ctr_drbg_free(&ctx);
Paul Elliottbda25dd2023-11-21 17:07:40 +0000418 mbedtls_free(entropy);
Paul Elliottbb0e48f2023-12-01 18:05:19 +0000419 mbedtls_free(threads);
Paul Elliott22dbaf02023-12-18 18:18:04 +0000420
421 AES_PSA_DONE();
Janos Follatha16ee6b2023-10-04 19:05:26 +0100422}
Janos Follatha16ee6b2023-10-04 19:05:26 +0100423/* END_CASE */
424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
Gilles Peskine449bd832023-01-11 14:50:10 +0100426void ctr_drbg_seed_file(char *path, int ret)
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100427{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 mbedtls_ctr_drbg_context ctx;
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100429
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 mbedtls_ctr_drbg_init(&ctx);
Manuel Pégourié-Gonnard8d128ef2015-04-28 22:38:08 +0200431
Valerio Settidc32ac22023-11-13 10:27:56 +0100432 AES_PSA_INIT();
433
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_rnd_std_rand,
435 NULL, NULL, 0) == 0);
436 TEST_ASSERT(mbedtls_ctr_drbg_write_seed_file(&ctx, path) == ret);
437 TEST_ASSERT(mbedtls_ctr_drbg_update_seed_file(&ctx, path) == ret);
Paul Bakkera317a982014-06-18 16:44:11 +0200438
Paul Bakkerbd51b262014-07-10 15:26:12 +0200439exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 mbedtls_ctr_drbg_free(&ctx);
Valerio Settidc32ac22023-11-13 10:27:56 +0100441 AES_PSA_DONE();
Manuel Pégourié-Gonnard7575daa2014-01-31 12:16:54 +0100442}
443/* END_CASE */
444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
Gilles Peskine449bd832023-01-11 14:50:10 +0100446void ctr_drbg_selftest()
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100447{
Valerio Settidc32ac22023-11-13 10:27:56 +0100448 AES_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 TEST_ASSERT(mbedtls_ctr_drbg_self_test(1) == 0);
Valerio Settidc32ac22023-11-13 10:27:56 +0100450 AES_PSA_DONE();
Manuel Pégourié-Gonnardb3b205e2014-01-31 12:04:06 +0100451}
452/* END_CASE */
Dave Rodgmanae730342024-01-13 17:31:13 +0000453
454/* BEGIN_CASE */
455void ctr_increment_rollover()
456{
457 uint8_t c[16];
458 uint8_t r[16];
459
460 // test all increments from 2^n - 1 to 2^n (i.e. where we roll over into the next bit)
461 for (int n = 0; n <= 128; n++) {
462 memset(c, 0, 16);
463 memset(r, 0, 16);
464
465 // set least significant (highest address) n bits to 1, i.e. generate (2^n - 1)
466 for (int i = 0; i < n; i++) {
467 int bit = i % 8;
468 int byte = (i / 8);
469 c[15 - byte] |= 1 << bit;
470 }
471 // increment to get 2^n
472 mbedtls_ctr_increment_counter(c);
473
474 // now generate a reference result equal to 2^n - i.e. set only bit (n + 1)
475 // if n == 127, this will not set any bits (i.e. wraps to 0).
476 int bit = n % 8;
477 int byte = n / 8;
478 if (byte < 16) {
479 r[15 - byte] = 1 << bit;
480 }
481
482 TEST_MEMORY_COMPARE(c, 16, r, 16);
483 }
484
485 uint64_t lsb = 10, msb = 20;
486 MBEDTLS_PUT_UINT64_BE(msb, c, 0);
487 MBEDTLS_PUT_UINT64_BE(lsb, c, 8);
488 memcpy(r, c, 16);
489 mbedtls_ctr_increment_counter(c);
490 for (int i = 15; i >= 0; i--) {
491 r[i] += 1;
492 if (r[i] != 0) {
493 break;
494 }
495 }
496 TEST_MEMORY_COMPARE(c, 16, r, 16);
497}
498/* END_CASE */
499
500/* BEGIN_CASE */
501void ctr_increment(data_t *x)
502{
503 uint8_t c[16];
504 uint8_t r[16];
505
506 // initialise c and r from test argument
507 memset(c, 0, 16);
508 memcpy(c, x->x, x->len);
509 memcpy(r, c, 16);
510
511 // increment c
512 mbedtls_ctr_increment_counter(c);
513 // increment reference
514 for (int i = 15; i >= 0; i--) {
515 r[i] += 1;
516 if (r[i] != 0) {
517 break;
518 }
519 }
520
521 // test that mbedtls_ctr_increment_counter behaviour matches reference
522 TEST_MEMORY_COMPARE(c, 16, r, 16);
523}
524/* END_CASE */