blob: 8f0b6732a2a7c99b17b2b0bb8eabeb7605ca5af9 [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) \
Tom Cosgrove65cd8512023-07-20 16:46:01 +010010 TEST_BUFFERS_EQUAL((a).p, (a).limbs * sizeof(mbedtls_mpi_uint), \
Gilles Peskine449bd832023-01-11 14:50:10 +010011 (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);
Minos Galanakis88e16df2023-05-09 14:11:43 +010053
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
Gilles Peskine449bd832023-01-11 14:50:10 +010066 TEST_EQUAL(ret, iret);
Werner Lewis0c6ea122022-09-30 13:02:16 +010067
Minos Galanakisdd365a52022-10-19 01:48:32 +010068 /* Only test if the constants have been set-up */
Gilles Peskine449bd832023-01-11 14:50:10 +010069 if (ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
Minos Galanakisdd365a52022-10-19 01:48:32 +010070 /* Test that the consts have been calculated */
Gilles Peskine449bd832023-01-11 14:50:10 +010071 TEST_ASSERT(m.rep.mont.rr != NULL);
72 TEST_ASSERT(m.rep.mont.mm != 0);
Minos Galanakisdd365a52022-10-19 01:48:32 +010073
Minos Galanakisdd365a52022-10-19 01:48:32 +010074 }
75
Werner Lewis0c6ea122022-09-30 13:02:16 +010076 /* Address sanitiser should catch if we try to free mp */
Gilles Peskine449bd832023-01-11 14:50:10 +010077 mbedtls_mpi_mod_modulus_free(&m);
Werner Lewis0c6ea122022-09-30 13:02:16 +010078
79 /* Make sure that the modulus doesn't have reference to mp anymore */
Gilles Peskine449bd832023-01-11 14:50:10 +010080 TEST_ASSERT(m.p != mp);
Werner Lewis0c6ea122022-09-30 13:02:16 +010081
Minos Galanakisdd365a52022-10-19 01:48:32 +010082 /* Only test if the constants have been set-up */
Gilles Peskine449bd832023-01-11 14:50:10 +010083 if (ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
Minos Galanakisdd365a52022-10-19 01:48:32 +010084 /* Verify the data and pointers allocated have been properly wiped */
Gilles Peskine449bd832023-01-11 14:50:10 +010085 TEST_ASSERT(m.rep.mont.rr == NULL);
86 TEST_ASSERT(m.rep.mont.mm == 0);
Minos Galanakisdd365a52022-10-19 01:48:32 +010087 }
Werner Lewis0c6ea122022-09-30 13:02:16 +010088exit:
89 /* It should be safe to call an mbedtls free several times */
Gilles Peskine449bd832023-01-11 14:50:10 +010090 mbedtls_mpi_mod_modulus_free(&m);
Werner Lewis0c6ea122022-09-30 13:02:16 +010091
92 #undef MLIMBS
93}
94/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +000095
Gabor Mezeieca74662022-12-13 10:53:50 +010096/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010097void mpi_mod_mul(char *input_A,
98 char *input_B,
99 char *input_N,
100 char *result)
Gabor Mezeieca74662022-12-13 10:53:50 +0100101{
Gabor Mezeieca74662022-12-13 10:53:50 +0100102 mbedtls_mpi_uint *X = NULL;
Gabor Mezeieca74662022-12-13 10:53:50 +0100103
Gabor Mezei78c4fb42022-12-20 18:09:49 +0100104 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
Gabor Mezeieca74662022-12-13 10:53:50 +0100109 mbedtls_mpi_mod_modulus m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 mbedtls_mpi_mod_modulus_init(&m);
Gabor Mezeieca74662022-12-13 10:53:50 +0100111
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100112 TEST_EQUAL(mbedtls_test_read_mpi_modulus(&m, input_N,
Minos Galanakis0f718c92023-05-19 14:22:06 +0100113 MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
Gabor Mezeieca74662022-12-13 10:53:50 +0100114
Gilles Peskine449bd832023-01-11 14:50:10 +0100115 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);
Gabor Mezei809baef2022-12-16 16:31:59 +0100118
119 const size_t limbs = m.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100120 const size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
Gabor Mezei809baef2022-12-16 16:31:59 +0100121
Gilles Peskine449bd832023-01-11 14:50:10 +0100122 TEST_EQUAL(rA.limbs, limbs);
123 TEST_EQUAL(rB.limbs, limbs);
124 TEST_EQUAL(rR.limbs, limbs);
Gabor Mezei809baef2022-12-16 16:31:59 +0100125
Gilles Peskine449bd832023-01-11 14:50:10 +0100126 ASSERT_ALLOC(X, limbs);
Gabor Mezeieca74662022-12-13 10:53:50 +0100127
Gilles Peskine449bd832023-01-11 14:50:10 +0100128 TEST_EQUAL(mbedtls_mpi_mod_residue_setup(&rX, &m, X, limbs), 0);
Gabor Mezeieca74662022-12-13 10:53:50 +0100129
Gilles Peskine449bd832023-01-11 14:50:10 +0100130 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &m), 0);
Tom Cosgrove65cd8512023-07-20 16:46:01 +0100131 TEST_BUFFERS_EQUAL(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100132
133 /* alias X to A */
Gilles Peskine449bd832023-01-11 14:50:10 +0100134 memcpy(rX.p, rA.p, bytes);
135 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rB, &m), 0);
Tom Cosgrove65cd8512023-07-20 16:46:01 +0100136 TEST_BUFFERS_EQUAL(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100137
138 /* alias X to B */
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 memcpy(rX.p, rB.p, bytes);
140 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rX, &m), 0);
Tom Cosgrove65cd8512023-07-20 16:46:01 +0100141 TEST_BUFFERS_EQUAL(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100142
143 /* A == B: alias A and B */
Gilles Peskine449bd832023-01-11 14:50:10 +0100144 if (memcmp(rA.p, rB.p, bytes) == 0) {
145 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rA, &m), 0);
Tom Cosgrove65cd8512023-07-20 16:46:01 +0100146 TEST_BUFFERS_EQUAL(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100147
148 /* X, A, B all aliased together */
Gilles Peskine449bd832023-01-11 14:50:10 +0100149 memcpy(rX.p, rA.p, bytes);
150 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rX, &m), 0);
Tom Cosgrove65cd8512023-07-20 16:46:01 +0100151 TEST_BUFFERS_EQUAL(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100152 }
Gabor Mezeieca74662022-12-13 10:53:50 +0100153 /* A != B: test B * A */
Gilles Peskine449bd832023-01-11 14:50:10 +0100154 else {
155 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rB, &rA, &m), 0);
Tom Cosgrove65cd8512023-07-20 16:46:01 +0100156 TEST_BUFFERS_EQUAL(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100157
158 /* B * A: alias X to A */
Gilles Peskine449bd832023-01-11 14:50:10 +0100159 memcpy(rX.p, rA.p, bytes);
160 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rB, &rX, &m), 0);
Tom Cosgrove65cd8512023-07-20 16:46:01 +0100161 TEST_BUFFERS_EQUAL(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100162
163 /* B + A: alias X to B */
Gilles Peskine449bd832023-01-11 14:50:10 +0100164 memcpy(rX.p, rB.p, bytes);
165 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rA, &m), 0);
Tom Cosgrove65cd8512023-07-20 16:46:01 +0100166 TEST_BUFFERS_EQUAL(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100167 }
168
169exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100170 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);
Gabor Mezeif9728132022-12-20 13:55:37 +0100175
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 mbedtls_mpi_mod_modulus_free(&m);
Gabor Mezeieca74662022-12-13 10:53:50 +0100177}
178/* END_CASE */
179
180/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100181void mpi_mod_mul_neg(char *input_A,
182 char *input_B,
183 char *input_N,
184 char *result,
185 int exp_ret)
Gabor Mezeieca74662022-12-13 10:53:50 +0100186{
Gabor Mezeieca74662022-12-13 10:53:50 +0100187 mbedtls_mpi_uint *X = NULL;
Gabor Mezeieca74662022-12-13 10:53:50 +0100188
Gabor Mezei78c4fb42022-12-20 18:09:49 +0100189 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
Gabor Mezeieca74662022-12-13 10:53:50 +0100194 mbedtls_mpi_mod_modulus m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100195 mbedtls_mpi_mod_modulus_init(&m);
Gabor Mezeieca74662022-12-13 10:53:50 +0100196
Gabor Mezeif65c71f2022-12-21 11:54:22 +0100197 mbedtls_mpi_mod_modulus fake_m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 mbedtls_mpi_mod_modulus_init(&fake_m);
Gabor Mezeif65c71f2022-12-21 11:54:22 +0100199
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100200 TEST_EQUAL(mbedtls_test_read_mpi_modulus(&m, input_N,
Minos Galanakis0f718c92023-05-19 14:22:06 +0100201 MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
Gabor Mezeieca74662022-12-13 10:53:50 +0100202
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 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);
Gabor Mezei809baef2022-12-16 16:31:59 +0100206
207 const size_t limbs = m.limbs;
208
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 ASSERT_ALLOC(X, limbs);
Gabor Mezeieca74662022-12-13 10:53:50 +0100210
Gilles Peskine449bd832023-01-11 14:50:10 +0100211 TEST_EQUAL(mbedtls_mpi_mod_residue_setup(&rX, &m, X, limbs), 0);
Gabor Mezei809baef2022-12-16 16:31:59 +0100212 rX.limbs = rR.limbs;
Gabor Mezeieca74662022-12-13 10:53:50 +0100213
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &m), exp_ret);
Gabor Mezeieca74662022-12-13 10:53:50 +0100215
216 /* Check when m is not initialized */
Gilles Peskine449bd832023-01-11 14:50:10 +0100217 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &fake_m),
218 MBEDTLS_ERR_MPI_BAD_INPUT_DATA);
Gabor Mezeieca74662022-12-13 10:53:50 +0100219
220exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100221 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);
Gabor Mezeif9728132022-12-20 13:55:37 +0100226
Gilles Peskine449bd832023-01-11 14:50:10 +0100227 mbedtls_mpi_mod_modulus_free(&m);
228 mbedtls_mpi_mod_modulus_free(&fake_m);
Gabor Mezeieca74662022-12-13 10:53:50 +0100229}
230/* END_CASE */
231
Tom Cosgrove62b20482022-12-01 14:27:37 +0000232/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100233void mpi_mod_sub(char *input_N,
234 char *input_A, char *input_B,
235 char *input_D, int expected_ret)
Tom Cosgrove62b20482022-12-01 14:27:37 +0000236{
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;
Janos Follath5933f692022-11-02 14:35:17 +0000242
Tom Cosgrove62b20482022-12-01 14:27:37 +0000243 mbedtls_mpi_mod_modulus m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 mbedtls_mpi_mod_modulus_init(&m);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000245
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 TEST_EQUAL(0,
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100247 mbedtls_test_read_mpi_modulus(&m, input_N,
Minos Galanakis0f718c92023-05-19 14:22:06 +0100248 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
Tom Cosgrove62b20482022-12-01 14:27:37 +0000249
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. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 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));
Tom Cosgrove62b20482022-12-01 14:27:37 +0000256
257 size_t limbs = m.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100258 size_t bytes = limbs * sizeof(*X_raw);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000259
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 if (expected_ret == 0) {
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000261 /* Negative test with too many limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100262 ASSERT_ALLOC(X_raw, limbs + 1);
Tom Cosgrove62b20482022-12-01 14:27:37 +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 Cosgrove62b20482022-12-01 14:27:37 +0000268
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 mbedtls_free(X_raw);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000270 X_raw = NULL;
271
272 /* Negative test with too few limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 if (limbs > 1) {
274 ASSERT_ALLOC(X_raw, limbs - 1);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000275
Tom Cosgrove62b20482022-12-01 14:27:37 +0000276 x.p = X_raw;
277 x.limbs = limbs - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100278 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
279 mbedtls_mpi_mod_sub(&x, &a, &b, &m));
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000280
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 mbedtls_free(X_raw);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000282 X_raw = NULL;
Tom Cosgrove62b20482022-12-01 14:27:37 +0000283 }
284
285 /* Negative testing with too many/too few limbs in a and b is covered by
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000286 * manually-written test cases with expected_ret != 0. */
Tom Cosgrove62b20482022-12-01 14:27:37 +0000287 }
288
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 ASSERT_ALLOC(X_raw, limbs);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &m, X_raw, limbs));
Tom Cosgrove62b20482022-12-01 14:27:37 +0000292
293 /* a - b => Correct result, or expected error */
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 TEST_EQUAL(expected_ret, mbedtls_mpi_mod_sub(&x, &a, &b, &m));
295 if (expected_ret != 0) {
Tom Cosgrove62b20482022-12-01 14:27:37 +0000296 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100297 }
Tom Cosgrove62b20482022-12-01 14:27:37 +0000298
Gilles Peskine449bd832023-01-11 14:50:10 +0100299 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000300
301 /* a - b: alias x to a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 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);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000305
306 /* a - b: alias x to b => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 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);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000310
Gilles Peskine449bd832023-01-11 14:50:10 +0100311 if (memcmp(a.p, b.p, bytes) == 0) {
Tom Cosgrove62b20482022-12-01 14:27:37 +0000312 /* a == b: alias a and b */
313
314 /* a - a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100315 TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &a, &a, &m));
316 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000317
318 /* a - a: x, a, b all aliased together => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100319 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);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000322 }
323
324exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100325 mbedtls_free((void *) m.p); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
326 mbedtls_mpi_mod_modulus_free(&m);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000327
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 mbedtls_free(a.p);
329 mbedtls_free(b.p);
330 mbedtls_free(d.p);
331 mbedtls_free(X_raw);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000332}
333/* END_CASE */
Tom Cosgrovedc197592022-12-15 16:59:40 +0000334
335/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100336void mpi_mod_inv_mont(char *input_N,
337 char *input_A, char *input_I,
338 int expected_ret)
Tom Cosgrovedc197592022-12-15 16:59:40 +0000339{
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;
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 mbedtls_mpi_mod_modulus_init(&N);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000347
Gilles Peskine449bd832023-01-11 14:50:10 +0100348 TEST_EQUAL(0,
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100349 mbedtls_test_read_mpi_modulus(&N, input_N,
Minos Galanakis0f718c92023-05-19 14:22:06 +0100350 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000351
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. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 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));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000357
358 size_t limbs = N.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100359 size_t bytes = limbs * sizeof(*X_raw);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000360
Gilles Peskine449bd832023-01-11 14:50:10 +0100361 ASSERT_ALLOC(X_raw, limbs);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000362
Gilles Peskine449bd832023-01-11 14:50:10 +0100363 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &N, X_raw, limbs));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000364
Gilles Peskine449bd832023-01-11 14:50:10 +0100365 TEST_EQUAL(expected_ret, mbedtls_mpi_mod_inv(&x, &a, &N));
366 if (expected_ret == 0) {
367 TEST_COMPARE_MPI_RESIDUES(x, i);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000368
369 /* a^-1: alias x to a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 memcpy(x.p, a.p, bytes);
371 TEST_EQUAL(0, mbedtls_mpi_mod_inv(&x, &x, &N));
372 TEST_COMPARE_MPI_RESIDUES(x, i);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000373 }
374
375exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 mbedtls_free((void *) N.p); /* mbedtls_mpi_mod_modulus_free() sets N.p = NULL */
377 mbedtls_mpi_mod_modulus_free(&N);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000378
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 mbedtls_free(a.p);
380 mbedtls_free(i.p);
381 mbedtls_free(X_raw);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000382}
383/* END_CASE */
384
385/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100386void mpi_mod_inv_non_mont(char *input_N,
387 char *input_A, char *input_I,
388 int expected_ret)
Tom Cosgrovedc197592022-12-15 16:59:40 +0000389{
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;
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 mbedtls_mpi_mod_modulus_init(&N);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000397
Gilles Peskine449bd832023-01-11 14:50:10 +0100398 TEST_EQUAL(0,
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100399 mbedtls_test_read_mpi_modulus(&N, input_N,
Minos Galanakis0f718c92023-05-19 14:22:06 +0100400 MBEDTLS_MPI_MOD_REP_OPT_RED));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000401
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. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 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));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000407
408 size_t limbs = N.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 size_t bytes = limbs * sizeof(*X_raw);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000410
Gilles Peskine449bd832023-01-11 14:50:10 +0100411 ASSERT_ALLOC(X_raw, limbs);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000412
Gilles Peskine449bd832023-01-11 14:50:10 +0100413 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &N, X_raw, limbs));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000414
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 TEST_EQUAL(expected_ret, mbedtls_mpi_mod_inv(&x, &a, &N));
416 if (expected_ret == 0) {
417 TEST_COMPARE_MPI_RESIDUES(x, i);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000418
419 /* a^-1: alias x to a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100420 memcpy(x.p, a.p, bytes);
421 TEST_EQUAL(0, mbedtls_mpi_mod_inv(&x, &x, &N));
422 TEST_COMPARE_MPI_RESIDUES(x, i);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000423 }
424
425exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 mbedtls_free((void *) N.p); /* mbedtls_mpi_mod_modulus_free() sets N.p = NULL */
427 mbedtls_mpi_mod_modulus_free(&N);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000428
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 mbedtls_free(a.p);
430 mbedtls_free(i.p);
431 mbedtls_free(X_raw);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000432}
433/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +0000434
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000435/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100436void mpi_mod_add(char *input_N,
437 char *input_A, char *input_B,
438 char *input_S, int expected_ret)
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000439{
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;
Janos Follath5933f692022-11-02 14:35:17 +0000445
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000446 mbedtls_mpi_mod_modulus m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100447 mbedtls_mpi_mod_modulus_init(&m);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000448
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 TEST_EQUAL(0,
Minos Galanakis67ebaaf2023-05-09 14:26:26 +0100450 mbedtls_test_read_mpi_modulus(&m, input_N,
Minos Galanakis0f718c92023-05-19 14:22:06 +0100451 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000452
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. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 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));
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000459
460 size_t limbs = m.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 size_t bytes = limbs * sizeof(*X_raw);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000462
Gilles Peskine449bd832023-01-11 14:50:10 +0100463 if (expected_ret == 0) {
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000464 /* Negative test with too many limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100465 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 Lewise1b6b7c2022-11-29 12:25:05 +0000471
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 mbedtls_free(X_raw);
Werner Lewis79341a42022-12-13 17:19:01 +0000473 X_raw = NULL;
474
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000475 /* Negative test with too few limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 if (limbs > 1) {
477 ASSERT_ALLOC(X_raw, limbs - 1);
Werner Lewis79341a42022-12-13 17:19:01 +0000478
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000479 x.p = X_raw;
480 x.limbs = limbs - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100481 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
482 mbedtls_mpi_mod_add(&x, &a, &b, &m));
Werner Lewis79341a42022-12-13 17:19:01 +0000483
Gilles Peskine449bd832023-01-11 14:50:10 +0100484 mbedtls_free(X_raw);
Werner Lewis79341a42022-12-13 17:19:01 +0000485 X_raw = NULL;
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000486 }
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
Werner Lewis79341a42022-12-13 17:19:01 +0000492 /* Allocate correct number of limbs for X_raw */
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 ASSERT_ALLOC(X_raw, limbs);
Werner Lewis79341a42022-12-13 17:19:01 +0000494
Gilles Peskine449bd832023-01-11 14:50:10 +0100495 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &m, X_raw, limbs));
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000496
497 /* A + B => Correct result or expected error */
Gilles Peskine449bd832023-01-11 14:50:10 +0100498 TEST_EQUAL(expected_ret, mbedtls_mpi_mod_add(&x, &a, &b, &m));
499 if (expected_ret != 0) {
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000500 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100501 }
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000502
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000504
505 /* a + b: alias x to a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100506 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);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000509
510 /* a + b: alias x to b => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100511 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);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000514
Gilles Peskine449bd832023-01-11 14:50:10 +0100515 if (memcmp(a.p, b.p, bytes) == 0) {
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000516 /* a == b: alias a and b */
517
518 /* a + a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100519 TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &a, &a, &m));
520 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000521
522 /* a + a: x, a, b all aliased together => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100523 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);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000526 }
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000527
528exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100529 mbedtls_free((void *) m.p); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
530 mbedtls_mpi_mod_modulus_free(&m);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000531
Gilles Peskine449bd832023-01-11 14:50:10 +0100532 mbedtls_free(a.p);
533 mbedtls_free(b.p);
534 mbedtls_free(s.p);
535 mbedtls_free(X_raw);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000536}
537/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +0000538
Minos Galanakis8f242702022-11-10 16:56:02 +0000539/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100540void mpi_residue_setup(char *input_N, char *input_R, int ret)
Minos Galanakisa17ad482022-11-16 16:29:15 +0000541{
Minos Galanakisa17ad482022-11-16 16:29:15 +0000542 mbedtls_mpi_uint *N = NULL;
543 mbedtls_mpi_uint *R = NULL;
Minos Galanakisaed832a2022-11-24 09:09:47 +0000544 size_t n_limbs, r_limbs;
Minos Galanakisa17ad482022-11-16 16:29:15 +0000545 mbedtls_mpi_mod_modulus m;
546 mbedtls_mpi_mod_residue r;
547
Gilles Peskine449bd832023-01-11 14:50:10 +0100548 mbedtls_mpi_mod_modulus_init(&m);
Minos Galanakisa17ad482022-11-16 16:29:15 +0000549
Minos Galanakisaed832a2022-11-24 09:09:47 +0000550 /* Allocate the memory for intermediate data structures */
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 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));
Minos Galanakisaed832a2022-11-24 09:09:47 +0000553
Minos Galanakis88e16df2023-05-09 14:11:43 +0100554 TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
Minos Galanakisa17ad482022-11-16 16:29:15 +0000555
Gilles Peskine449bd832023-01-11 14:50:10 +0100556 TEST_EQUAL(ret, mbedtls_mpi_mod_residue_setup(&r, &m, R, r_limbs));
Minos Galanakisa17ad482022-11-16 16:29:15 +0000557
Gilles Peskine449bd832023-01-11 14:50:10 +0100558 if (ret == 0) {
559 TEST_EQUAL(r.limbs, r_limbs);
560 TEST_ASSERT(r.p == R);
Janos Follath91f3abd2022-11-26 11:47:14 +0000561 }
562
Minos Galanakisa17ad482022-11-16 16:29:15 +0000563exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 mbedtls_mpi_mod_modulus_free(&m);
565 mbedtls_free(N);
566 mbedtls_free(R);
Minos Galanakisa17ad482022-11-16 16:29:15 +0000567}
568/* END_CASE */
Minos Galanakisaed832a2022-11-24 09:09:47 +0000569
Minos Galanakisa17ad482022-11-16 16:29:15 +0000570/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100571void mpi_mod_io_neg(char *input_N, data_t *buf, int ret)
Minos Galanakis8f242702022-11-10 16:56:02 +0000572{
Minos Galanakis8f242702022-11-10 16:56:02 +0000573 mbedtls_mpi_uint *N = NULL;
574 mbedtls_mpi_uint *R = NULL;
Minos Galanakis8f242702022-11-10 16:56:02 +0000575
576 mbedtls_mpi_mod_modulus m;
Janos Follathe7190a22022-11-26 18:46:54 +0000577 mbedtls_mpi_mod_residue r = { NULL, 0 };
Minos Galanakis96070a52022-11-25 19:32:10 +0000578 mbedtls_mpi_mod_ext_rep endian = MBEDTLS_MPI_MOD_EXT_REP_LE;
Minos Galanakis8f242702022-11-10 16:56:02 +0000579
Gilles Peskine449bd832023-01-11 14:50:10 +0100580 mbedtls_mpi_mod_modulus_init(&m);
Janos Follath799eaee2022-11-25 15:57:04 +0000581
Janos Follath339b4392022-11-26 12:20:41 +0000582 size_t n_limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100583 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
Janos Follath339b4392022-11-26 12:20:41 +0000584 size_t r_limbs = n_limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100585 ASSERT_ALLOC(R, r_limbs);
Minos Galanakis8f242702022-11-10 16:56:02 +0000586
Janos Follathe7190a22022-11-26 18:46:54 +0000587 /* modulus->p == NULL || residue->p == NULL ( m has not been set-up ) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
589 mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
Minos Galanakis8f242702022-11-10 16:56:02 +0000590
Gilles Peskine449bd832023-01-11 14:50:10 +0100591 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
592 mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
Minos Galanakis8f242702022-11-10 16:56:02 +0000593
Janos Follathe7190a22022-11-26 18:46:54 +0000594 /* Set up modulus and test with residue->p == NULL */
Minos Galanakis88e16df2023-05-09 14:11:43 +0100595 TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
Minos Galanakis96070a52022-11-25 19:32:10 +0000596
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 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));
Janos Follathe7190a22022-11-26 18:46:54 +0000601
602 /* Do the rest of the tests with a residue set up with the input data */
Gilles Peskine449bd832023-01-11 14:50:10 +0100603 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r, &m, R, r_limbs));
Minos Galanakis96070a52022-11-25 19:32:10 +0000604
Janos Follathd7bb3522022-11-26 14:59:27 +0000605 /* Fail for r_limbs < m->limbs */
606 r.limbs--;
Gilles Peskine449bd832023-01-11 14:50:10 +0100607 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));
Janos Follathd7bb3522022-11-26 14:59:27 +0000612 r.limbs++;
613
614 /* Fail for r_limbs > m->limbs */
615 m.limbs--;
Gilles Peskine449bd832023-01-11 14:50:10 +0100616 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));
Janos Follathd7bb3522022-11-26 14:59:27 +0000621 m.limbs++;
Minos Galanakis96070a52022-11-25 19:32:10 +0000622
623 /* Test the read */
Gilles Peskine449bd832023-01-11 14:50:10 +0100624 TEST_EQUAL(ret, mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
Minos Galanakis96070a52022-11-25 19:32:10 +0000625
626 /* Test write overflow only when the representation is large and read is successful */
Gilles Peskine449bd832023-01-11 14:50:10 +0100627 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 }
Janos Follathd7bb3522022-11-26 14:59:27 +0000631
Minos Galanakis8f242702022-11-10 16:56:02 +0000632exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 mbedtls_mpi_mod_residue_release(&r);
634 mbedtls_mpi_mod_modulus_free(&m);
635 mbedtls_free(N);
636 mbedtls_free(R);
Minos Galanakis8f242702022-11-10 16:56:02 +0000637}
638/* END_CASE */
639
640/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100641void mpi_mod_io(char *input_N, data_t *input_A, int endian)
Minos Galanakis8f242702022-11-10 16:56:02 +0000642{
643 mbedtls_mpi_uint *N = NULL;
644 mbedtls_mpi_uint *R = NULL;
Janos Follath8dfc8c42022-11-26 15:39:02 +0000645 mbedtls_mpi_uint *R_COPY = NULL;
Janos Follath0020df92022-11-26 17:23:16 +0000646 unsigned char *obuf = NULL;
647 unsigned char *ref_buf = NULL;
Minos Galanakis8f242702022-11-10 16:56:02 +0000648 mbedtls_mpi_mod_modulus m;
649 mbedtls_mpi_mod_residue r;
Janos Follath8dfc8c42022-11-26 15:39:02 +0000650 mbedtls_mpi_mod_residue r_copy;
Minos Galanakis8f242702022-11-10 16:56:02 +0000651 size_t n_limbs, n_bytes, a_bytes;
652
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 mbedtls_mpi_mod_modulus_init(&m);
Janos Follath799eaee2022-11-25 15:57:04 +0000654
Minos Galanakis8f242702022-11-10 16:56:02 +0000655 /* Read inputs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100656 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
657 n_bytes = n_limbs * sizeof(mbedtls_mpi_uint);
Janos Follath6ef582f2022-11-26 14:19:02 +0000658 a_bytes = input_A->len;
Minos Galanakis8f242702022-11-10 16:56:02 +0000659
660 /* Allocate the memory for intermediate data structures */
Gilles Peskine449bd832023-01-11 14:50:10 +0100661 ASSERT_ALLOC(R, n_bytes);
662 ASSERT_ALLOC(R_COPY, n_bytes);
Minos Galanakis8f242702022-11-10 16:56:02 +0000663
664 /* Test that input's size is not greater to modulo's */
Gilles Peskine449bd832023-01-11 14:50:10 +0100665 TEST_LE_U(a_bytes, n_bytes);
Minos Galanakis8f242702022-11-10 16:56:02 +0000666
667 /* Init Structures */
Minos Galanakis88e16df2023-05-09 14:11:43 +0100668 TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
Minos Galanakis8f242702022-11-10 16:56:02 +0000669
670 /* Enforcing p_limbs >= m->limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100671 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r, &m, R, n_limbs));
Minos Galanakis8f242702022-11-10 16:56:02 +0000672
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 TEST_EQUAL(0, mbedtls_mpi_mod_read(&r, &m, input_A->x, input_A->len,
674 endian));
Minos Galanakis8f242702022-11-10 16:56:02 +0000675
Janos Follath0020df92022-11-26 17:23:16 +0000676 /* Read a copy for checking that writing didn't change the value of r */
Gilles Peskine449bd832023-01-11 14:50:10 +0100677 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));
Janos Follath8dfc8c42022-11-26 15:39:02 +0000681
Janos Follath0020df92022-11-26 17:23:16 +0000682 /* Get number of bytes without leading zeroes */
683 size_t a_bytes_trimmed = a_bytes;
Gilles Peskine449bd832023-01-11 14:50:10 +0100684 while (a_bytes_trimmed > 0) {
685 unsigned char *r_byte_array = (unsigned char *) r.p;
686 if (r_byte_array[--a_bytes_trimmed] != 0) {
Janos Follath0020df92022-11-26 17:23:16 +0000687 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100688 }
Janos Follath0020df92022-11-26 17:23:16 +0000689 }
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];
Gilles Peskine449bd832023-01-11 14:50:10 +0100695 const size_t obuf_sizes_len = sizeof(obuf_sizes) / sizeof(obuf_sizes[0]);
Janos Follath0020df92022-11-26 17:23:16 +0000696 obuf_sizes[0] = a_bytes_trimmed;
697 obuf_sizes[1] = a_bytes;
698 obuf_sizes[2] = a_bytes + 8;
699
Gilles Peskine449bd832023-01-11 14:50:10 +0100700 for (size_t i = 0; i < obuf_sizes_len; i++) {
701 ASSERT_ALLOC(obuf, obuf_sizes[i]);
702 TEST_EQUAL(0, mbedtls_mpi_mod_write(&r, &m, obuf, obuf_sizes[i], endian));
Janos Follath0020df92022-11-26 17:23:16 +0000703
704 /* Make sure that writing didn't corrupt the value of r */
Tom Cosgrove65cd8512023-07-20 16:46:01 +0100705 TEST_BUFFERS_EQUAL(r.p, r.limbs, r_copy.p, r_copy.limbs);
Janos Follath0020df92022-11-26 17:23:16 +0000706
707 /* Set up reference output for checking the result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100708 ASSERT_ALLOC(ref_buf, obuf_sizes[i]);
709 switch (endian) {
Janos Follath0020df92022-11-26 17:23:16 +0000710 case MBEDTLS_MPI_MOD_EXT_REP_LE:
Gilles Peskine449bd832023-01-11 14:50:10 +0100711 memcpy(ref_buf, input_A->x, a_bytes_trimmed);
Janos Follath0020df92022-11-26 17:23:16 +0000712 break;
713 case MBEDTLS_MPI_MOD_EXT_REP_BE:
Gilles Peskine449bd832023-01-11 14:50:10 +0100714 {
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;
Janos Follath0020df92022-11-26 17:23:16 +0000721 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100722 TEST_ASSERT(0);
Janos Follath0020df92022-11-26 17:23:16 +0000723 }
724
725 /* Check the result */
Tom Cosgrove65cd8512023-07-20 16:46:01 +0100726 TEST_BUFFERS_EQUAL(obuf, obuf_sizes[i], ref_buf, obuf_sizes[i]);
Janos Follath0020df92022-11-26 17:23:16 +0000727
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 mbedtls_free(ref_buf);
Janos Follath0020df92022-11-26 17:23:16 +0000729 ref_buf = NULL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100730 mbedtls_free(obuf);
Janos Follath0020df92022-11-26 17:23:16 +0000731 obuf = NULL;
732 }
733
Minos Galanakis8f242702022-11-10 16:56:02 +0000734exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100735 mbedtls_mpi_mod_modulus_free(&m);
736 mbedtls_free(N);
737 mbedtls_free(R);
738 mbedtls_free(R_COPY);
739 mbedtls_free(obuf);
Minos Galanakis8f242702022-11-10 16:56:02 +0000740}
741/* END_CASE */