1/* BEGIN_HEADER */ 2#include "mbedtls/entropy.h" 3#include "mbedtls/ctr_drbg.h" 4#include "string.h" 5#include "ctr.h" 6 7#if defined(MBEDTLS_THREADING_PTHREAD) 8#include "mbedtls/threading.h" 9#endif 10 11/* Modes for ctr_drbg_validate */ 12enum reseed_mode { 13 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 19static size_t test_offset_idx = 0; 20static size_t test_max_idx = 0; 21static int mbedtls_test_entropy_func(void *data, unsigned char *buf, size_t len) 22{ 23 const unsigned char *p = (unsigned char *) data; 24 if (test_offset_idx + len > test_max_idx) { 25 return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; 26 } 27 memcpy(buf, p + test_offset_idx, len); 28 test_offset_idx += len; 29 return 0; 30} 31 32static 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) 37{ 38 mbedtls_ctr_drbg_context ctx; 39 mbedtls_ctr_drbg_init(&ctx); 40 unsigned char buf[64]; 41 42 size_t entropy_chunk_len = (size_t) entropy_len_arg; 43 TEST_ASSERT(entropy_chunk_len <= sizeof(buf)); 44 45 test_offset_idx = 0; 46 test_max_idx = entropy->len; 47 48 /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>) 49 * where nonce||perso = nonce[nonce->len] */ 50 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) { 57 mbedtls_ctr_drbg_set_prediction_resistance( 58 &ctx, 59 MBEDTLS_CTR_DRBG_PR_ON); 60 } 61 62 if (reseed_mode == RESEED_FIRST) { 63 /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len], 64 * reseed[:reseed->len]) */ 65 TEST_ASSERT(mbedtls_ctr_drbg_reseed( 66 &ctx, 67 reseed->x, reseed->len) == 0); 68 } 69 70 /* CTR_DRBG_Generate(result->len * 8 bits, add1[:add1->len]) -> buf */ 71 /* Then reseed if prediction resistance is enabled. */ 72 TEST_ASSERT(mbedtls_ctr_drbg_random_with_add( 73 &ctx, 74 buf, result->len, 75 add1->x, add1->len) == 0); 76 77 78 if (reseed_mode == RESEED_SECOND) { 79 /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len], 80 * reseed[:reseed->len]) */ 81 TEST_ASSERT(mbedtls_ctr_drbg_reseed( 82 &ctx, 83 reseed->x, reseed->len) == 0); 84 } 85 86 /* CTR_DRBG_Generate(result->len * 8 bits, add2->x[:add2->len]) -> buf */ 87 /* Then reseed if prediction resistance is enabled. */ 88 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); 93 94exit: 95 mbedtls_ctr_drbg_free(&ctx); 96} 97 98static const int thread_random_reps = 10; 99void *thread_random_function(void *ctx); /* only used conditionally in ctr_drbg_threads */ 100void *thread_random_function(void *ctx) 101{ 102 unsigned char out[16]; 103 memset(out, 0, sizeof(out)); 104 105 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); 107 } 108 109exit: 110 return NULL; 111} 112/* END_HEADER */ 113 114/* BEGIN_DEPENDENCIES 115 * depends_on:MBEDTLS_CTR_DRBG_C 116 * END_DEPENDENCIES 117 */ 118 119/* BEGIN_CASE */ 120void ctr_drbg_special_behaviours() 121{ 122 mbedtls_ctr_drbg_context ctx; 123 unsigned char output[512]; 124 unsigned char additional[512]; 125 126 mbedtls_ctr_drbg_init(&ctx); 127 memset(output, 0, sizeof(output)); 128 memset(additional, 0, sizeof(additional)); 129 130 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); 138 139 TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, additional, 140 MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 1) == 141 MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG); 142 143 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); 147exit: 148 mbedtls_ctr_drbg_free(&ctx); 149} 150/* END_CASE */ 151 152 153/* BEGIN_CASE */ 154void ctr_drbg_validate_no_reseed(data_t *add_init, data_t *entropy, 155 data_t *add1, data_t *add2, 156 data_t *result_string) 157{ 158 data_t empty = { 0, 0 }; 159 AES_PSA_INIT(); 160 ctr_drbg_validate_internal(RESEED_NEVER, add_init, 161 entropy->len, entropy, 162 &empty, add1, add2, 163 result_string); 164 AES_PSA_DONE(); 165 goto exit; // goto is needed to avoid warning ( no test assertions in func) 166} 167/* END_CASE */ 168 169/* BEGIN_CASE */ 170void ctr_drbg_validate_pr(data_t *add_init, data_t *entropy, 171 data_t *add1, data_t *add2, 172 data_t *result_string) 173{ 174 data_t empty = { 0, 0 }; 175 AES_PSA_INIT(); 176 ctr_drbg_validate_internal(RESEED_ALWAYS, add_init, 177 entropy->len / 3, entropy, 178 &empty, add1, add2, 179 result_string); 180 AES_PSA_DONE(); 181 goto exit; // goto is needed to avoid warning ( no test assertions in func) 182} 183/* END_CASE */ 184 185/* BEGIN_CASE */ 186void 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) 189{ 190 AES_PSA_INIT(); 191 ctr_drbg_validate_internal(RESEED_SECOND, add_init, 192 entropy->len / 2, entropy, 193 add_reseed, add1, add2, 194 result_string); 195 AES_PSA_DONE(); 196 goto exit; // goto is needed to avoid warning ( no test assertions in func) 197} 198/* END_CASE */ 199 200/* BEGIN_CASE */ 201void 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) 204{ 205 AES_PSA_INIT(); 206 ctr_drbg_validate_internal(RESEED_FIRST, add_init, 207 entropy->len / 2, entropy, 208 add_reseed, add1, add2, 209 result_string); 210 AES_PSA_DONE(); 211 goto exit; // goto is needed to avoid warning ( no test assertions in func) 212} 213/* END_CASE */ 214 215/* BEGIN_CASE */ 216void ctr_drbg_entropy_strength(int expected_bit_strength) 217{ 218 unsigned char entropy[/*initial entropy*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN + 219 /*nonce*/ MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN + 220 /*reseed*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN]; 221 mbedtls_ctr_drbg_context ctx; 222 size_t last_idx; 223 size_t byte_strength = expected_bit_strength / 8; 224 225 mbedtls_ctr_drbg_init(&ctx); 226 227 AES_PSA_INIT(); 228 test_offset_idx = 0; 229 test_max_idx = sizeof(entropy); 230 memset(entropy, 0, sizeof(entropy)); 231 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. */ 234 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); 238 last_idx = test_offset_idx; 239 240 /* A reseed must grab at least byte_strength bytes of entropy. */ 241 TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0) == 0); 242 TEST_ASSERT(test_offset_idx - last_idx >= byte_strength); 243 244exit: 245 mbedtls_ctr_drbg_free(&ctx); 246 AES_PSA_DONE(); 247} 248/* END_CASE */ 249 250/* BEGIN_CASE */ 251void ctr_drbg_entropy_usage(int entropy_nonce_len) 252{ 253 unsigned char out[16]; 254 unsigned char add[16]; 255 unsigned char entropy[1024]; 256 mbedtls_ctr_drbg_context ctx; 257 size_t i, reps = 10; 258 size_t expected_idx = 0; 259 260 mbedtls_ctr_drbg_init(&ctx); 261 262 AES_PSA_INIT(); 263 264 test_offset_idx = 0; 265 test_max_idx = sizeof(entropy); 266 memset(entropy, 0, sizeof(entropy)); 267 memset(out, 0, sizeof(out)); 268 memset(add, 0, sizeof(add)); 269 270 if (entropy_nonce_len >= 0) { 271 TEST_ASSERT(mbedtls_ctr_drbg_set_nonce_len(&ctx, entropy_nonce_len) == 0); 272 } 273 274 /* Set reseed interval before seed */ 275 mbedtls_ctr_drbg_set_reseed_interval(&ctx, 2 * reps); 276 277 /* Init must use entropy */ 278 TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0) == 0); 279 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN; 280 if (entropy_nonce_len >= 0) { 281 expected_idx += entropy_nonce_len; 282 } else { 283 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN; 284 } 285 TEST_EQUAL(test_offset_idx, expected_idx); 286 287 /* By default, PR is off, and reseed interval was set to 288 * 2 * reps so the next few calls should not use entropy */ 289 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); 293 } 294 TEST_EQUAL(test_offset_idx, expected_idx); 295 296 /* While at it, make sure we didn't write past the requested length */ 297 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); 301 302 /* There have been 2 * reps calls to random. The next call should reseed */ 303 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0); 304 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN; 305 TEST_EQUAL(test_offset_idx, expected_idx); 306 307 /* Set reseed interval after seed */ 308 mbedtls_ctr_drbg_set_reseed_interval(&ctx, 4 * reps + 1); 309 310 /* The next few calls should not reseed */ 311 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); 315 } 316 TEST_EQUAL(test_offset_idx, expected_idx); 317 318 /* Call update with too much data (sizeof(entropy) > MAX(_SEED)_INPUT). 319 * Make sure it's detected as an error and doesn't cause memory 320 * corruption. */ 321 TEST_ASSERT(mbedtls_ctr_drbg_update( 322 &ctx, entropy, sizeof(entropy)) != 0); 323 324 /* Now enable PR, so the next few calls should all reseed */ 325 mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON); 326 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0); 327 expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN; 328 TEST_EQUAL(test_offset_idx, expected_idx); 329 330 /* Finally, check setting entropy_len */ 331 mbedtls_ctr_drbg_set_entropy_len(&ctx, 42); 332 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0); 333 expected_idx += 42; 334 TEST_EQUAL(test_offset_idx, expected_idx); 335 336 mbedtls_ctr_drbg_set_entropy_len(&ctx, 13); 337 TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0); 338 expected_idx += 13; 339 TEST_EQUAL(test_offset_idx, expected_idx); 340 341exit: 342 mbedtls_ctr_drbg_free(&ctx); 343 AES_PSA_DONE(); 344} 345/* END_CASE */ 346 347/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD:!MBEDTLS_CTR_DRBG_USE_128_BIT_KEY:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ 348void ctr_drbg_threads(data_t *expected_result, int reseed, int arg_thread_count) 349{ 350 size_t thread_count = (size_t) arg_thread_count; 351 mbedtls_test_thread_t *threads = NULL; 352 353 unsigned char out[16]; 354 unsigned char *entropy = NULL; 355 356 const size_t n_random_calls = thread_count * thread_random_reps + 1; 357 358 /* 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. */ 364 const size_t entropy_len = 48; 365 366 AES_PSA_INIT(); 367 368 TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count); 369 memset(out, 0, sizeof(out)); 370 371 mbedtls_ctr_drbg_context ctx; 372 mbedtls_ctr_drbg_init(&ctx); 373 374 test_offset_idx = 0; 375 376 /* Need to set a non-default fixed entropy len, to ensure same output across 377 * all configs - see above for details. */ 378 mbedtls_ctr_drbg_set_entropy_len(&ctx, entropy_len); 379 380 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 384 TEST_CALLOC(entropy, entropy_len + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN); 385 test_max_idx = entropy_len + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN; 386 } else { 387 const size_t entropy_size = ((n_random_calls + 1) * entropy_len) 388 + MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN; 389 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 } 395 396 TEST_EQUAL( 397 mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0), 398 0); 399 400 for (size_t i = 0; i < thread_count; i++) { 401 TEST_EQUAL( 402 mbedtls_test_thread_create(&threads[i], 403 thread_random_function, (void *) &ctx), 404 0); 405 } 406 407 for (size_t i = 0; i < thread_count; i++) { 408 TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0); 409 } 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); 418 mbedtls_free(entropy); 419 mbedtls_free(threads); 420 421 AES_PSA_DONE(); 422} 423/* END_CASE */ 424 425/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */ 426void ctr_drbg_seed_file(char *path, int ret) 427{ 428 mbedtls_ctr_drbg_context ctx; 429 430 mbedtls_ctr_drbg_init(&ctx); 431 432 AES_PSA_INIT(); 433 434 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); 438 439exit: 440 mbedtls_ctr_drbg_free(&ctx); 441 AES_PSA_DONE(); 442} 443/* END_CASE */ 444 445/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ 446void ctr_drbg_selftest() 447{ 448 AES_PSA_INIT(); 449 TEST_ASSERT(mbedtls_ctr_drbg_self_test(1) == 0); 450 AES_PSA_DONE(); 451} 452/* END_CASE */ 453 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 */ 525