Add a function to maybe memcpy() a value, in constant time.

This commit is contained in:
Nick Mathewson 2020-01-16 19:23:20 -05:00
parent b6250236a2
commit 4269ab97c6
3 changed files with 59 additions and 0 deletions

View File

@ -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;
}
}

View File

@ -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) */

View File

@ -4571,6 +4571,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)
{
@ -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),