summaryrefslogtreecommitdiffstats
path: root/crypto/apr_siphash.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/apr_siphash.c')
-rw-r--r--crypto/apr_siphash.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/crypto/apr_siphash.c b/crypto/apr_siphash.c
new file mode 100644
index 0000000..c9cabe2
--- /dev/null
+++ b/crypto/apr_siphash.c
@@ -0,0 +1,196 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * SipHash (C reference implementation, APR-ized), originating from:
+ * https://131002.net/siphash/siphash24.c.
+ */
+
+#include "apr_siphash.h"
+
+#define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))
+
+#define U8TO64_LE(p) \
+ (((apr_uint64_t)((p)[0]) ) | \
+ ((apr_uint64_t)((p)[1]) << 8) | \
+ ((apr_uint64_t)((p)[2]) << 16) | \
+ ((apr_uint64_t)((p)[3]) << 24) | \
+ ((apr_uint64_t)((p)[4]) << 32) | \
+ ((apr_uint64_t)((p)[5]) << 40) | \
+ ((apr_uint64_t)((p)[6]) << 48) | \
+ ((apr_uint64_t)((p)[7]) << 56))
+
+#define U64TO8_LE(p, v) \
+do { \
+ (p)[0] = (unsigned char)((v) ); \
+ (p)[1] = (unsigned char)((v) >> 8); \
+ (p)[2] = (unsigned char)((v) >> 16); \
+ (p)[3] = (unsigned char)((v) >> 24); \
+ (p)[4] = (unsigned char)((v) >> 32); \
+ (p)[5] = (unsigned char)((v) >> 40); \
+ (p)[6] = (unsigned char)((v) >> 48); \
+ (p)[7] = (unsigned char)((v) >> 56); \
+} while (0)
+
+#define SIPROUND() \
+do { \
+ v0 += v1; v1=ROTL64(v1,13); v1 ^= v0; v0=ROTL64(v0,32); \
+ v2 += v3; v3=ROTL64(v3,16); v3 ^= v2; \
+ v0 += v3; v3=ROTL64(v3,21); v3 ^= v0; \
+ v2 += v1; v1=ROTL64(v1,17); v1 ^= v2; v2=ROTL64(v2,32); \
+} while(0)
+
+#define SIPHASH(r, s, n, k) \
+do { \
+ const unsigned char *ptr, *end; \
+ apr_uint64_t v0, v1, v2, v3, m; \
+ apr_uint64_t k0, k1; \
+ unsigned int rem; \
+ \
+ k0 = U8TO64_LE(k + 0); \
+ k1 = U8TO64_LE(k + 8); \
+ v3 = k1 ^ (apr_uint64_t)0x7465646279746573ULL; \
+ v2 = k0 ^ (apr_uint64_t)0x6c7967656e657261ULL; \
+ v1 = k1 ^ (apr_uint64_t)0x646f72616e646f6dULL; \
+ v0 = k0 ^ (apr_uint64_t)0x736f6d6570736575ULL; \
+ \
+ rem = (unsigned int)(n & 0x7); \
+ for (ptr = s, end = ptr + n - rem; ptr < end; ptr += 8) { \
+ m = U8TO64_LE(ptr); \
+ v3 ^= m; \
+ cROUNDS \
+ v0 ^= m; \
+ } \
+ m = (apr_uint64_t)(n & 0xff) << 56; \
+ switch (rem) { \
+ case 7: m |= (apr_uint64_t)ptr[6] << 48; \
+ case 6: m |= (apr_uint64_t)ptr[5] << 40; \
+ case 5: m |= (apr_uint64_t)ptr[4] << 32; \
+ case 4: m |= (apr_uint64_t)ptr[3] << 24; \
+ case 3: m |= (apr_uint64_t)ptr[2] << 16; \
+ case 2: m |= (apr_uint64_t)ptr[1] << 8; \
+ case 1: m |= (apr_uint64_t)ptr[0]; \
+ case 0: break; \
+ } \
+ v3 ^= m; \
+ cROUNDS \
+ v0 ^= m; \
+ \
+ v2 ^= 0xff; \
+ dROUNDS \
+ \
+ r = v0 ^ v1 ^ v2 ^ v3; \
+} while (0)
+
+APU_DECLARE(apr_uint64_t) apr_siphash(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE],
+ unsigned int c, unsigned int d)
+{
+ apr_uint64_t h;
+ unsigned int i;
+
+#undef cROUNDS
+#define cROUNDS \
+ for (i = 0; i < c; ++i) { \
+ SIPROUND(); \
+ }
+
+#undef dROUNDS
+#define dROUNDS \
+ for (i = 0; i < d; ++i) { \
+ SIPROUND(); \
+ }
+
+ SIPHASH(h, src, len, key);
+ return h;
+}
+
+APU_DECLARE(void) apr_siphash_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE],
+ unsigned int c, unsigned int d)
+{
+ apr_uint64_t h;
+ h = apr_siphash(src, len, key, c, d);
+ U64TO8_LE(out, h);
+}
+
+APU_DECLARE(apr_uint64_t) apr_siphash24(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+
+#undef cROUNDS
+#define cROUNDS \
+ SIPROUND(); \
+ SIPROUND();
+
+#undef dROUNDS
+#define dROUNDS \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND();
+
+ SIPHASH(h, src, len, key);
+ return h;
+}
+
+APU_DECLARE(void) apr_siphash24_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+ h = apr_siphash24(src, len, key);
+ U64TO8_LE(out, h);
+}
+
+APU_DECLARE(apr_uint64_t) apr_siphash48(const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+
+#undef cROUNDS
+#define cROUNDS \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND();
+
+#undef dROUNDS
+#define dROUNDS \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND(); \
+ SIPROUND();
+
+ SIPHASH(h, src, len, key);
+ return h;
+}
+
+APU_DECLARE(void) apr_siphash48_auth(unsigned char out[APR_SIPHASH_DSIZE],
+ const void *src, apr_size_t len,
+ const unsigned char key[APR_SIPHASH_KSIZE])
+{
+ apr_uint64_t h;
+ h = apr_siphash48(src, len, key);
+ U64TO8_LE(out, h);
+}
+