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