1a8e1175bSopenharmony_ci/* BEGIN_HEADER */
2a8e1175bSopenharmony_ci#include "mbedtls/bignum.h"
3a8e1175bSopenharmony_ci#include "mbedtls/entropy.h"
4a8e1175bSopenharmony_ci#include "bignum_core.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#include "bignum_mod_raw_invasive.h"
10a8e1175bSopenharmony_ci
11a8e1175bSopenharmony_ci/* END_HEADER */
12a8e1175bSopenharmony_ci
13a8e1175bSopenharmony_ci/* BEGIN_DEPENDENCIES
14a8e1175bSopenharmony_ci * depends_on:MBEDTLS_BIGNUM_C:MBEDTLS_ECP_WITH_MPI_UINT
15a8e1175bSopenharmony_ci * END_DEPENDENCIES
16a8e1175bSopenharmony_ci */
17a8e1175bSopenharmony_ci
18a8e1175bSopenharmony_ci/* BEGIN_CASE */
19a8e1175bSopenharmony_civoid mpi_mod_raw_io(data_t *input, int nb_int, int nx_32_int,
20a8e1175bSopenharmony_ci                    int iendian, int iret, int oret)
21a8e1175bSopenharmony_ci{
22a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
23a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
24a8e1175bSopenharmony_ci
25a8e1175bSopenharmony_ci    if (iret != 0) {
26a8e1175bSopenharmony_ci        TEST_ASSERT(oret == 0);
27a8e1175bSopenharmony_ci    }
28a8e1175bSopenharmony_ci
29a8e1175bSopenharmony_ci    TEST_LE_S(0, nb_int);
30a8e1175bSopenharmony_ci    size_t nb = nb_int;
31a8e1175bSopenharmony_ci
32a8e1175bSopenharmony_ci    unsigned char buf[1024];
33a8e1175bSopenharmony_ci    TEST_LE_U(nb, sizeof(buf));
34a8e1175bSopenharmony_ci
35a8e1175bSopenharmony_ci    /* nx_32_int is the number of 32 bit limbs, if we have 64 bit limbs we need
36a8e1175bSopenharmony_ci     * to halve the number of limbs to have the same size. */
37a8e1175bSopenharmony_ci    size_t nx;
38a8e1175bSopenharmony_ci    TEST_LE_S(0, nx_32_int);
39a8e1175bSopenharmony_ci    if (sizeof(mbedtls_mpi_uint) == 8) {
40a8e1175bSopenharmony_ci        nx = nx_32_int / 2 + nx_32_int % 2;
41a8e1175bSopenharmony_ci    } else {
42a8e1175bSopenharmony_ci        nx = nx_32_int;
43a8e1175bSopenharmony_ci    }
44a8e1175bSopenharmony_ci
45a8e1175bSopenharmony_ci    mbedtls_mpi_uint X[sizeof(buf) / sizeof(mbedtls_mpi_uint)];
46a8e1175bSopenharmony_ci    TEST_LE_U(nx, sizeof(X) / sizeof(X[0]));
47a8e1175bSopenharmony_ci
48a8e1175bSopenharmony_ci    int endian;
49a8e1175bSopenharmony_ci    if (iendian == MBEDTLS_MPI_MOD_EXT_REP_INVALID) {
50a8e1175bSopenharmony_ci        endian = MBEDTLS_MPI_MOD_EXT_REP_LE;
51a8e1175bSopenharmony_ci    } else {
52a8e1175bSopenharmony_ci        endian = iendian;
53a8e1175bSopenharmony_ci    }
54a8e1175bSopenharmony_ci
55a8e1175bSopenharmony_ci    mbedtls_mpi_uint init[sizeof(X) / sizeof(X[0])];
56a8e1175bSopenharmony_ci    memset(init, 0xFF, sizeof(init));
57a8e1175bSopenharmony_ci    int ret = mbedtls_mpi_mod_modulus_setup(&m, init, nx);
58a8e1175bSopenharmony_ci    TEST_EQUAL(ret, 0);
59a8e1175bSopenharmony_ci
60a8e1175bSopenharmony_ci    if (iendian == MBEDTLS_MPI_MOD_EXT_REP_INVALID && iret != 0) {
61a8e1175bSopenharmony_ci        endian = MBEDTLS_MPI_MOD_EXT_REP_INVALID;
62a8e1175bSopenharmony_ci    }
63a8e1175bSopenharmony_ci
64a8e1175bSopenharmony_ci    ret = mbedtls_mpi_mod_raw_read(X, &m, input->x, input->len, endian);
65a8e1175bSopenharmony_ci    TEST_EQUAL(ret, iret);
66a8e1175bSopenharmony_ci
67a8e1175bSopenharmony_ci    if (iret == 0) {
68a8e1175bSopenharmony_ci        if (iendian == MBEDTLS_MPI_MOD_EXT_REP_INVALID && oret != 0) {
69a8e1175bSopenharmony_ci            endian = MBEDTLS_MPI_MOD_EXT_REP_INVALID;
70a8e1175bSopenharmony_ci        }
71a8e1175bSopenharmony_ci
72a8e1175bSopenharmony_ci        ret = mbedtls_mpi_mod_raw_write(X, &m, buf, nb, endian);
73a8e1175bSopenharmony_ci        TEST_EQUAL(ret, oret);
74a8e1175bSopenharmony_ci    }
75a8e1175bSopenharmony_ci
76a8e1175bSopenharmony_ci    if ((iret == 0) && (oret == 0)) {
77a8e1175bSopenharmony_ci        if (nb > input->len) {
78a8e1175bSopenharmony_ci            if (endian == MBEDTLS_MPI_MOD_EXT_REP_BE) {
79a8e1175bSopenharmony_ci                size_t leading_zeroes = nb - input->len;
80a8e1175bSopenharmony_ci                TEST_ASSERT(memcmp(buf + nb - input->len, input->x, input->len) == 0);
81a8e1175bSopenharmony_ci                for (size_t i = 0; i < leading_zeroes; i++) {
82a8e1175bSopenharmony_ci                    TEST_EQUAL(buf[i], 0);
83a8e1175bSopenharmony_ci                }
84a8e1175bSopenharmony_ci            } else {
85a8e1175bSopenharmony_ci                TEST_ASSERT(memcmp(buf, input->x, input->len) == 0);
86a8e1175bSopenharmony_ci                for (size_t i = input->len; i < nb; i++) {
87a8e1175bSopenharmony_ci                    TEST_EQUAL(buf[i], 0);
88a8e1175bSopenharmony_ci                }
89a8e1175bSopenharmony_ci            }
90a8e1175bSopenharmony_ci        } else {
91a8e1175bSopenharmony_ci            if (endian == MBEDTLS_MPI_MOD_EXT_REP_BE) {
92a8e1175bSopenharmony_ci                size_t leading_zeroes = input->len - nb;
93a8e1175bSopenharmony_ci                TEST_ASSERT(memcmp(input->x + input->len - nb, buf, nb) == 0);
94a8e1175bSopenharmony_ci                for (size_t i = 0; i < leading_zeroes; i++) {
95a8e1175bSopenharmony_ci                    TEST_EQUAL(input->x[i], 0);
96a8e1175bSopenharmony_ci                }
97a8e1175bSopenharmony_ci            } else {
98a8e1175bSopenharmony_ci                TEST_ASSERT(memcmp(input->x, buf, nb) == 0);
99a8e1175bSopenharmony_ci                for (size_t i = nb; i < input->len; i++) {
100a8e1175bSopenharmony_ci                    TEST_EQUAL(input->x[i], 0);
101a8e1175bSopenharmony_ci                }
102a8e1175bSopenharmony_ci            }
103a8e1175bSopenharmony_ci        }
104a8e1175bSopenharmony_ci    }
105a8e1175bSopenharmony_ci
106a8e1175bSopenharmony_ciexit:
107a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
108a8e1175bSopenharmony_ci}
109a8e1175bSopenharmony_ci/* END_CASE */
110a8e1175bSopenharmony_ci
111a8e1175bSopenharmony_ci/* BEGIN_CASE */
112a8e1175bSopenharmony_civoid mpi_mod_raw_cond_assign(char *input_X,
113a8e1175bSopenharmony_ci                             char *input_Y,
114a8e1175bSopenharmony_ci                             int input_bytes)
115a8e1175bSopenharmony_ci{
116a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
117a8e1175bSopenharmony_ci    mbedtls_mpi_uint *Y = NULL;
118a8e1175bSopenharmony_ci    mbedtls_mpi_uint *buff_m = NULL;
119a8e1175bSopenharmony_ci    size_t limbs_X;
120a8e1175bSopenharmony_ci    size_t limbs_Y;
121a8e1175bSopenharmony_ci
122a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
123a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
124a8e1175bSopenharmony_ci
125a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&X, &limbs_X, input_X), 0);
126a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&Y, &limbs_Y, input_Y), 0);
127a8e1175bSopenharmony_ci
128a8e1175bSopenharmony_ci    size_t limbs = limbs_X;
129a8e1175bSopenharmony_ci    size_t copy_limbs = CHARS_TO_LIMBS(input_bytes);
130a8e1175bSopenharmony_ci    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
131a8e1175bSopenharmony_ci    size_t copy_bytes = copy_limbs * sizeof(mbedtls_mpi_uint);
132a8e1175bSopenharmony_ci
133a8e1175bSopenharmony_ci    TEST_EQUAL(limbs_X, limbs_Y);
134a8e1175bSopenharmony_ci    TEST_ASSERT(copy_limbs <= limbs);
135a8e1175bSopenharmony_ci
136a8e1175bSopenharmony_ci    TEST_CALLOC(buff_m, copy_limbs);
137a8e1175bSopenharmony_ci    memset(buff_m, 0xFF, copy_limbs);
138a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
139a8e1175bSopenharmony_ci                   &m, buff_m, copy_limbs), 0);
140a8e1175bSopenharmony_ci
141a8e1175bSopenharmony_ci    /* condition is false */
142a8e1175bSopenharmony_ci    TEST_CF_SECRET(X, bytes);
143a8e1175bSopenharmony_ci    TEST_CF_SECRET(Y, bytes);
144a8e1175bSopenharmony_ci
145a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_cond_assign(X, Y, &m, 0);
146a8e1175bSopenharmony_ci
147a8e1175bSopenharmony_ci    TEST_CF_PUBLIC(X, bytes);
148a8e1175bSopenharmony_ci    TEST_CF_PUBLIC(Y, bytes);
149a8e1175bSopenharmony_ci
150a8e1175bSopenharmony_ci    TEST_ASSERT(memcmp(X, Y, bytes) != 0);
151a8e1175bSopenharmony_ci
152a8e1175bSopenharmony_ci    /* condition is true */
153a8e1175bSopenharmony_ci    TEST_CF_SECRET(X, bytes);
154a8e1175bSopenharmony_ci    TEST_CF_SECRET(Y, bytes);
155a8e1175bSopenharmony_ci
156a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_cond_assign(X, Y, &m, 1);
157a8e1175bSopenharmony_ci
158a8e1175bSopenharmony_ci    TEST_CF_PUBLIC(X, bytes);
159a8e1175bSopenharmony_ci    TEST_CF_PUBLIC(Y, bytes);
160a8e1175bSopenharmony_ci
161a8e1175bSopenharmony_ci    /* Check if the given length is copied even it is smaller
162a8e1175bSopenharmony_ci       than the length of the given MPIs. */
163a8e1175bSopenharmony_ci    if (copy_limbs < limbs) {
164a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, copy_bytes, Y, copy_bytes);
165a8e1175bSopenharmony_ci        TEST_ASSERT(memcmp(X, Y, bytes) != 0);
166a8e1175bSopenharmony_ci    } else {
167a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, Y, bytes);
168a8e1175bSopenharmony_ci    }
169a8e1175bSopenharmony_ci
170a8e1175bSopenharmony_ciexit:
171a8e1175bSopenharmony_ci    mbedtls_free(X);
172a8e1175bSopenharmony_ci    mbedtls_free(Y);
173a8e1175bSopenharmony_ci
174a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
175a8e1175bSopenharmony_ci    mbedtls_free(buff_m);
176a8e1175bSopenharmony_ci}
177a8e1175bSopenharmony_ci/* END_CASE */
178a8e1175bSopenharmony_ci
179a8e1175bSopenharmony_ci/* BEGIN_CASE */
180a8e1175bSopenharmony_civoid mpi_mod_raw_cond_swap(char *input_X,
181a8e1175bSopenharmony_ci                           char *input_Y,
182a8e1175bSopenharmony_ci                           int input_bytes)
183a8e1175bSopenharmony_ci{
184a8e1175bSopenharmony_ci    mbedtls_mpi_uint *tmp_X = NULL;
185a8e1175bSopenharmony_ci    mbedtls_mpi_uint *tmp_Y = NULL;
186a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
187a8e1175bSopenharmony_ci    mbedtls_mpi_uint *Y = NULL;
188a8e1175bSopenharmony_ci    mbedtls_mpi_uint *buff_m = NULL;
189a8e1175bSopenharmony_ci    size_t limbs_X;
190a8e1175bSopenharmony_ci    size_t limbs_Y;
191a8e1175bSopenharmony_ci
192a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
193a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
194a8e1175bSopenharmony_ci
195a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&tmp_X, &limbs_X, input_X), 0);
196a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&tmp_Y, &limbs_Y, input_Y), 0);
197a8e1175bSopenharmony_ci
198a8e1175bSopenharmony_ci    size_t limbs = limbs_X;
199a8e1175bSopenharmony_ci    size_t copy_limbs = CHARS_TO_LIMBS(input_bytes);
200a8e1175bSopenharmony_ci    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
201a8e1175bSopenharmony_ci    size_t copy_bytes = copy_limbs * sizeof(mbedtls_mpi_uint);
202a8e1175bSopenharmony_ci
203a8e1175bSopenharmony_ci    TEST_EQUAL(limbs_X, limbs_Y);
204a8e1175bSopenharmony_ci    TEST_ASSERT(copy_limbs <= limbs);
205a8e1175bSopenharmony_ci
206a8e1175bSopenharmony_ci    TEST_CALLOC(buff_m, copy_limbs);
207a8e1175bSopenharmony_ci    memset(buff_m, 0xFF, copy_limbs);
208a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
209a8e1175bSopenharmony_ci                   &m, buff_m, copy_limbs), 0);
210a8e1175bSopenharmony_ci
211a8e1175bSopenharmony_ci    TEST_CALLOC(X, limbs);
212a8e1175bSopenharmony_ci    memcpy(X, tmp_X, bytes);
213a8e1175bSopenharmony_ci
214a8e1175bSopenharmony_ci    TEST_CALLOC(Y, bytes);
215a8e1175bSopenharmony_ci    memcpy(Y, tmp_Y, bytes);
216a8e1175bSopenharmony_ci
217a8e1175bSopenharmony_ci    /* condition is false */
218a8e1175bSopenharmony_ci    TEST_CF_SECRET(X, bytes);
219a8e1175bSopenharmony_ci    TEST_CF_SECRET(Y, bytes);
220a8e1175bSopenharmony_ci
221a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_cond_swap(X, Y, &m, 0);
222a8e1175bSopenharmony_ci
223a8e1175bSopenharmony_ci    TEST_CF_PUBLIC(X, bytes);
224a8e1175bSopenharmony_ci    TEST_CF_PUBLIC(Y, bytes);
225a8e1175bSopenharmony_ci
226a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(X, bytes, tmp_X, bytes);
227a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(Y, bytes, tmp_Y, bytes);
228a8e1175bSopenharmony_ci
229a8e1175bSopenharmony_ci    /* condition is true */
230a8e1175bSopenharmony_ci    TEST_CF_SECRET(X, bytes);
231a8e1175bSopenharmony_ci    TEST_CF_SECRET(Y, bytes);
232a8e1175bSopenharmony_ci
233a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_cond_swap(X, Y, &m, 1);
234a8e1175bSopenharmony_ci
235a8e1175bSopenharmony_ci    TEST_CF_PUBLIC(X, bytes);
236a8e1175bSopenharmony_ci    TEST_CF_PUBLIC(Y, bytes);
237a8e1175bSopenharmony_ci
238a8e1175bSopenharmony_ci    /* Check if the given length is copied even it is smaller
239a8e1175bSopenharmony_ci       than the length of the given MPIs. */
240a8e1175bSopenharmony_ci    if (copy_limbs < limbs) {
241a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, copy_bytes, tmp_Y, copy_bytes);
242a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(Y, copy_bytes, tmp_X, copy_bytes);
243a8e1175bSopenharmony_ci        TEST_ASSERT(memcmp(X, tmp_X, bytes) != 0);
244a8e1175bSopenharmony_ci        TEST_ASSERT(memcmp(X, tmp_Y, bytes) != 0);
245a8e1175bSopenharmony_ci        TEST_ASSERT(memcmp(Y, tmp_X, bytes) != 0);
246a8e1175bSopenharmony_ci        TEST_ASSERT(memcmp(Y, tmp_Y, bytes) != 0);
247a8e1175bSopenharmony_ci    } else {
248a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, tmp_Y, bytes);
249a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(Y, bytes, tmp_X, bytes);
250a8e1175bSopenharmony_ci    }
251a8e1175bSopenharmony_ci
252a8e1175bSopenharmony_ciexit:
253a8e1175bSopenharmony_ci    mbedtls_free(tmp_X);
254a8e1175bSopenharmony_ci    mbedtls_free(tmp_Y);
255a8e1175bSopenharmony_ci    mbedtls_free(X);
256a8e1175bSopenharmony_ci    mbedtls_free(Y);
257a8e1175bSopenharmony_ci
258a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
259a8e1175bSopenharmony_ci    mbedtls_free(buff_m);
260a8e1175bSopenharmony_ci}
261a8e1175bSopenharmony_ci/* END_CASE */
262a8e1175bSopenharmony_ci
263a8e1175bSopenharmony_ci/* BEGIN_CASE */
264a8e1175bSopenharmony_civoid mpi_mod_raw_sub(char *input_A,
265a8e1175bSopenharmony_ci                     char *input_B,
266a8e1175bSopenharmony_ci                     char *input_N,
267a8e1175bSopenharmony_ci                     char *result)
268a8e1175bSopenharmony_ci{
269a8e1175bSopenharmony_ci    mbedtls_mpi_uint *A = NULL;
270a8e1175bSopenharmony_ci    mbedtls_mpi_uint *B = NULL;
271a8e1175bSopenharmony_ci    mbedtls_mpi_uint *N = NULL;
272a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
273a8e1175bSopenharmony_ci    mbedtls_mpi_uint *res = NULL;
274a8e1175bSopenharmony_ci    size_t limbs_A;
275a8e1175bSopenharmony_ci    size_t limbs_B;
276a8e1175bSopenharmony_ci    size_t limbs_N;
277a8e1175bSopenharmony_ci    size_t limbs_res;
278a8e1175bSopenharmony_ci
279a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
280a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
281a8e1175bSopenharmony_ci
282a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&A,   &limbs_A,   input_A), 0);
283a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&B,   &limbs_B,   input_B), 0);
284a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&N,   &limbs_N,   input_N), 0);
285a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&res, &limbs_res, result), 0);
286a8e1175bSopenharmony_ci
287a8e1175bSopenharmony_ci    size_t limbs = limbs_N;
288a8e1175bSopenharmony_ci    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
289a8e1175bSopenharmony_ci
290a8e1175bSopenharmony_ci    TEST_EQUAL(limbs_A,   limbs);
291a8e1175bSopenharmony_ci    TEST_EQUAL(limbs_B,   limbs);
292a8e1175bSopenharmony_ci    TEST_EQUAL(limbs_res, limbs);
293a8e1175bSopenharmony_ci
294a8e1175bSopenharmony_ci    TEST_CALLOC(X, limbs);
295a8e1175bSopenharmony_ci
296a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
297a8e1175bSopenharmony_ci                   &m, N, limbs), 0);
298a8e1175bSopenharmony_ci
299a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_sub(X, A, B, &m);
300a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(X, bytes, res, bytes);
301a8e1175bSopenharmony_ci
302a8e1175bSopenharmony_ci    /* alias X to A */
303a8e1175bSopenharmony_ci    memcpy(X, A, bytes);
304a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_sub(X, X, B, &m);
305a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(X, bytes, res, bytes);
306a8e1175bSopenharmony_ci
307a8e1175bSopenharmony_ci    /* alias X to B */
308a8e1175bSopenharmony_ci    memcpy(X, B, bytes);
309a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_sub(X, A, X, &m);
310a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(X, bytes, res, bytes);
311a8e1175bSopenharmony_ci
312a8e1175bSopenharmony_ci    /* A == B: alias A and B */
313a8e1175bSopenharmony_ci    if (memcmp(A, B, bytes) == 0) {
314a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_sub(X, A, A, &m);
315a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, res, bytes);
316a8e1175bSopenharmony_ci
317a8e1175bSopenharmony_ci        /* X, A, B all aliased together */
318a8e1175bSopenharmony_ci        memcpy(X, A, bytes);
319a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_sub(X, X, X, &m);
320a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, res, bytes);
321a8e1175bSopenharmony_ci    }
322a8e1175bSopenharmony_ciexit:
323a8e1175bSopenharmony_ci    mbedtls_free(A);
324a8e1175bSopenharmony_ci    mbedtls_free(B);
325a8e1175bSopenharmony_ci    mbedtls_free(X);
326a8e1175bSopenharmony_ci    mbedtls_free(res);
327a8e1175bSopenharmony_ci
328a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
329a8e1175bSopenharmony_ci    mbedtls_free(N);
330a8e1175bSopenharmony_ci}
331a8e1175bSopenharmony_ci/* END_CASE */
332a8e1175bSopenharmony_ci
333a8e1175bSopenharmony_ci/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
334a8e1175bSopenharmony_civoid mpi_mod_raw_fix_quasi_reduction(char *input_N,
335a8e1175bSopenharmony_ci                                     char *input_X,
336a8e1175bSopenharmony_ci                                     char *result)
337a8e1175bSopenharmony_ci{
338a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
339a8e1175bSopenharmony_ci    mbedtls_mpi_uint *N = NULL;
340a8e1175bSopenharmony_ci    mbedtls_mpi_uint *res = NULL;
341a8e1175bSopenharmony_ci    mbedtls_mpi_uint *tmp = NULL;
342a8e1175bSopenharmony_ci    size_t limbs_X;
343a8e1175bSopenharmony_ci    size_t limbs_N;
344a8e1175bSopenharmony_ci    size_t limbs_res;
345a8e1175bSopenharmony_ci
346a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
347a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
348a8e1175bSopenharmony_ci
349a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&X,   &limbs_X,   input_X), 0);
350a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&N,   &limbs_N,   input_N), 0);
351a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&res, &limbs_res, result),  0);
352a8e1175bSopenharmony_ci
353a8e1175bSopenharmony_ci    size_t limbs = limbs_N;
354a8e1175bSopenharmony_ci    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
355a8e1175bSopenharmony_ci
356a8e1175bSopenharmony_ci    TEST_EQUAL(limbs_X,   limbs);
357a8e1175bSopenharmony_ci    TEST_EQUAL(limbs_res, limbs);
358a8e1175bSopenharmony_ci
359a8e1175bSopenharmony_ci    TEST_CALLOC(tmp, limbs);
360a8e1175bSopenharmony_ci    memcpy(tmp, X, bytes);
361a8e1175bSopenharmony_ci
362a8e1175bSopenharmony_ci    /* Check that 0 <= X < 2N */
363a8e1175bSopenharmony_ci    mbedtls_mpi_uint c = mbedtls_mpi_core_sub(tmp, X, N, limbs);
364a8e1175bSopenharmony_ci    TEST_ASSERT(c || mbedtls_mpi_core_lt_ct(tmp, N, limbs));
365a8e1175bSopenharmony_ci
366a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
367a8e1175bSopenharmony_ci                   &m, N, limbs), 0);
368a8e1175bSopenharmony_ci
369a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_fix_quasi_reduction(X, &m);
370a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(X, bytes, res, bytes);
371a8e1175bSopenharmony_ci
372a8e1175bSopenharmony_ciexit:
373a8e1175bSopenharmony_ci    mbedtls_free(X);
374a8e1175bSopenharmony_ci    mbedtls_free(res);
375a8e1175bSopenharmony_ci    mbedtls_free(tmp);
376a8e1175bSopenharmony_ci
377a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
378a8e1175bSopenharmony_ci    mbedtls_free(N);
379a8e1175bSopenharmony_ci}
380a8e1175bSopenharmony_ci/* END_CASE */
381a8e1175bSopenharmony_ci
382a8e1175bSopenharmony_ci/* BEGIN_CASE */
383a8e1175bSopenharmony_civoid mpi_mod_raw_mul(char *input_A,
384a8e1175bSopenharmony_ci                     char *input_B,
385a8e1175bSopenharmony_ci                     char *input_N,
386a8e1175bSopenharmony_ci                     char *result)
387a8e1175bSopenharmony_ci{
388a8e1175bSopenharmony_ci    mbedtls_mpi_uint *A = NULL;
389a8e1175bSopenharmony_ci    mbedtls_mpi_uint *B = NULL;
390a8e1175bSopenharmony_ci    mbedtls_mpi_uint *N = NULL;
391a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
392a8e1175bSopenharmony_ci    mbedtls_mpi_uint *R = NULL;
393a8e1175bSopenharmony_ci    mbedtls_mpi_uint *T = NULL;
394a8e1175bSopenharmony_ci    size_t limbs_A;
395a8e1175bSopenharmony_ci    size_t limbs_B;
396a8e1175bSopenharmony_ci    size_t limbs_N;
397a8e1175bSopenharmony_ci    size_t limbs_R;
398a8e1175bSopenharmony_ci
399a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
400a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
401a8e1175bSopenharmony_ci
402a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&A, &limbs_A, input_A), 0);
403a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&B, &limbs_B, input_B), 0);
404a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&N, &limbs_N, input_N), 0);
405a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_test_read_mpi_core(&R, &limbs_R, result), 0);
406a8e1175bSopenharmony_ci
407a8e1175bSopenharmony_ci    const size_t limbs = limbs_N;
408a8e1175bSopenharmony_ci    const size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
409a8e1175bSopenharmony_ci
410a8e1175bSopenharmony_ci    TEST_EQUAL(limbs_A, limbs);
411a8e1175bSopenharmony_ci    TEST_EQUAL(limbs_B, limbs);
412a8e1175bSopenharmony_ci    TEST_EQUAL(limbs_R, limbs);
413a8e1175bSopenharmony_ci
414a8e1175bSopenharmony_ci    TEST_CALLOC(X, limbs);
415a8e1175bSopenharmony_ci
416a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
417a8e1175bSopenharmony_ci                   &m, N, limbs), 0);
418a8e1175bSopenharmony_ci
419a8e1175bSopenharmony_ci    const size_t limbs_T = limbs * 2 + 1;
420a8e1175bSopenharmony_ci    TEST_CALLOC(T, limbs_T);
421a8e1175bSopenharmony_ci
422a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_mul(X, A, B, &m, T);
423a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(X, bytes, R, bytes);
424a8e1175bSopenharmony_ci
425a8e1175bSopenharmony_ci    /* alias X to A */
426a8e1175bSopenharmony_ci    memcpy(X, A, bytes);
427a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_mul(X, X, B, &m, T);
428a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(X, bytes, R, bytes);
429a8e1175bSopenharmony_ci
430a8e1175bSopenharmony_ci    /* alias X to B */
431a8e1175bSopenharmony_ci    memcpy(X, B, bytes);
432a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_mul(X, A, X, &m, T);
433a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(X, bytes, R, bytes);
434a8e1175bSopenharmony_ci
435a8e1175bSopenharmony_ci    /* A == B: alias A and B */
436a8e1175bSopenharmony_ci    if (memcmp(A, B, bytes) == 0) {
437a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_mul(X, A, A, &m, T);
438a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, R, bytes);
439a8e1175bSopenharmony_ci
440a8e1175bSopenharmony_ci        /* X, A, B all aliased together */
441a8e1175bSopenharmony_ci        memcpy(X, A, bytes);
442a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_mul(X, X, X, &m, T);
443a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, R, bytes);
444a8e1175bSopenharmony_ci    }
445a8e1175bSopenharmony_ci    /* A != B: test B * A */
446a8e1175bSopenharmony_ci    else {
447a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_mul(X, B, A, &m, T);
448a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, R, bytes);
449a8e1175bSopenharmony_ci
450a8e1175bSopenharmony_ci        /* B * A: alias X to A */
451a8e1175bSopenharmony_ci        memcpy(X, A, bytes);
452a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_mul(X, B, X, &m, T);
453a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, R, bytes);
454a8e1175bSopenharmony_ci
455a8e1175bSopenharmony_ci        /* B + A: alias X to B */
456a8e1175bSopenharmony_ci        memcpy(X, B, bytes);
457a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_mul(X, X, A, &m, T);
458a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, R, bytes);
459a8e1175bSopenharmony_ci    }
460a8e1175bSopenharmony_ci
461a8e1175bSopenharmony_ciexit:
462a8e1175bSopenharmony_ci    mbedtls_free(A);
463a8e1175bSopenharmony_ci    mbedtls_free(B);
464a8e1175bSopenharmony_ci    mbedtls_free(X);
465a8e1175bSopenharmony_ci    mbedtls_free(R);
466a8e1175bSopenharmony_ci    mbedtls_free(T);
467a8e1175bSopenharmony_ci
468a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
469a8e1175bSopenharmony_ci    mbedtls_free(N);
470a8e1175bSopenharmony_ci}
471a8e1175bSopenharmony_ci/* END_CASE */
472a8e1175bSopenharmony_ci
473a8e1175bSopenharmony_ci/* BEGIN_CASE */
474a8e1175bSopenharmony_civoid mpi_mod_raw_inv_prime(char *input_N, char *input_A, char *input_X)
475a8e1175bSopenharmony_ci{
476a8e1175bSopenharmony_ci    mbedtls_mpi_uint *A = NULL;
477a8e1175bSopenharmony_ci    mbedtls_mpi_uint *N = NULL;
478a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
479a8e1175bSopenharmony_ci    size_t A_limbs, N_limbs, X_limbs;
480a8e1175bSopenharmony_ci    mbedtls_mpi_uint *Y = NULL;
481a8e1175bSopenharmony_ci    mbedtls_mpi_uint *T = NULL;
482a8e1175bSopenharmony_ci    const mbedtls_mpi_uint *R2 = NULL;
483a8e1175bSopenharmony_ci
484a8e1175bSopenharmony_ci    /* Legacy MPIs for computing R2 */
485a8e1175bSopenharmony_ci    mbedtls_mpi N_mpi;  /* gets set up manually, aliasing N, so no need to free */
486a8e1175bSopenharmony_ci    mbedtls_mpi R2_mpi;
487a8e1175bSopenharmony_ci    mbedtls_mpi_init(&R2_mpi);
488a8e1175bSopenharmony_ci
489a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &A_limbs, input_A));
490a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &N_limbs, input_N));
491a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X));
492a8e1175bSopenharmony_ci    TEST_CALLOC(Y, N_limbs);
493a8e1175bSopenharmony_ci
494a8e1175bSopenharmony_ci    TEST_EQUAL(A_limbs, N_limbs);
495a8e1175bSopenharmony_ci    TEST_EQUAL(X_limbs, N_limbs);
496a8e1175bSopenharmony_ci
497a8e1175bSopenharmony_ci    N_mpi.s = 1;
498a8e1175bSopenharmony_ci    N_mpi.p = N;
499a8e1175bSopenharmony_ci    N_mpi.n = N_limbs;
500a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_core_get_mont_r2_unsafe(&R2_mpi, &N_mpi));
501a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_grow(&R2_mpi, N_limbs));
502a8e1175bSopenharmony_ci    R2 = R2_mpi.p;
503a8e1175bSopenharmony_ci
504a8e1175bSopenharmony_ci    size_t working_limbs = mbedtls_mpi_mod_raw_inv_prime_working_limbs(N_limbs);
505a8e1175bSopenharmony_ci
506a8e1175bSopenharmony_ci    /* No point exactly duplicating the code in mbedtls_mpi_mod_raw_inv_prime_working_limbs()
507a8e1175bSopenharmony_ci     * to see if the output is correct, but we can check that it's in a
508a8e1175bSopenharmony_ci     * reasonable range.  The current calculation works out as
509a8e1175bSopenharmony_ci     * `1 + N_limbs * (welem + 4)`, where welem is the number of elements in
510a8e1175bSopenharmony_ci     * the window (1 << 1 up to 1 << 6).
511a8e1175bSopenharmony_ci     */
512a8e1175bSopenharmony_ci    size_t min_expected_working_limbs = 1 + N_limbs * 5;
513a8e1175bSopenharmony_ci    size_t max_expected_working_limbs = 1 + N_limbs * 68;
514a8e1175bSopenharmony_ci
515a8e1175bSopenharmony_ci    TEST_LE_U(min_expected_working_limbs, working_limbs);
516a8e1175bSopenharmony_ci    TEST_LE_U(working_limbs, max_expected_working_limbs);
517a8e1175bSopenharmony_ci
518a8e1175bSopenharmony_ci    /* Should also be at least mbedtls_mpi_core_montmul_working_limbs() */
519a8e1175bSopenharmony_ci    TEST_LE_U(mbedtls_mpi_core_montmul_working_limbs(N_limbs),
520a8e1175bSopenharmony_ci              working_limbs);
521a8e1175bSopenharmony_ci
522a8e1175bSopenharmony_ci    TEST_CALLOC(T, working_limbs);
523a8e1175bSopenharmony_ci
524a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_inv_prime(Y, A, N, N_limbs, R2, T);
525a8e1175bSopenharmony_ci
526a8e1175bSopenharmony_ci    TEST_EQUAL(0, memcmp(X, Y, N_limbs * sizeof(mbedtls_mpi_uint)));
527a8e1175bSopenharmony_ci
528a8e1175bSopenharmony_ci    /* Check when output aliased to input */
529a8e1175bSopenharmony_ci
530a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_inv_prime(A, A, N, N_limbs, R2, T);
531a8e1175bSopenharmony_ci
532a8e1175bSopenharmony_ci    TEST_EQUAL(0, memcmp(X, A, N_limbs * sizeof(mbedtls_mpi_uint)));
533a8e1175bSopenharmony_ci
534a8e1175bSopenharmony_ciexit:
535a8e1175bSopenharmony_ci    mbedtls_free(T);
536a8e1175bSopenharmony_ci    mbedtls_free(A);
537a8e1175bSopenharmony_ci    mbedtls_free(N);
538a8e1175bSopenharmony_ci    mbedtls_free(X);
539a8e1175bSopenharmony_ci    mbedtls_free(Y);
540a8e1175bSopenharmony_ci    mbedtls_mpi_free(&R2_mpi);
541a8e1175bSopenharmony_ci    // R2 doesn't need to be freed as it is only aliasing R2_mpi
542a8e1175bSopenharmony_ci    // N_mpi doesn't need to be freed as it is only aliasing N
543a8e1175bSopenharmony_ci}
544a8e1175bSopenharmony_ci/* END_CASE */
545a8e1175bSopenharmony_ci
546a8e1175bSopenharmony_ci/* BEGIN_CASE */
547a8e1175bSopenharmony_civoid mpi_mod_raw_add(char *input_N,
548a8e1175bSopenharmony_ci                     char *input_A, char *input_B,
549a8e1175bSopenharmony_ci                     char *input_S)
550a8e1175bSopenharmony_ci{
551a8e1175bSopenharmony_ci    mbedtls_mpi_uint *A = NULL;
552a8e1175bSopenharmony_ci    mbedtls_mpi_uint *B = NULL;
553a8e1175bSopenharmony_ci    mbedtls_mpi_uint *S = NULL;
554a8e1175bSopenharmony_ci    mbedtls_mpi_uint *N = NULL;
555a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
556a8e1175bSopenharmony_ci    size_t A_limbs, B_limbs, N_limbs, S_limbs;
557a8e1175bSopenharmony_ci
558a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
559a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
560a8e1175bSopenharmony_ci
561a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &A_limbs, input_A));
562a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&B, &B_limbs, input_B));
563a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &N_limbs, input_N));
564a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&S, &S_limbs, input_S));
565a8e1175bSopenharmony_ci
566a8e1175bSopenharmony_ci    /* Modulus gives the number of limbs; all inputs must have the same. */
567a8e1175bSopenharmony_ci    size_t limbs = N_limbs;
568a8e1175bSopenharmony_ci    size_t bytes = limbs * sizeof(*A);
569a8e1175bSopenharmony_ci
570a8e1175bSopenharmony_ci    TEST_EQUAL(A_limbs, limbs);
571a8e1175bSopenharmony_ci    TEST_EQUAL(B_limbs, limbs);
572a8e1175bSopenharmony_ci    TEST_EQUAL(S_limbs, limbs);
573a8e1175bSopenharmony_ci
574a8e1175bSopenharmony_ci    TEST_CALLOC(X, limbs);
575a8e1175bSopenharmony_ci
576a8e1175bSopenharmony_ci    TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
577a8e1175bSopenharmony_ci                   &m, N, limbs), 0);
578a8e1175bSopenharmony_ci
579a8e1175bSopenharmony_ci    /* A + B => Correct result */
580a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_add(X, A, B, &m);
581a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(X, bytes, S, bytes);
582a8e1175bSopenharmony_ci
583a8e1175bSopenharmony_ci    /* A + B: alias X to A => Correct result */
584a8e1175bSopenharmony_ci    memcpy(X, A, bytes);
585a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_add(X, X, B, &m);
586a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(X, bytes, S, bytes);
587a8e1175bSopenharmony_ci
588a8e1175bSopenharmony_ci    /* A + B: alias X to B => Correct result */
589a8e1175bSopenharmony_ci    memcpy(X, B, bytes);
590a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_add(X, A, X, &m);
591a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(X, bytes, S, bytes);
592a8e1175bSopenharmony_ci
593a8e1175bSopenharmony_ci    if (memcmp(A, B, bytes) == 0) {
594a8e1175bSopenharmony_ci        /* A == B: alias A and B */
595a8e1175bSopenharmony_ci
596a8e1175bSopenharmony_ci        /* A + A => Correct result */
597a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_add(X, A, A, &m);
598a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
599a8e1175bSopenharmony_ci
600a8e1175bSopenharmony_ci        /* A + A: X, A, B all aliased together => Correct result */
601a8e1175bSopenharmony_ci        memcpy(X, A, bytes);
602a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_add(X, X, X, &m);
603a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
604a8e1175bSopenharmony_ci    } else {
605a8e1175bSopenharmony_ci        /* A != B: test B + A */
606a8e1175bSopenharmony_ci
607a8e1175bSopenharmony_ci        /* B + A => Correct result */
608a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_add(X, B, A, &m);
609a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
610a8e1175bSopenharmony_ci
611a8e1175bSopenharmony_ci        /* B + A: alias X to A => Correct result */
612a8e1175bSopenharmony_ci        memcpy(X, A, bytes);
613a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_add(X, B, X, &m);
614a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
615a8e1175bSopenharmony_ci
616a8e1175bSopenharmony_ci        /* B + A: alias X to B => Correct result */
617a8e1175bSopenharmony_ci        memcpy(X, B, bytes);
618a8e1175bSopenharmony_ci        mbedtls_mpi_mod_raw_add(X, X, A, &m);
619a8e1175bSopenharmony_ci        TEST_MEMORY_COMPARE(X, bytes, S, bytes);
620a8e1175bSopenharmony_ci    }
621a8e1175bSopenharmony_ci
622a8e1175bSopenharmony_ciexit:
623a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
624a8e1175bSopenharmony_ci
625a8e1175bSopenharmony_ci    mbedtls_free(A);
626a8e1175bSopenharmony_ci    mbedtls_free(B);
627a8e1175bSopenharmony_ci    mbedtls_free(S);
628a8e1175bSopenharmony_ci    mbedtls_free(N);
629a8e1175bSopenharmony_ci    mbedtls_free(X);
630a8e1175bSopenharmony_ci}
631a8e1175bSopenharmony_ci/* END_CASE */
632a8e1175bSopenharmony_ci
633a8e1175bSopenharmony_ci/* BEGIN_CASE */
634a8e1175bSopenharmony_civoid mpi_mod_raw_canonical_to_modulus_rep(const char *input_N, int rep,
635a8e1175bSopenharmony_ci                                          const char *input_A,
636a8e1175bSopenharmony_ci                                          const char *input_X)
637a8e1175bSopenharmony_ci{
638a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus N;
639a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&N);
640a8e1175bSopenharmony_ci    mbedtls_mpi_uint *A = NULL;
641a8e1175bSopenharmony_ci    size_t A_limbs = 0;;
642a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
643a8e1175bSopenharmony_ci    size_t X_limbs = 0;
644a8e1175bSopenharmony_ci
645a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_modulus(&N, input_N, rep));
646a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &A_limbs, input_A));
647a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X));
648a8e1175bSopenharmony_ci
649a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_raw_canonical_to_modulus_rep(A, &N));
650a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(A, A_limbs * sizeof(mbedtls_mpi_uint),
651a8e1175bSopenharmony_ci                        X, X_limbs * sizeof(mbedtls_mpi_uint));
652a8e1175bSopenharmony_ci
653a8e1175bSopenharmony_ciexit:
654a8e1175bSopenharmony_ci    mbedtls_test_mpi_mod_modulus_free_with_limbs(&N);
655a8e1175bSopenharmony_ci    mbedtls_free(A);
656a8e1175bSopenharmony_ci    mbedtls_free(X);
657a8e1175bSopenharmony_ci}
658a8e1175bSopenharmony_ci/* END_CASE */
659a8e1175bSopenharmony_ci
660a8e1175bSopenharmony_ci/* BEGIN_CASE */
661a8e1175bSopenharmony_civoid mpi_mod_raw_modulus_to_canonical_rep(const char *input_N, int rep,
662a8e1175bSopenharmony_ci                                          const char *input_A,
663a8e1175bSopenharmony_ci                                          const char *input_X)
664a8e1175bSopenharmony_ci{
665a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus N;
666a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&N);
667a8e1175bSopenharmony_ci    mbedtls_mpi_uint *A = NULL;
668a8e1175bSopenharmony_ci    size_t A_limbs = 0;
669a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
670a8e1175bSopenharmony_ci    size_t X_limbs = 0;
671a8e1175bSopenharmony_ci
672a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_modulus(&N, input_N, rep));
673a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &A_limbs, input_A));
674a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X));
675a8e1175bSopenharmony_ci
676a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_raw_modulus_to_canonical_rep(A, &N));
677a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(A, A_limbs * sizeof(mbedtls_mpi_uint),
678a8e1175bSopenharmony_ci                        X, X_limbs * sizeof(mbedtls_mpi_uint));
679a8e1175bSopenharmony_ci
680a8e1175bSopenharmony_ciexit:
681a8e1175bSopenharmony_ci    mbedtls_test_mpi_mod_modulus_free_with_limbs(&N);
682a8e1175bSopenharmony_ci    mbedtls_free(A);
683a8e1175bSopenharmony_ci    mbedtls_free(X);
684a8e1175bSopenharmony_ci}
685a8e1175bSopenharmony_ci/* END_CASE */
686a8e1175bSopenharmony_ci
687a8e1175bSopenharmony_ci/* BEGIN_CASE */
688a8e1175bSopenharmony_civoid mpi_mod_raw_to_mont_rep(char *input_N, char *input_A, char *input_X)
689a8e1175bSopenharmony_ci{
690a8e1175bSopenharmony_ci    mbedtls_mpi_uint *N = NULL;
691a8e1175bSopenharmony_ci    mbedtls_mpi_uint *A = NULL;
692a8e1175bSopenharmony_ci    mbedtls_mpi_uint *R = NULL; /* for result of low-level conversion */
693a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
694a8e1175bSopenharmony_ci    mbedtls_mpi_uint *T = NULL;
695a8e1175bSopenharmony_ci    size_t n_limbs, a_limbs, x_limbs;
696a8e1175bSopenharmony_ci
697a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
698a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
699a8e1175bSopenharmony_ci
700a8e1175bSopenharmony_ci    /* Read inputs */
701a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
702a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &a_limbs, input_A));
703a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &x_limbs, input_X));
704a8e1175bSopenharmony_ci
705a8e1175bSopenharmony_ci    /* Number to convert must have same number of limbs as modulus */
706a8e1175bSopenharmony_ci    TEST_EQUAL(a_limbs, n_limbs);
707a8e1175bSopenharmony_ci
708a8e1175bSopenharmony_ci    /* Higher-level conversion is in-place, so expected result must have the
709a8e1175bSopenharmony_ci     * same number of limbs too */
710a8e1175bSopenharmony_ci    TEST_EQUAL(x_limbs, n_limbs);
711a8e1175bSopenharmony_ci
712a8e1175bSopenharmony_ci    size_t limbs = n_limbs;
713a8e1175bSopenharmony_ci    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
714a8e1175bSopenharmony_ci
715a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
716a8e1175bSopenharmony_ci
717a8e1175bSopenharmony_ci    /* 1. Test low-level function first */
718a8e1175bSopenharmony_ci
719a8e1175bSopenharmony_ci    /* It has separate output, and requires temporary working storage */
720a8e1175bSopenharmony_ci    size_t temp_limbs = mbedtls_mpi_core_montmul_working_limbs(limbs);
721a8e1175bSopenharmony_ci    TEST_CALLOC(T, temp_limbs);
722a8e1175bSopenharmony_ci    TEST_CALLOC(R, limbs);
723a8e1175bSopenharmony_ci    mbedtls_mpi_core_to_mont_rep(R, A, N, n_limbs,
724a8e1175bSopenharmony_ci                                 m.rep.mont.mm, m.rep.mont.rr, T);
725a8e1175bSopenharmony_ci    /* Test that the low-level function gives the required value */
726a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(R, bytes, X, bytes);
727a8e1175bSopenharmony_ci
728a8e1175bSopenharmony_ci    /* Test when output is aliased to input */
729a8e1175bSopenharmony_ci    memcpy(R, A, bytes);
730a8e1175bSopenharmony_ci    mbedtls_mpi_core_to_mont_rep(R, R, N, n_limbs,
731a8e1175bSopenharmony_ci                                 m.rep.mont.mm, m.rep.mont.rr, T);
732a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(R, bytes, X, bytes);
733a8e1175bSopenharmony_ci
734a8e1175bSopenharmony_ci    /* 2. Test higher-level cannonical to Montgomery conversion */
735a8e1175bSopenharmony_ci
736a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_raw_to_mont_rep(A, &m));
737a8e1175bSopenharmony_ci
738a8e1175bSopenharmony_ci    /* The result matches expected value */
739a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(A, bytes, X, bytes);
740a8e1175bSopenharmony_ci
741a8e1175bSopenharmony_ciexit:
742a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
743a8e1175bSopenharmony_ci    mbedtls_free(T);
744a8e1175bSopenharmony_ci    mbedtls_free(N);
745a8e1175bSopenharmony_ci    mbedtls_free(A);
746a8e1175bSopenharmony_ci    mbedtls_free(R);
747a8e1175bSopenharmony_ci    mbedtls_free(X);
748a8e1175bSopenharmony_ci}
749a8e1175bSopenharmony_ci/* END_CASE */
750a8e1175bSopenharmony_ci
751a8e1175bSopenharmony_ci/* BEGIN_CASE */
752a8e1175bSopenharmony_civoid mpi_mod_raw_from_mont_rep(char *input_N, char *input_A, char *input_X)
753a8e1175bSopenharmony_ci{
754a8e1175bSopenharmony_ci    mbedtls_mpi_uint *N = NULL;
755a8e1175bSopenharmony_ci    mbedtls_mpi_uint *A = NULL;
756a8e1175bSopenharmony_ci    mbedtls_mpi_uint *R = NULL; /* for result of low-level conversion */
757a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
758a8e1175bSopenharmony_ci    mbedtls_mpi_uint *T = NULL;
759a8e1175bSopenharmony_ci    size_t n_limbs, a_limbs, x_limbs;
760a8e1175bSopenharmony_ci
761a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
762a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
763a8e1175bSopenharmony_ci
764a8e1175bSopenharmony_ci    /* Read inputs */
765a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
766a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &a_limbs, input_A));
767a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &x_limbs, input_X));
768a8e1175bSopenharmony_ci
769a8e1175bSopenharmony_ci    /* Number to convert must have same number of limbs as modulus */
770a8e1175bSopenharmony_ci    TEST_EQUAL(a_limbs, n_limbs);
771a8e1175bSopenharmony_ci
772a8e1175bSopenharmony_ci    /* Higher-level conversion is in-place, so expected result must have the
773a8e1175bSopenharmony_ci     * same number of limbs too */
774a8e1175bSopenharmony_ci    TEST_EQUAL(x_limbs, n_limbs);
775a8e1175bSopenharmony_ci
776a8e1175bSopenharmony_ci    size_t limbs = n_limbs;
777a8e1175bSopenharmony_ci    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
778a8e1175bSopenharmony_ci
779a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
780a8e1175bSopenharmony_ci
781a8e1175bSopenharmony_ci    /* 1. Test low-level function first */
782a8e1175bSopenharmony_ci
783a8e1175bSopenharmony_ci    /* It has separate output, and requires temporary working storage */
784a8e1175bSopenharmony_ci    size_t temp_limbs = mbedtls_mpi_core_montmul_working_limbs(limbs);
785a8e1175bSopenharmony_ci    TEST_CALLOC(T, temp_limbs);
786a8e1175bSopenharmony_ci    TEST_CALLOC(R, limbs);
787a8e1175bSopenharmony_ci    mbedtls_mpi_core_from_mont_rep(R, A, N, n_limbs,
788a8e1175bSopenharmony_ci                                   m.rep.mont.mm, T);
789a8e1175bSopenharmony_ci    /* Test that the low-level function gives the required value */
790a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(R, bytes, X, bytes);
791a8e1175bSopenharmony_ci
792a8e1175bSopenharmony_ci    /* Test when output is aliased to input */
793a8e1175bSopenharmony_ci    memcpy(R, A, bytes);
794a8e1175bSopenharmony_ci    mbedtls_mpi_core_from_mont_rep(R, R, N, n_limbs,
795a8e1175bSopenharmony_ci                                   m.rep.mont.mm, T);
796a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(R, bytes, X, bytes);
797a8e1175bSopenharmony_ci
798a8e1175bSopenharmony_ci    /* 2. Test higher-level Montgomery to cannonical conversion */
799a8e1175bSopenharmony_ci
800a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_raw_from_mont_rep(A, &m));
801a8e1175bSopenharmony_ci
802a8e1175bSopenharmony_ci    /* The result matches expected value */
803a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(A, bytes, X, bytes);
804a8e1175bSopenharmony_ci
805a8e1175bSopenharmony_ciexit:
806a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
807a8e1175bSopenharmony_ci    mbedtls_free(T);
808a8e1175bSopenharmony_ci    mbedtls_free(N);
809a8e1175bSopenharmony_ci    mbedtls_free(A);
810a8e1175bSopenharmony_ci    mbedtls_free(R);
811a8e1175bSopenharmony_ci    mbedtls_free(X);
812a8e1175bSopenharmony_ci}
813a8e1175bSopenharmony_ci/* END_CASE */
814a8e1175bSopenharmony_ci
815a8e1175bSopenharmony_ci/* BEGIN_CASE */
816a8e1175bSopenharmony_civoid mpi_mod_raw_neg(char *input_N, char *input_A, char *input_X)
817a8e1175bSopenharmony_ci{
818a8e1175bSopenharmony_ci    mbedtls_mpi_uint *N = NULL;
819a8e1175bSopenharmony_ci    mbedtls_mpi_uint *A = NULL;
820a8e1175bSopenharmony_ci    mbedtls_mpi_uint *X = NULL;
821a8e1175bSopenharmony_ci    mbedtls_mpi_uint *R = NULL;
822a8e1175bSopenharmony_ci    mbedtls_mpi_uint *Z = NULL;
823a8e1175bSopenharmony_ci    size_t n_limbs, a_limbs, x_limbs, bytes;
824a8e1175bSopenharmony_ci
825a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus m;
826a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_init(&m);
827a8e1175bSopenharmony_ci
828a8e1175bSopenharmony_ci    /* Read inputs */
829a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
830a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &a_limbs, input_A));
831a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &x_limbs, input_X));
832a8e1175bSopenharmony_ci
833a8e1175bSopenharmony_ci    TEST_EQUAL(a_limbs, n_limbs);
834a8e1175bSopenharmony_ci    TEST_EQUAL(x_limbs, n_limbs);
835a8e1175bSopenharmony_ci    bytes = n_limbs * sizeof(mbedtls_mpi_uint);
836a8e1175bSopenharmony_ci
837a8e1175bSopenharmony_ci    TEST_CALLOC(R, n_limbs);
838a8e1175bSopenharmony_ci    TEST_CALLOC(Z, n_limbs);
839a8e1175bSopenharmony_ci
840a8e1175bSopenharmony_ci    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
841a8e1175bSopenharmony_ci
842a8e1175bSopenharmony_ci    /* Neg( A == 0 ) => Zero result */
843a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_neg(R, Z, &m);
844a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(R, bytes, Z, bytes);
845a8e1175bSopenharmony_ci
846a8e1175bSopenharmony_ci    /* Neg( A == N ) => Zero result */
847a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_neg(R, N, &m);
848a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(R, bytes, Z, bytes);
849a8e1175bSopenharmony_ci
850a8e1175bSopenharmony_ci    /* Neg( A ) => Correct result */
851a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_neg(R, A, &m);
852a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(R, bytes, X, bytes);
853a8e1175bSopenharmony_ci
854a8e1175bSopenharmony_ci    /* Neg( A ): alias A to R => Correct result */
855a8e1175bSopenharmony_ci    mbedtls_mpi_mod_raw_neg(A, A, &m);
856a8e1175bSopenharmony_ci    TEST_MEMORY_COMPARE(A, bytes, X, bytes);
857a8e1175bSopenharmony_ciexit:
858a8e1175bSopenharmony_ci    mbedtls_mpi_mod_modulus_free(&m);
859a8e1175bSopenharmony_ci    mbedtls_free(N);
860a8e1175bSopenharmony_ci    mbedtls_free(A);
861a8e1175bSopenharmony_ci    mbedtls_free(X);
862a8e1175bSopenharmony_ci    mbedtls_free(R);
863a8e1175bSopenharmony_ci    mbedtls_free(Z);
864a8e1175bSopenharmony_ci}
865a8e1175bSopenharmony_ci/* END_CASE */
866