[PATCH] mpi_swap_conditional

NIIBE Yutaka gniibe at fsij.org
Thu Jun 19 07:52:59 CEST 2014


Hello,

For implementing Curve25519 to be constant-time, I need a function
which swaps values conditionally, in constant-time.  If SW=1 it swaps,
it doesn't if not, both cases are executed in same timings.

Here, I named it as mpi_swap_conditional.

I think that this is useful for other parts of gcrypt.

diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index d59c095..91d9d8f 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -4341,6 +4341,11 @@ small values (usually up to the word size of the CPU).
 Swap the values of @var{a} and @var{b}.
 @end deftypefun
 
+ at deftypefun void gcry_mpi_swap_conditional (@w{gcry_mpi_t @var{a}}, @w{gcry_mpi_t @var{b}}, @w{unsigned long @var{sw}})
+
+Swap the values of @var{a} and @var{b}, when @var{sw} is 1.
+ at end deftypefun
+
 @deftypefun void gcry_mpi_snatch (@w{gcry_mpi_t @var{w}}, @
                                   @w{const gcry_mpi_t @var{u}})
 
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index fdce578..e0afec0 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -541,6 +541,43 @@ _gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
     tmp = *a; *a = *b; *b = tmp;
 }
 
+void
+_gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap)
+{
+  size_t i;
+  size_t nlimbs = a->nlimbs;
+  unsigned long mask = -(long)swap;
+
+  if (b->alloced < a->nlimbs)
+    {
+      mpi_resize (b, a->nlimbs);
+      nlimbs = a->nlimbs;
+    }
+  else if (a->alloced < b->nlimbs)
+    {
+      mpi_resize (a, b->nlimbs);
+      nlimbs = b->nlimbs;
+    }
+  else if (b->nlimbs < a->nlimbs)
+    {
+      mpi_resize (b, a->nlimbs);
+      nlimbs = b->nlimbs = a->nlimbs;
+    }
+  else if (a->nlimbs < b->nlimbs)
+    {
+      mpi_resize (a, b->nlimbs);
+      nlimbs = a->nlimbs = b->nlimbs;
+    }
+
+  for (i = 0; i < nlimbs; i++)
+    {
+      unsigned long x = mask & (a->d[i] ^ b->d[i]);
+      a->d[i] = a->d[i] ^ x;
+      b->d[i] = b->d[i] ^ x;
+    }
+}
+
+
 
 gcry_mpi_t
 _gcry_mpi_new (unsigned int nbits)
diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h
index 8a6df84..42b72d6 100644
--- a/src/gcrypt-int.h
+++ b/src/gcrypt-int.h
@@ -371,6 +371,7 @@ gcry_mpi_t _gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u);
 gcry_mpi_t _gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u);
 gcry_err_code_t _gcry_mpi_get_ui (gcry_mpi_t w, ulong *u);
 void _gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b);
+void _gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long sw);
 int _gcry_mpi_is_neg (gcry_mpi_t a);
 void _gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u);
 void _gcry_mpi_abs (gcry_mpi_t w);
@@ -475,6 +476,7 @@ int _gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
 #define mpi_set_ui( w, u)      _gcry_mpi_set_ui( (w), (u) )
 #define mpi_get_ui(a,b)        _gcry_mpi_get_ui( (a), (b) )
 #define mpi_swap(a,b)          _gcry_mpi_swap ((a),(b))
+#define mpi_swap_conditional(a,b,sw)          _gcry_mpi_swap_conditional ((a),(b),(sw))
 #define mpi_abs( w )           _gcry_mpi_abs( (w) )
 #define mpi_neg( w, u)         _gcry_mpi_neg( (w), (u) )
 #define mpi_cmp( u, v )        _gcry_mpi_cmp( (u), (v) )
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index bd38a24..ed0141e 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -544,6 +544,9 @@ gcry_mpi_t gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u);
 /* Swap the values of A and B. */
 void gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b);
 
