diff options
author | Nick Mathewson <nickm@torproject.org> | 2012-12-25 22:22:07 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2013-01-03 11:29:48 -0500 |
commit | f07a5125cb5bb9ee5968ded163cfdd73e5ad028c (patch) | |
tree | 03444d1dbfe2a58e242e9923728971c7303717b9 | |
parent | 92d6a83e9895da874eae81e20e14df20231f25bf (diff) | |
download | tor-f07a5125cb5bb9ee5968ded163cfdd73e5ad028c.tar.gz tor-f07a5125cb5bb9ee5968ded163cfdd73e5ad028c.zip |
Implement a constant-time safe_mem_is_zero.
-rw-r--r-- | src/common/di_ops.c | 17 | ||||
-rw-r--r-- | src/common/di_ops.h | 2 | ||||
-rw-r--r-- | src/test/test_util.c | 10 |
3 files changed, 29 insertions, 0 deletions
diff --git a/src/common/di_ops.c b/src/common/di_ops.c index b73a3cc492..e299e31507 100644 --- a/src/common/di_ops.c +++ b/src/common/di_ops.c @@ -203,3 +203,20 @@ dimap_search(const di_digest256_map_t *map, const uint8_t *key, return (void *)result; } +/** + * Return true iff the <b>sz</b> bytes at <b>mem</b> are all zero. Runs in + * time independent of the contents of <b>mem</b>. + */ +int +safe_mem_is_zero(const void *mem, size_t sz) +{ + uint32_t total = 0; + const uint8_t *ptr = mem; + + while (sz--) { + total |= *ptr++; + } + + return 1 & ((total - 1) >> 8); +} + diff --git a/src/common/di_ops.h b/src/common/di_ops.h index a86f56c966..144482811f 100644 --- a/src/common/di_ops.h +++ b/src/common/di_ops.h @@ -27,6 +27,8 @@ int tor_memeq(const void *a, const void *b, size_t sz); #define fast_memeq(a,b,c) (0==memcmp((a),(b),(c))) #define fast_memneq(a,b,c) (0!=memcmp((a),(b),(c))) +int safe_mem_is_zero(const void *mem, size_t sz); + /** A type for a map from DIGEST256_LEN-byte blobs to void*, such that * data lookups take an amount of time proportional only to the size * of the map, and not to the position or presence of the item in the map. diff --git a/src/test/test_util.c b/src/test/test_util.c index 04ca42dcd9..f949c6db91 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -2843,6 +2843,16 @@ test_util_di_ops(void) test_eq(neq1, !eq1); } + tt_int_op(1, ==, safe_mem_is_zero("", 0)); + tt_int_op(1, ==, safe_mem_is_zero("", 1)); + tt_int_op(0, ==, safe_mem_is_zero("a", 1)); + tt_int_op(0, ==, safe_mem_is_zero("a", 2)); + tt_int_op(0, ==, safe_mem_is_zero("\0a", 2)); + tt_int_op(1, ==, safe_mem_is_zero("\0\0a", 2)); + tt_int_op(1, ==, safe_mem_is_zero("\0\0\0\0\0\0\0\0", 8)); + tt_int_op(1, ==, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 8)); + tt_int_op(0, ==, safe_mem_is_zero("\0\0\0\0\0\0\0\0a", 9)); + done: ; } |