"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/isc/siphash.c" (4 Sep 2020, 5423 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "siphash.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 9.17.3_vs_9.17.4.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 #include <inttypes.h>
   13 #include <string.h>
   14 #include <unistd.h>
   15 
   16 #include <isc/endian.h>
   17 #include <isc/siphash.h>
   18 #include <isc/util.h>
   19 
   20 /*
   21  * The implementation is based on SipHash reference C implementation by
   22  *
   23  * Copyright (c) 2012-2016 Jean-Philippe Aumasson
   24  * <jeanphilippe.aumasson@gmail.com> Copyright (c) 2012-2014 Daniel J. Bernstein
   25  * <djb@cr.yp.to>
   26  *
   27  * To the extent possible under law, the author(s) have dedicated all copyright
   28  * and related and neighboring rights to this software to the public domain
   29  * worldwide. This software is distributed without any warranty.  You should
   30  * have received a copy of the CC0 Public Domain Dedication along with this
   31  * software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
   32  */
   33 
   34 #define cROUNDS 2
   35 #define dROUNDS 4
   36 
   37 #define ROTATE64(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
   38 
   39 #define HALF_ROUND64(a, b, c, d, s, t) \
   40     a += b;                        \
   41     c += d;                        \
   42     b = ROTATE64(b, s) ^ a;        \
   43     d = ROTATE64(d, t) ^ c;        \
   44     a = ROTATE64(a, 32);
   45 
   46 #define FULL_ROUND64(v0, v1, v2, v3)          \
   47     HALF_ROUND64(v0, v1, v2, v3, 13, 16); \
   48     HALF_ROUND64(v2, v1, v0, v3, 17, 21);
   49 
   50 #define SIPROUND FULL_ROUND64
   51 
   52 #define ROTATE32(x, b) (uint32_t)(((x) << (b)) | ((x) >> (32 - (b))))
   53 
   54 #define HALF_ROUND32(a, b, c, d, s, t) \
   55     a += b;                        \
   56     c += d;                        \
   57     b = ROTATE32(b, s) ^ a;        \
   58     d = ROTATE32(d, t) ^ c;        \
   59     a = ROTATE32(a, 16);
   60 
   61 #define FULL_ROUND32(v0, v1, v2, v3)        \
   62     HALF_ROUND32(v0, v1, v2, v3, 5, 8); \
   63     HALF_ROUND32(v2, v1, v0, v3, 13, 7);
   64 
   65 #define HALFSIPROUND FULL_ROUND32
   66 
   67 #define U32TO8_LE(p, v)                \
   68     (p)[0] = (uint8_t)((v));       \
   69     (p)[1] = (uint8_t)((v) >> 8);  \
   70     (p)[2] = (uint8_t)((v) >> 16); \
   71     (p)[3] = (uint8_t)((v) >> 24);
   72 
   73 #define U8TO32_LE(p)                                        \
   74     (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
   75      ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
   76 
   77 #define U64TO8_LE(p, v)                  \
   78     U32TO8_LE((p), (uint32_t)((v))); \
   79     U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
   80 
   81 #define U8TO64_LE(p)                                               \
   82     (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) |        \
   83      ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
   84      ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
   85      ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
   86 
   87 void
   88 isc_siphash24(const uint8_t *k, const uint8_t *in, const size_t inlen,
   89           uint8_t *out) {
   90     REQUIRE(k != NULL);
   91     REQUIRE(out != NULL);
   92 
   93     uint64_t k0 = U8TO64_LE(k);
   94     uint64_t k1 = U8TO64_LE(k + 8);
   95 
   96     uint64_t v0 = UINT64_C(0x736f6d6570736575) ^ k0;
   97     uint64_t v1 = UINT64_C(0x646f72616e646f6d) ^ k1;
   98     uint64_t v2 = UINT64_C(0x6c7967656e657261) ^ k0;
   99     uint64_t v3 = UINT64_C(0x7465646279746573) ^ k1;
  100 
  101     uint64_t b = ((uint64_t)inlen) << 56;
  102 
  103     const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
  104     const size_t left = inlen & 7;
  105 
  106     for (; in != end; in += 8) {
  107         uint64_t m = U8TO64_LE(in);
  108 
  109         v3 ^= m;
  110 
  111         for (size_t i = 0; i < cROUNDS; ++i) {
  112             SIPROUND(v0, v1, v2, v3);
  113         }
  114 
  115         v0 ^= m;
  116     }
  117 
  118     switch (left) {
  119     case 7:
  120         b |= ((uint64_t)in[6]) << 48;
  121     /* FALLTHROUGH */
  122     case 6:
  123         b |= ((uint64_t)in[5]) << 40;
  124     /* FALLTHROUGH */
  125     case 5:
  126         b |= ((uint64_t)in[4]) << 32;
  127     /* FALLTHROUGH */
  128     case 4:
  129         b |= ((uint64_t)in[3]) << 24;
  130     /* FALLTHROUGH */
  131     case 3:
  132         b |= ((uint64_t)in[2]) << 16;
  133     /* FALLTHROUGH */
  134     case 2:
  135         b |= ((uint64_t)in[1]) << 8;
  136     /* FALLTHROUGH */
  137     case 1:
  138         b |= ((uint64_t)in[0]);
  139     /* FALLTHROUGH */
  140     case 0:
  141         break;
  142     default:
  143         INSIST(0);
  144         ISC_UNREACHABLE();
  145     }
  146 
  147     v3 ^= b;
  148 
  149     for (size_t i = 0; i < cROUNDS; ++i) {
  150         SIPROUND(v0, v1, v2, v3);
  151     }
  152 
  153     v0 ^= b;
  154 
  155     v2 ^= 0xff;
  156 
  157     for (size_t i = 0; i < dROUNDS; ++i) {
  158         SIPROUND(v0, v1, v2, v3);
  159     }
  160 
  161     b = v0 ^ v1 ^ v2 ^ v3;
  162 
  163     U64TO8_LE(out, b);
  164 }
  165 
  166 void
  167 isc_halfsiphash24(const uint8_t *k, const uint8_t *in, const size_t inlen,
  168           uint8_t *out) {
  169     REQUIRE(k != NULL);
  170     REQUIRE(out != NULL);
  171 
  172     uint32_t k0 = U8TO32_LE(k);
  173     uint32_t k1 = U8TO32_LE(k + 4);
  174 
  175     uint32_t v0 = UINT32_C(0x00000000) ^ k0;
  176     uint32_t v1 = UINT32_C(0x00000000) ^ k1;
  177     uint32_t v2 = UINT32_C(0x6c796765) ^ k0;
  178     uint32_t v3 = UINT32_C(0x74656462) ^ k1;
  179 
  180     uint32_t b = ((uint32_t)inlen) << 24;
  181 
  182     const uint8_t *end = in + inlen - (inlen % sizeof(uint32_t));
  183     const int left = inlen & 3;
  184 
  185     for (; in != end; in += 4) {
  186         uint32_t m = U8TO32_LE(in);
  187         v3 ^= m;
  188 
  189         for (size_t i = 0; i < cROUNDS; ++i) {
  190             HALFSIPROUND(v0, v1, v2, v3);
  191         }
  192 
  193         v0 ^= m;
  194     }
  195 
  196     switch (left) {
  197     case 3:
  198         b |= ((uint32_t)in[2]) << 16;
  199     /* FALLTHROUGH */
  200     case 2:
  201         b |= ((uint32_t)in[1]) << 8;
  202     /* FALLTHROUGH */
  203     case 1:
  204         b |= ((uint32_t)in[0]);
  205     /* FALLTHROUGH */
  206     case 0:
  207         break;
  208     default:
  209         INSIST(0);
  210         ISC_UNREACHABLE();
  211     }
  212 
  213     v3 ^= b;
  214 
  215     for (size_t i = 0; i < cROUNDS; ++i) {
  216         HALFSIPROUND(v0, v1, v2, v3);
  217     }
  218 
  219     v0 ^= b;
  220 
  221     v2 ^= 0xff;
  222 
  223     for (size_t i = 0; i < dROUNDS; ++i) {
  224         HALFSIPROUND(v0, v1, v2, v3);
  225     }
  226 
  227     b = v1 ^ v3;
  228     U32TO8_LE(out, b);
  229 }