/* 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) APR_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; } APR_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); } APR_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; } APR_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); } APR_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; } APR_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); }