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