From 8127f4db30799d96b786509b74f49db4768cf6f1 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 5 May 2014 12:13:33 -0400 Subject: [PATCH 1/3] Use siphash on channel/circuit-id map too Fixes ticket 11750. --- changes/bug11750 | 5 +++++ src/or/circuitlist.c | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 changes/bug11750 diff --git a/changes/bug11750 b/changes/bug11750 new file mode 100644 index 0000000000..f779ac8fe0 --- /dev/null +++ b/changes/bug11750 @@ -0,0 +1,5 @@ + o Minor features (security): + - Apply the secure SipHash-2-4 function to the hash table mapping + circuit IDs and channels to circuits. We missed this one when we + were converting all the other hash functions to use SipHash back + in 0.2.5.3-alpha. Resolves ticket 11750. diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 90fc93f3a8..58fb22d8ce 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -76,7 +76,14 @@ chan_circid_entries_eq_(chan_circid_circuit_map_t *a, static INLINE unsigned int chan_circid_entry_hash_(chan_circid_circuit_map_t *a) { - return ((unsigned)a->circ_id) ^ (unsigned)(uintptr_t)(a->chan); + struct { + void *chan; + circid_t circid; + } s; + memset(&s, 0, sizeof(s)); + s.chan = a->chan; + s.circid = a->circ_id; + return (unsigned) siphash24g(&s, sizeof(s)); } /** Map from [chan,circid] to circuit. */ From 0ad607d6042e59e8d63a32ddd98a6673ed5f79db Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 6 May 2014 12:27:18 -0400 Subject: [PATCH 2/3] Faster chan_circid_entry_hash implementation Since this is critical-path, let's tune the value we pass to csiphash a little so it fits into one whole round. --- src/or/circuitlist.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 58fb22d8ce..e5ed9c04fd 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -76,14 +76,15 @@ chan_circid_entries_eq_(chan_circid_circuit_map_t *a, static INLINE unsigned int chan_circid_entry_hash_(chan_circid_circuit_map_t *a) { - struct { - void *chan; - circid_t circid; - } s; - memset(&s, 0, sizeof(s)); - s.chan = a->chan; - s.circid = a->circ_id; - return (unsigned) siphash24g(&s, sizeof(s)); + /* Try to squeze the siphash input into 8 bytes to save any extra siphash + * rounds. This hash function is in the critical path. */ + uintptr_t chan = (uintptr_t) (void*) a->chan; + uint32_t array[2]; + array[0] = a->circ_id; + /* The low bits of the channel pointer are uninteresting, since the channel + * is a pretty big structure. */ + array[1] = (uint32_t) (chan >> 6); + return (unsigned) siphash24g(array, sizeof(array)); } /** Map from [chan,circid] to circuit. */ From e9c1c3ff7f3123495493bad7aa77ef6194005c75 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 6 May 2014 12:55:39 -0400 Subject: [PATCH 3/3] Add a siphash benchmark. --- src/test/bench.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/test/bench.c b/src/test/bench.c index c9cc101b72..a3fa7fe319 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -337,6 +337,30 @@ bench_dmap(void) smartlist_free(sl2); } +static void +bench_siphash(void) +{ + char buf[128]; + int lens[] = { 7, 8, 15, 16, 20, 32, 111, 128, -1 }; + int i, j; + uint64_t total; + uint64_t start, end; + const int N = 300000; + crypto_rand(buf, sizeof(buf)); + + for (i = 0; lens[i] > 0; ++i) { + total = 0; + reset_perftime(); + start = perftime(); + for (j = 0; j < N; ++j) { + total += siphash24g(buf, lens[i]); + } + end = perftime(); + printf("siphash24g(%d): %.2f ns per call\n", + lens[i], NANOCOUNT(start,end,N)); + } +} + static void bench_cell_ops(void) { @@ -487,6 +511,7 @@ typedef struct benchmark_t { static struct benchmark_t benchmarks[] = { ENT(dmap), + ENT(siphash), ENT(aes), ENT(onion_TAP), #ifdef CURVE25519_ENABLED