aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib/siphash-internals.h
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-03-21 21:48:53 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-03-21 21:48:53 -0400
commit5ee185a4896e43c67b6d299becfa616da78fb9f4 (patch)
tree183ceef2fd21230c89334d7d039255d1c86c5dca /src/stdlib/siphash-internals.h
parentf4aaf7b73481248f6768302be688700a364a1af8 (diff)
Move stdlib into src/
Diffstat (limited to 'src/stdlib/siphash-internals.h')
-rw-r--r--src/stdlib/siphash-internals.h126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/stdlib/siphash-internals.h b/src/stdlib/siphash-internals.h
new file mode 100644
index 00000000..b359cea7
--- /dev/null
+++ b/src/stdlib/siphash-internals.h
@@ -0,0 +1,126 @@
+#pragma once
+
+// This file holds the internals for the SipHash implementation. For a few
+// cases, we want to include this for incrementally computing hashes.
+// Otherwise, it suffices to just use the siphash24() function from siphash.h
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "siphash.h"
+
+/* <MIT License>
+ Copyright (c) 2013 Marek Majkowski <marek@popcount.org>
+ Copyright (c) 2018 Samantha McVey <samantham@posteo.net>
+ Copyright (c) 2024 Bruce Hill <bruce@bruce-hill.com>
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ </MIT License>
+
+ Original location:
+ https://github.com/majek/csiphash/
+
+ Original solution inspired by code from:
+ Samuel Neves (supercop/crypto_auth/siphash24/little)
+ djb (supercop/crypto_auth/siphash24/little2)
+ Jean-Philippe Aumasson (https://131002.net/siphash/siphash24.c)
+
+ Extensive modifications for MoarVM by Samantha McVey
+
+ Further modifications for Tomo by Bruce Hill
+*/
+struct siphash {
+ uint64_t v0;
+ uint64_t v1;
+ uint64_t v2;
+ uint64_t v3;
+ uint64_t b;
+};
+typedef struct siphash siphash;
+#define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )
+
+#define HALF_ROUND(a,b,c,d,s,t) \
+ a += b; c += d; \
+ b = ROTATE(b, s) ^ a; \
+ d = ROTATE(d, t) ^ c; \
+ a = ROTATE(a, 32);
+
+#define DOUBLE_ROUND(v0,v1,v2,v3) \
+ HALF_ROUND(v0,v1,v2,v3,13,16); \
+ HALF_ROUND(v2,v1,v0,v3,17,21); \
+ HALF_ROUND(v0,v1,v2,v3,13,16); \
+ HALF_ROUND(v2,v1,v0,v3,17,21);
+
+MACROLIKE void siphashinit (siphash *sh, size_t src_sz) {
+ const uint64_t k0 = TOMO_HASH_KEY[0];
+ const uint64_t k1 = TOMO_HASH_KEY[1];
+ sh->b = (uint64_t)src_sz << 56;
+ sh->v0 = k0 ^ 0x736f6d6570736575ULL;
+ sh->v1 = k1 ^ 0x646f72616e646f6dULL;
+ sh->v2 = k0 ^ 0x6c7967656e657261ULL;
+ sh->v3 = k1 ^ 0x7465646279746573ULL;
+}
+MACROLIKE void siphashadd64bits (siphash *sh, const uint64_t in) {
+ const uint64_t mi = in;
+ sh->v3 ^= mi;
+ DOUBLE_ROUND(sh->v0,sh->v1,sh->v2,sh->v3);
+ sh->v0 ^= mi;
+}
+MACROLIKE uint64_t siphashfinish_last_part (siphash *sh, uint64_t t) {
+ sh->b |= t;
+ sh->v3 ^= sh->b;
+ DOUBLE_ROUND(sh->v0,sh->v1,sh->v2,sh->v3);
+ sh->v0 ^= sh->b;
+ sh->v2 ^= 0xff;
+ DOUBLE_ROUND(sh->v0,sh->v1,sh->v2,sh->v3);
+ DOUBLE_ROUND(sh->v0,sh->v1,sh->v2,sh->v3);
+ return (sh->v0 ^ sh->v1) ^ (sh->v2 ^ sh->v3);
+}
+/* This union helps us avoid doing weird things with pointers that can cause old
+ * compilers like GCC 4 to generate bad code. In addition it is nicely more C
+ * standards compliant to keep type punning to a minimum. */
+union SipHash64_union {
+ uint64_t u64;
+ uint32_t u32;
+ uint8_t u8[8];
+};
+MACROLIKE uint64_t siphashfinish (siphash *sh, const uint8_t *src, size_t src_sz) {
+ union SipHash64_union t = { 0 };
+ switch (src_sz) {
+ /* Falls through */
+ case 7: t.u8[6] = src[6];
+ /* Falls through */
+ case 6: t.u8[5] = src[5];
+ /* Falls through */
+ case 5: t.u8[4] = src[4];
+ /* Falls through */
+ case 4: t.u8[3] = src[3];
+ /* Falls through */
+ case 3: t.u8[2] = src[2];
+ /* Falls through */
+ case 2: t.u8[1] = src[1];
+ /* Falls through */
+ case 1: t.u8[0] = src[0];
+ default: break;
+ }
+ return siphashfinish_last_part(sh, t.u64);
+}
+
+// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0