Document and test aliasing of output for mbedtls_mpi_core_montmul()

Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
diff --git a/library/bignum_core.h b/library/bignum_core.h
index adfb81a..3a2d5a1 100644
--- a/library/bignum_core.h
+++ b/library/bignum_core.h
@@ -245,6 +245,14 @@
 /**
  * \brief Montgomery multiplication: X = A * B * R^-1 mod N  (HAC 14.36)
  *
+ * \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.
+ *
  * \param[out]    X         The destination MPI, as a little-endian array of
  *                          length \p AN_limbs.
  *                          On successful completion, X contains the result of
diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function
index 60000d3..bd98a2c 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -2114,6 +2114,33 @@
     size_t bytes = N.n * sizeof(mbedtls_mpi_uint);
     ASSERT_COMPARE( R.p, bytes, X->p, bytes );
 
+    /* The output (R, above) may be aliased to A - use R to save the value of A */
+
+    memcpy( R.p, A.p, bytes );
+
+    mbedtls_mpi_core_montmul( A.p, A.p, B.p, B.n, N.p, N.n, mm, T.p );
+    ASSERT_COMPARE( A.p, bytes, X->p, bytes );
+
+    memcpy( A.p, R.p, bytes );  /* restore A */
+
+    /* The output may be aliased to N - use R to save the value of N */
+
+    memcpy( R.p, N.p, bytes );
+
+    mbedtls_mpi_core_montmul( N.p, A.p, B.p, B.n, N.p, N.n, mm, T.p );
+    ASSERT_COMPARE( N.p, bytes, X->p, bytes );
+
+    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 */
+        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 );
+    }
+
 exit:
     mbedtls_mpi_free( &A );
     mbedtls_mpi_free( &B );