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