Drop excess siphash round (see comment for more details) main
authorMatt Corallo <git@bluematt.me>
Tue, 18 Jun 2024 00:59:22 +0000 (00:59 +0000)
committerMatt Corallo <git@bluematt.me>
Tue, 18 Jun 2024 00:59:22 +0000 (00:59 +0000)
siphash.h

index f6d5fb3a93b25951426523cd3ebbfa01314a8321..cfcaad96824dc056a501ff5a18910fe7b04bd455 100644 (file)
--- a/siphash.h
+++ b/siphash.h
@@ -104,11 +104,23 @@ static inline uint64_t siphash(const uint64_t *in, const size_t inwords, const u
         v0 ^= m;
     }
 
         v0 ^= m;
     }
 
-    v3 ^= b;
+    // Generally, here siphash writes any extra bytes that weren't an even
+    // multiple of eight as well as the length (in the form of `b`). Then,
+    // because we've written fresh attacker-controlled data into our state, we
+    // do an extra `cROUNDS` `SIPROUND`s. This ensures we have
+    // `cROUNDS` + `dROUNDS` `SIPROUND`s between any attacker-controlled data
+    // and the output, which for SipHash 1-3 means the four rounds required for
+    // good mixing.
+    //
+    // However, in our use-case the input is always a multiple of eight bytes
+    // and the attacker doesn't control the length. Thus, we skip the extra
+    // round here, giving us a very slightly tweaked SipHash 1-2 which is
+    // equivalent to SipHash 1-3 with a fixed input of N*8+7 bytes.
+    /*v3 ^= b;
 
     TRACE;
     for (i = 0; i < cROUNDS; ++i)
 
     TRACE;
     for (i = 0; i < cROUNDS; ++i)
-        SIPROUND;
+        SIPROUND;*/
 
     v0 ^= b;
     v2 ^= 0xff;
 
     v0 ^= b;
     v2 ^= 0xff;