1a8e1175bSopenharmony_ci/* BEGIN_HEADER */
2a8e1175bSopenharmony_ci#include "mbedtls/bignum.h"
3a8e1175bSopenharmony_ci#include "mbedtls/entropy.h"
4a8e1175bSopenharmony_ci#include "bignum_mod.h"
5a8e1175bSopenharmony_ci#include "bignum_mod_raw.h"
6a8e1175bSopenharmony_ci#include "constant_time_internal.h"
7a8e1175bSopenharmony_ci#include "test/constant_flow.h"
8a8e1175bSopenharmony_ci
9a8e1175bSopenharmony_ci#define TEST_COMPARE_MPI_RESIDUES(a, b) \
10a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE((a).p, (a).limbs * sizeof(mbedtls_mpi_uint), \
11a8e1175bSopenharmony_ci                        (b).p, (b).limbs * sizeof(mbedtls_mpi_uint))
12a8e1175bSopenharmony_ci
13a8e1175bSopenharmony_cistatic int test_read_residue(mbedtls_mpi_mod_residue *r,
14a8e1175bSopenharmony_ci                             const mbedtls_mpi_mod_modulus *m,
15a8e1175bSopenharmony_ci                             char *input,
16a8e1175bSopenharmony_ci                             int skip_limbs_and_value_checks)
17a8e1175bSopenharmony_ci{
18a8e1175bSopenharmony_ci    mbedtls_mpi_uint *p = NULL;
19a8e1175bSopenharmony_ci    size_t limbs;
20a8e1175bSopenharmony_ci
21a8e1175bSopenharmony_ci    int ret = mbedtls_test_read_mpi_core(&p, &limbs, input);
22a8e1175bSopenharmony_ci    if (ret != 0) {
23a8e1175bSopenharmony_ci        return ret;
24a8e1175bSopenharmony_ci    }
25a8e1175bSopenharmony_ci
26a8e1175bSopenharmony_ci    if (skip_limbs_and_value_checks) {
27a8e1175bSopenharmony_ci        r->p = p;
28a8e1175bSopenharmony_ci        r->limbs = limbs;
29a8e1175bSopenharmony_ci        return 0;
30a8e1175bSopenharmony_ci    }
31a8e1175bSopenharmony_ci
32a8e1175bSopenharmony_ci    /* mbedtls_mpi_mod_residue_setup() checks limbs, and that value < m */
33a8e1175bSopenharmony_ci    return mbedtls_mpi_mod_residue_setup(r, m, p, limbs);
34a8e1175bSopenharmony_ci}
35a8e1175bSopenharmony_ci/* END_HEADER */
36a8e1175bSopenharmony_ci
37a8e1175bSopenharmony_ci/* BEGIN_DEPENDENCIES
38a8e1175bSopenharmony_ci * depends_on:MBEDTLS_BIGNUM_C:MBEDTLS_ECP_WITH_MPI_UINT
39a8e1175bSopenharmony_ci * END_DEPENDENCIES
40a8e1175bSopenharmony_ci */
41a8e1175bSopenharmony_ci
42a8e1175bSopenharmony_ci/* BEGIN_CASE */
43a8e1175bSopenharmony_civoid mpi_mod_setup(int int_rep, int iret)
44a8e1175bSopenharmony_ci{
45a8e1175bSopenharmony_ci    #define MLIMBS 8
46a8e1175bSopenharmony_ci    mbedtls_mpi_uint mp[MLIMBS];
47a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
48a8e1175bSopenharmony_ci    int ret;
49a8e1175bSopenharmony_ci
50a8e1175bSopenharmony_ci    memset(mp, 0xFF, sizeof(mp));
51a8e1175bSopenharmony_ci
52a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
53a8e1175bSopenharmony_ci
54a8e1175bSopenharmony_ci    switch (int_rep) {
55a8e1175bSopenharmony_ci        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
56a8e1175bSopenharmony_ci            ret = mbedtls_mpi_mod_modulus_setup(&m, mp, MLIMBS);
57a8e1175bSopenharmony_ci            break;
58a8e1175bSopenharmony_ci        case MBEDTLS_MPI_MOD_REP_OPT_RED:
59a8e1175bSopenharmony_ci            ret = mbedtls_mpi_mod_optred_modulus_setup(&m, mp, MLIMBS, NULL);
60a8e1175bSopenharmony_ci            break;
61a8e1175bSopenharmony_ci        default:
62a8e1175bSopenharmony_ci            ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
63a8e1175bSopenharmony_ci            break;
64a8e1175bSopenharmony_ci    }
65a8e1175bSopenharmony_ci
66a8e1175bSopenharmony_ci    TEST_EQUAL(ret, iret);
67a8e1175bSopenharmony_ci
68a8e1175bSopenharmony_ci    /* Only test if the constants have been set-up  */
69a8e1175bSopenharmony_ci    if (ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
70a8e1175bSopenharmony_ci        /* Test that the consts have been calculated */
71a8e1175bSopenharmony_ci        TEST_ASSERT(m.rep.mont.rr != NULL);
72a8e1175bSopenharmony_ci        TEST_ASSERT(m.rep.mont.mm != 0);
73a8e1175bSopenharmony_ci
74a8e1175bSopenharmony_ci    }
75a8e1175bSopenharmony_ci
76a8e1175bSopenharmony_ci    /* Address sanitiser should catch if we try to free mp */
77a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
78a8e1175bSopenharmony_ci
79a8e1175bSopenharmony_ci    /* Make sure that the modulus doesn't have reference to mp anymore */
80a8e1175bSopenharmony_ci    TEST_ASSERT(m.p != mp);
81a8e1175bSopenharmony_ci
82a8e1175bSopenharmony_ci    /* Only test if the constants have been set-up  */
83a8e1175bSopenharmony_ci    if (ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
84a8e1175bSopenharmony_ci        /* Verify the data and pointers allocated have been properly wiped */
85a8e1175bSopenharmony_ci        TEST_ASSERT(m.rep.mont.rr == NULL);
86a8e1175bSopenharmony_ci        TEST_ASSERT(m.rep.mont.mm == 0);
87a8e1175bSopenharmony_ci    }
88a8e1175bSopenharmony_ciexit:
89a8e1175bSopenharmony_ci    /* It should be safe to call an mbedtls free several times */
90a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
91a8e1175bSopenharmony_ci
92a8e1175bSopenharmony_ci    #undef MLIMBS
93a8e1175bSopenharmony_ci}
94a8e1175bSopenharmony_ci/* END_CASE */
95a8e1175bSopenharmony_ci
96a8e1175bSopenharmony_ci/* BEGIN_CASE */
97a8e1175bSopenharmony_civoid mpi_mod_mul(char *input_A,
98a8e1175bSopenharmony_ci                 char *input_B,
99a8e1175bSopenharmony_ci                 char *input_N,
100a8e1175bSopenharmony_ci                 char *result)
101a8e1175bSopenharmony_ci{
102a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
103a8e1175bSopenharmony_ci
104a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue rA = { NULL, 0 };
105a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue rB = { NULL, 0 };
106a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue rR = { NULL, 0 };
107a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue rX = { NULL, 0 };
108a8e1175bSopenharmony_ci
109a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
110a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
111a8e1175bSopenharmony_ci
112a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_modulus(&m, input_N,
113a8e1175bSopenharmony_ci                                             MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
114a8e1175bSopenharmony_ci
115a8e1175bSopenharmony_ci    TEST_EQUAL(test_read_residue(&rA, &m, input_A, 0), 0);
116a8e1175bSopenharmony_ci    TEST_EQUAL(test_read_residue(&rB, &m, input_B, 0), 0);
117a8e1175bSopenharmony_ci    TEST_EQUAL(test_read_residue(&rR, &m, result,  0), 0);
118a8e1175bSopenharmony_ci
119a8e1175bSopenharmony_ci    const size_t limbs = m.limbs;
120a8e1175bSopenharmony_ci    const size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
121a8e1175bSopenharmony_ci
122a8e1175bSopenharmony_ci    TEST_EQUAL(rA.limbs, limbs);
123a8e1175bSopenharmony_ci    TEST_EQUAL(rB.limbs, limbs);
124a8e1175bSopenharmony_ci    TEST_EQUAL(rR.limbs, limbs);
125a8e1175bSopenharmony_ci
126a8e1175bSopenharmony_ci    TEST_CALLOC(X, limbs);
127a8e1175bSopenharmony_ci
128a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_residue_setup(&rX, &m, X, limbs), 0);
129a8e1175bSopenharmony_ci
130a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &m), 0);
131a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(rX.p, bytes, rR.p, bytes);
132a8e1175bSopenharmony_ci
133a8e1175bSopenharmony_ci    /* alias X to A */
134a8e1175bSopenharmony_ci    memcpy(rX.p, rA.p, bytes);
135a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rB, &m), 0);
136a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(rX.p, bytes, rR.p, bytes);
137a8e1175bSopenharmony_ci
138a8e1175bSopenharmony_ci    /* alias X to B */
139a8e1175bSopenharmony_ci    memcpy(rX.p, rB.p, bytes);
140a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rX, &m), 0);
141a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(rX.p, bytes, rR.p, bytes);
142a8e1175bSopenharmony_ci
143a8e1175bSopenharmony_ci    /* A == B: alias A and B */
144a8e1175bSopenharmony_ci    if (memcmp(rA.p, rB.p, bytes) == 0) {
145a8e1175bSopenharmony_ci        TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rA, &m), 0);
146a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(rX.p, bytes, rR.p, bytes);
147a8e1175bSopenharmony_ci
148a8e1175bSopenharmony_ci        /* X, A, B all aliased together */
149a8e1175bSopenharmony_ci        memcpy(rX.p, rA.p, bytes);
150a8e1175bSopenharmony_ci        TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rX, &m), 0);
151a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(rX.p, bytes, rR.p, bytes);
152a8e1175bSopenharmony_ci    }
153a8e1175bSopenharmony_ci    /* A != B: test B * A */
154a8e1175bSopenharmony_ci    else {
155a8e1175bSopenharmony_ci        TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rB, &rA, &m), 0);
156a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(rX.p, bytes, rR.p, bytes);
157a8e1175bSopenharmony_ci
158a8e1175bSopenharmony_ci        /* B * A: alias X to A */
159a8e1175bSopenharmony_ci        memcpy(rX.p, rA.p, bytes);
160a8e1175bSopenharmony_ci        TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rB, &rX, &m), 0);
161a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(rX.p, bytes, rR.p, bytes);
162a8e1175bSopenharmony_ci
163a8e1175bSopenharmony_ci        /* B + A: alias X to B */
164a8e1175bSopenharmony_ci        memcpy(rX.p, rB.p, bytes);
165a8e1175bSopenharmony_ci        TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rA, &m), 0);
166a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(rX.p, bytes, rR.p, bytes);
167a8e1175bSopenharmony_ci    }
168a8e1175bSopenharmony_ci
169a8e1175bSopenharmony_ciexit:
170a8e1175bSopenharmony_ci    mbedtls_free(rA.p);
171a8e1175bSopenharmony_ci    mbedtls_free(rB.p);
172a8e1175bSopenharmony_ci    mbedtls_free(rR.p);
173a8e1175bSopenharmony_ci    mbedtls_free(X);
174a8e1175bSopenharmony_ci    mbedtls_free((mbedtls_mpi_uint *) m.p);
175a8e1175bSopenharmony_ci
176a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
177a8e1175bSopenharmony_ci}
178a8e1175bSopenharmony_ci/* END_CASE */
179a8e1175bSopenharmony_ci
180a8e1175bSopenharmony_ci/* BEGIN_CASE */
181a8e1175bSopenharmony_civoid mpi_mod_mul_neg(char *input_A,
182a8e1175bSopenharmony_ci                     char *input_B,
183a8e1175bSopenharmony_ci                     char *input_N,
184a8e1175bSopenharmony_ci                     char *result,
185a8e1175bSopenharmony_ci                     int exp_ret)
186a8e1175bSopenharmony_ci{
187a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
188a8e1175bSopenharmony_ci
189a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue rA = { NULL, 0 };
190a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue rB = { NULL, 0 };
191a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue rR = { NULL, 0 };
192a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue rX = { NULL, 0 };
193a8e1175bSopenharmony_ci
194a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
195a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
196a8e1175bSopenharmony_ci
197a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus fake_m;
198a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&fake_m);
199a8e1175bSopenharmony_ci
200a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_modulus(&m, input_N,
201a8e1175bSopenharmony_ci                                             MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
202a8e1175bSopenharmony_ci
203a8e1175bSopenharmony_ci    TEST_EQUAL(test_read_residue(&rA, &m, input_A, 1), 0);
204a8e1175bSopenharmony_ci    TEST_EQUAL(test_read_residue(&rB, &m, input_B, 1), 0);
205a8e1175bSopenharmony_ci    TEST_EQUAL(test_read_residue(&rR, &m, result,  1), 0);
206a8e1175bSopenharmony_ci
207a8e1175bSopenharmony_ci    const size_t limbs = m.limbs;
208a8e1175bSopenharmony_ci
209a8e1175bSopenharmony_ci    TEST_CALLOC(X, limbs);
210a8e1175bSopenharmony_ci
211a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_residue_setup(&rX, &m, X, limbs), 0);
212a8e1175bSopenharmony_ci    rX.limbs = rR.limbs;
213a8e1175bSopenharmony_ci
214a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &m), exp_ret);
215a8e1175bSopenharmony_ci
216a8e1175bSopenharmony_ci    /* Check when m is not initialized */
217a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &fake_m),
218a8e1175bSopenharmony_ci               MBEDTLS_ERR_MPI_BAD_INPUT_DATA);
219a8e1175bSopenharmony_ci
220a8e1175bSopenharmony_ciexit:
221a8e1175bSopenharmony_ci    mbedtls_free(rA.p);
222a8e1175bSopenharmony_ci    mbedtls_free(rB.p);
223a8e1175bSopenharmony_ci    mbedtls_free(rR.p);
224a8e1175bSopenharmony_ci    mbedtls_free(X);
225a8e1175bSopenharmony_ci    mbedtls_free((mbedtls_mpi_uint *) m.p);
226a8e1175bSopenharmony_ci
227a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
228a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&fake_m);
229a8e1175bSopenharmony_ci}
230a8e1175bSopenharmony_ci/* END_CASE */
231a8e1175bSopenharmony_ci
232a8e1175bSopenharmony_ci/* BEGIN_CASE */
233a8e1175bSopenharmony_civoid mpi_mod_sub(char *input_N,
234a8e1175bSopenharmony_ci                 char *input_A, char *input_B,
235a8e1175bSopenharmony_ci                 char *input_D, int expected_ret)
236a8e1175bSopenharmony_ci{
237a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue a = { NULL, 0 };
238a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue b = { NULL, 0 };
239a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue d = { NULL, 0 };
240a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue x = { NULL, 0 };
241a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X_raw = NULL;
242a8e1175bSopenharmony_ci
243a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
244a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
245a8e1175bSopenharmony_ci
246a8e1175bSopenharmony_ci    TEST_EQUAL(0,
247a8e1175bSopenharmony_ci               mbedtls_test_read_mpi_modulus(&m, input_N,
248a8e1175bSopenharmony_ci                                             MBEDTLS_MPI_MOD_REP_MONTGOMERY));
249a8e1175bSopenharmony_ci
250a8e1175bSopenharmony_ci    /* test_read_residue() normally checks that inputs have the same number of
251a8e1175bSopenharmony_ci     * limbs as the modulus. For negative testing we can ask it to skip this
252a8e1175bSopenharmony_ci     * with a non-zero final parameter. */
253a8e1175bSopenharmony_ci    TEST_EQUAL(0, test_read_residue(&a, &m, input_A, expected_ret != 0));
254a8e1175bSopenharmony_ci    TEST_EQUAL(0, test_read_residue(&b, &m, input_B, expected_ret != 0));
255a8e1175bSopenharmony_ci    TEST_EQUAL(0, test_read_residue(&d, &m, input_D, expected_ret != 0));
256a8e1175bSopenharmony_ci
257a8e1175bSopenharmony_ci    size_t limbs = m.limbs;
258a8e1175bSopenharmony_ci    size_t bytes = limbs * sizeof(*X_raw);
259a8e1175bSopenharmony_ci
260a8e1175bSopenharmony_ci    if (expected_ret == 0) {
261a8e1175bSopenharmony_ci        /* Negative test with too many limbs in output */
262a8e1175bSopenharmony_ci        TEST_CALLOC(X_raw, limbs + 1);
263a8e1175bSopenharmony_ci
264a8e1175bSopenharmony_ci        x.p = X_raw;
265a8e1175bSopenharmony_ci        x.limbs = limbs + 1;
266a8e1175bSopenharmony_ci        TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
267a8e1175bSopenharmony_ci                   mbedtls_mpi_mod_sub(&x, &a, &b, &m));
268a8e1175bSopenharmony_ci
269a8e1175bSopenharmony_ci        mbedtls_free(X_raw);
270a8e1175bSopenharmony_ci        X_raw = NULL;
271a8e1175bSopenharmony_ci
272a8e1175bSopenharmony_ci        /* Negative test with too few limbs in output */
273a8e1175bSopenharmony_ci        if (limbs > 1) {
274a8e1175bSopenharmony_ci            TEST_CALLOC(X_raw, limbs - 1);
275a8e1175bSopenharmony_ci
276a8e1175bSopenharmony_ci            x.p = X_raw;
277a8e1175bSopenharmony_ci            x.limbs = limbs - 1;
278a8e1175bSopenharmony_ci            TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
279a8e1175bSopenharmony_ci                       mbedtls_mpi_mod_sub(&x, &a, &b, &m));
280a8e1175bSopenharmony_ci
281a8e1175bSopenharmony_ci            mbedtls_free(X_raw);
282a8e1175bSopenharmony_ci            X_raw = NULL;
283a8e1175bSopenharmony_ci        }
284a8e1175bSopenharmony_ci
285a8e1175bSopenharmony_ci        /* Negative testing with too many/too few limbs in a and b is covered by
286a8e1175bSopenharmony_ci         * manually-written test cases with expected_ret != 0. */
287a8e1175bSopenharmony_ci    }
288a8e1175bSopenharmony_ci
289a8e1175bSopenharmony_ci    TEST_CALLOC(X_raw, limbs);
290a8e1175bSopenharmony_ci
291a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &m, X_raw, limbs));
292a8e1175bSopenharmony_ci
293a8e1175bSopenharmony_ci    /* a - b => Correct result, or expected error */
294a8e1175bSopenharmony_ci    TEST_EQUAL(expected_ret, mbedtls_mpi_mod_sub(&x, &a, &b, &m));
295a8e1175bSopenharmony_ci    if (expected_ret != 0) {
296a8e1175bSopenharmony_ci        goto exit;
297a8e1175bSopenharmony_ci    }
298a8e1175bSopenharmony_ci
299a8e1175bSopenharmony_ci    TEST_COMPARE_MPI_RESIDUES(x, d);
300a8e1175bSopenharmony_ci
301a8e1175bSopenharmony_ci    /* a - b: alias x to a => Correct result */
302a8e1175bSopenharmony_ci    memcpy(x.p, a.p, bytes);
303a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &x, &b, &m));
304a8e1175bSopenharmony_ci    TEST_COMPARE_MPI_RESIDUES(x, d);
305a8e1175bSopenharmony_ci
306a8e1175bSopenharmony_ci    /* a - b: alias x to b => Correct result */
307a8e1175bSopenharmony_ci    memcpy(x.p, b.p, bytes);
308a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &a, &x, &m));
309a8e1175bSopenharmony_ci    TEST_COMPARE_MPI_RESIDUES(x, d);
310a8e1175bSopenharmony_ci
311a8e1175bSopenharmony_ci    if (memcmp(a.p, b.p, bytes) == 0) {
312a8e1175bSopenharmony_ci        /* a == b: alias a and b */
313a8e1175bSopenharmony_ci
314a8e1175bSopenharmony_ci        /* a - a => Correct result */
315a8e1175bSopenharmony_ci        TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &a, &a, &m));
316a8e1175bSopenharmony_ci        TEST_COMPARE_MPI_RESIDUES(x, d);
317a8e1175bSopenharmony_ci
318a8e1175bSopenharmony_ci        /* a - a: x, a, b all aliased together => Correct result */
319a8e1175bSopenharmony_ci        memcpy(x.p, a.p, bytes);
320a8e1175bSopenharmony_ci        TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &x, &x, &m));
321a8e1175bSopenharmony_ci        TEST_COMPARE_MPI_RESIDUES(x, d);
322a8e1175bSopenharmony_ci    }
323a8e1175bSopenharmony_ci
324a8e1175bSopenharmony_ciexit:
325a8e1175bSopenharmony_ci    mbedtls_free((void *) m.p);  /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
326a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
327a8e1175bSopenharmony_ci
328a8e1175bSopenharmony_ci    mbedtls_free(a.p);
329a8e1175bSopenharmony_ci    mbedtls_free(b.p);
330a8e1175bSopenharmony_ci    mbedtls_free(d.p);
331a8e1175bSopenharmony_ci    mbedtls_free(X_raw);
332a8e1175bSopenharmony_ci}
333a8e1175bSopenharmony_ci/* END_CASE */
334a8e1175bSopenharmony_ci
335a8e1175bSopenharmony_ci/* BEGIN_CASE */
336a8e1175bSopenharmony_civoid mpi_mod_inv_mont(char *input_N,
337a8e1175bSopenharmony_ci                      char *input_A, char *input_I,
338a8e1175bSopenharmony_ci                      int expected_ret)
339a8e1175bSopenharmony_ci{
340a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue a = { NULL, 0 };    /* argument */
341a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue i = { NULL, 0 };    /* expected inverse wrt N */
342a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue x = { NULL, 0 };    /* output */
343a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X_raw = NULL;
344a8e1175bSopenharmony_ci
345a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus N;
346a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&N);
347a8e1175bSopenharmony_ci
348a8e1175bSopenharmony_ci    TEST_EQUAL(0,
349a8e1175bSopenharmony_ci               mbedtls_test_read_mpi_modulus(&N, input_N,
350a8e1175bSopenharmony_ci                                             MBEDTLS_MPI_MOD_REP_MONTGOMERY));
351a8e1175bSopenharmony_ci
352a8e1175bSopenharmony_ci    /* test_read_residue() normally checks that inputs have the same number of
353a8e1175bSopenharmony_ci     * limbs as the modulus. For negative testing we can ask it to skip this
354a8e1175bSopenharmony_ci     * with a non-zero final parameter. */
355a8e1175bSopenharmony_ci    TEST_EQUAL(0, test_read_residue(&a, &N, input_A, expected_ret != 0));
356a8e1175bSopenharmony_ci    TEST_EQUAL(0, test_read_residue(&i, &N, input_I, expected_ret != 0));
357a8e1175bSopenharmony_ci
358a8e1175bSopenharmony_ci    size_t limbs = N.limbs;
359a8e1175bSopenharmony_ci    size_t bytes = limbs * sizeof(*X_raw);
360a8e1175bSopenharmony_ci
361a8e1175bSopenharmony_ci    TEST_CALLOC(X_raw, limbs);
362a8e1175bSopenharmony_ci
363a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &N, X_raw, limbs));
364a8e1175bSopenharmony_ci
365a8e1175bSopenharmony_ci    TEST_EQUAL(expected_ret, mbedtls_mpi_mod_inv(&x, &a, &N));
366a8e1175bSopenharmony_ci    if (expected_ret == 0) {
367a8e1175bSopenharmony_ci        TEST_COMPARE_MPI_RESIDUES(x, i);
368a8e1175bSopenharmony_ci
369a8e1175bSopenharmony_ci        /* a^-1: alias x to a => Correct result */
370a8e1175bSopenharmony_ci        memcpy(x.p, a.p, bytes);
371a8e1175bSopenharmony_ci        TEST_EQUAL(0, mbedtls_mpi_mod_inv(&x, &x, &N));
372a8e1175bSopenharmony_ci        TEST_COMPARE_MPI_RESIDUES(x, i);
373a8e1175bSopenharmony_ci    }
374a8e1175bSopenharmony_ci
375a8e1175bSopenharmony_ciexit:
376a8e1175bSopenharmony_ci    mbedtls_free((void *) N.p);  /* mbedtls_mpi_mod_modulus_free() sets N.p = NULL */
377a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&N);
378a8e1175bSopenharmony_ci
379a8e1175bSopenharmony_ci    mbedtls_free(a.p);
380a8e1175bSopenharmony_ci    mbedtls_free(i.p);
381a8e1175bSopenharmony_ci    mbedtls_free(X_raw);
382a8e1175bSopenharmony_ci}
383a8e1175bSopenharmony_ci/* END_CASE */
384a8e1175bSopenharmony_ci
385a8e1175bSopenharmony_ci/* BEGIN_CASE */
386a8e1175bSopenharmony_civoid mpi_mod_inv_non_mont(char *input_N,
387a8e1175bSopenharmony_ci                          char *input_A, char *input_I,
388a8e1175bSopenharmony_ci                          int expected_ret)
389a8e1175bSopenharmony_ci{
390a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue a = { NULL, 0 };    /* argument */
391a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue i = { NULL, 0 };    /* expected inverse wrt N */
392a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue x = { NULL, 0 };    /* output */
393a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X_raw = NULL;
394a8e1175bSopenharmony_ci
395a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus N;
396a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&N);
397a8e1175bSopenharmony_ci
398a8e1175bSopenharmony_ci    TEST_EQUAL(0,
399a8e1175bSopenharmony_ci               mbedtls_test_read_mpi_modulus(&N, input_N,
400a8e1175bSopenharmony_ci                                             MBEDTLS_MPI_MOD_REP_OPT_RED));
401a8e1175bSopenharmony_ci
402a8e1175bSopenharmony_ci    /* test_read_residue() normally checks that inputs have the same number of
403a8e1175bSopenharmony_ci     * limbs as the modulus. For negative testing we can ask it to skip this
404a8e1175bSopenharmony_ci     * with a non-zero final parameter. */
405a8e1175bSopenharmony_ci    TEST_EQUAL(0, test_read_residue(&a, &N, input_A, expected_ret != 0));
406a8e1175bSopenharmony_ci    TEST_EQUAL(0, test_read_residue(&i, &N, input_I, expected_ret != 0));
407a8e1175bSopenharmony_ci
408a8e1175bSopenharmony_ci    size_t limbs = N.limbs;
409a8e1175bSopenharmony_ci    size_t bytes = limbs * sizeof(*X_raw);
410a8e1175bSopenharmony_ci
411a8e1175bSopenharmony_ci    TEST_CALLOC(X_raw, limbs);
412a8e1175bSopenharmony_ci
413a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &N, X_raw, limbs));
414a8e1175bSopenharmony_ci
415a8e1175bSopenharmony_ci    TEST_EQUAL(expected_ret, mbedtls_mpi_mod_inv(&x, &a, &N));
416a8e1175bSopenharmony_ci    if (expected_ret == 0) {
417a8e1175bSopenharmony_ci        TEST_COMPARE_MPI_RESIDUES(x, i);
418a8e1175bSopenharmony_ci
419a8e1175bSopenharmony_ci        /* a^-1: alias x to a => Correct result */
420a8e1175bSopenharmony_ci        memcpy(x.p, a.p, bytes);
421a8e1175bSopenharmony_ci        TEST_EQUAL(0, mbedtls_mpi_mod_inv(&x, &x, &N));
422a8e1175bSopenharmony_ci        TEST_COMPARE_MPI_RESIDUES(x, i);
423a8e1175bSopenharmony_ci    }
424a8e1175bSopenharmony_ci
425a8e1175bSopenharmony_ciexit:
426a8e1175bSopenharmony_ci    mbedtls_free((void *) N.p);  /* mbedtls_mpi_mod_modulus_free() sets N.p = NULL */
427a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&N);
428a8e1175bSopenharmony_ci
429a8e1175bSopenharmony_ci    mbedtls_free(a.p);
430a8e1175bSopenharmony_ci    mbedtls_free(i.p);
431a8e1175bSopenharmony_ci    mbedtls_free(X_raw);
432a8e1175bSopenharmony_ci}
433a8e1175bSopenharmony_ci/* END_CASE */
434a8e1175bSopenharmony_ci
435a8e1175bSopenharmony_ci/* BEGIN_CASE */
436a8e1175bSopenharmony_civoid mpi_mod_add(char *input_N,
437a8e1175bSopenharmony_ci                 char *input_A, char *input_B,
438a8e1175bSopenharmony_ci                 char *input_S, int expected_ret)
439a8e1175bSopenharmony_ci{
440a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue a = { NULL, 0 };
441a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue b = { NULL, 0 };
442a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue s = { NULL, 0 };
443a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue x = { NULL, 0 };
444a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X_raw = NULL;
445a8e1175bSopenharmony_ci
446a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
447a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
448a8e1175bSopenharmony_ci
449a8e1175bSopenharmony_ci    TEST_EQUAL(0,
450a8e1175bSopenharmony_ci               mbedtls_test_read_mpi_modulus(&m, input_N,
451a8e1175bSopenharmony_ci                                             MBEDTLS_MPI_MOD_REP_MONTGOMERY));
452a8e1175bSopenharmony_ci
453a8e1175bSopenharmony_ci    /* test_read_residue() normally checks that inputs have the same number of
454a8e1175bSopenharmony_ci     * limbs as the modulus. For negative testing we can ask it to skip this
455a8e1175bSopenharmony_ci     * with a non-zero final parameter. */
456a8e1175bSopenharmony_ci    TEST_EQUAL(0, test_read_residue(&a, &m, input_A, expected_ret != 0));
457a8e1175bSopenharmony_ci    TEST_EQUAL(0, test_read_residue(&b, &m, input_B, expected_ret != 0));
458a8e1175bSopenharmony_ci    TEST_EQUAL(0, test_read_residue(&s, &m, input_S, expected_ret != 0));
459a8e1175bSopenharmony_ci
460a8e1175bSopenharmony_ci    size_t limbs = m.limbs;
461a8e1175bSopenharmony_ci    size_t bytes = limbs * sizeof(*X_raw);
462a8e1175bSopenharmony_ci
463a8e1175bSopenharmony_ci    if (expected_ret == 0) {
464a8e1175bSopenharmony_ci        /* Negative test with too many limbs in output */
465a8e1175bSopenharmony_ci        TEST_CALLOC(X_raw, limbs + 1);
466a8e1175bSopenharmony_ci
467a8e1175bSopenharmony_ci        x.p = X_raw;
468a8e1175bSopenharmony_ci        x.limbs = limbs + 1;
469a8e1175bSopenharmony_ci        TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
470a8e1175bSopenharmony_ci                   mbedtls_mpi_mod_add(&x, &a, &b, &m));
471a8e1175bSopenharmony_ci
472a8e1175bSopenharmony_ci        mbedtls_free(X_raw);
473a8e1175bSopenharmony_ci        X_raw = NULL;
474a8e1175bSopenharmony_ci
475a8e1175bSopenharmony_ci        /* Negative test with too few limbs in output */
476a8e1175bSopenharmony_ci        if (limbs > 1) {
477a8e1175bSopenharmony_ci            TEST_CALLOC(X_raw, limbs - 1);
478a8e1175bSopenharmony_ci
479a8e1175bSopenharmony_ci            x.p = X_raw;
480a8e1175bSopenharmony_ci            x.limbs = limbs - 1;
481a8e1175bSopenharmony_ci            TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
482a8e1175bSopenharmony_ci                       mbedtls_mpi_mod_add(&x, &a, &b, &m));
483a8e1175bSopenharmony_ci
484a8e1175bSopenharmony_ci            mbedtls_free(X_raw);
485a8e1175bSopenharmony_ci            X_raw = NULL;
486a8e1175bSopenharmony_ci        }
487a8e1175bSopenharmony_ci
488a8e1175bSopenharmony_ci        /* Negative testing with too many/too few limbs in a and b is covered by
489a8e1175bSopenharmony_ci         * manually-written test cases with oret != 0. */
490a8e1175bSopenharmony_ci    }
491a8e1175bSopenharmony_ci
492a8e1175bSopenharmony_ci    /* Allocate correct number of limbs for X_raw */
493a8e1175bSopenharmony_ci    TEST_CALLOC(X_raw, limbs);
494a8e1175bSopenharmony_ci
495a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &m, X_raw, limbs));
496a8e1175bSopenharmony_ci
497a8e1175bSopenharmony_ci    /* A + B => Correct result or expected error */
498a8e1175bSopenharmony_ci    TEST_EQUAL(expected_ret, mbedtls_mpi_mod_add(&x, &a, &b, &m));
499a8e1175bSopenharmony_ci    if (expected_ret != 0) {
500a8e1175bSopenharmony_ci        goto exit;
501a8e1175bSopenharmony_ci    }
502a8e1175bSopenharmony_ci
503a8e1175bSopenharmony_ci    TEST_COMPARE_MPI_RESIDUES(x, s);
504a8e1175bSopenharmony_ci
505a8e1175bSopenharmony_ci    /* a + b: alias x to a => Correct result */
506a8e1175bSopenharmony_ci    memcpy(x.p, a.p, bytes);
507a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &x, &b, &m));
508a8e1175bSopenharmony_ci    TEST_COMPARE_MPI_RESIDUES(x, s);
509a8e1175bSopenharmony_ci
510a8e1175bSopenharmony_ci    /* a + b: alias x to b => Correct result */
511a8e1175bSopenharmony_ci    memcpy(x.p, b.p, bytes);
512a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &a, &x, &m));
513a8e1175bSopenharmony_ci    TEST_COMPARE_MPI_RESIDUES(x, s);
514a8e1175bSopenharmony_ci
515a8e1175bSopenharmony_ci    if (memcmp(a.p, b.p, bytes) == 0) {
516a8e1175bSopenharmony_ci        /* a == b: alias a and b */
517a8e1175bSopenharmony_ci
518a8e1175bSopenharmony_ci        /* a + a => Correct result */
519a8e1175bSopenharmony_ci        TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &a, &a, &m));
520a8e1175bSopenharmony_ci        TEST_COMPARE_MPI_RESIDUES(x, s);
521a8e1175bSopenharmony_ci
522a8e1175bSopenharmony_ci        /* a + a: x, a, b all aliased together => Correct result */
523a8e1175bSopenharmony_ci        memcpy(x.p, a.p, bytes);
524a8e1175bSopenharmony_ci        TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &x, &x, &m));
525a8e1175bSopenharmony_ci        TEST_COMPARE_MPI_RESIDUES(x, s);
526a8e1175bSopenharmony_ci    }
527a8e1175bSopenharmony_ci
528a8e1175bSopenharmony_ciexit:
529a8e1175bSopenharmony_ci    mbedtls_free((void *) m.p);  /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
530a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
531a8e1175bSopenharmony_ci
532a8e1175bSopenharmony_ci    mbedtls_free(a.p);
533a8e1175bSopenharmony_ci    mbedtls_free(b.p);
534a8e1175bSopenharmony_ci    mbedtls_free(s.p);
535a8e1175bSopenharmony_ci    mbedtls_free(X_raw);
536a8e1175bSopenharmony_ci}
537a8e1175bSopenharmony_ci/* END_CASE */
538a8e1175bSopenharmony_ci
539a8e1175bSopenharmony_ci/* BEGIN_CASE */
540a8e1175bSopenharmony_civoid mpi_residue_setup(char *input_N, char *input_R, int ret)
541a8e1175bSopenharmony_ci{
542a8e1175bSopenharmony_ci    mbedtls_mpi_uint *N = NULL;
543a8e1175bSopenharmony_ci    mbedtls_mpi_uint *R = NULL;
544a8e1175bSopenharmony_ci    size_t n_limbs, r_limbs;
545a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
546a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue r;
547a8e1175bSopenharmony_ci
548a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
549a8e1175bSopenharmony_ci
550a8e1175bSopenharmony_ci    /* Allocate the memory for intermediate data structures */
551a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
552a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&R, &r_limbs, input_R));
553a8e1175bSopenharmony_ci
554a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
555a8e1175bSopenharmony_ci
556a8e1175bSopenharmony_ci    TEST_EQUAL(ret, mbedtls_mpi_mod_residue_setup(&r, &m, R, r_limbs));
557a8e1175bSopenharmony_ci
558a8e1175bSopenharmony_ci    if (ret == 0) {
559a8e1175bSopenharmony_ci        TEST_EQUAL(r.limbs, r_limbs);
560a8e1175bSopenharmony_ci        TEST_ASSERT(r.p == R);
561a8e1175bSopenharmony_ci    }
562a8e1175bSopenharmony_ci
563a8e1175bSopenharmony_ciexit:
564a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
565a8e1175bSopenharmony_ci    mbedtls_free(N);
566a8e1175bSopenharmony_ci    mbedtls_free(R);
567a8e1175bSopenharmony_ci}
568a8e1175bSopenharmony_ci/* END_CASE */
569a8e1175bSopenharmony_ci
570a8e1175bSopenharmony_ci/* BEGIN_CASE */
571a8e1175bSopenharmony_civoid mpi_mod_io_neg(char *input_N, data_t *buf, int ret)
572a8e1175bSopenharmony_ci{
573a8e1175bSopenharmony_ci    mbedtls_mpi_uint *N = NULL;
574a8e1175bSopenharmony_ci    mbedtls_mpi_uint *R = NULL;
575a8e1175bSopenharmony_ci
576a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
577a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue r = { NULL, 0 };
578a8e1175bSopenharmony_ci    mbedtls_mpi_mod_ext_rep endian = MBEDTLS_MPI_MOD_EXT_REP_LE;
579a8e1175bSopenharmony_ci
580a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
581a8e1175bSopenharmony_ci
582a8e1175bSopenharmony_ci    size_t n_limbs;
583a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
584a8e1175bSopenharmony_ci    size_t r_limbs = n_limbs;
585a8e1175bSopenharmony_ci    TEST_CALLOC(R, r_limbs);
586a8e1175bSopenharmony_ci
587a8e1175bSopenharmony_ci    /* modulus->p == NULL || residue->p == NULL ( m has not been set-up ) */
588a8e1175bSopenharmony_ci    TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
589a8e1175bSopenharmony_ci               mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
590a8e1175bSopenharmony_ci
591a8e1175bSopenharmony_ci    TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
592a8e1175bSopenharmony_ci               mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
593a8e1175bSopenharmony_ci
594a8e1175bSopenharmony_ci    /* Set up modulus and test with residue->p == NULL */
595a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
596a8e1175bSopenharmony_ci
597a8e1175bSopenharmony_ci    TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
598a8e1175bSopenharmony_ci               mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
599a8e1175bSopenharmony_ci    TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
600a8e1175bSopenharmony_ci               mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
601a8e1175bSopenharmony_ci
602a8e1175bSopenharmony_ci    /* Do the rest of the tests with a residue set up with the input data */
603a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r, &m, R, r_limbs));
604a8e1175bSopenharmony_ci
605a8e1175bSopenharmony_ci    /* Fail for r_limbs < m->limbs */
606a8e1175bSopenharmony_ci    r.limbs--;
607a8e1175bSopenharmony_ci    TEST_ASSERT(r.limbs < m.limbs);
608a8e1175bSopenharmony_ci    TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
609a8e1175bSopenharmony_ci               mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
610a8e1175bSopenharmony_ci    TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
611a8e1175bSopenharmony_ci               mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
612a8e1175bSopenharmony_ci    r.limbs++;
613a8e1175bSopenharmony_ci
614a8e1175bSopenharmony_ci    /* Fail for r_limbs > m->limbs */
615a8e1175bSopenharmony_ci    m.limbs--;
616a8e1175bSopenharmony_ci    TEST_ASSERT(r.limbs > m.limbs);
617a8e1175bSopenharmony_ci    TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
618a8e1175bSopenharmony_ci               mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
619a8e1175bSopenharmony_ci    TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
620a8e1175bSopenharmony_ci               mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
621a8e1175bSopenharmony_ci    m.limbs++;
622a8e1175bSopenharmony_ci
623a8e1175bSopenharmony_ci    /* Test the read */
624a8e1175bSopenharmony_ci    TEST_EQUAL(ret, mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
625a8e1175bSopenharmony_ci
626a8e1175bSopenharmony_ci    /* Test write overflow only when the representation is large and read is successful  */
627a8e1175bSopenharmony_ci    if (r.limbs > 1 && ret == 0) {
628a8e1175bSopenharmony_ci        TEST_EQUAL(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL,
629a8e1175bSopenharmony_ci                   mbedtls_mpi_mod_write(&r, &m, buf->x, 1, endian));
630a8e1175bSopenharmony_ci    }
631a8e1175bSopenharmony_ci
632a8e1175bSopenharmony_ciexit:
633a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue_release(&r);
634a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
635a8e1175bSopenharmony_ci    mbedtls_free(N);
636a8e1175bSopenharmony_ci    mbedtls_free(R);
637a8e1175bSopenharmony_ci}
638a8e1175bSopenharmony_ci/* END_CASE */
639a8e1175bSopenharmony_ci
640a8e1175bSopenharmony_ci/* BEGIN_CASE */
641a8e1175bSopenharmony_civoid mpi_mod_io(char *input_N, data_t *input_A, int endian)
642a8e1175bSopenharmony_ci{
643a8e1175bSopenharmony_ci    mbedtls_mpi_uint *N = NULL;
644a8e1175bSopenharmony_ci    mbedtls_mpi_uint *R = NULL;
645a8e1175bSopenharmony_ci    mbedtls_mpi_uint *R_COPY = NULL;
646a8e1175bSopenharmony_ci    unsigned char *obuf = NULL;
647a8e1175bSopenharmony_ci    unsigned char *ref_buf = NULL;
648a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
649a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue r;
650a8e1175bSopenharmony_ci    mbedtls_mpi_mod_residue r_copy;
651a8e1175bSopenharmony_ci    size_t n_limbs, n_bytes, a_bytes;
652a8e1175bSopenharmony_ci
653a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
654a8e1175bSopenharmony_ci
655a8e1175bSopenharmony_ci    /* Read inputs */
656a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
657a8e1175bSopenharmony_ci    n_bytes = n_limbs * sizeof(mbedtls_mpi_uint);
658a8e1175bSopenharmony_ci    a_bytes = input_A->len;
659a8e1175bSopenharmony_ci
660a8e1175bSopenharmony_ci    /* Allocate the memory for intermediate data structures */
661a8e1175bSopenharmony_ci    TEST_CALLOC(R, n_bytes);
662a8e1175bSopenharmony_ci    TEST_CALLOC(R_COPY, n_bytes);
663a8e1175bSopenharmony_ci
664a8e1175bSopenharmony_ci    /* Test that input's size is not greater to modulo's */
665a8e1175bSopenharmony_ci    TEST_LE_U(a_bytes, n_bytes);
666a8e1175bSopenharmony_ci
667a8e1175bSopenharmony_ci    /* Init Structures */
668a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
669a8e1175bSopenharmony_ci
670a8e1175bSopenharmony_ci    /* Enforcing p_limbs >= m->limbs */
671a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r, &m, R, n_limbs));
672a8e1175bSopenharmony_ci
673a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_read(&r, &m, input_A->x, input_A->len,
674a8e1175bSopenharmony_ci                                       endian));
675a8e1175bSopenharmony_ci
676a8e1175bSopenharmony_ci    /* Read a copy for checking that writing didn't change the value of r */
677a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r_copy, &m,
678a8e1175bSopenharmony_ci                                                R_COPY, n_limbs));
679a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_read(&r_copy, &m, input_A->x, input_A->len,
680a8e1175bSopenharmony_ci                                       endian));
681a8e1175bSopenharmony_ci
682a8e1175bSopenharmony_ci    /* Get number of bytes without leading zeroes */
683a8e1175bSopenharmony_ci    size_t a_bytes_trimmed = a_bytes;
684a8e1175bSopenharmony_ci    while (a_bytes_trimmed > 0) {
685a8e1175bSopenharmony_ci        unsigned char *r_byte_array = (unsigned char *) r.p;
686a8e1175bSopenharmony_ci        if (r_byte_array[--a_bytes_trimmed] != 0) {
687a8e1175bSopenharmony_ci            break;
688a8e1175bSopenharmony_ci        }
689a8e1175bSopenharmony_ci    }
690a8e1175bSopenharmony_ci    a_bytes_trimmed++;
691a8e1175bSopenharmony_ci
692a8e1175bSopenharmony_ci    /* Test write with three output buffer sizes: tight, same as input and
693a8e1175bSopenharmony_ci     * longer than the input */
694a8e1175bSopenharmony_ci    size_t obuf_sizes[3];
695a8e1175bSopenharmony_ci    const size_t obuf_sizes_len = sizeof(obuf_sizes) / sizeof(obuf_sizes[0]);
696a8e1175bSopenharmony_ci    obuf_sizes[0] = a_bytes_trimmed;
697a8e1175bSopenharmony_ci    obuf_sizes[1] = a_bytes;
698a8e1175bSopenharmony_ci    obuf_sizes[2] = a_bytes + 8;
699a8e1175bSopenharmony_ci
700a8e1175bSopenharmony_ci    for (size_t i = 0; i < obuf_sizes_len; i++) {
701a8e1175bSopenharmony_ci        TEST_CALLOC(obuf, obuf_sizes[i]);
702a8e1175bSopenharmony_ci        TEST_EQUAL(0, mbedtls_mpi_mod_write(&r, &m, obuf, obuf_sizes[i], endian));
703a8e1175bSopenharmony_ci
704a8e1175bSopenharmony_ci        /* Make sure that writing didn't corrupt the value of r */
705a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(r.p, r.limbs, r_copy.p, r_copy.limbs);
706a8e1175bSopenharmony_ci
707a8e1175bSopenharmony_ci        /* Set up reference output for checking the result */
708a8e1175bSopenharmony_ci        TEST_CALLOC(ref_buf, obuf_sizes[i]);
709a8e1175bSopenharmony_ci        switch (endian) {
710a8e1175bSopenharmony_ci            case MBEDTLS_MPI_MOD_EXT_REP_LE:
711a8e1175bSopenharmony_ci                memcpy(ref_buf, input_A->x, a_bytes_trimmed);
712a8e1175bSopenharmony_ci                break;
713a8e1175bSopenharmony_ci            case MBEDTLS_MPI_MOD_EXT_REP_BE:
714a8e1175bSopenharmony_ci            {
715a8e1175bSopenharmony_ci                size_t a_offset = input_A->len - a_bytes_trimmed;
716a8e1175bSopenharmony_ci                size_t ref_offset = obuf_sizes[i] - a_bytes_trimmed;
717a8e1175bSopenharmony_ci                memcpy(ref_buf + ref_offset, input_A->x + a_offset,
718a8e1175bSopenharmony_ci                       a_bytes_trimmed);
719a8e1175bSopenharmony_ci            }
720a8e1175bSopenharmony_ci            break;
721a8e1175bSopenharmony_ci            default:
722a8e1175bSopenharmony_ci                TEST_ASSERT(0);
723a8e1175bSopenharmony_ci        }
724a8e1175bSopenharmony_ci
725a8e1175bSopenharmony_ci        /* Check the result */
726a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(obuf, obuf_sizes[i], ref_buf, obuf_sizes[i]);
727a8e1175bSopenharmony_ci
728a8e1175bSopenharmony_ci        mbedtls_free(ref_buf);
729a8e1175bSopenharmony_ci        ref_buf = NULL;
730a8e1175bSopenharmony_ci        mbedtls_free(obuf);
731a8e1175bSopenharmony_ci        obuf = NULL;
732a8e1175bSopenharmony_ci    }
733a8e1175bSopenharmony_ci
734a8e1175bSopenharmony_ciexit:
735a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
736a8e1175bSopenharmony_ci    mbedtls_free(N);
737a8e1175bSopenharmony_ci    mbedtls_free(R);
738a8e1175bSopenharmony_ci    mbedtls_free(R_COPY);
739a8e1175bSopenharmony_ci    mbedtls_free(obuf);
740a8e1175bSopenharmony_ci    mbedtls_free(ref_buf);
741a8e1175bSopenharmony_ci}
742a8e1175bSopenharmony_ci/* END_CASE */
743