aboutsummaryrefslogtreecommitdiff
path: root/siphash.c
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2015-02-28 19:53:23 +0100
committerPřemysl Janouch <p.janouch@gmail.com>2015-02-28 19:53:23 +0100
commit087645848baec5e59e4296817850bd5dd240cbb2 (patch)
treef5b3d507c4a65a95a26a52a17136fdf94811b785 /siphash.c
downloadliberty-087645848baec5e59e4296817850bd5dd240cbb2.tar.gz
liberty-087645848baec5e59e4296817850bd5dd240cbb2.tar.xz
liberty-087645848baec5e59e4296817850bd5dd240cbb2.zip
Initial commit
Diffstat (limited to 'siphash.c')
-rw-r--r--siphash.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/siphash.c b/siphash.c
new file mode 100644
index 0000000..7a5c8d4
--- /dev/null
+++ b/siphash.c
@@ -0,0 +1,87 @@
+// Code taken from https://github.com/floodyberry/siphash with some edits.
+//
+// To the extent possible under law, the author(s) have dedicated all copyright
+// and related and neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+#include "siphash.h"
+
+inline static uint64_t
+u8to64_le (const unsigned char *p)
+{
+ return
+ (uint64_t) p[0] |
+ (uint64_t) p[1] << 8 |
+ (uint64_t) p[2] << 16 |
+ (uint64_t) p[3] << 24 |
+ (uint64_t) p[4] << 32 |
+ (uint64_t) p[5] << 40 |
+ (uint64_t) p[6] << 48 |
+ (uint64_t) p[7] << 56 ;
+}
+
+uint64_t
+siphash (const unsigned char key[16], const unsigned char *m, size_t len)
+{
+ uint64_t v0, v1, v2, v3;
+ uint64_t mi, k0, k1;
+ uint64_t last7;
+ size_t i, blocks;
+
+ k0 = u8to64_le (key + 0);
+ k1 = u8to64_le (key + 8);
+ v0 = k0 ^ 0x736f6d6570736575ull;
+ v1 = k1 ^ 0x646f72616e646f6dull;
+ v2 = k0 ^ 0x6c7967656e657261ull;
+ v3 = k1 ^ 0x7465646279746573ull;
+
+ last7 = (uint64_t) (len & 0xff) << 56;
+
+#define ROTL64(a,b) (((a)<<(b))|((a)>>(64-b)))
+
+#define COMPRESS \
+ v0 += v1; v2 += v3; \
+ v1 = ROTL64 (v1,13); v3 = ROTL64 (v3,16); \
+ v1 ^= v0; v3 ^= v2; \
+ v0 = ROTL64 (v0,32); \
+ v2 += v1; v0 += v3; \
+ v1 = ROTL64 (v1,17); v3 = ROTL64 (v3,21); \
+ v1 ^= v2; v3 ^= v0; \
+ v2 = ROTL64(v2,32);
+
+ for (i = 0, blocks = (len & ~(size_t) 7); i < blocks; i += 8)
+ {
+ mi = u8to64_le (m + i);
+ v3 ^= mi;
+ COMPRESS
+ COMPRESS
+ v0 ^= mi;
+ }
+
+ switch (len - blocks)
+ {
+ case 7: last7 |= (uint64_t) m[i + 6] << 48;
+ case 6: last7 |= (uint64_t) m[i + 5] << 40;
+ case 5: last7 |= (uint64_t) m[i + 4] << 32;
+ case 4: last7 |= (uint64_t) m[i + 3] << 24;
+ case 3: last7 |= (uint64_t) m[i + 2] << 16;
+ case 2: last7 |= (uint64_t) m[i + 1] << 8;
+ case 1: last7 |= (uint64_t) m[i + 0] ;
+ default:;
+ };
+ v3 ^= last7;
+ COMPRESS
+ COMPRESS
+ v0 ^= last7;
+ v2 ^= 0xff;
+ COMPRESS
+ COMPRESS
+ COMPRESS
+ COMPRESS
+
+ return v0 ^ v1 ^ v2 ^ v3;
+}
+