1a8e1175bSopenharmony_ci/* BEGIN_HEADER */ 2a8e1175bSopenharmony_ci/* Dedicated test suite for mbedtls_mpi_core_random() and the upper-layer 3a8e1175bSopenharmony_ci * functions. Due to the complexity of how these functions are tested, 4a8e1175bSopenharmony_ci * we test all the layers in a single test suite, unlike the way other 5a8e1175bSopenharmony_ci * functions are tested with each layer in its own test suite. 6a8e1175bSopenharmony_ci * 7a8e1175bSopenharmony_ci * Test strategy 8a8e1175bSopenharmony_ci * ============= 9a8e1175bSopenharmony_ci * 10a8e1175bSopenharmony_ci * There are three main goals for testing random() functions: 11a8e1175bSopenharmony_ci * - Parameter validation. 12a8e1175bSopenharmony_ci * - Correctness of outputs (well-formed, in range). 13a8e1175bSopenharmony_ci * - Distribution of outputs. 14a8e1175bSopenharmony_ci * 15a8e1175bSopenharmony_ci * We test parameter validation in a standard way, with unit tests with 16a8e1175bSopenharmony_ci * positive and negative cases: 17a8e1175bSopenharmony_ci * - mbedtls_mpi_core_random(): negative cases for mpi_core_random_basic. 18a8e1175bSopenharmony_ci * - mbedtls_mpi_mod_raw_random(), mbedtls_mpi_mod_random(): negative 19a8e1175bSopenharmony_ci * cases for mpi_mod_random_validation. 20a8e1175bSopenharmony_ci * - mbedtls_mpi_random(): mpi_random_fail. 21a8e1175bSopenharmony_ci * 22a8e1175bSopenharmony_ci * We test the correctness of outputs in positive tests: 23a8e1175bSopenharmony_ci * - mbedtls_mpi_core_random(): positive cases for mpi_core_random_basic, 24a8e1175bSopenharmony_ci * and mpi_random_many. 25a8e1175bSopenharmony_ci * - mbedtls_mpi_mod_raw_random(), mbedtls_mpi_mod_random(): tested indirectly 26a8e1175bSopenharmony_ci * via mpi_mod_random_values. 27a8e1175bSopenharmony_ci * - mbedtls_mpi_random(): mpi_random_sizes, plus indirectly via 28a8e1175bSopenharmony_ci * mpi_random_values. 29a8e1175bSopenharmony_ci * 30a8e1175bSopenharmony_ci * We test the distribution of outputs only for mbedtls_mpi_core_random(), 31a8e1175bSopenharmony_ci * in mpi_random_many, which runs the function multiple times. This also 32a8e1175bSopenharmony_ci * helps in validating the output range, through test cases with a small 33a8e1175bSopenharmony_ci * range where any output out of range would be very likely to lead to a 34a8e1175bSopenharmony_ci * test failure. For the other functions, we validate the distribution 35a8e1175bSopenharmony_ci * indirectly by testing that these functions consume the random generator 36a8e1175bSopenharmony_ci * in the same way as mbedtls_mpi_core_random(). This is done in 37a8e1175bSopenharmony_ci * mpi_mod_random_values and mpi_legacy_random_values. 38a8e1175bSopenharmony_ci */ 39a8e1175bSopenharmony_ci 40a8e1175bSopenharmony_ci#include "mbedtls/bignum.h" 41a8e1175bSopenharmony_ci#include "mbedtls/entropy.h" 42a8e1175bSopenharmony_ci#include "bignum_core.h" 43a8e1175bSopenharmony_ci#include "bignum_mod_raw.h" 44a8e1175bSopenharmony_ci#include "constant_time_internal.h" 45a8e1175bSopenharmony_ci 46a8e1175bSopenharmony_ci/* This test suite only manipulates non-negative bignums. */ 47a8e1175bSopenharmony_cistatic int sign_is_valid(const mbedtls_mpi *X) 48a8e1175bSopenharmony_ci{ 49a8e1175bSopenharmony_ci return X->s == 1; 50a8e1175bSopenharmony_ci} 51a8e1175bSopenharmony_ci 52a8e1175bSopenharmony_ci/* A common initializer for test functions that should generate the same 53a8e1175bSopenharmony_ci * sequences for reproducibility and good coverage. */ 54a8e1175bSopenharmony_ciconst mbedtls_test_rnd_pseudo_info rnd_pseudo_seed = { 55a8e1175bSopenharmony_ci /* 16-word key */ 56a8e1175bSopenharmony_ci { 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 57a8e1175bSopenharmony_ci 'a', ' ', 's', 'e', 'e', 'd', '!', 0 }, 58a8e1175bSopenharmony_ci /* 2-word initial state, should be zero */ 59a8e1175bSopenharmony_ci 0, 0 60a8e1175bSopenharmony_ci}; 61a8e1175bSopenharmony_ci 62a8e1175bSopenharmony_ci/* Test whether bytes represents (in big-endian base 256) a number b that 63a8e1175bSopenharmony_ci * is significantly above a power of 2. That is, b must not have a long run 64a8e1175bSopenharmony_ci * of unset bits after the most significant bit. 65a8e1175bSopenharmony_ci * 66a8e1175bSopenharmony_ci * Let n be the bit-size of b, i.e. the integer such that 2^n <= b < 2^{n+1}. 67a8e1175bSopenharmony_ci * This function returns 1 if, when drawing a number between 0 and b, 68a8e1175bSopenharmony_ci * the probability that this number is at least 2^n is not negligible. 69a8e1175bSopenharmony_ci * This probability is (b - 2^n) / b and this function checks that this 70a8e1175bSopenharmony_ci * number is above some threshold A. The threshold value is heuristic and 71a8e1175bSopenharmony_ci * based on the needs of mpi_random_many(). 72a8e1175bSopenharmony_ci */ 73a8e1175bSopenharmony_cistatic int is_significantly_above_a_power_of_2(data_t *bytes) 74a8e1175bSopenharmony_ci{ 75a8e1175bSopenharmony_ci const uint8_t *p = bytes->x; 76a8e1175bSopenharmony_ci size_t len = bytes->len; 77a8e1175bSopenharmony_ci unsigned x; 78a8e1175bSopenharmony_ci 79a8e1175bSopenharmony_ci /* Skip leading null bytes */ 80a8e1175bSopenharmony_ci while (len > 0 && p[0] == 0) { 81a8e1175bSopenharmony_ci ++p; 82a8e1175bSopenharmony_ci --len; 83a8e1175bSopenharmony_ci } 84a8e1175bSopenharmony_ci /* 0 is not significantly above a power of 2 */ 85a8e1175bSopenharmony_ci if (len == 0) { 86a8e1175bSopenharmony_ci return 0; 87a8e1175bSopenharmony_ci } 88a8e1175bSopenharmony_ci /* Extract the (up to) 2 most significant bytes */ 89a8e1175bSopenharmony_ci if (len == 1) { 90a8e1175bSopenharmony_ci x = p[0]; 91a8e1175bSopenharmony_ci } else { 92a8e1175bSopenharmony_ci x = (p[0] << 8) | p[1]; 93a8e1175bSopenharmony_ci } 94a8e1175bSopenharmony_ci 95a8e1175bSopenharmony_ci /* Shift the most significant bit of x to position 8 and mask it out */ 96a8e1175bSopenharmony_ci while ((x & 0xfe00) != 0) { 97a8e1175bSopenharmony_ci x >>= 1; 98a8e1175bSopenharmony_ci } 99a8e1175bSopenharmony_ci x &= 0x00ff; 100a8e1175bSopenharmony_ci 101a8e1175bSopenharmony_ci /* At this point, x = floor((b - 2^n) / 2^(n-8)). b is significantly above 102a8e1175bSopenharmony_ci * a power of 2 iff x is significantly above 0 compared to 2^8. 103a8e1175bSopenharmony_ci * Testing x >= 2^4 amounts to picking A = 1/16 in the function 104a8e1175bSopenharmony_ci * description above. */ 105a8e1175bSopenharmony_ci return x >= 0x10; 106a8e1175bSopenharmony_ci} 107a8e1175bSopenharmony_ci 108a8e1175bSopenharmony_ci/* END_HEADER */ 109a8e1175bSopenharmony_ci 110a8e1175bSopenharmony_ci/* BEGIN_DEPENDENCIES 111a8e1175bSopenharmony_ci * depends_on:MBEDTLS_BIGNUM_C 112a8e1175bSopenharmony_ci * END_DEPENDENCIES 113a8e1175bSopenharmony_ci */ 114a8e1175bSopenharmony_ci 115a8e1175bSopenharmony_ci/* BEGIN_CASE */ 116a8e1175bSopenharmony_civoid mpi_core_random_basic(int min, char *bound_bytes, int expected_ret) 117a8e1175bSopenharmony_ci{ 118a8e1175bSopenharmony_ci /* Same RNG as in mpi_random_values */ 119a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_info rnd = rnd_pseudo_seed; 120a8e1175bSopenharmony_ci size_t limbs; 121a8e1175bSopenharmony_ci mbedtls_mpi_uint *lower_bound = NULL; 122a8e1175bSopenharmony_ci mbedtls_mpi_uint *upper_bound = NULL; 123a8e1175bSopenharmony_ci mbedtls_mpi_uint *result = NULL; 124a8e1175bSopenharmony_ci 125a8e1175bSopenharmony_ci TEST_EQUAL(0, mbedtls_test_read_mpi_core(&upper_bound, &limbs, 126a8e1175bSopenharmony_ci bound_bytes)); 127a8e1175bSopenharmony_ci TEST_CALLOC(lower_bound, limbs); 128a8e1175bSopenharmony_ci lower_bound[0] = min; 129a8e1175bSopenharmony_ci TEST_CALLOC(result, limbs); 130a8e1175bSopenharmony_ci 131a8e1175bSopenharmony_ci TEST_EQUAL(expected_ret, 132a8e1175bSopenharmony_ci mbedtls_mpi_core_random(result, min, upper_bound, limbs, 133a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_rand, &rnd)); 134a8e1175bSopenharmony_ci 135a8e1175bSopenharmony_ci if (expected_ret == 0) { 136a8e1175bSopenharmony_ci TEST_EQUAL(0, mbedtls_mpi_core_lt_ct(result, lower_bound, limbs)); 137a8e1175bSopenharmony_ci TEST_ASSERT(0 != mbedtls_mpi_core_lt_ct(result, upper_bound, limbs)); 138a8e1175bSopenharmony_ci } 139a8e1175bSopenharmony_ci 140a8e1175bSopenharmony_ciexit: 141a8e1175bSopenharmony_ci mbedtls_free(lower_bound); 142a8e1175bSopenharmony_ci mbedtls_free(upper_bound); 143a8e1175bSopenharmony_ci mbedtls_free(result); 144a8e1175bSopenharmony_ci} 145a8e1175bSopenharmony_ci/* END_CASE */ 146a8e1175bSopenharmony_ci 147a8e1175bSopenharmony_ci/* BEGIN_CASE */ 148a8e1175bSopenharmony_civoid mpi_legacy_random_values(int min, char *max_hex) 149a8e1175bSopenharmony_ci{ 150a8e1175bSopenharmony_ci /* Same RNG as in mpi_core_random_basic */ 151a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_info rnd_core = rnd_pseudo_seed; 152a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_info rnd_legacy; 153a8e1175bSopenharmony_ci memcpy(&rnd_legacy, &rnd_core, sizeof(rnd_core)); 154a8e1175bSopenharmony_ci mbedtls_mpi max_legacy; 155a8e1175bSopenharmony_ci mbedtls_mpi_init(&max_legacy); 156a8e1175bSopenharmony_ci mbedtls_mpi_uint *R_core = NULL; 157a8e1175bSopenharmony_ci mbedtls_mpi R_legacy; 158a8e1175bSopenharmony_ci mbedtls_mpi_init(&R_legacy); 159a8e1175bSopenharmony_ci 160a8e1175bSopenharmony_ci TEST_EQUAL(0, mbedtls_test_read_mpi(&max_legacy, max_hex)); 161a8e1175bSopenharmony_ci size_t limbs = max_legacy.n; 162a8e1175bSopenharmony_ci TEST_CALLOC(R_core, limbs); 163a8e1175bSopenharmony_ci 164a8e1175bSopenharmony_ci /* Call the legacy function and the core function with the same random 165a8e1175bSopenharmony_ci * stream. */ 166a8e1175bSopenharmony_ci int core_ret = mbedtls_mpi_core_random(R_core, min, max_legacy.p, limbs, 167a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_rand, 168a8e1175bSopenharmony_ci &rnd_core); 169a8e1175bSopenharmony_ci int legacy_ret = mbedtls_mpi_random(&R_legacy, min, &max_legacy, 170a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_rand, 171a8e1175bSopenharmony_ci &rnd_legacy); 172a8e1175bSopenharmony_ci 173a8e1175bSopenharmony_ci /* They must return the same status, and, on success, output the 174a8e1175bSopenharmony_ci * same number, with the same limb count. */ 175a8e1175bSopenharmony_ci TEST_EQUAL(core_ret, legacy_ret); 176a8e1175bSopenharmony_ci if (core_ret == 0) { 177a8e1175bSopenharmony_ci TEST_MEMORY_COMPARE(R_core, limbs * ciL, 178a8e1175bSopenharmony_ci R_legacy.p, R_legacy.n * ciL); 179a8e1175bSopenharmony_ci } 180a8e1175bSopenharmony_ci 181a8e1175bSopenharmony_ci /* Also check that they have consumed the RNG in the same way. */ 182a8e1175bSopenharmony_ci /* This may theoretically fail on rare platforms with padding in 183a8e1175bSopenharmony_ci * the structure! If this is a problem in practice, change to a 184a8e1175bSopenharmony_ci * field-by-field comparison. */ 185a8e1175bSopenharmony_ci TEST_MEMORY_COMPARE(&rnd_core, sizeof(rnd_core), 186a8e1175bSopenharmony_ci &rnd_legacy, sizeof(rnd_legacy)); 187a8e1175bSopenharmony_ci 188a8e1175bSopenharmony_ciexit: 189a8e1175bSopenharmony_ci mbedtls_mpi_free(&max_legacy); 190a8e1175bSopenharmony_ci mbedtls_free(R_core); 191a8e1175bSopenharmony_ci mbedtls_mpi_free(&R_legacy); 192a8e1175bSopenharmony_ci} 193a8e1175bSopenharmony_ci/* END_CASE */ 194a8e1175bSopenharmony_ci 195a8e1175bSopenharmony_ci/* BEGIN_CASE depends_on:MBEDTLS_ECP_WITH_MPI_UINT */ 196a8e1175bSopenharmony_civoid mpi_mod_random_values(int min, char *max_hex, int rep) 197a8e1175bSopenharmony_ci{ 198a8e1175bSopenharmony_ci /* Same RNG as in mpi_core_random_basic */ 199a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_info rnd_core = rnd_pseudo_seed; 200a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_info rnd_mod_raw; 201a8e1175bSopenharmony_ci memcpy(&rnd_mod_raw, &rnd_core, sizeof(rnd_core)); 202a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_info rnd_mod; 203a8e1175bSopenharmony_ci memcpy(&rnd_mod, &rnd_core, sizeof(rnd_core)); 204a8e1175bSopenharmony_ci mbedtls_mpi_uint *R_core = NULL; 205a8e1175bSopenharmony_ci mbedtls_mpi_uint *R_mod_raw = NULL; 206a8e1175bSopenharmony_ci mbedtls_mpi_uint *R_mod_digits = NULL; 207a8e1175bSopenharmony_ci mbedtls_mpi_mod_residue R_mod; 208a8e1175bSopenharmony_ci mbedtls_mpi_mod_modulus N; 209a8e1175bSopenharmony_ci mbedtls_mpi_mod_modulus_init(&N); 210a8e1175bSopenharmony_ci 211a8e1175bSopenharmony_ci TEST_EQUAL(mbedtls_test_read_mpi_modulus(&N, max_hex, rep), 0); 212a8e1175bSopenharmony_ci TEST_CALLOC(R_core, N.limbs); 213a8e1175bSopenharmony_ci TEST_CALLOC(R_mod_raw, N.limbs); 214a8e1175bSopenharmony_ci TEST_CALLOC(R_mod_digits, N.limbs); 215a8e1175bSopenharmony_ci TEST_EQUAL(mbedtls_mpi_mod_residue_setup(&R_mod, &N, 216a8e1175bSopenharmony_ci R_mod_digits, N.limbs), 217a8e1175bSopenharmony_ci 0); 218a8e1175bSopenharmony_ci 219a8e1175bSopenharmony_ci /* Call the core and mod random() functions with the same random stream. */ 220a8e1175bSopenharmony_ci int core_ret = mbedtls_mpi_core_random(R_core, 221a8e1175bSopenharmony_ci min, N.p, N.limbs, 222a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_rand, 223a8e1175bSopenharmony_ci &rnd_core); 224a8e1175bSopenharmony_ci int mod_raw_ret = mbedtls_mpi_mod_raw_random(R_mod_raw, 225a8e1175bSopenharmony_ci min, &N, 226a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_rand, 227a8e1175bSopenharmony_ci &rnd_mod_raw); 228a8e1175bSopenharmony_ci int mod_ret = mbedtls_mpi_mod_random(&R_mod, 229a8e1175bSopenharmony_ci min, &N, 230a8e1175bSopenharmony_ci mbedtls_test_rnd_pseudo_rand, 231a8e1175bSopenharmony_ci &rnd_mod); 232a8e1175bSopenharmony_ci 233a8e1175bSopenharmony_ci /* They must return the same status, and, on success, output the 234a8e1175bSopenharmony_ci * same number, with the same limb count. */ 235a8e1175bSopenharmony_ci TEST_EQUAL(core_ret, mod_raw_ret); 236a8e1175bSopenharmony_ci TEST_EQUAL(core_ret, mod_ret); 237a8e1175bSopenharmony_ci if (core_ret == 0) { 238a8e1175bSopenharmony_ci TEST_EQUAL(mbedtls_mpi_mod_raw_modulus_to_canonical_rep(R_mod_raw, &N), 239a8e1175bSopenharmony_ci 0); 240a8e1175bSopenharmony_ci TEST_MEMORY_COMPARE(R_core, N.limbs * ciL, 241a8e1175bSopenharmony_ci R_mod_raw, N.limbs * ciL); 242a8e1175bSopenharmony_ci TEST_EQUAL(mbedtls_mpi_mod_raw_modulus_to_canonical_rep(R_mod_digits, &N), 243a8e1175bSopenharmony_ci 0); 244a8e1175bSopenharmony_ci TEST_MEMORY_COMPARE(R_core, N.limbs * ciL, 245a8e1175bSopenharmony_ci R_mod_digits, N.limbs * ciL); 246a8e1175bSopenharmony_ci } 247a8e1175bSopenharmony_ci 248a8e1175bSopenharmony_ci /* Also check that they have consumed the RNG in the same way. */ 249a8e1175bSopenharmony_ci /* This may theoretically fail on rare platforms with padding in 250a8e1175bSopenharmony_ci * the structure! If this is a problem in practice, change to a 251a8e1175bSopenharmony_ci * field-by-field comparison. */ 252a8e1175bSopenharmony_ci TEST_MEMORY_COMPARE(&rnd_core, sizeof(rnd_core), 253a8e1175bSopenharmony_ci &rnd_mod_raw, sizeof(rnd_mod_raw)); 254a8e1175bSopenharmony_ci TEST_MEMORY_COMPARE(&rnd_core, sizeof(rnd_core), 255a8e1175bSopenharmony_ci &rnd_mod, sizeof(rnd_mod)); 256a8e1175bSopenharmony_ci 257a8e1175bSopenharmony_ciexit: 258a8e1175bSopenharmony_ci mbedtls_test_mpi_mod_modulus_free_with_limbs(&N); 259a8e1175bSopenharmony_ci mbedtls_free(R_core); 260a8e1175bSopenharmony_ci mbedtls_free(R_mod_raw); 261a8e1175bSopenharmony_ci mbedtls_free(R_mod_digits); 262a8e1175bSopenharmony_ci} 263a8e1175bSopenharmony_ci/* END_CASE */ 264a8e1175bSopenharmony_ci 265a8e1175bSopenharmony_ci/* BEGIN_CASE */ 266a8e1175bSopenharmony_civoid mpi_random_many(int min, char *bound_hex, int iterations) 267a8e1175bSopenharmony_ci{ 268a8e1175bSopenharmony_ci /* Generate numbers in the range 1..bound-1. Do it iterations times. 269a8e1175bSopenharmony_ci * This function assumes that the value of bound is at least 2 and 270a8e1175bSopenharmony_ci * that iterations is large enough that a one-in-2^iterations chance 271a8e1175bSopenharmony_ci * effectively never occurs. 272a8e1175bSopenharmony_ci */ 273a8e1175bSopenharmony_ci 274a8e1175bSopenharmony_ci data_t bound_bytes = { NULL, 0 }; 275a8e1175bSopenharmony_ci mbedtls_mpi_uint *upper_bound = NULL; 276a8e1175bSopenharmony_ci size_t limbs; 277a8e1175bSopenharmony_ci size_t n_bits; 278a8e1175bSopenharmony_ci mbedtls_mpi_uint *result = NULL; 279a8e1175bSopenharmony_ci size_t b; 280a8e1175bSopenharmony_ci /* If upper_bound is small, stats[b] is the number of times the value b 281a8e1175bSopenharmony_ci * has been generated. Otherwise stats[b] is the number of times a 282a8e1175bSopenharmony_ci * value with bit b set has been generated. */ 283a8e1175bSopenharmony_ci size_t *stats = NULL; 284a8e1175bSopenharmony_ci size_t stats_len; 285a8e1175bSopenharmony_ci int full_stats; 286a8e1175bSopenharmony_ci size_t i; 287a8e1175bSopenharmony_ci 288a8e1175bSopenharmony_ci TEST_EQUAL(0, mbedtls_test_read_mpi_core(&upper_bound, &limbs, 289a8e1175bSopenharmony_ci bound_hex)); 290a8e1175bSopenharmony_ci TEST_CALLOC(result, limbs); 291a8e1175bSopenharmony_ci 292a8e1175bSopenharmony_ci n_bits = mbedtls_mpi_core_bitlen(upper_bound, limbs); 293a8e1175bSopenharmony_ci /* Consider a bound "small" if it's less than 2^5. This value is chosen 294a8e1175bSopenharmony_ci * to be small enough that the probability of missing one value is 295a8e1175bSopenharmony_ci * negligible given the number of iterations. It must be less than 296a8e1175bSopenharmony_ci * 256 because some of the code below assumes that "small" values 297a8e1175bSopenharmony_ci * fit in a byte. */ 298a8e1175bSopenharmony_ci if (n_bits <= 5) { 299a8e1175bSopenharmony_ci full_stats = 1; 300a8e1175bSopenharmony_ci stats_len = (uint8_t) upper_bound[0]; 301a8e1175bSopenharmony_ci } else { 302a8e1175bSopenharmony_ci full_stats = 0; 303a8e1175bSopenharmony_ci stats_len = n_bits; 304a8e1175bSopenharmony_ci } 305a8e1175bSopenharmony_ci TEST_CALLOC(stats, stats_len); 306a8e1175bSopenharmony_ci 307a8e1175bSopenharmony_ci for (i = 0; i < (size_t) iterations; i++) { 308a8e1175bSopenharmony_ci mbedtls_test_set_step(i); 309a8e1175bSopenharmony_ci TEST_EQUAL(0, mbedtls_mpi_core_random(result, 310a8e1175bSopenharmony_ci min, upper_bound, limbs, 311a8e1175bSopenharmony_ci mbedtls_test_rnd_std_rand, NULL)); 312a8e1175bSopenharmony_ci 313a8e1175bSopenharmony_ci /* Temporarily use a legacy MPI for analysis, because the 314a8e1175bSopenharmony_ci * necessary auxiliary functions don't exist yet in core. */ 315a8e1175bSopenharmony_ci mbedtls_mpi B = { .s = 1, .n = limbs, .p = upper_bound }; 316a8e1175bSopenharmony_ci mbedtls_mpi R = { .s = 1, .n = limbs, .p = result }; 317a8e1175bSopenharmony_ci 318a8e1175bSopenharmony_ci TEST_ASSERT(mbedtls_mpi_cmp_mpi(&R, &B) < 0); 319a8e1175bSopenharmony_ci TEST_ASSERT(mbedtls_mpi_cmp_int(&R, min) >= 0); 320a8e1175bSopenharmony_ci if (full_stats) { 321a8e1175bSopenharmony_ci uint8_t value; 322a8e1175bSopenharmony_ci TEST_EQUAL(0, mbedtls_mpi_write_binary(&R, &value, 1)); 323a8e1175bSopenharmony_ci TEST_ASSERT(value < stats_len); 324a8e1175bSopenharmony_ci ++stats[value]; 325a8e1175bSopenharmony_ci } else { 326a8e1175bSopenharmony_ci for (b = 0; b < n_bits; b++) { 327a8e1175bSopenharmony_ci stats[b] += mbedtls_mpi_get_bit(&R, b); 328a8e1175bSopenharmony_ci } 329a8e1175bSopenharmony_ci } 330a8e1175bSopenharmony_ci } 331a8e1175bSopenharmony_ci 332a8e1175bSopenharmony_ci if (full_stats) { 333a8e1175bSopenharmony_ci for (b = min; b < stats_len; b++) { 334a8e1175bSopenharmony_ci mbedtls_test_set_step(1000000 + b); 335a8e1175bSopenharmony_ci /* Assert that each value has been reached at least once. 336a8e1175bSopenharmony_ci * This is almost guaranteed if the iteration count is large 337a8e1175bSopenharmony_ci * enough. This is a very crude way of checking the distribution. 338a8e1175bSopenharmony_ci */ 339a8e1175bSopenharmony_ci TEST_ASSERT(stats[b] > 0); 340a8e1175bSopenharmony_ci } 341a8e1175bSopenharmony_ci } else { 342a8e1175bSopenharmony_ci bound_bytes.len = limbs * sizeof(mbedtls_mpi_uint); 343a8e1175bSopenharmony_ci TEST_CALLOC(bound_bytes.x, bound_bytes.len); 344a8e1175bSopenharmony_ci mbedtls_mpi_core_write_be(upper_bound, limbs, 345a8e1175bSopenharmony_ci bound_bytes.x, bound_bytes.len); 346a8e1175bSopenharmony_ci int statistically_safe_all_the_way = 347a8e1175bSopenharmony_ci is_significantly_above_a_power_of_2(&bound_bytes); 348a8e1175bSopenharmony_ci for (b = 0; b < n_bits; b++) { 349a8e1175bSopenharmony_ci mbedtls_test_set_step(1000000 + b); 350a8e1175bSopenharmony_ci /* Assert that each bit has been set in at least one result and 351a8e1175bSopenharmony_ci * clear in at least one result. Provided that iterations is not 352a8e1175bSopenharmony_ci * too small, it would be extremely unlikely for this not to be 353a8e1175bSopenharmony_ci * the case if the results are uniformly distributed. 354a8e1175bSopenharmony_ci * 355a8e1175bSopenharmony_ci * As an exception, the top bit may legitimately never be set 356a8e1175bSopenharmony_ci * if bound is a power of 2 or only slightly above. 357a8e1175bSopenharmony_ci */ 358a8e1175bSopenharmony_ci if (statistically_safe_all_the_way || b != n_bits - 1) { 359a8e1175bSopenharmony_ci TEST_ASSERT(stats[b] > 0); 360a8e1175bSopenharmony_ci } 361a8e1175bSopenharmony_ci TEST_ASSERT(stats[b] < (size_t) iterations); 362a8e1175bSopenharmony_ci } 363a8e1175bSopenharmony_ci } 364a8e1175bSopenharmony_ci 365a8e1175bSopenharmony_ciexit: 366a8e1175bSopenharmony_ci mbedtls_free(bound_bytes.x); 367a8e1175bSopenharmony_ci mbedtls_free(upper_bound); 368a8e1175bSopenharmony_ci mbedtls_free(result); 369a8e1175bSopenharmony_ci mbedtls_free(stats); 370a8e1175bSopenharmony_ci} 371a8e1175bSopenharmony_ci/* END_CASE */ 372a8e1175bSopenharmony_ci 373a8e1175bSopenharmony_ci/* BEGIN_CASE */ 374a8e1175bSopenharmony_civoid mpi_random_sizes(int min, data_t *bound_bytes, int nlimbs, int before) 375a8e1175bSopenharmony_ci{ 376a8e1175bSopenharmony_ci mbedtls_mpi upper_bound; 377a8e1175bSopenharmony_ci mbedtls_mpi result; 378a8e1175bSopenharmony_ci 379a8e1175bSopenharmony_ci mbedtls_mpi_init(&upper_bound); 380a8e1175bSopenharmony_ci mbedtls_mpi_init(&result); 381a8e1175bSopenharmony_ci 382a8e1175bSopenharmony_ci if (before != 0) { 383a8e1175bSopenharmony_ci /* Set result to sign(before) * 2^(|before|-1) */ 384a8e1175bSopenharmony_ci TEST_ASSERT(mbedtls_mpi_lset(&result, before > 0 ? 1 : -1) == 0); 385a8e1175bSopenharmony_ci if (before < 0) { 386a8e1175bSopenharmony_ci before = -before; 387a8e1175bSopenharmony_ci } 388a8e1175bSopenharmony_ci TEST_ASSERT(mbedtls_mpi_shift_l(&result, before - 1) == 0); 389a8e1175bSopenharmony_ci } 390a8e1175bSopenharmony_ci 391a8e1175bSopenharmony_ci TEST_EQUAL(0, mbedtls_mpi_grow(&result, nlimbs)); 392a8e1175bSopenharmony_ci TEST_EQUAL(0, mbedtls_mpi_read_binary(&upper_bound, 393a8e1175bSopenharmony_ci bound_bytes->x, bound_bytes->len)); 394a8e1175bSopenharmony_ci TEST_EQUAL(0, mbedtls_mpi_random(&result, min, &upper_bound, 395a8e1175bSopenharmony_ci mbedtls_test_rnd_std_rand, NULL)); 396a8e1175bSopenharmony_ci TEST_ASSERT(sign_is_valid(&result)); 397a8e1175bSopenharmony_ci TEST_ASSERT(mbedtls_mpi_cmp_mpi(&result, &upper_bound) < 0); 398a8e1175bSopenharmony_ci TEST_ASSERT(mbedtls_mpi_cmp_int(&result, min) >= 0); 399a8e1175bSopenharmony_ci 400a8e1175bSopenharmony_ciexit: 401a8e1175bSopenharmony_ci mbedtls_mpi_free(&upper_bound); 402a8e1175bSopenharmony_ci mbedtls_mpi_free(&result); 403a8e1175bSopenharmony_ci} 404a8e1175bSopenharmony_ci/* END_CASE */ 405a8e1175bSopenharmony_ci 406a8e1175bSopenharmony_ci/* BEGIN_CASE depends_on:MBEDTLS_ECP_WITH_MPI_UINT */ 407a8e1175bSopenharmony_civoid mpi_mod_random_validation(int min, char *bound_hex, 408a8e1175bSopenharmony_ci int result_limbs_delta, 409a8e1175bSopenharmony_ci int expected_ret) 410a8e1175bSopenharmony_ci{ 411a8e1175bSopenharmony_ci mbedtls_mpi_uint *result_digits = NULL; 412a8e1175bSopenharmony_ci mbedtls_mpi_mod_modulus N; 413a8e1175bSopenharmony_ci mbedtls_mpi_mod_modulus_init(&N); 414a8e1175bSopenharmony_ci 415a8e1175bSopenharmony_ci TEST_EQUAL(mbedtls_test_read_mpi_modulus(&N, bound_hex, 416a8e1175bSopenharmony_ci MBEDTLS_MPI_MOD_REP_OPT_RED), 417a8e1175bSopenharmony_ci 0); 418a8e1175bSopenharmony_ci size_t result_limbs = N.limbs + result_limbs_delta; 419a8e1175bSopenharmony_ci TEST_CALLOC(result_digits, result_limbs); 420a8e1175bSopenharmony_ci /* Build a reside that might not match the modulus, to test that 421a8e1175bSopenharmony_ci * the library function rejects that as expected. */ 422a8e1175bSopenharmony_ci mbedtls_mpi_mod_residue result = { result_digits, result_limbs }; 423a8e1175bSopenharmony_ci 424a8e1175bSopenharmony_ci TEST_EQUAL(mbedtls_mpi_mod_random(&result, min, &N, 425a8e1175bSopenharmony_ci mbedtls_test_rnd_std_rand, NULL), 426a8e1175bSopenharmony_ci expected_ret); 427a8e1175bSopenharmony_ci if (expected_ret == 0) { 428a8e1175bSopenharmony_ci /* Success should only be expected when the result has the same 429a8e1175bSopenharmony_ci * size as the modulus, otherwise it's a mistake in the test data. */ 430a8e1175bSopenharmony_ci TEST_EQUAL(result_limbs, N.limbs); 431a8e1175bSopenharmony_ci /* Sanity check: check that the result is in range */ 432a8e1175bSopenharmony_ci TEST_ASSERT(0 != mbedtls_mpi_core_lt_ct(result_digits, N.p, N.limbs)); 433a8e1175bSopenharmony_ci /* Check result >= min (changes result) */ 434a8e1175bSopenharmony_ci TEST_EQUAL(mbedtls_mpi_core_sub_int(result_digits, result_digits, min, 435a8e1175bSopenharmony_ci result_limbs), 436a8e1175bSopenharmony_ci 0); 437a8e1175bSopenharmony_ci } 438a8e1175bSopenharmony_ci 439a8e1175bSopenharmony_ci /* When the result has the right number of limbs, also test mod_raw 440a8e1175bSopenharmony_ci * (for which this is an unchecked precondition). */ 441a8e1175bSopenharmony_ci if (result_limbs_delta == 0) { 442a8e1175bSopenharmony_ci TEST_EQUAL(mbedtls_mpi_mod_raw_random(result_digits, min, &N, 443a8e1175bSopenharmony_ci mbedtls_test_rnd_std_rand, NULL), 444a8e1175bSopenharmony_ci expected_ret); 445a8e1175bSopenharmony_ci if (expected_ret == 0) { 446a8e1175bSopenharmony_ci TEST_ASSERT(0 != mbedtls_mpi_core_lt_ct(result_digits, N.p, N.limbs)); 447a8e1175bSopenharmony_ci TEST_EQUAL(mbedtls_mpi_core_sub_int(result_digits, result.p, min, 448a8e1175bSopenharmony_ci result_limbs), 449a8e1175bSopenharmony_ci 0); 450a8e1175bSopenharmony_ci } 451a8e1175bSopenharmony_ci } 452a8e1175bSopenharmony_ci 453a8e1175bSopenharmony_ciexit: 454a8e1175bSopenharmony_ci mbedtls_test_mpi_mod_modulus_free_with_limbs(&N); 455a8e1175bSopenharmony_ci mbedtls_free(result_digits); 456a8e1175bSopenharmony_ci} 457a8e1175bSopenharmony_ci/* END_CASE */ 458a8e1175bSopenharmony_ci 459a8e1175bSopenharmony_ci/* BEGIN_CASE */ 460a8e1175bSopenharmony_civoid mpi_random_fail(int min, data_t *bound_bytes, int expected_ret) 461a8e1175bSopenharmony_ci{ 462a8e1175bSopenharmony_ci mbedtls_mpi upper_bound; 463a8e1175bSopenharmony_ci mbedtls_mpi result; 464a8e1175bSopenharmony_ci int actual_ret; 465a8e1175bSopenharmony_ci 466a8e1175bSopenharmony_ci mbedtls_mpi_init(&upper_bound); 467a8e1175bSopenharmony_ci mbedtls_mpi_init(&result); 468a8e1175bSopenharmony_ci 469a8e1175bSopenharmony_ci TEST_EQUAL(0, mbedtls_mpi_read_binary(&upper_bound, 470a8e1175bSopenharmony_ci bound_bytes->x, bound_bytes->len)); 471a8e1175bSopenharmony_ci actual_ret = mbedtls_mpi_random(&result, min, &upper_bound, 472a8e1175bSopenharmony_ci mbedtls_test_rnd_std_rand, NULL); 473a8e1175bSopenharmony_ci TEST_EQUAL(expected_ret, actual_ret); 474a8e1175bSopenharmony_ci 475a8e1175bSopenharmony_ciexit: 476a8e1175bSopenharmony_ci mbedtls_mpi_free(&upper_bound); 477a8e1175bSopenharmony_ci mbedtls_mpi_free(&result); 478a8e1175bSopenharmony_ci} 479a8e1175bSopenharmony_ci/* END_CASE */ 480