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