diff --git a/library/bignum_core.c b/library/bignum_core.c index 541b1c73a..c47292eec 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -439,7 +439,7 @@ void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X, * So the correct return value is already in X if (carry ^ borrow) = 0, * but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1. */ - mbedtls_ct_mpi_uint_cond_assign( AN_limbs, X, T, (unsigned char) ( carry ^ borrow ) ); + mbedtls_ct_mpi_uint_cond_assign( AN_limbs, X, T, (unsigned char) ( carry ^ borrow ) ); } #endif /* MBEDTLS_BIGNUM_C */ diff --git a/library/bignum_core.h b/library/bignum_core.h index cbeab244c..1ef1b683c 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -250,15 +250,15 @@ mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *X, size_t X_limbs, mbedtls_mpi_uint mbedtls_mpi_core_montmul_init( const mbedtls_mpi_uint *N ); /** - * \brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36) + * \brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36) + * + * \p A and \p B must be in canonical form. That is, < \p N. * * \p X may be aliased to \p A or \p N, or even \p B (if \p AN_limbs == * \p B_limbs) but may not overlap any parameters otherwise. * - * \p A, \p B and \p N must not alias or overlap each other in any way, even - * if \p AN_limbs == \p B_limbs. - * - * \p A and \p B must be in canonical form: that is, <= \p N. + * \p A and \p B may alias each other, if \p AN_limbs == \p B_limbs. They may + * not alias \p N (since they must be in canonical form, they cannot == \p N). * * \param[out] X The destination MPI, as a little-endian array of * length \p AN_limbs. @@ -273,13 +273,16 @@ mbedtls_mpi_uint mbedtls_mpi_core_montmul_init( const mbedtls_mpi_uint *N ); * \param[in] N Little-endian presentation of the modulus. * This must be odd, and have exactly the same number * of limbs as \p A. + * It must not alias or otherwise overlap any of the + * other parameters. * \param[in] AN_limbs The number of limbs in \p X, \p A and \p N. * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. * This can be calculated by `mbedtls_mpi_core_montmul_init()`. * \param[in,out] T Temporary storage of size at least 2*AN_limbs+1 limbs. * Its initial content is unused and * its final content is indeterminate. - * It must not overlap any of the other parameters. + * It must not alias or otherwise overlap any of the + * other parameters. */ void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function index a82c73e81..ff2eaac4b 100644 --- a/tests/suites/test_suite_mpi.function +++ b/tests/suites/test_suite_mpi.function @@ -2140,11 +2140,22 @@ void mpi_core_montmul( int limbs_AN4, int limbs_B4, memcpy( N.p, R.p, bytes ); - /* The output may even be aliased to B, if AN_limbs == B_limbs */ - if (limbs_AN == limbs_B) { - /* Note: last test, so we don't save B */ + /* Test when A aliased to B (requires A == B on input values) */ + if ( memcmp( A.p, B.p, bytes ) == 0 ) + { + /* Test with A aliased to B and output, since this is permitted - + * don't bother with yet another test with only A and B aliased */ + + mbedtls_mpi_core_montmul( B.p, B.p, B.p, B.n, N.p, N.n, mm, T.p ); + ASSERT_COMPARE( B.p, bytes, X->p, bytes ); + + memcpy( B.p, A.p, bytes ); /* restore B from equal value A */ + } + + /* The output may be aliased to B - last test, so we don't save B */ + mbedtls_mpi_core_montmul( B.p, A.p, B.p, B.n, N.p, N.n, mm, T.p ); ASSERT_COMPARE( B.p, bytes, X->p, bytes ); }