1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* 18 * SipHash (C reference implementation, APR-ized), originating from: 19 * https://131002.net/siphash/siphash24.c. 20 */ 21 22#include "apr_siphash.h" 23 24#define ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n)))) 25 26#define U8TO64_LE(p) \ 27 (((apr_uint64_t)((p)[0]) ) | \ 28 ((apr_uint64_t)((p)[1]) << 8) | \ 29 ((apr_uint64_t)((p)[2]) << 16) | \ 30 ((apr_uint64_t)((p)[3]) << 24) | \ 31 ((apr_uint64_t)((p)[4]) << 32) | \ 32 ((apr_uint64_t)((p)[5]) << 40) | \ 33 ((apr_uint64_t)((p)[6]) << 48) | \ 34 ((apr_uint64_t)((p)[7]) << 56)) 35 36#define U64TO8_LE(p, v) \ 37do { \ 38 (p)[0] = (unsigned char)((v) ); \ 39 (p)[1] = (unsigned char)((v) >> 8); \ 40 (p)[2] = (unsigned char)((v) >> 16); \ 41 (p)[3] = (unsigned char)((v) >> 24); \ 42 (p)[4] = (unsigned char)((v) >> 32); \ 43 (p)[5] = (unsigned char)((v) >> 40); \ 44 (p)[6] = (unsigned char)((v) >> 48); \ 45 (p)[7] = (unsigned char)((v) >> 56); \ 46} while (0) 47 48#define SIPROUND() \ 49do { \ 50 v0 += v1; v1=ROTL64(v1,13); v1 ^= v0; v0=ROTL64(v0,32); \ 51 v2 += v3; v3=ROTL64(v3,16); v3 ^= v2; \ 52 v0 += v3; v3=ROTL64(v3,21); v3 ^= v0; \ 53 v2 += v1; v1=ROTL64(v1,17); v1 ^= v2; v2=ROTL64(v2,32); \ 54} while(0) 55 56#define SIPHASH(r, s, n, k) \ 57do { \ 58 const unsigned char *ptr, *end; \ 59 apr_uint64_t v0, v1, v2, v3, m; \ 60 apr_uint64_t k0, k1; \ 61 unsigned int rem; \ 62 \ 63 k0 = U8TO64_LE(k + 0); \ 64 k1 = U8TO64_LE(k + 8); \ 65 v3 = k1 ^ (apr_uint64_t)0x7465646279746573ULL; \ 66 v2 = k0 ^ (apr_uint64_t)0x6c7967656e657261ULL; \ 67 v1 = k1 ^ (apr_uint64_t)0x646f72616e646f6dULL; \ 68 v0 = k0 ^ (apr_uint64_t)0x736f6d6570736575ULL; \ 69 \ 70 rem = (unsigned int)(n & 0x7); \ 71 for (ptr = s, end = ptr + n - rem; ptr < end; ptr += 8) { \ 72 m = U8TO64_LE(ptr); \ 73 v3 ^= m; \ 74 cROUNDS \ 75 v0 ^= m; \ 76 } \ 77 m = (apr_uint64_t)(n & 0xff) << 56; \ 78 switch (rem) { \ 79 case 7: m |= (apr_uint64_t)ptr[6] << 48; \ 80 case 6: m |= (apr_uint64_t)ptr[5] << 40; \ 81 case 5: m |= (apr_uint64_t)ptr[4] << 32; \ 82 case 4: m |= (apr_uint64_t)ptr[3] << 24; \ 83 case 3: m |= (apr_uint64_t)ptr[2] << 16; \ 84 case 2: m |= (apr_uint64_t)ptr[1] << 8; \ 85 case 1: m |= (apr_uint64_t)ptr[0]; \ 86 case 0: break; \ 87 } \ 88 v3 ^= m; \ 89 cROUNDS \ 90 v0 ^= m; \ 91 \ 92 v2 ^= 0xff; \ 93 dROUNDS \ 94 \ 95 r = v0 ^ v1 ^ v2 ^ v3; \ 96} while (0) 97 98APU_DECLARE(apr_uint64_t) apr_siphash(const void *src, apr_size_t len, 99 const unsigned char key[APR_SIPHASH_KSIZE], 100 unsigned int c, unsigned int d) 101{ 102 apr_uint64_t h; 103 unsigned int i; 104 105#undef cROUNDS 106#define cROUNDS \ 107 for (i = 0; i < c; ++i) { \ 108 SIPROUND(); \ 109 } 110 111#undef dROUNDS 112#define dROUNDS \ 113 for (i = 0; i < d; ++i) { \ 114 SIPROUND(); \ 115 } 116 117 SIPHASH(h, src, len, key); 118 return h; 119} 120 121APU_DECLARE(void) apr_siphash_auth(unsigned char out[APR_SIPHASH_DSIZE], 122 const void *src, apr_size_t len, 123 const unsigned char key[APR_SIPHASH_KSIZE], 124 unsigned int c, unsigned int d) 125{ 126 apr_uint64_t h; 127 h = apr_siphash(src, len, key, c, d); 128 U64TO8_LE(out, h); 129} 130 131APU_DECLARE(apr_uint64_t) apr_siphash24(const void *src, apr_size_t len, 132 const unsigned char key[APR_SIPHASH_KSIZE]) 133{ 134 apr_uint64_t h; 135 136#undef cROUNDS 137#define cROUNDS \ 138 SIPROUND(); \ 139 SIPROUND(); 140 141#undef dROUNDS 142#define dROUNDS \ 143 SIPROUND(); \ 144 SIPROUND(); \ 145 SIPROUND(); \ 146 SIPROUND(); 147 148 SIPHASH(h, src, len, key); 149 return h; 150} 151 152APU_DECLARE(void) apr_siphash24_auth(unsigned char out[APR_SIPHASH_DSIZE], 153 const void *src, apr_size_t len, 154 const unsigned char key[APR_SIPHASH_KSIZE]) 155{ 156 apr_uint64_t h; 157 h = apr_siphash24(src, len, key); 158 U64TO8_LE(out, h); 159} 160 161APU_DECLARE(apr_uint64_t) apr_siphash48(const void *src, apr_size_t len, 162 const unsigned char key[APR_SIPHASH_KSIZE]) 163{ 164 apr_uint64_t h; 165 166#undef cROUNDS 167#define cROUNDS \ 168 SIPROUND(); \ 169 SIPROUND(); \ 170 SIPROUND(); \ 171 SIPROUND(); 172 173#undef dROUNDS 174#define dROUNDS \ 175 SIPROUND(); \ 176 SIPROUND(); \ 177 SIPROUND(); \ 178 SIPROUND(); \ 179 SIPROUND(); \ 180 SIPROUND(); \ 181 SIPROUND(); \ 182 SIPROUND(); 183 184 SIPHASH(h, src, len, key); 185 return h; 186} 187 188APU_DECLARE(void) apr_siphash48_auth(unsigned char out[APR_SIPHASH_DSIZE], 189 const void *src, apr_size_t len, 190 const unsigned char key[APR_SIPHASH_KSIZE]) 191{ 192 apr_uint64_t h; 193 h = apr_siphash48(src, len, key); 194 U64TO8_LE(out, h); 195} 196 197