summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2016-04-27 10:33:46 -0400
committerNick Mathewson <nickm@torproject.org>2016-05-12 11:21:28 -0400
commite40cfc4425d1e173b5d122e38ab07dd798b11925 (patch)
tree4fd8f84d80731b17635857c6a7629f35e1dab434 /src/common
parent20432fc541bf0fb8f136f0d4635b264c624ce3eb (diff)
downloadtor-e40cfc4425d1e173b5d122e38ab07dd798b11925.tar.gz
tor-e40cfc4425d1e173b5d122e38ab07dd798b11925.zip
Move the ctime part of choose_array_element_by_weight into di_ops
This way it gets the ctime options.
Diffstat (limited to 'src/common')
-rw-r--r--src/common/di_ops.c45
-rw-r--r--src/common/di_ops.h2
2 files changed, 47 insertions, 0 deletions
diff --git a/src/common/di_ops.c b/src/common/di_ops.c
index 5dfe828066..e671af6fac 100644
--- a/src/common/di_ops.c
+++ b/src/common/di_ops.c
@@ -226,3 +226,48 @@ safe_mem_is_zero(const void *mem, size_t sz)
return 1 & ((total - 1) >> 8);
}
+/** Time-invariant 64-bit greater-than; works on two integers in the range
+ * (0,INT64_MAX). */
+#if SIZEOF_VOID_P == 8
+#define gt_i64_timei(a,b) ((a) > (b))
+#else
+static inline int
+gt_i64_timei(uint64_t a, uint64_t b)
+{
+ int64_t diff = (int64_t) (b - a);
+ int res = diff >> 63;
+ return res & 1;
+}
+#endif
+
+/**
+ * Given an array of list of <b>n_entries</b> uint64_t values, whose sum is
+ * <b>total</b>, find the first i such that the total of all elements 0...i is
+ * greater than rand_val.
+ *
+ * Try to perform this operation in a constant-time way.
+ */
+int
+select_array_member_cumulative_timei(const uint64_t *entries, int n_entries,
+ uint64_t total, uint64_t rand_val)
+{
+ int i, i_chosen=-1, n_chosen=0;
+ uint64_t total_so_far = 0;
+
+ for (i = 0; i < n_entries; ++i) {
+ total_so_far += entries[i];
+ if (gt_i64_timei(total_so_far, rand_val)) {
+ i_chosen = i;
+ n_chosen++;
+ /* Set rand_val to INT64_MAX rather than stopping the loop. This way,
+ * the time we spend in the loop does not leak which element we chose. */
+ rand_val = INT64_MAX;
+ }
+ }
+ tor_assert(total_so_far == total);
+ tor_assert(n_chosen == 1);
+ tor_assert(i_chosen >= 0);
+ tor_assert(i_chosen < n_entries);
+
+ return i_chosen;
+}
diff --git a/src/common/di_ops.h b/src/common/di_ops.h
index 6e77b5cfd7..f1050a00db 100644
--- a/src/common/di_ops.h
+++ b/src/common/di_ops.h
@@ -42,6 +42,8 @@ void dimap_add_entry(di_digest256_map_t **map,
const uint8_t *key, void *val);
void *dimap_search(const di_digest256_map_t *map, const uint8_t *key,
void *dflt_val);
+int select_array_member_cumulative_timei(const uint64_t *entries, int n_entries,
+ uint64_t total, uint64_t rand_val);
#endif