blob: 98ba4b491fba23cfb474280f7d8d664d644809be [file] [log] [blame]
Werner Lewis0c6ea122022-09-30 13:02:16 +01001/* BEGIN_HEADER */
2#include "mbedtls/bignum.h"
3#include "mbedtls/entropy.h"
4#include "bignum_mod.h"
Gabor Mezeieca74662022-12-13 10:53:50 +01005#include "bignum_mod_raw.h"
Werner Lewis0c6ea122022-09-30 13:02:16 +01006#include "constant_time_internal.h"
7#include "test/constant_flow.h"
Tom Cosgrove62b20482022-12-01 14:27:37 +00008
Gilles Peskine449bd832023-01-11 14:50:10 +01009#define TEST_COMPARE_MPI_RESIDUES(a, b) \
10 ASSERT_COMPARE((a).p, (a).limbs * sizeof(mbedtls_mpi_uint), \
11 (b).p, (b).limbs * sizeof(mbedtls_mpi_uint))
Tom Cosgrove62b20482022-12-01 14:27:37 +000012
Gilles Peskine449bd832023-01-11 14:50:10 +010013static 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)
Tom Cosgrove62b20482022-12-01 14:27:37 +000017{
18 mbedtls_mpi_uint *p = NULL;
19 size_t limbs;
20
Gilles Peskine449bd832023-01-11 14:50:10 +010021 int ret = mbedtls_test_read_mpi_core(&p, &limbs, input);
22 if (ret != 0) {
23 return ret;
24 }
Tom Cosgrove62b20482022-12-01 14:27:37 +000025
Gilles Peskine449bd832023-01-11 14:50:10 +010026 if (skip_limbs_and_value_checks) {
Tom Cosgrove62b20482022-12-01 14:27:37 +000027 r->p = p;
28 r->limbs = limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +010029 return 0;
Tom Cosgrove62b20482022-12-01 14:27:37 +000030 }
31
32 /* mbedtls_mpi_mod_residue_setup() checks limbs, and that value < m */
Gilles Peskine449bd832023-01-11 14:50:10 +010033 return mbedtls_mpi_mod_residue_setup(r, m, p, limbs);
Tom Cosgrove62b20482022-12-01 14:27:37 +000034}
Werner Lewis0c6ea122022-09-30 13:02:16 +010035/* END_HEADER */
36
37/* BEGIN_DEPENDENCIES
38 * depends_on:MBEDTLS_BIGNUM_C
39 * END_DEPENDENCIES
40 */
41
42/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010043void mpi_mod_setup(int int_rep, int iret)
Werner Lewis0c6ea122022-09-30 13:02:16 +010044{
45 #define MLIMBS 8
46 mbedtls_mpi_uint mp[MLIMBS];
47 mbedtls_mpi_mod_modulus m;
48 int ret;
49
Gilles Peskine449bd832023-01-11 14:50:10 +010050 memset(mp, 0xFF, sizeof(mp));
Werner Lewis0c6ea122022-09-30 13:02:16 +010051
Gilles Peskine449bd832023-01-11 14:50:10 +010052 mbedtls_mpi_mod_modulus_init(&m);
53 ret = mbedtls_mpi_mod_modulus_setup(&m, mp, MLIMBS, int_rep);
54 TEST_EQUAL(ret, iret);
Werner Lewis0c6ea122022-09-30 13:02:16 +010055
Minos Galanakisdd365a52022-10-19 01:48:32 +010056 /* Only test if the constants have been set-up */
Gilles Peskine449bd832023-01-11 14:50:10 +010057 if (ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
Minos Galanakisdd365a52022-10-19 01:48:32 +010058 /* Test that the consts have been calculated */
Gilles Peskine449bd832023-01-11 14:50:10 +010059 TEST_ASSERT(m.rep.mont.rr != NULL);
60 TEST_ASSERT(m.rep.mont.mm != 0);
Minos Galanakisdd365a52022-10-19 01:48:32 +010061
Minos Galanakisdd365a52022-10-19 01:48:32 +010062 }
63
Werner Lewis0c6ea122022-09-30 13:02:16 +010064 /* Address sanitiser should catch if we try to free mp */
Gilles Peskine449bd832023-01-11 14:50:10 +010065 mbedtls_mpi_mod_modulus_free(&m);
Werner Lewis0c6ea122022-09-30 13:02:16 +010066
67 /* Make sure that the modulus doesn't have reference to mp anymore */
Gilles Peskine449bd832023-01-11 14:50:10 +010068 TEST_ASSERT(m.p != mp);
Werner Lewis0c6ea122022-09-30 13:02:16 +010069
Minos Galanakisdd365a52022-10-19 01:48:32 +010070 /* Only test if the constants have been set-up */
Gilles Peskine449bd832023-01-11 14:50:10 +010071 if (ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
Minos Galanakisdd365a52022-10-19 01:48:32 +010072 /* Verify the data and pointers allocated have been properly wiped */
Gilles Peskine449bd832023-01-11 14:50:10 +010073 TEST_ASSERT(m.rep.mont.rr == NULL);
74 TEST_ASSERT(m.rep.mont.mm == 0);
Minos Galanakisdd365a52022-10-19 01:48:32 +010075 }
Werner Lewis0c6ea122022-09-30 13:02:16 +010076exit:
77 /* It should be safe to call an mbedtls free several times */
Gilles Peskine449bd832023-01-11 14:50:10 +010078 mbedtls_mpi_mod_modulus_free(&m);
Werner Lewis0c6ea122022-09-30 13:02:16 +010079
80 #undef MLIMBS
81}
82/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +000083
Gabor Mezeieca74662022-12-13 10:53:50 +010084/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010085void mpi_mod_mul(char *input_A,
86 char *input_B,
87 char *input_N,
88 char *result)
Gabor Mezeieca74662022-12-13 10:53:50 +010089{
Gabor Mezeieca74662022-12-13 10:53:50 +010090 mbedtls_mpi_uint *X = NULL;
Gabor Mezeieca74662022-12-13 10:53:50 +010091
Gabor Mezei78c4fb42022-12-20 18:09:49 +010092 mbedtls_mpi_mod_residue rA = { NULL, 0 };
93 mbedtls_mpi_mod_residue rB = { NULL, 0 };
94 mbedtls_mpi_mod_residue rR = { NULL, 0 };
95 mbedtls_mpi_mod_residue rX = { NULL, 0 };
96
Gabor Mezeieca74662022-12-13 10:53:50 +010097 mbedtls_mpi_mod_modulus m;
Gilles Peskine449bd832023-01-11 14:50:10 +010098 mbedtls_mpi_mod_modulus_init(&m);
Gabor Mezeieca74662022-12-13 10:53:50 +010099
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100100 TEST_EQUAL(mbedtls_test_read_mpi_modulus(&m, input_N,
101 MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
Gabor Mezeieca74662022-12-13 10:53:50 +0100102
Gilles Peskine449bd832023-01-11 14:50:10 +0100103 TEST_EQUAL(test_read_residue(&rA, &m, input_A, 0), 0);
104 TEST_EQUAL(test_read_residue(&rB, &m, input_B, 0), 0);
105 TEST_EQUAL(test_read_residue(&rR, &m, result, 0), 0);
Gabor Mezei809baef2022-12-16 16:31:59 +0100106
107 const size_t limbs = m.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 const size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
Gabor Mezei809baef2022-12-16 16:31:59 +0100109
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 TEST_EQUAL(rA.limbs, limbs);
111 TEST_EQUAL(rB.limbs, limbs);
112 TEST_EQUAL(rR.limbs, limbs);
Gabor Mezei809baef2022-12-16 16:31:59 +0100113
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 ASSERT_ALLOC(X, limbs);
Gabor Mezeieca74662022-12-13 10:53:50 +0100115
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 TEST_EQUAL(mbedtls_mpi_mod_residue_setup(&rX, &m, X, limbs), 0);
Gabor Mezeieca74662022-12-13 10:53:50 +0100117
Gilles Peskine449bd832023-01-11 14:50:10 +0100118 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &m), 0);
119 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100120
121 /* alias X to A */
Gilles Peskine449bd832023-01-11 14:50:10 +0100122 memcpy(rX.p, rA.p, bytes);
123 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rB, &m), 0);
124 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100125
126 /* alias X to B */
Gilles Peskine449bd832023-01-11 14:50:10 +0100127 memcpy(rX.p, rB.p, bytes);
128 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rX, &m), 0);
129 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100130
131 /* A == B: alias A and B */
Gilles Peskine449bd832023-01-11 14:50:10 +0100132 if (memcmp(rA.p, rB.p, bytes) == 0) {
133 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rA, &m), 0);
134 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100135
136 /* X, A, B all aliased together */
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 memcpy(rX.p, rA.p, bytes);
138 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rX, &m), 0);
139 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100140 }
Gabor Mezeieca74662022-12-13 10:53:50 +0100141 /* A != B: test B * A */
Gilles Peskine449bd832023-01-11 14:50:10 +0100142 else {
143 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rB, &rA, &m), 0);
144 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100145
146 /* B * A: alias X to A */
Gilles Peskine449bd832023-01-11 14:50:10 +0100147 memcpy(rX.p, rA.p, bytes);
148 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rB, &rX, &m), 0);
149 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100150
151 /* B + A: alias X to B */
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 memcpy(rX.p, rB.p, bytes);
153 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rA, &m), 0);
154 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100155 }
156
157exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100158 mbedtls_free(rA.p);
159 mbedtls_free(rB.p);
160 mbedtls_free(rR.p);
161 mbedtls_free(X);
162 mbedtls_free((mbedtls_mpi_uint *) m.p);
Gabor Mezeif9728132022-12-20 13:55:37 +0100163
Gilles Peskine449bd832023-01-11 14:50:10 +0100164 mbedtls_mpi_mod_modulus_free(&m);
Gabor Mezeieca74662022-12-13 10:53:50 +0100165}
166/* END_CASE */
167
168/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100169void mpi_mod_mul_neg(char *input_A,
170 char *input_B,
171 char *input_N,
172 char *result,
173 int exp_ret)
Gabor Mezeieca74662022-12-13 10:53:50 +0100174{
Gabor Mezeieca74662022-12-13 10:53:50 +0100175 mbedtls_mpi_uint *X = NULL;
Gabor Mezeieca74662022-12-13 10:53:50 +0100176
Gabor Mezei78c4fb42022-12-20 18:09:49 +0100177 mbedtls_mpi_mod_residue rA = { NULL, 0 };
178 mbedtls_mpi_mod_residue rB = { NULL, 0 };
179 mbedtls_mpi_mod_residue rR = { NULL, 0 };
180 mbedtls_mpi_mod_residue rX = { NULL, 0 };
181
Gabor Mezeieca74662022-12-13 10:53:50 +0100182 mbedtls_mpi_mod_modulus m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100183 mbedtls_mpi_mod_modulus_init(&m);
Gabor Mezeieca74662022-12-13 10:53:50 +0100184
Gabor Mezeif65c71f2022-12-21 11:54:22 +0100185 mbedtls_mpi_mod_modulus fake_m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100186 mbedtls_mpi_mod_modulus_init(&fake_m);
Gabor Mezeif65c71f2022-12-21 11:54:22 +0100187
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100188 TEST_EQUAL(mbedtls_test_read_mpi_modulus(&m, input_N,
189 MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
Gabor Mezeieca74662022-12-13 10:53:50 +0100190
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 TEST_EQUAL(test_read_residue(&rA, &m, input_A, 1), 0);
192 TEST_EQUAL(test_read_residue(&rB, &m, input_B, 1), 0);
193 TEST_EQUAL(test_read_residue(&rR, &m, result, 1), 0);
Gabor Mezei809baef2022-12-16 16:31:59 +0100194
195 const size_t limbs = m.limbs;
196
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 ASSERT_ALLOC(X, limbs);
Gabor Mezeieca74662022-12-13 10:53:50 +0100198
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 TEST_EQUAL(mbedtls_mpi_mod_residue_setup(&rX, &m, X, limbs), 0);
Gabor Mezei809baef2022-12-16 16:31:59 +0100200 rX.limbs = rR.limbs;
Gabor Mezeieca74662022-12-13 10:53:50 +0100201
Gilles Peskine449bd832023-01-11 14:50:10 +0100202 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &m), exp_ret);
Gabor Mezeieca74662022-12-13 10:53:50 +0100203
204 /* Check when m is not initialized */
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &fake_m),
206 MBEDTLS_ERR_MPI_BAD_INPUT_DATA);
Gabor Mezeieca74662022-12-13 10:53:50 +0100207
208exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 mbedtls_free(rA.p);
210 mbedtls_free(rB.p);
211 mbedtls_free(rR.p);
212 mbedtls_free(X);
213 mbedtls_free((mbedtls_mpi_uint *) m.p);
Gabor Mezeif9728132022-12-20 13:55:37 +0100214
Gilles Peskine449bd832023-01-11 14:50:10 +0100215 mbedtls_mpi_mod_modulus_free(&m);
216 mbedtls_mpi_mod_modulus_free(&fake_m);
Gabor Mezeieca74662022-12-13 10:53:50 +0100217}
218/* END_CASE */
219
Tom Cosgrove62b20482022-12-01 14:27:37 +0000220/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100221void mpi_mod_sub(char *input_N,
222 char *input_A, char *input_B,
223 char *input_D, int expected_ret)
Tom Cosgrove62b20482022-12-01 14:27:37 +0000224{
225 mbedtls_mpi_mod_residue a = { NULL, 0 };
226 mbedtls_mpi_mod_residue b = { NULL, 0 };
227 mbedtls_mpi_mod_residue d = { NULL, 0 };
228 mbedtls_mpi_mod_residue x = { NULL, 0 };
229 mbedtls_mpi_uint *X_raw = NULL;
Janos Follath5933f692022-11-02 14:35:17 +0000230
Tom Cosgrove62b20482022-12-01 14:27:37 +0000231 mbedtls_mpi_mod_modulus m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 mbedtls_mpi_mod_modulus_init(&m);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000233
Gilles Peskine449bd832023-01-11 14:50:10 +0100234 TEST_EQUAL(0,
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100235 mbedtls_test_read_mpi_modulus(&m, input_N,
236 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
Tom Cosgrove62b20482022-12-01 14:27:37 +0000237
238 /* test_read_residue() normally checks that inputs have the same number of
239 * limbs as the modulus. For negative testing we can ask it to skip this
240 * with a non-zero final parameter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 TEST_EQUAL(0, test_read_residue(&a, &m, input_A, expected_ret != 0));
242 TEST_EQUAL(0, test_read_residue(&b, &m, input_B, expected_ret != 0));
243 TEST_EQUAL(0, test_read_residue(&d, &m, input_D, expected_ret != 0));
Tom Cosgrove62b20482022-12-01 14:27:37 +0000244
245 size_t limbs = m.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 size_t bytes = limbs * sizeof(*X_raw);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000247
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 if (expected_ret == 0) {
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000249 /* Negative test with too many limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 ASSERT_ALLOC(X_raw, limbs + 1);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000251
Tom Cosgrove62b20482022-12-01 14:27:37 +0000252 x.p = X_raw;
253 x.limbs = limbs + 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
255 mbedtls_mpi_mod_sub(&x, &a, &b, &m));
Tom Cosgrove62b20482022-12-01 14:27:37 +0000256
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 mbedtls_free(X_raw);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000258 X_raw = NULL;
259
260 /* Negative test with too few limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 if (limbs > 1) {
262 ASSERT_ALLOC(X_raw, limbs - 1);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000263
Tom Cosgrove62b20482022-12-01 14:27:37 +0000264 x.p = X_raw;
265 x.limbs = limbs - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
267 mbedtls_mpi_mod_sub(&x, &a, &b, &m));
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000268
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 mbedtls_free(X_raw);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000270 X_raw = NULL;
Tom Cosgrove62b20482022-12-01 14:27:37 +0000271 }
272
273 /* Negative testing with too many/too few limbs in a and b is covered by
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000274 * manually-written test cases with expected_ret != 0. */
Tom Cosgrove62b20482022-12-01 14:27:37 +0000275 }
276
Gilles Peskine449bd832023-01-11 14:50:10 +0100277 ASSERT_ALLOC(X_raw, limbs);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000278
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &m, X_raw, limbs));
Tom Cosgrove62b20482022-12-01 14:27:37 +0000280
281 /* a - b => Correct result, or expected error */
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 TEST_EQUAL(expected_ret, mbedtls_mpi_mod_sub(&x, &a, &b, &m));
283 if (expected_ret != 0) {
Tom Cosgrove62b20482022-12-01 14:27:37 +0000284 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 }
Tom Cosgrove62b20482022-12-01 14:27:37 +0000286
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000288
289 /* a - b: alias x to a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100290 memcpy(x.p, a.p, bytes);
291 TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &x, &b, &m));
292 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000293
294 /* a - b: alias x to b => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 memcpy(x.p, b.p, bytes);
296 TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &a, &x, &m));
297 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000298
Gilles Peskine449bd832023-01-11 14:50:10 +0100299 if (memcmp(a.p, b.p, bytes) == 0) {
Tom Cosgrove62b20482022-12-01 14:27:37 +0000300 /* a == b: alias a and b */
301
302 /* a - a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &a, &a, &m));
304 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000305
306 /* a - a: x, a, b all aliased together => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 memcpy(x.p, a.p, bytes);
308 TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &x, &x, &m));
309 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000310 }
311
312exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100313 mbedtls_free((void *) m.p); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
314 mbedtls_mpi_mod_modulus_free(&m);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000315
Gilles Peskine449bd832023-01-11 14:50:10 +0100316 mbedtls_free(a.p);
317 mbedtls_free(b.p);
318 mbedtls_free(d.p);
319 mbedtls_free(X_raw);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000320}
321/* END_CASE */
Tom Cosgrovedc197592022-12-15 16:59:40 +0000322
323/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100324void mpi_mod_inv_mont(char *input_N,
325 char *input_A, char *input_I,
326 int expected_ret)
Tom Cosgrovedc197592022-12-15 16:59:40 +0000327{
328 mbedtls_mpi_mod_residue a = { NULL, 0 }; /* argument */
329 mbedtls_mpi_mod_residue i = { NULL, 0 }; /* expected inverse wrt N */
330 mbedtls_mpi_mod_residue x = { NULL, 0 }; /* output */
331 mbedtls_mpi_uint *X_raw = NULL;
332
333 mbedtls_mpi_mod_modulus N;
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 mbedtls_mpi_mod_modulus_init(&N);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000335
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 TEST_EQUAL(0,
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100337 mbedtls_test_read_mpi_modulus(&N, input_N,
338 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000339
340 /* test_read_residue() normally checks that inputs have the same number of
341 * limbs as the modulus. For negative testing we can ask it to skip this
342 * with a non-zero final parameter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 TEST_EQUAL(0, test_read_residue(&a, &N, input_A, expected_ret != 0));
344 TEST_EQUAL(0, test_read_residue(&i, &N, input_I, expected_ret != 0));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000345
346 size_t limbs = N.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 size_t bytes = limbs * sizeof(*X_raw);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000348
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 ASSERT_ALLOC(X_raw, limbs);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000350
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &N, X_raw, limbs));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000352
Gilles Peskine449bd832023-01-11 14:50:10 +0100353 TEST_EQUAL(expected_ret, mbedtls_mpi_mod_inv(&x, &a, &N));
354 if (expected_ret == 0) {
355 TEST_COMPARE_MPI_RESIDUES(x, i);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000356
357 /* a^-1: alias x to a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 memcpy(x.p, a.p, bytes);
359 TEST_EQUAL(0, mbedtls_mpi_mod_inv(&x, &x, &N));
360 TEST_COMPARE_MPI_RESIDUES(x, i);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000361 }
362
363exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100364 mbedtls_free((void *) N.p); /* mbedtls_mpi_mod_modulus_free() sets N.p = NULL */
365 mbedtls_mpi_mod_modulus_free(&N);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000366
Gilles Peskine449bd832023-01-11 14:50:10 +0100367 mbedtls_free(a.p);
368 mbedtls_free(i.p);
369 mbedtls_free(X_raw);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000370}
371/* END_CASE */
372
373/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100374void mpi_mod_inv_non_mont(char *input_N,
375 char *input_A, char *input_I,
376 int expected_ret)
Tom Cosgrovedc197592022-12-15 16:59:40 +0000377{
378 mbedtls_mpi_mod_residue a = { NULL, 0 }; /* argument */
379 mbedtls_mpi_mod_residue i = { NULL, 0 }; /* expected inverse wrt N */
380 mbedtls_mpi_mod_residue x = { NULL, 0 }; /* output */
381 mbedtls_mpi_uint *X_raw = NULL;
382
383 mbedtls_mpi_mod_modulus N;
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 mbedtls_mpi_mod_modulus_init(&N);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000385
Gilles Peskine449bd832023-01-11 14:50:10 +0100386 TEST_EQUAL(0,
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100387 mbedtls_test_read_mpi_modulus(&N, input_N,
388 MBEDTLS_MPI_MOD_REP_OPT_RED));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000389
390 /* test_read_residue() normally checks that inputs have the same number of
391 * limbs as the modulus. For negative testing we can ask it to skip this
392 * with a non-zero final parameter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 TEST_EQUAL(0, test_read_residue(&a, &N, input_A, expected_ret != 0));
394 TEST_EQUAL(0, test_read_residue(&i, &N, input_I, expected_ret != 0));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000395
396 size_t limbs = N.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 size_t bytes = limbs * sizeof(*X_raw);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000398
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 ASSERT_ALLOC(X_raw, limbs);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000400
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &N, X_raw, limbs));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000402
Gilles Peskine449bd832023-01-11 14:50:10 +0100403 TEST_EQUAL(expected_ret, mbedtls_mpi_mod_inv(&x, &a, &N));
404 if (expected_ret == 0) {
405 TEST_COMPARE_MPI_RESIDUES(x, i);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000406
407 /* a^-1: alias x to a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100408 memcpy(x.p, a.p, bytes);
409 TEST_EQUAL(0, mbedtls_mpi_mod_inv(&x, &x, &N));
410 TEST_COMPARE_MPI_RESIDUES(x, i);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000411 }
412
413exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100414 mbedtls_free((void *) N.p); /* mbedtls_mpi_mod_modulus_free() sets N.p = NULL */
415 mbedtls_mpi_mod_modulus_free(&N);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000416
Gilles Peskine449bd832023-01-11 14:50:10 +0100417 mbedtls_free(a.p);
418 mbedtls_free(i.p);
419 mbedtls_free(X_raw);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000420}
421/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +0000422
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000423/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100424void mpi_mod_add(char *input_N,
425 char *input_A, char *input_B,
426 char *input_S, int expected_ret)
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000427{
428 mbedtls_mpi_mod_residue a = { NULL, 0 };
429 mbedtls_mpi_mod_residue b = { NULL, 0 };
430 mbedtls_mpi_mod_residue s = { NULL, 0 };
431 mbedtls_mpi_mod_residue x = { NULL, 0 };
432 mbedtls_mpi_uint *X_raw = NULL;
Janos Follath5933f692022-11-02 14:35:17 +0000433
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000434 mbedtls_mpi_mod_modulus m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 mbedtls_mpi_mod_modulus_init(&m);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000436
Gilles Peskine449bd832023-01-11 14:50:10 +0100437 TEST_EQUAL(0,
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100438 mbedtls_test_read_mpi_modulus(&m, input_N,
439 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000440
441 /* test_read_residue() normally checks that inputs have the same number of
442 * limbs as the modulus. For negative testing we can ask it to skip this
443 * with a non-zero final parameter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 TEST_EQUAL(0, test_read_residue(&a, &m, input_A, expected_ret != 0));
445 TEST_EQUAL(0, test_read_residue(&b, &m, input_B, expected_ret != 0));
446 TEST_EQUAL(0, test_read_residue(&s, &m, input_S, expected_ret != 0));
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000447
448 size_t limbs = m.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 size_t bytes = limbs * sizeof(*X_raw);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000450
Gilles Peskine449bd832023-01-11 14:50:10 +0100451 if (expected_ret == 0) {
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000452 /* Negative test with too many limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100453 ASSERT_ALLOC(X_raw, limbs + 1);
Werner Lewis79341a42022-12-13 17:19:01 +0000454
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000455 x.p = X_raw;
456 x.limbs = limbs + 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100457 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
458 mbedtls_mpi_mod_add(&x, &a, &b, &m));
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000459
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 mbedtls_free(X_raw);
Werner Lewis79341a42022-12-13 17:19:01 +0000461 X_raw = NULL;
462
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000463 /* Negative test with too few limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 if (limbs > 1) {
465 ASSERT_ALLOC(X_raw, limbs - 1);
Werner Lewis79341a42022-12-13 17:19:01 +0000466
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000467 x.p = X_raw;
468 x.limbs = limbs - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
470 mbedtls_mpi_mod_add(&x, &a, &b, &m));
Werner Lewis79341a42022-12-13 17:19:01 +0000471
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 mbedtls_free(X_raw);
Werner Lewis79341a42022-12-13 17:19:01 +0000473 X_raw = NULL;
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000474 }
475
476 /* Negative testing with too many/too few limbs in a and b is covered by
477 * manually-written test cases with oret != 0. */
478 }
479
Werner Lewis79341a42022-12-13 17:19:01 +0000480 /* Allocate correct number of limbs for X_raw */
Gilles Peskine449bd832023-01-11 14:50:10 +0100481 ASSERT_ALLOC(X_raw, limbs);
Werner Lewis79341a42022-12-13 17:19:01 +0000482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &m, X_raw, limbs));
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000484
485 /* A + B => Correct result or expected error */
Gilles Peskine449bd832023-01-11 14:50:10 +0100486 TEST_EQUAL(expected_ret, mbedtls_mpi_mod_add(&x, &a, &b, &m));
487 if (expected_ret != 0) {
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000488 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100489 }
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000490
Gilles Peskine449bd832023-01-11 14:50:10 +0100491 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000492
493 /* a + b: alias x to a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 memcpy(x.p, a.p, bytes);
495 TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &x, &b, &m));
496 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000497
498 /* a + b: alias x to b => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100499 memcpy(x.p, b.p, bytes);
500 TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &a, &x, &m));
501 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000502
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 if (memcmp(a.p, b.p, bytes) == 0) {
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000504 /* a == b: alias a and b */
505
506 /* a + a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &a, &a, &m));
508 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000509
510 /* a + a: x, a, b all aliased together => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100511 memcpy(x.p, a.p, bytes);
512 TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &x, &x, &m));
513 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000514 }
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000515
516exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 mbedtls_free((void *) m.p); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
518 mbedtls_mpi_mod_modulus_free(&m);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000519
Gilles Peskine449bd832023-01-11 14:50:10 +0100520 mbedtls_free(a.p);
521 mbedtls_free(b.p);
522 mbedtls_free(s.p);
523 mbedtls_free(X_raw);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000524}
525/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +0000526
Minos Galanakis8f242702022-11-10 16:56:02 +0000527/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100528void mpi_residue_setup(char *input_N, char *input_R, int ret)
Minos Galanakisa17ad482022-11-16 16:29:15 +0000529{
Minos Galanakisa17ad482022-11-16 16:29:15 +0000530 mbedtls_mpi_uint *N = NULL;
531 mbedtls_mpi_uint *R = NULL;
Minos Galanakisaed832a2022-11-24 09:09:47 +0000532 size_t n_limbs, r_limbs;
Minos Galanakisa17ad482022-11-16 16:29:15 +0000533 mbedtls_mpi_mod_modulus m;
534 mbedtls_mpi_mod_residue r;
535
Gilles Peskine449bd832023-01-11 14:50:10 +0100536 mbedtls_mpi_mod_modulus_init(&m);
Minos Galanakisa17ad482022-11-16 16:29:15 +0000537
Minos Galanakisaed832a2022-11-24 09:09:47 +0000538 /* Allocate the memory for intermediate data structures */
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
540 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&R, &r_limbs, input_R));
Minos Galanakisaed832a2022-11-24 09:09:47 +0000541
Gilles Peskine449bd832023-01-11 14:50:10 +0100542 TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
543 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
Minos Galanakisa17ad482022-11-16 16:29:15 +0000544
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 TEST_EQUAL(ret, mbedtls_mpi_mod_residue_setup(&r, &m, R, r_limbs));
Minos Galanakisa17ad482022-11-16 16:29:15 +0000546
Gilles Peskine449bd832023-01-11 14:50:10 +0100547 if (ret == 0) {
548 TEST_EQUAL(r.limbs, r_limbs);
549 TEST_ASSERT(r.p == R);
Janos Follath91f3abd2022-11-26 11:47:14 +0000550 }
551
Minos Galanakisa17ad482022-11-16 16:29:15 +0000552exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 mbedtls_mpi_mod_modulus_free(&m);
554 mbedtls_free(N);
555 mbedtls_free(R);
Minos Galanakisa17ad482022-11-16 16:29:15 +0000556}
557/* END_CASE */
Minos Galanakisaed832a2022-11-24 09:09:47 +0000558
Minos Galanakisa17ad482022-11-16 16:29:15 +0000559/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100560void mpi_mod_io_neg(char *input_N, data_t *buf, int ret)
Minos Galanakis8f242702022-11-10 16:56:02 +0000561{
Minos Galanakis8f242702022-11-10 16:56:02 +0000562 mbedtls_mpi_uint *N = NULL;
563 mbedtls_mpi_uint *R = NULL;
Minos Galanakis8f242702022-11-10 16:56:02 +0000564
565 mbedtls_mpi_mod_modulus m;
Janos Follathe7190a22022-11-26 18:46:54 +0000566 mbedtls_mpi_mod_residue r = { NULL, 0 };
Minos Galanakis96070a52022-11-25 19:32:10 +0000567 mbedtls_mpi_mod_ext_rep endian = MBEDTLS_MPI_MOD_EXT_REP_LE;
Minos Galanakis8f242702022-11-10 16:56:02 +0000568
Gilles Peskine449bd832023-01-11 14:50:10 +0100569 mbedtls_mpi_mod_modulus_init(&m);
Janos Follath799eaee2022-11-25 15:57:04 +0000570
Janos Follath339b4392022-11-26 12:20:41 +0000571 size_t n_limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100572 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
Janos Follath339b4392022-11-26 12:20:41 +0000573 size_t r_limbs = n_limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100574 ASSERT_ALLOC(R, r_limbs);
Minos Galanakis8f242702022-11-10 16:56:02 +0000575
Janos Follathe7190a22022-11-26 18:46:54 +0000576 /* modulus->p == NULL || residue->p == NULL ( m has not been set-up ) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100577 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
578 mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
Minos Galanakis8f242702022-11-10 16:56:02 +0000579
Gilles Peskine449bd832023-01-11 14:50:10 +0100580 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
581 mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
Minos Galanakis8f242702022-11-10 16:56:02 +0000582
Janos Follathe7190a22022-11-26 18:46:54 +0000583 /* Set up modulus and test with residue->p == NULL */
Gilles Peskine449bd832023-01-11 14:50:10 +0100584 TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
585 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
Minos Galanakis96070a52022-11-25 19:32:10 +0000586
Gilles Peskine449bd832023-01-11 14:50:10 +0100587 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
588 mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
589 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
590 mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
Janos Follathe7190a22022-11-26 18:46:54 +0000591
592 /* Do the rest of the tests with a residue set up with the input data */
Gilles Peskine449bd832023-01-11 14:50:10 +0100593 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r, &m, R, r_limbs));
Minos Galanakis96070a52022-11-25 19:32:10 +0000594
Janos Follathd7bb3522022-11-26 14:59:27 +0000595 /* Fail for r_limbs < m->limbs */
596 r.limbs--;
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 TEST_ASSERT(r.limbs < m.limbs);
598 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
599 mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
600 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
601 mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
Janos Follathd7bb3522022-11-26 14:59:27 +0000602 r.limbs++;
603
604 /* Fail for r_limbs > m->limbs */
605 m.limbs--;
Gilles Peskine449bd832023-01-11 14:50:10 +0100606 TEST_ASSERT(r.limbs > m.limbs);
607 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
608 mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
609 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
610 mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
Janos Follathd7bb3522022-11-26 14:59:27 +0000611 m.limbs++;
Minos Galanakis96070a52022-11-25 19:32:10 +0000612
613 /* Test the read */
Gilles Peskine449bd832023-01-11 14:50:10 +0100614 TEST_EQUAL(ret, mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
Minos Galanakis96070a52022-11-25 19:32:10 +0000615
616 /* Test write overflow only when the representation is large and read is successful */
Gilles Peskine449bd832023-01-11 14:50:10 +0100617 if (r.limbs > 1 && ret == 0) {
618 TEST_EQUAL(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL,
619 mbedtls_mpi_mod_write(&r, &m, buf->x, 1, endian));
620 }
Janos Follathd7bb3522022-11-26 14:59:27 +0000621
Minos Galanakis8f242702022-11-10 16:56:02 +0000622exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100623 mbedtls_mpi_mod_residue_release(&r);
624 mbedtls_mpi_mod_modulus_free(&m);
625 mbedtls_free(N);
626 mbedtls_free(R);
Minos Galanakis8f242702022-11-10 16:56:02 +0000627}
628/* END_CASE */
629
630/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100631void mpi_mod_io(char *input_N, data_t *input_A, int endian)
Minos Galanakis8f242702022-11-10 16:56:02 +0000632{
633 mbedtls_mpi_uint *N = NULL;
634 mbedtls_mpi_uint *R = NULL;
Janos Follath8dfc8c42022-11-26 15:39:02 +0000635 mbedtls_mpi_uint *R_COPY = NULL;
Janos Follath0020df92022-11-26 17:23:16 +0000636 unsigned char *obuf = NULL;
637 unsigned char *ref_buf = NULL;
Minos Galanakis8f242702022-11-10 16:56:02 +0000638 mbedtls_mpi_mod_modulus m;
639 mbedtls_mpi_mod_residue r;
Janos Follath8dfc8c42022-11-26 15:39:02 +0000640 mbedtls_mpi_mod_residue r_copy;
Minos Galanakis8f242702022-11-10 16:56:02 +0000641 size_t n_limbs, n_bytes, a_bytes;
642
Gilles Peskine449bd832023-01-11 14:50:10 +0100643 mbedtls_mpi_mod_modulus_init(&m);
Janos Follath799eaee2022-11-25 15:57:04 +0000644
Minos Galanakis8f242702022-11-10 16:56:02 +0000645 /* Read inputs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100646 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
647 n_bytes = n_limbs * sizeof(mbedtls_mpi_uint);
Janos Follath6ef582f2022-11-26 14:19:02 +0000648 a_bytes = input_A->len;
Minos Galanakis8f242702022-11-10 16:56:02 +0000649
650 /* Allocate the memory for intermediate data structures */
Gilles Peskine449bd832023-01-11 14:50:10 +0100651 ASSERT_ALLOC(R, n_bytes);
652 ASSERT_ALLOC(R_COPY, n_bytes);
Minos Galanakis8f242702022-11-10 16:56:02 +0000653
654 /* Test that input's size is not greater to modulo's */
Gilles Peskine449bd832023-01-11 14:50:10 +0100655 TEST_LE_U(a_bytes, n_bytes);
Minos Galanakis8f242702022-11-10 16:56:02 +0000656
657 /* Init Structures */
Gilles Peskine449bd832023-01-11 14:50:10 +0100658 TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
659 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
Minos Galanakis8f242702022-11-10 16:56:02 +0000660
661 /* Enforcing p_limbs >= m->limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100662 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r, &m, R, n_limbs));
Minos Galanakis8f242702022-11-10 16:56:02 +0000663
Gilles Peskine449bd832023-01-11 14:50:10 +0100664 TEST_EQUAL(0, mbedtls_mpi_mod_read(&r, &m, input_A->x, input_A->len,
665 endian));
Minos Galanakis8f242702022-11-10 16:56:02 +0000666
Janos Follath0020df92022-11-26 17:23:16 +0000667 /* Read a copy for checking that writing didn't change the value of r */
Gilles Peskine449bd832023-01-11 14:50:10 +0100668 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r_copy, &m,
669 R_COPY, n_limbs));
670 TEST_EQUAL(0, mbedtls_mpi_mod_read(&r_copy, &m, input_A->x, input_A->len,
671 endian));
Janos Follath8dfc8c42022-11-26 15:39:02 +0000672
Janos Follath0020df92022-11-26 17:23:16 +0000673 /* Get number of bytes without leading zeroes */
674 size_t a_bytes_trimmed = a_bytes;
Gilles Peskine449bd832023-01-11 14:50:10 +0100675 while (a_bytes_trimmed > 0) {
676 unsigned char *r_byte_array = (unsigned char *) r.p;
677 if (r_byte_array[--a_bytes_trimmed] != 0) {
Janos Follath0020df92022-11-26 17:23:16 +0000678 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 }
Janos Follath0020df92022-11-26 17:23:16 +0000680 }
681 a_bytes_trimmed++;
682
683 /* Test write with three output buffer sizes: tight, same as input and
684 * longer than the input */
685 size_t obuf_sizes[3];
Gilles Peskine449bd832023-01-11 14:50:10 +0100686 const size_t obuf_sizes_len = sizeof(obuf_sizes) / sizeof(obuf_sizes[0]);
Janos Follath0020df92022-11-26 17:23:16 +0000687 obuf_sizes[0] = a_bytes_trimmed;
688 obuf_sizes[1] = a_bytes;
689 obuf_sizes[2] = a_bytes + 8;
690
Gilles Peskine449bd832023-01-11 14:50:10 +0100691 for (size_t i = 0; i < obuf_sizes_len; i++) {
692 ASSERT_ALLOC(obuf, obuf_sizes[i]);
693 TEST_EQUAL(0, mbedtls_mpi_mod_write(&r, &m, obuf, obuf_sizes[i], endian));
Janos Follath0020df92022-11-26 17:23:16 +0000694
695 /* Make sure that writing didn't corrupt the value of r */
Gilles Peskine449bd832023-01-11 14:50:10 +0100696 ASSERT_COMPARE(r.p, r.limbs, r_copy.p, r_copy.limbs);
Janos Follath0020df92022-11-26 17:23:16 +0000697
698 /* Set up reference output for checking the result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100699 ASSERT_ALLOC(ref_buf, obuf_sizes[i]);
700 switch (endian) {
Janos Follath0020df92022-11-26 17:23:16 +0000701 case MBEDTLS_MPI_MOD_EXT_REP_LE:
Gilles Peskine449bd832023-01-11 14:50:10 +0100702 memcpy(ref_buf, input_A->x, a_bytes_trimmed);
Janos Follath0020df92022-11-26 17:23:16 +0000703 break;
704 case MBEDTLS_MPI_MOD_EXT_REP_BE:
Gilles Peskine449bd832023-01-11 14:50:10 +0100705 {
706 size_t a_offset = input_A->len - a_bytes_trimmed;
707 size_t ref_offset = obuf_sizes[i] - a_bytes_trimmed;
708 memcpy(ref_buf + ref_offset, input_A->x + a_offset,
709 a_bytes_trimmed);
710 }
711 break;
Janos Follath0020df92022-11-26 17:23:16 +0000712 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100713 TEST_ASSERT(0);
Janos Follath0020df92022-11-26 17:23:16 +0000714 }
715
716 /* Check the result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100717 ASSERT_COMPARE(obuf, obuf_sizes[i], ref_buf, obuf_sizes[i]);
Janos Follath0020df92022-11-26 17:23:16 +0000718
Gilles Peskine449bd832023-01-11 14:50:10 +0100719 mbedtls_free(ref_buf);
Janos Follath0020df92022-11-26 17:23:16 +0000720 ref_buf = NULL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100721 mbedtls_free(obuf);
Janos Follath0020df92022-11-26 17:23:16 +0000722 obuf = NULL;
723 }
724
Minos Galanakis8f242702022-11-10 16:56:02 +0000725exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100726 mbedtls_mpi_mod_modulus_free(&m);
727 mbedtls_free(N);
728 mbedtls_free(R);
729 mbedtls_free(R_COPY);
730 mbedtls_free(obuf);
Minos Galanakis8f242702022-11-10 16:56:02 +0000731}
732/* END_CASE */