+/* Swap the values of A and B if SW is 1. */
+void gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long sw);
+
 /* Return 1 if A is negative; 0 if zero or positive.  */
 int gcry_mpi_is_neg (gcry_mpi_t a);
 
diff --git a/src/libgcrypt.def b/src/libgcrypt.def
index 57ed490..aee85ac 100644
--- a/src/libgcrypt.def
+++ b/src/libgcrypt.def
@@ -276,5 +276,6 @@ EXPORTS
       gcry_mac_ctl              @242
       gcry_mac_get_algo         @243
 
+      gcry_mpi_swap_conditional @244
 
 ;; end of file with public symbols for Windows.
diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers
index 7ee0541..0540850 100644
--- a/src/libgcrypt.vers
+++ b/src/libgcrypt.vers
@@ -96,7 +96,7 @@ GCRYPT_1.6 {
     gcry_mpi_set_flag; gcry_mpi_set_highbit;
     gcry_mpi_set_opaque; gcry_mpi_set_opaque_copy;
     gcry_mpi_set_ui; gcry_mpi_snew; gcry_mpi_sub; gcry_mpi_sub_ui;
-    gcry_mpi_subm; gcry_mpi_swap; gcry_mpi_test_bit;
+    gcry_mpi_subm; gcry_mpi_swap; gcry_mpi_swap_conditional; gcry_mpi_test_bit;
     gcry_mpi_lshift; gcry_mpi_snatch;
     gcry_mpi_point_new; gcry_mpi_point_release;
     gcry_mpi_point_get; gcry_mpi_point_snatch_get;
diff --git a/src/mpi.h b/src/mpi.h
index eb0730e..7859dec 100644
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -125,6 +125,7 @@ gcry_mpi_t  _gcry_mpi_alloc_like( gcry_mpi_t a );
 gcry_mpi_t  _gcry_mpi_alloc_set_ui( unsigned long u);
 void _gcry_mpi_m_check( gcry_mpi_t a );
 void _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b);
+void _gcry_mpi_swap_conditional(gcry_mpi_t a, gcry_mpi_t b, unsigned long sw);
 gcry_mpi_t _gcry_mpi_new (unsigned int nbits);
 gcry_mpi_t _gcry_mpi_snew (unsigned int nbits);
 gcry_mpi_t _gcry_mpi_set_opaque_copy (gcry_mpi_t a,
diff --git a/src/visibility.c b/src/visibility.c
index 6ed57ca..ec3b644 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -319,6 +319,12 @@ gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
   _gcry_mpi_swap (a, b);
 }
 
+void
+gcry_mpi_swap_conditional (gcry_mpi_t a, gcry_mpi_t b, unsigned long sw)
+{
+  _gcry_mpi_swap_conditional (a, b, sw);
+}
+
 int
 gcry_mpi_is_neg (gcry_mpi_t a)
 {
diff --git a/src/visibility.h b/src/visibility.h
index 96b5235..54767e3 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -266,6 +266,7 @@ MARK_VISIBLEX (gcry_mpi_sub)
 MARK_VISIBLEX (gcry_mpi_sub_ui)
 MARK_VISIBLEX (gcry_mpi_subm)
 MARK_VISIBLEX (gcry_mpi_swap)
+MARK_VISIBLEX (gcry_mpi_swap_conditional)
 MARK_VISIBLEX (gcry_mpi_test_bit)
 
 MARK_VISIBLEX (gcry_ctx_release)
@@ -482,6 +483,7 @@ MARK_VISIBLEX (_gcry_mpi_get_const)
 #define gcry_mpi_sub_ui             _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_mpi_subm               _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_mpi_swap               _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_mpi_swap_conditional   _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_mpi_test_bit           _gcry_USE_THE_UNDERSCORED_FUNCTION
 
 #define gcry_mpi_abs                _gcry_USE_THE_UNDERSCORED_FUNCTION
-- 





More information about the Gcrypt-devel mailing list