[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