[tor-commits] [tor/master] Add a function to maybe memcpy() a value, in constant time.

nickm at torproject.org nickm at torproject.org
Mon Feb 24 12:48:35 UTC 2020


commit 4269ab97c685cb3bef9607cbada8af5b6b84640c
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Jan 16 19:23:20 2020 -0500

    Add a function to maybe memcpy() a value, in constant time.
---
 src/lib/ctime/di_ops.c | 27 +++++++++++++++++++++++++++
 src/lib/ctime/di_ops.h |  2 ++
 src/test/test_util.c   | 30 ++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+)

diff --git a/src/lib/ctime/di_ops.c b/src/lib/ctime/di_ops.c
index 7448a9973..0859dd8be 100644
--- a/src/lib/ctime/di_ops.c
+++ b/src/lib/ctime/di_ops.c
@@ -279,3 +279,30 @@ select_array_member_cumulative_timei(const uint64_t *entries, int n_entries,
 
   return i_chosen;
 }
+
+/**
+ * If <b>s</b> is true, then copy <b>n</b> bytes from <b>src</d> to
+ * <b>dest</b>.  Otherwise leave <b>dest</b> alone.
+ *
+ * This function behaves the same as
+ *
+ *      if (s)
+ *         memcpy(dest, src, n);
+ *
+ * except that it tries to run in the same amount of time whether <b>s</b> is
+ * true or not.
+ **/
+void
+memcpy_if_true_timei(bool s, void *dest, const void *src, size_t n)
+{
+  // If s is true, mask will be ~0.  If s is false, mask will be 0.
+  const char mask = (char) -(signed char)s;
+
+  char *destp = dest;
+  const char *srcp = src;
+  for (size_t i = 0; i < n; ++i) {
+    *destp = (*destp & ~mask) | (*srcp & mask);
+    ++destp;
+    ++srcp;
+  }
+}
diff --git a/src/lib/ctime/di_ops.h b/src/lib/ctime/di_ops.h
index 4ff8f0316..9fe2884ec 100644
--- a/src/lib/ctime/di_ops.h
+++ b/src/lib/ctime/di_ops.h
@@ -73,4 +73,6 @@ int select_array_member_cumulative_timei(const uint64_t *entries,
                                          int n_entries,
                                          uint64_t total, uint64_t rand_val);
 
+void memcpy_if_true_timei(bool s, void *dest, const void *src, size_t n);
+
 #endif /* !defined(TOR_DI_OPS_H) */
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 07c31f02d..7a375b06b 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -4572,6 +4572,35 @@ test_util_di_ops(void *arg)
 }
 
 static void
+test_util_memcpy_iftrue_timei(void *arg)
+{
+  (void)arg;
+  char buf1[25];
+  char buf2[25];
+  char buf3[25];
+
+  for (int i = 0; i < 100; ++i) {
+    crypto_rand(buf1, sizeof(buf1));
+    crypto_rand(buf2, sizeof(buf2));
+    memcpy(buf3, buf1, sizeof(buf1));
+
+    /* We just copied buf1 into buf3.  Now we're going to copy buf2 into buf2,
+       iff our coin flip comes up heads. */
+    bool coinflip = crypto_rand_int(2) == 0;
+
+    memcpy_if_true_timei(coinflip, buf3, buf2, sizeof(buf3));
+
+    if (coinflip) {
+      tt_mem_op(buf3, OP_EQ, buf2, sizeof(buf2));
+    } else {
+      tt_mem_op(buf3, OP_EQ, buf1, sizeof(buf1));
+    }
+  }
+ done:
+  ;
+}
+
+static void
 test_util_di_map(void *arg)
 {
   (void)arg;
@@ -6386,6 +6415,7 @@ struct testcase_t util_tests[] = {
   UTIL_LEGACY(path_is_relative),
   UTIL_LEGACY(strtok),
   UTIL_LEGACY(di_ops),
+  UTIL_TEST(memcpy_iftrue_timei, 0),
   UTIL_TEST(di_map, 0),
   UTIL_TEST(round_to_next_multiple_of, 0),
   UTIL_TEST(laplace, 0),





More information about the tor-commits mailing list