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