blob: 233d3a982b3155d8760aff333bb874d33c75d3d7 [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_modulus(mbedtls_mpi_mod_modulus *m,
14 mbedtls_mpi_mod_rep_selector int_rep,
15 char *input)
Tom Cosgrove62b20482022-12-01 14:27:37 +000016{
17 mbedtls_mpi_uint *p = NULL;
18 size_t limbs;
19
Gilles Peskine449bd832023-01-11 14:50:10 +010020 int ret = mbedtls_test_read_mpi_core(&p, &limbs, input);
21 if (ret != 0) {
22 return ret;
23 }
Tom Cosgrove62b20482022-12-01 14:27:37 +000024
Gilles Peskine449bd832023-01-11 14:50:10 +010025 return mbedtls_mpi_mod_modulus_setup(m, p, limbs, int_rep);
Tom Cosgrove62b20482022-12-01 14:27:37 +000026}
27
Gilles Peskine449bd832023-01-11 14:50:10 +010028static int test_read_residue(mbedtls_mpi_mod_residue *r,
29 const mbedtls_mpi_mod_modulus *m,
30 char *input,
31 int skip_limbs_and_value_checks)
Tom Cosgrove62b20482022-12-01 14:27:37 +000032{
33 mbedtls_mpi_uint *p = NULL;
34 size_t limbs;
35
Gilles Peskine449bd832023-01-11 14:50:10 +010036 int ret = mbedtls_test_read_mpi_core(&p, &limbs, input);
37 if (ret != 0) {
38 return ret;
39 }
Tom Cosgrove62b20482022-12-01 14:27:37 +000040
Gilles Peskine449bd832023-01-11 14:50:10 +010041 if (skip_limbs_and_value_checks) {
Tom Cosgrove62b20482022-12-01 14:27:37 +000042 r->p = p;
43 r->limbs = limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +010044 return 0;
Tom Cosgrove62b20482022-12-01 14:27:37 +000045 }
46
47 /* mbedtls_mpi_mod_residue_setup() checks limbs, and that value < m */
Gilles Peskine449bd832023-01-11 14:50:10 +010048 return mbedtls_mpi_mod_residue_setup(r, m, p, limbs);
Tom Cosgrove62b20482022-12-01 14:27:37 +000049}
Werner Lewis0c6ea122022-09-30 13:02:16 +010050/* END_HEADER */
51
52/* BEGIN_DEPENDENCIES
53 * depends_on:MBEDTLS_BIGNUM_C
54 * END_DEPENDENCIES
55 */
56
57/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010058void mpi_mod_setup(int int_rep, int iret)
Werner Lewis0c6ea122022-09-30 13:02:16 +010059{
60 #define MLIMBS 8
61 mbedtls_mpi_uint mp[MLIMBS];
62 mbedtls_mpi_mod_modulus m;
63 int ret;
64
Gilles Peskine449bd832023-01-11 14:50:10 +010065 memset(mp, 0xFF, sizeof(mp));
Werner Lewis0c6ea122022-09-30 13:02:16 +010066
Gilles Peskine449bd832023-01-11 14:50:10 +010067 mbedtls_mpi_mod_modulus_init(&m);
68 ret = mbedtls_mpi_mod_modulus_setup(&m, mp, MLIMBS, int_rep);
69 TEST_EQUAL(ret, iret);
Werner Lewis0c6ea122022-09-30 13:02:16 +010070
Minos Galanakisdd365a52022-10-19 01:48:32 +010071 /* Only test if the constants have been set-up */
Gilles Peskine449bd832023-01-11 14:50:10 +010072 if (ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
Minos Galanakisdd365a52022-10-19 01:48:32 +010073 /* Test that the consts have been calculated */
Gilles Peskine449bd832023-01-11 14:50:10 +010074 TEST_ASSERT(m.rep.mont.rr != NULL);
75 TEST_ASSERT(m.rep.mont.mm != 0);
Minos Galanakisdd365a52022-10-19 01:48:32 +010076
Minos Galanakisdd365a52022-10-19 01:48:32 +010077 }
78
Werner Lewis0c6ea122022-09-30 13:02:16 +010079 /* Address sanitiser should catch if we try to free mp */
Gilles Peskine449bd832023-01-11 14:50:10 +010080 mbedtls_mpi_mod_modulus_free(&m);
Werner Lewis0c6ea122022-09-30 13:02:16 +010081
82 /* Make sure that the modulus doesn't have reference to mp anymore */
Gilles Peskine449bd832023-01-11 14:50:10 +010083 TEST_ASSERT(m.p != mp);
Werner Lewis0c6ea122022-09-30 13:02:16 +010084
Minos Galanakisdd365a52022-10-19 01:48:32 +010085 /* Only test if the constants have been set-up */
Gilles Peskine449bd832023-01-11 14:50:10 +010086 if (ret == 0 && int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
Minos Galanakisdd365a52022-10-19 01:48:32 +010087 /* Verify the data and pointers allocated have been properly wiped */
Gilles Peskine449bd832023-01-11 14:50:10 +010088 TEST_ASSERT(m.rep.mont.rr == NULL);
89 TEST_ASSERT(m.rep.mont.mm == 0);
Minos Galanakisdd365a52022-10-19 01:48:32 +010090 }
Werner Lewis0c6ea122022-09-30 13:02:16 +010091exit:
92 /* It should be safe to call an mbedtls free several times */
Gilles Peskine449bd832023-01-11 14:50:10 +010093 mbedtls_mpi_mod_modulus_free(&m);
Werner Lewis0c6ea122022-09-30 13:02:16 +010094
95 #undef MLIMBS
96}
97/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +000098
Gabor Mezeieca74662022-12-13 10:53:50 +010099/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100100void mpi_mod_mul(char *input_A,
101 char *input_B,
102 char *input_N,
103 char *result)
Gabor Mezeieca74662022-12-13 10:53:50 +0100104{
Gabor Mezeieca74662022-12-13 10:53:50 +0100105 mbedtls_mpi_uint *X = NULL;
Gabor Mezeieca74662022-12-13 10:53:50 +0100106
Gabor Mezei78c4fb42022-12-20 18:09:49 +0100107 mbedtls_mpi_mod_residue rA = { NULL, 0 };
108 mbedtls_mpi_mod_residue rB = { NULL, 0 };
109 mbedtls_mpi_mod_residue rR = { NULL, 0 };
110 mbedtls_mpi_mod_residue rX = { NULL, 0 };
111
Gabor Mezeieca74662022-12-13 10:53:50 +0100112 mbedtls_mpi_mod_modulus m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100113 mbedtls_mpi_mod_modulus_init(&m);
Gabor Mezeieca74662022-12-13 10:53:50 +0100114
Gilles Peskine449bd832023-01-11 14:50:10 +0100115 TEST_EQUAL(test_read_modulus(&m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N),
116 0);
Gabor Mezeieca74662022-12-13 10:53:50 +0100117
Gilles Peskine449bd832023-01-11 14:50:10 +0100118 TEST_EQUAL(test_read_residue(&rA, &m, input_A, 0), 0);
119 TEST_EQUAL(test_read_residue(&rB, &m, input_B, 0), 0);
120 TEST_EQUAL(test_read_residue(&rR, &m, result, 0), 0);
Gabor Mezei809baef2022-12-16 16:31:59 +0100121
122 const size_t limbs = m.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100123 const size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
Gabor Mezei809baef2022-12-16 16:31:59 +0100124
Gilles Peskine449bd832023-01-11 14:50:10 +0100125 TEST_EQUAL(rA.limbs, limbs);
126 TEST_EQUAL(rB.limbs, limbs);
127 TEST_EQUAL(rR.limbs, limbs);
Gabor Mezei809baef2022-12-16 16:31:59 +0100128
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 ASSERT_ALLOC(X, limbs);
Gabor Mezeieca74662022-12-13 10:53:50 +0100130
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 TEST_EQUAL(mbedtls_mpi_mod_residue_setup(&rX, &m, X, limbs), 0);
Gabor Mezeieca74662022-12-13 10:53:50 +0100132
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &m), 0);
134 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100135
136 /* alias X to A */
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 memcpy(rX.p, rA.p, bytes);
138 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rB, &m), 0);
139 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100140
141 /* alias X to B */
Gilles Peskine449bd832023-01-11 14:50:10 +0100142 memcpy(rX.p, rB.p, bytes);
143 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rX, &m), 0);
144 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100145
146 /* A == B: alias A and B */
Gilles Peskine449bd832023-01-11 14:50:10 +0100147 if (memcmp(rA.p, rB.p, bytes) == 0) {
148 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rA, &m), 0);
149 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100150
151 /* X, A, B all aliased together */
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 memcpy(rX.p, rA.p, bytes);
153 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rX, &m), 0);
154 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100155 }
Gabor Mezeieca74662022-12-13 10:53:50 +0100156 /* A != B: test B * A */
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 else {
158 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rB, &rA, &m), 0);
159 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100160
161 /* B * A: alias X to A */
Gilles Peskine449bd832023-01-11 14:50:10 +0100162 memcpy(rX.p, rA.p, bytes);
163 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rB, &rX, &m), 0);
164 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100165
166 /* B + A: alias X to B */
Gilles Peskine449bd832023-01-11 14:50:10 +0100167 memcpy(rX.p, rB.p, bytes);
168 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rX, &rA, &m), 0);
169 ASSERT_COMPARE(rX.p, bytes, rR.p, bytes);
Gabor Mezeieca74662022-12-13 10:53:50 +0100170 }
171
172exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100173 mbedtls_free(rA.p);
174 mbedtls_free(rB.p);
175 mbedtls_free(rR.p);
176 mbedtls_free(X);
177 mbedtls_free((mbedtls_mpi_uint *) m.p);
Gabor Mezeif9728132022-12-20 13:55:37 +0100178
Gilles Peskine449bd832023-01-11 14:50:10 +0100179 mbedtls_mpi_mod_modulus_free(&m);
Gabor Mezeieca74662022-12-13 10:53:50 +0100180}
181/* END_CASE */
182
183/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100184void mpi_mod_mul_neg(char *input_A,
185 char *input_B,
186 char *input_N,
187 char *result,
188 int exp_ret)
Gabor Mezeieca74662022-12-13 10:53:50 +0100189{
Gabor Mezeieca74662022-12-13 10:53:50 +0100190 mbedtls_mpi_uint *X = NULL;
Gabor Mezeieca74662022-12-13 10:53:50 +0100191
Gabor Mezei78c4fb42022-12-20 18:09:49 +0100192 mbedtls_mpi_mod_residue rA = { NULL, 0 };
193 mbedtls_mpi_mod_residue rB = { NULL, 0 };
194 mbedtls_mpi_mod_residue rR = { NULL, 0 };
195 mbedtls_mpi_mod_residue rX = { NULL, 0 };
196
Gabor Mezeieca74662022-12-13 10:53:50 +0100197 mbedtls_mpi_mod_modulus m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 mbedtls_mpi_mod_modulus_init(&m);
Gabor Mezeieca74662022-12-13 10:53:50 +0100199
Gabor Mezeif65c71f2022-12-21 11:54:22 +0100200 mbedtls_mpi_mod_modulus fake_m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 mbedtls_mpi_mod_modulus_init(&fake_m);
Gabor Mezeif65c71f2022-12-21 11:54:22 +0100202
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 TEST_EQUAL(test_read_modulus(&m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N),
204 0);
Gabor Mezeieca74662022-12-13 10:53:50 +0100205
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 TEST_EQUAL(test_read_residue(&rA, &m, input_A, 1), 0);
207 TEST_EQUAL(test_read_residue(&rB, &m, input_B, 1), 0);
208 TEST_EQUAL(test_read_residue(&rR, &m, result, 1), 0);
Gabor Mezei809baef2022-12-16 16:31:59 +0100209
210 const size_t limbs = m.limbs;
211
Gilles Peskine449bd832023-01-11 14:50:10 +0100212 ASSERT_ALLOC(X, limbs);
Gabor Mezeieca74662022-12-13 10:53:50 +0100213
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 TEST_EQUAL(mbedtls_mpi_mod_residue_setup(&rX, &m, X, limbs), 0);
Gabor Mezei809baef2022-12-16 16:31:59 +0100215 rX.limbs = rR.limbs;
Gabor Mezeieca74662022-12-13 10:53:50 +0100216
Gilles Peskine449bd832023-01-11 14:50:10 +0100217 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &m), exp_ret);
Gabor Mezeieca74662022-12-13 10:53:50 +0100218
219 /* Check when m is not initialized */
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 TEST_EQUAL(mbedtls_mpi_mod_mul(&rX, &rA, &rB, &fake_m),
221 MBEDTLS_ERR_MPI_BAD_INPUT_DATA);
Gabor Mezeieca74662022-12-13 10:53:50 +0100222
223exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100224 mbedtls_free(rA.p);
225 mbedtls_free(rB.p);
226 mbedtls_free(rR.p);
227 mbedtls_free(X);
228 mbedtls_free((mbedtls_mpi_uint *) m.p);
Gabor Mezeif9728132022-12-20 13:55:37 +0100229
Gilles Peskine449bd832023-01-11 14:50:10 +0100230 mbedtls_mpi_mod_modulus_free(&m);
231 mbedtls_mpi_mod_modulus_free(&fake_m);
Gabor Mezeieca74662022-12-13 10:53:50 +0100232}
233/* END_CASE */
234
Tom Cosgrove62b20482022-12-01 14:27:37 +0000235/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100236void mpi_mod_sub(char *input_N,
237 char *input_A, char *input_B,
238 char *input_D, int expected_ret)
Tom Cosgrove62b20482022-12-01 14:27:37 +0000239{
240 mbedtls_mpi_mod_residue a = { NULL, 0 };
241 mbedtls_mpi_mod_residue b = { NULL, 0 };
242 mbedtls_mpi_mod_residue d = { NULL, 0 };
243 mbedtls_mpi_mod_residue x = { NULL, 0 };
244 mbedtls_mpi_uint *X_raw = NULL;
Janos Follath5933f692022-11-02 14:35:17 +0000245
Tom Cosgrove62b20482022-12-01 14:27:37 +0000246 mbedtls_mpi_mod_modulus m;
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 mbedtls_mpi_mod_modulus_init(&m);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000248
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 TEST_EQUAL(0,
250 test_read_modulus(&m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N));
Tom Cosgrove62b20482022-12-01 14:27:37 +0000251
252 /* test_read_residue() normally checks that inputs have the same number of
253 * limbs as the modulus. For negative testing we can ask it to skip this
254 * with a non-zero final parameter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100255 TEST_EQUAL(0, test_read_residue(&a, &m, input_A, expected_ret != 0));
256 TEST_EQUAL(0, test_read_residue(&b, &m, input_B, expected_ret != 0));
257 TEST_EQUAL(0, test_read_residue(&d, &m, input_D, expected_ret != 0));
Tom Cosgrove62b20482022-12-01 14:27:37 +0000258
259 size_t limbs = m.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 size_t bytes = limbs * sizeof(*X_raw);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000261
Gilles Peskine449bd832023-01-11 14:50:10 +0100262 if (expected_ret == 0) {
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000263 /* Negative test with too many limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 ASSERT_ALLOC(X_raw, limbs + 1);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000265
Tom Cosgrove62b20482022-12-01 14:27:37 +0000266 x.p = X_raw;
267 x.limbs = limbs + 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
269 mbedtls_mpi_mod_sub(&x, &a, &b, &m));
Tom Cosgrove62b20482022-12-01 14:27:37 +0000270
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 mbedtls_free(X_raw);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000272 X_raw = NULL;
273
274 /* Negative test with too few limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 if (limbs > 1) {
276 ASSERT_ALLOC(X_raw, limbs - 1);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000277
Tom Cosgrove62b20482022-12-01 14:27:37 +0000278 x.p = X_raw;
279 x.limbs = limbs - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
281 mbedtls_mpi_mod_sub(&x, &a, &b, &m));
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000282
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 mbedtls_free(X_raw);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000284 X_raw = NULL;
Tom Cosgrove62b20482022-12-01 14:27:37 +0000285 }
286
287 /* Negative testing with too many/too few limbs in a and b is covered by
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000288 * manually-written test cases with expected_ret != 0. */
Tom Cosgrove62b20482022-12-01 14:27:37 +0000289 }
290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 ASSERT_ALLOC(X_raw, limbs);
Tom Cosgrove7f4d15e2022-12-15 10:55:15 +0000292
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &m, X_raw, limbs));
Tom Cosgrove62b20482022-12-01 14:27:37 +0000294
295 /* a - b => Correct result, or expected error */
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 TEST_EQUAL(expected_ret, mbedtls_mpi_mod_sub(&x, &a, &b, &m));
297 if (expected_ret != 0) {
Tom Cosgrove62b20482022-12-01 14:27:37 +0000298 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100299 }
Tom Cosgrove62b20482022-12-01 14:27:37 +0000300
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000302
303 /* a - b: alias x to a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 memcpy(x.p, a.p, bytes);
305 TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &x, &b, &m));
306 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000307
308 /* a - b: alias x to b => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100309 memcpy(x.p, b.p, bytes);
310 TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &a, &x, &m));
311 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000312
Gilles Peskine449bd832023-01-11 14:50:10 +0100313 if (memcmp(a.p, b.p, bytes) == 0) {
Tom Cosgrove62b20482022-12-01 14:27:37 +0000314 /* a == b: alias a and b */
315
316 /* a - a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100317 TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &a, &a, &m));
318 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000319
320 /* a - a: x, a, b all aliased together => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100321 memcpy(x.p, a.p, bytes);
322 TEST_EQUAL(0, mbedtls_mpi_mod_sub(&x, &x, &x, &m));
323 TEST_COMPARE_MPI_RESIDUES(x, d);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000324 }
325
326exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100327 mbedtls_free((void *) m.p); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
328 mbedtls_mpi_mod_modulus_free(&m);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000329
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 mbedtls_free(a.p);
331 mbedtls_free(b.p);
332 mbedtls_free(d.p);
333 mbedtls_free(X_raw);
Tom Cosgrove62b20482022-12-01 14:27:37 +0000334}
335/* END_CASE */
Tom Cosgrovedc197592022-12-15 16:59:40 +0000336
337/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100338void mpi_mod_inv_mont(char *input_N,
339 char *input_A, char *input_I,
340 int expected_ret)
Tom Cosgrovedc197592022-12-15 16:59:40 +0000341{
342 mbedtls_mpi_mod_residue a = { NULL, 0 }; /* argument */
343 mbedtls_mpi_mod_residue i = { NULL, 0 }; /* expected inverse wrt N */
344 mbedtls_mpi_mod_residue x = { NULL, 0 }; /* output */
345 mbedtls_mpi_uint *X_raw = NULL;
346
347 mbedtls_mpi_mod_modulus N;
Gilles Peskine449bd832023-01-11 14:50:10 +0100348 mbedtls_mpi_mod_modulus_init(&N);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000349
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 TEST_EQUAL(0,
351 test_read_modulus(&N, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000352
353 /* test_read_residue() normally checks that inputs have the same number of
354 * limbs as the modulus. For negative testing we can ask it to skip this
355 * with a non-zero final parameter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100356 TEST_EQUAL(0, test_read_residue(&a, &N, input_A, expected_ret != 0));
357 TEST_EQUAL(0, test_read_residue(&i, &N, input_I, expected_ret != 0));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000358
359 size_t limbs = N.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100360 size_t bytes = limbs * sizeof(*X_raw);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000361
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 ASSERT_ALLOC(X_raw, limbs);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000363
Gilles Peskine449bd832023-01-11 14:50:10 +0100364 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &N, X_raw, limbs));
Tom Cosgrovedc197592022-12-15 16:59:40 +0000365
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 TEST_EQUAL(expected_ret, mbedtls_mpi_mod_inv(&x, &a, &N));
367 if (expected_ret == 0) {
368 TEST_COMPARE_MPI_RESIDUES(x, i);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000369
370 /* a^-1: alias x to a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 memcpy(x.p, a.p, bytes);
372 TEST_EQUAL(0, mbedtls_mpi_mod_inv(&x, &x, &N));
373 TEST_COMPARE_MPI_RESIDUES(x, i);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000374 }
375
376exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100377 mbedtls_free((void *) N.p); /* mbedtls_mpi_mod_modulus_free() sets N.p = NULL */
378 mbedtls_mpi_mod_modulus_free(&N);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000379
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 mbedtls_free(a.p);
381 mbedtls_free(i.p);
382 mbedtls_free(X_raw);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000383}
384/* END_CASE */
385
386/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100387void mpi_mod_inv_non_mont(char *input_N,
388 char *input_A, char *input_I,
389 int expected_ret)
Tom Cosgrovedc197592022-12-15 16:59:40 +0000390{
391 mbedtls_mpi_mod_residue a = { NULL, 0 }; /* argument */
392 mbedtls_mpi_mod_residue i = { NULL, 0 }; /* expected inverse wrt N */
393 mbedtls_mpi_mod_residue x = { NULL, 0 }; /* output */
394 mbedtls_mpi_uint *X_raw = NULL;
395
396 mbedtls_mpi_mod_modulus N;
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 mbedtls_mpi_mod_modulus_init(&N);
Tom Cosgrovedc197592022-12-15 16:59:40 +0000398
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 TEST_EQUAL(0,
400 test_read_modulus(&N, MBEDTLS_MPI_MOD_REP_OPT_RED, input_N));
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,
450 test_read_modulus(&m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N));
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000451
452 /* test_read_residue() normally checks that inputs have the same number of
453 * limbs as the modulus. For negative testing we can ask it to skip this
454 * with a non-zero final parameter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 TEST_EQUAL(0, test_read_residue(&a, &m, input_A, expected_ret != 0));
456 TEST_EQUAL(0, test_read_residue(&b, &m, input_B, expected_ret != 0));
457 TEST_EQUAL(0, test_read_residue(&s, &m, input_S, expected_ret != 0));
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000458
459 size_t limbs = m.limbs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 size_t bytes = limbs * sizeof(*X_raw);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000461
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 if (expected_ret == 0) {
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000463 /* Negative test with too many limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 ASSERT_ALLOC(X_raw, limbs + 1);
Werner Lewis79341a42022-12-13 17:19:01 +0000465
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000466 x.p = X_raw;
467 x.limbs = limbs + 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
469 mbedtls_mpi_mod_add(&x, &a, &b, &m));
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000470
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 mbedtls_free(X_raw);
Werner Lewis79341a42022-12-13 17:19:01 +0000472 X_raw = NULL;
473
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000474 /* Negative test with too few limbs in output */
Gilles Peskine449bd832023-01-11 14:50:10 +0100475 if (limbs > 1) {
476 ASSERT_ALLOC(X_raw, limbs - 1);
Werner Lewis79341a42022-12-13 17:19:01 +0000477
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000478 x.p = X_raw;
479 x.limbs = limbs - 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100480 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
481 mbedtls_mpi_mod_add(&x, &a, &b, &m));
Werner Lewis79341a42022-12-13 17:19:01 +0000482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 mbedtls_free(X_raw);
Werner Lewis79341a42022-12-13 17:19:01 +0000484 X_raw = NULL;
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000485 }
486
487 /* Negative testing with too many/too few limbs in a and b is covered by
488 * manually-written test cases with oret != 0. */
489 }
490
Werner Lewis79341a42022-12-13 17:19:01 +0000491 /* Allocate correct number of limbs for X_raw */
Gilles Peskine449bd832023-01-11 14:50:10 +0100492 ASSERT_ALLOC(X_raw, limbs);
Werner Lewis79341a42022-12-13 17:19:01 +0000493
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&x, &m, X_raw, limbs));
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000495
496 /* A + B => Correct result or expected error */
Gilles Peskine449bd832023-01-11 14:50:10 +0100497 TEST_EQUAL(expected_ret, mbedtls_mpi_mod_add(&x, &a, &b, &m));
498 if (expected_ret != 0) {
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000499 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 }
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000503
504 /* a + b: alias x to a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100505 memcpy(x.p, a.p, bytes);
506 TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &x, &b, &m));
507 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000508
509 /* a + b: alias x to b => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100510 memcpy(x.p, b.p, bytes);
511 TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &a, &x, &m));
512 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000513
Gilles Peskine449bd832023-01-11 14:50:10 +0100514 if (memcmp(a.p, b.p, bytes) == 0) {
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000515 /* a == b: alias a and b */
516
517 /* a + a => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &a, &a, &m));
519 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000520
521 /* a + a: x, a, b all aliased together => Correct result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 memcpy(x.p, a.p, bytes);
523 TEST_EQUAL(0, mbedtls_mpi_mod_add(&x, &x, &x, &m));
524 TEST_COMPARE_MPI_RESIDUES(x, s);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000525 }
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000526
527exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 mbedtls_free((void *) m.p); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
529 mbedtls_mpi_mod_modulus_free(&m);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000530
Gilles Peskine449bd832023-01-11 14:50:10 +0100531 mbedtls_free(a.p);
532 mbedtls_free(b.p);
533 mbedtls_free(s.p);
534 mbedtls_free(X_raw);
Werner Lewise1b6b7c2022-11-29 12:25:05 +0000535}
536/* END_CASE */
Janos Follath5933f692022-11-02 14:35:17 +0000537
Minos Galanakis8f242702022-11-10 16:56:02 +0000538/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100539void mpi_residue_setup(char *input_N, char *input_R, int ret)
Minos Galanakisa17ad482022-11-16 16:29:15 +0000540{
Minos Galanakisa17ad482022-11-16 16:29:15 +0000541 mbedtls_mpi_uint *N = NULL;
542 mbedtls_mpi_uint *R = NULL;
Minos Galanakisaed832a2022-11-24 09:09:47 +0000543 size_t n_limbs, r_limbs;
Minos Galanakisa17ad482022-11-16 16:29:15 +0000544 mbedtls_mpi_mod_modulus m;
545 mbedtls_mpi_mod_residue r;
546
Gilles Peskine449bd832023-01-11 14:50:10 +0100547 mbedtls_mpi_mod_modulus_init(&m);
Minos Galanakisa17ad482022-11-16 16:29:15 +0000548
Minos Galanakisaed832a2022-11-24 09:09:47 +0000549 /* Allocate the memory for intermediate data structures */
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
551 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&R, &r_limbs, input_R));
Minos Galanakisaed832a2022-11-24 09:09:47 +0000552
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
554 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
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 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100595 TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
596 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
Minos Galanakis96070a52022-11-25 19:32:10 +0000597
Gilles Peskine449bd832023-01-11 14:50:10 +0100598 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 Follathe7190a22022-11-26 18:46:54 +0000602
603 /* Do the rest of the tests with a residue set up with the input data */
Gilles Peskine449bd832023-01-11 14:50:10 +0100604 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r, &m, R, r_limbs));
Minos Galanakis96070a52022-11-25 19:32:10 +0000605
Janos Follathd7bb3522022-11-26 14:59:27 +0000606 /* Fail for r_limbs < m->limbs */
607 r.limbs--;
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 TEST_ASSERT(r.limbs < m.limbs);
609 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
610 mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
611 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
612 mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
Janos Follathd7bb3522022-11-26 14:59:27 +0000613 r.limbs++;
614
615 /* Fail for r_limbs > m->limbs */
616 m.limbs--;
Gilles Peskine449bd832023-01-11 14:50:10 +0100617 TEST_ASSERT(r.limbs > m.limbs);
618 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
619 mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
620 TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
621 mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
Janos Follathd7bb3522022-11-26 14:59:27 +0000622 m.limbs++;
Minos Galanakis96070a52022-11-25 19:32:10 +0000623
624 /* Test the read */
Gilles Peskine449bd832023-01-11 14:50:10 +0100625 TEST_EQUAL(ret, mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
Minos Galanakis96070a52022-11-25 19:32:10 +0000626
627 /* Test write overflow only when the representation is large and read is successful */
Gilles Peskine449bd832023-01-11 14:50:10 +0100628 if (r.limbs > 1 && ret == 0) {
629 TEST_EQUAL(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL,
630 mbedtls_mpi_mod_write(&r, &m, buf->x, 1, endian));
631 }
Janos Follathd7bb3522022-11-26 14:59:27 +0000632
Minos Galanakis8f242702022-11-10 16:56:02 +0000633exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100634 mbedtls_mpi_mod_residue_release(&r);
635 mbedtls_mpi_mod_modulus_free(&m);
636 mbedtls_free(N);
637 mbedtls_free(R);
Minos Galanakis8f242702022-11-10 16:56:02 +0000638}
639/* END_CASE */
640
641/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100642void mpi_mod_io(char *input_N, data_t *input_A, int endian)
Minos Galanakis8f242702022-11-10 16:56:02 +0000643{
644 mbedtls_mpi_uint *N = NULL;
645 mbedtls_mpi_uint *R = NULL;
Janos Follath8dfc8c42022-11-26 15:39:02 +0000646 mbedtls_mpi_uint *R_COPY = NULL;
Janos Follath0020df92022-11-26 17:23:16 +0000647 unsigned char *obuf = NULL;
648 unsigned char *ref_buf = NULL;
Minos Galanakis8f242702022-11-10 16:56:02 +0000649 mbedtls_mpi_mod_modulus m;
650 mbedtls_mpi_mod_residue r;
Janos Follath8dfc8c42022-11-26 15:39:02 +0000651 mbedtls_mpi_mod_residue r_copy;
Minos Galanakis8f242702022-11-10 16:56:02 +0000652 size_t n_limbs, n_bytes, a_bytes;
653
Gilles Peskine449bd832023-01-11 14:50:10 +0100654 mbedtls_mpi_mod_modulus_init(&m);
Janos Follath799eaee2022-11-25 15:57:04 +0000655
Minos Galanakis8f242702022-11-10 16:56:02 +0000656 /* Read inputs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100657 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
658 n_bytes = n_limbs * sizeof(mbedtls_mpi_uint);
Janos Follath6ef582f2022-11-26 14:19:02 +0000659 a_bytes = input_A->len;
Minos Galanakis8f242702022-11-10 16:56:02 +0000660
661 /* Allocate the memory for intermediate data structures */
Gilles Peskine449bd832023-01-11 14:50:10 +0100662 ASSERT_ALLOC(R, n_bytes);
663 ASSERT_ALLOC(R_COPY, n_bytes);
Minos Galanakis8f242702022-11-10 16:56:02 +0000664
665 /* Test that input's size is not greater to modulo's */
Gilles Peskine449bd832023-01-11 14:50:10 +0100666 TEST_LE_U(a_bytes, n_bytes);
Minos Galanakis8f242702022-11-10 16:56:02 +0000667
668 /* Init Structures */
Gilles Peskine449bd832023-01-11 14:50:10 +0100669 TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
670 MBEDTLS_MPI_MOD_REP_MONTGOMERY));
Minos Galanakis8f242702022-11-10 16:56:02 +0000671
672 /* Enforcing p_limbs >= m->limbs */
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r, &m, R, n_limbs));
Minos Galanakis8f242702022-11-10 16:56:02 +0000674
Gilles Peskine449bd832023-01-11 14:50:10 +0100675 TEST_EQUAL(0, mbedtls_mpi_mod_read(&r, &m, input_A->x, input_A->len,
676 endian));
Minos Galanakis8f242702022-11-10 16:56:02 +0000677
Janos Follath0020df92022-11-26 17:23:16 +0000678 /* Read a copy for checking that writing didn't change the value of r */
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r_copy, &m,
680 R_COPY, n_limbs));
681 TEST_EQUAL(0, mbedtls_mpi_mod_read(&r_copy, &m, input_A->x, input_A->len,
682 endian));
Janos Follath8dfc8c42022-11-26 15:39:02 +0000683
Janos Follath0020df92022-11-26 17:23:16 +0000684 /* Get number of bytes without leading zeroes */
685 size_t a_bytes_trimmed = a_bytes;
Gilles Peskine449bd832023-01-11 14:50:10 +0100686 while (a_bytes_trimmed > 0) {
687 unsigned char *r_byte_array = (unsigned char *) r.p;
688 if (r_byte_array[--a_bytes_trimmed] != 0) {
Janos Follath0020df92022-11-26 17:23:16 +0000689 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100690 }
Janos Follath0020df92022-11-26 17:23:16 +0000691 }
692 a_bytes_trimmed++;
693
694 /* Test write with three output buffer sizes: tight, same as input and
695 * longer than the input */
696 size_t obuf_sizes[3];
Gilles Peskine449bd832023-01-11 14:50:10 +0100697 const size_t obuf_sizes_len = sizeof(obuf_sizes) / sizeof(obuf_sizes[0]);
Janos Follath0020df92022-11-26 17:23:16 +0000698 obuf_sizes[0] = a_bytes_trimmed;
699 obuf_sizes[1] = a_bytes;
700 obuf_sizes[2] = a_bytes + 8;
701
Gilles Peskine449bd832023-01-11 14:50:10 +0100702 for (size_t i = 0; i < obuf_sizes_len; i++) {
703 ASSERT_ALLOC(obuf, obuf_sizes[i]);
704 TEST_EQUAL(0, mbedtls_mpi_mod_write(&r, &m, obuf, obuf_sizes[i], endian));
Janos Follath0020df92022-11-26 17:23:16 +0000705
706 /* Make sure that writing didn't corrupt the value of r */
Gilles Peskine449bd832023-01-11 14:50:10 +0100707 ASSERT_COMPARE(r.p, r.limbs, r_copy.p, r_copy.limbs);
Janos Follath0020df92022-11-26 17:23:16 +0000708
709 /* Set up reference output for checking the result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100710 ASSERT_ALLOC(ref_buf, obuf_sizes[i]);
711 switch (endian) {
Janos Follath0020df92022-11-26 17:23:16 +0000712 case MBEDTLS_MPI_MOD_EXT_REP_LE:
Gilles Peskine449bd832023-01-11 14:50:10 +0100713 memcpy(ref_buf, input_A->x, a_bytes_trimmed);
Janos Follath0020df92022-11-26 17:23:16 +0000714 break;
715 case MBEDTLS_MPI_MOD_EXT_REP_BE:
Gilles Peskine449bd832023-01-11 14:50:10 +0100716 {
717 size_t a_offset = input_A->len - a_bytes_trimmed;
718 size_t ref_offset = obuf_sizes[i] - a_bytes_trimmed;
719 memcpy(ref_buf + ref_offset, input_A->x + a_offset,
720 a_bytes_trimmed);
721 }
722 break;
Janos Follath0020df92022-11-26 17:23:16 +0000723 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100724 TEST_ASSERT(0);
Janos Follath0020df92022-11-26 17:23:16 +0000725 }
726
727 /* Check the result */
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 ASSERT_COMPARE(obuf, obuf_sizes[i], ref_buf, obuf_sizes[i]);
Janos Follath0020df92022-11-26 17:23:16 +0000729
Gilles Peskine449bd832023-01-11 14:50:10 +0100730 mbedtls_free(ref_buf);
Janos Follath0020df92022-11-26 17:23:16 +0000731 ref_buf = NULL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100732 mbedtls_free(obuf);
Janos Follath0020df92022-11-26 17:23:16 +0000733 obuf = NULL;
734 }
735
Minos Galanakis8f242702022-11-10 16:56:02 +0000736exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100737 mbedtls_mpi_mod_modulus_free(&m);
738 mbedtls_free(N);
739 mbedtls_free(R);
740 mbedtls_free(R_COPY);
741 mbedtls_free(obuf);
Minos Galanakis8f242702022-11-10 16:56:02 +0000742}
743/* END_CASE */