[PATCH] addm/subm/mulm: fix case when destination is same MPI as divider

Jussi Kivilinna jussi.kivilinna at iki.fi
Sat Jun 3 12:23:26 CEST 2023


* mpi/mpi-add.c (_gcry_mpi_addm, _gcry_mpi_subm): Take copy of M when
W and M are the same MPI.
* mpi/mpi-mul.c (_gcry_mpi_mulm): Likewise.
* tests/mpitests.c (test_addm_subm_mulm): New.
(main): Run addm/subm/mulm test.
--

Reported-by: Guido Vranken <guidovranken at gmail.com>
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 mpi/mpi-add.c    | 22 ++++++++++++++++++++
 mpi/mpi-mul.c    | 11 ++++++++++
 tests/mpitests.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 86 insertions(+)

diff --git a/mpi/mpi-add.c b/mpi/mpi-add.c
index 41dc3900..51dc71b7 100644
--- a/mpi/mpi-add.c
+++ b/mpi/mpi-add.c
@@ -227,13 +227,35 @@ _gcry_mpi_sub(gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
 void
 _gcry_mpi_addm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m)
 {
+  gcry_mpi_t temp_m = NULL;
+
+  if (w == m)
+    {
+      temp_m = mpi_copy (m);
+      m = temp_m;
+    }
+
   mpi_add (w, u, v);
   mpi_mod (w, w, m);
+
+  if (temp_m)
+    mpi_free(temp_m);
 }
 
 void
 _gcry_mpi_subm( gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m)
 {
+  gcry_mpi_t temp_m = NULL;
+
+  if (w == m)
+    {
+      temp_m = mpi_copy (m);
+      m = temp_m;
+    }
+
   mpi_sub (w, u, v);
   mpi_mod (w, w, m);
+
+  if (temp_m)
+    mpi_free(temp_m);
 }
diff --git a/mpi/mpi-mul.c b/mpi/mpi-mul.c
index 60f1ca48..e8e57475 100644
--- a/mpi/mpi-mul.c
+++ b/mpi/mpi-mul.c
@@ -207,6 +207,17 @@ _gcry_mpi_mul (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v)
 void
 _gcry_mpi_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, gcry_mpi_t m)
 {
+  gcry_mpi_t temp_m = NULL;
+
+  if (w == m)
+    {
+      temp_m = mpi_copy (m);
+      m = temp_m;
+    }
+
   mpi_mul (w, u, v);
   _gcry_mpi_tdiv_r (w, w, m);
+
+  if (temp_m)
+    mpi_free(temp_m);
 }
diff --git a/tests/mpitests.c b/tests/mpitests.c
index 48ea18b2..1203acdd 100644
--- a/tests/mpitests.c
+++ b/tests/mpitests.c
@@ -687,6 +687,58 @@ test_powm (void)
 }
 
 
+/* What we test here is that we don't overwrite our divider and that
+   using the same mpi for divider and result works.  */
+static int
+test_addm_subm_mulm (void)
+{
+  int i;
+
+  for (i = 0; i < 3; i++)
+    {
+      unsigned int expect;
+      const char *func;
+      gcry_mpi_t A;
+      gcry_mpi_t B;
+      gcry_mpi_t C;
+
+      A = gcry_mpi_set_ui (NULL, 2);
+      B = gcry_mpi_set_ui (NULL, 4);
+      C = gcry_mpi_set_ui (NULL, 7);
+
+      if (i == 0)
+	{
+	  func = "mpi_addm";
+	  expect = 6;
+	  gcry_mpi_addm(C, A, B, C);
+	}
+      else if (i == 1)
+	{
+	  func = "mpi_subm";
+	  expect = 5;
+	  gcry_mpi_subm(C, A, B, C);
+	}
+      else if (i == 2)
+	{
+	  func = "mpi_mulm";
+	  expect = 1;
+	  gcry_mpi_mulm(C, A, B, C);
+	}
+
+      if (gcry_mpi_is_neg (C) || gcry_mpi_cmp_ui (C, expect))
+	{
+	  die ("test_addm_subm_mulm failed for %s at %d\n", func, __LINE__);
+	}
+
+      gcry_mpi_release(A);
+      gcry_mpi_release(B);
+      gcry_mpi_release(C);
+    }
+
+  return 1;
+}
+
+
 int
 main (int argc, char* argv[])
 {
@@ -710,6 +762,7 @@ main (int argc, char* argv[])
   test_sub ();
   test_mul ();
   test_powm ();
+  test_addm_subm_mulm ();
 
   return !!error_count;
 }
-- 
2.39.2




More information about the Gcrypt-devel mailing list