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