[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