anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

siphash.cpp (4007B)

      1 /* SipHash-2-4 routines.
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  *
      8  * Based on the original code of Epona by Lara.
      9  * Based on the original code of Services by Andy Church.
     10  */
     11 
     12 /* <MIT License>
     13  Copyright (c) 2013  Marek Majkowski <marek@popcount.org>
     14  Permission is hereby granted, free of charge, to any person obtaining a copy
     15  of this software and associated documentation files (the "Software"), to deal
     16  in the Software without restriction, including without limitation the rights
     17  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     18  copies of the Software, and to permit persons to whom the Software is
     19  furnished to do so, subject to the following conditions:
     20  The above copyright notice and this permission notice shall be included in
     21  all copies or substantial portions of the Software.
     22  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     23  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     24  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     25  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     26  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     27  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     28  THE SOFTWARE.
     29  </MIT License>
     30  Original location:
     31     https://github.com/majek/csiphash/
     32  Solution inspired by code from:
     33     Samuel Neves (supercop/crypto_auth/siphash24/little)
     34     djb (supercop/crypto_auth/siphash24/little2)
     35     Jean-Philippe Aumasson (https://131002.net/siphash/siphash24.c)
     36 */
     37 
     38 #include "services.h"
     39 #include "anope.h"
     40 
     41 // WARNING: This ifdef maze could be a lot simpler but unfortunately
     42 // that will cause find_includes to be unable to parse it.
     43 
     44 #ifdef __APPLE__
     45 #  include <libkern/OSByteOrder.h>
     46 #  define _le64toh(x) OSSwapLittleToHostInt64(x)
     47 #endif
     48 
     49 #ifdef __FreeBSD__
     50 #  include <sys/endian.h>
     51 #  define _le64toh(x) le64toh(x)
     52 #endif
     53 
     54 #ifdef __linux__
     55 #  include <endian.h>
     56 #endif
     57 
     58 #ifdef __NetBSD__
     59 #  include <sys/endian.h>
     60 #  define _le64toh(x) le64toh(x)
     61 #endif
     62 
     63 #ifdef __OpenBSD__
     64 #  include <sys/endian.h>
     65 #  define _le64toh(x) le64toh(x)
     66 #endif
     67 
     68 // Windows is always little endian.
     69 #ifdef _WIN32
     70 #  define _le64toh(x) ((uint64_t)(x))
     71 #endif
     72 
     73 // Attempt to work on unenumerated platforms.
     74 #if defined(le64toh) && !defined(_le64toh)
     75 #  define _le64toh le64toh
     76 #endif
     77 
     78 // We can't do anything about this.
     79 #ifndef _le64toh
     80 #  error Please define _le64toh for your platform!
     81 #endif
     82 
     83 #define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )
     84 
     85 #define HALF_ROUND(a,b,c,d,s,t)			\
     86 	a += b; c += d;				\
     87 	b = ROTATE(b, s) ^ a;			\
     88 	d = ROTATE(d, t) ^ c;			\
     89 	a = ROTATE(a, 32);
     90 
     91 #define DOUBLE_ROUND(v0,v1,v2,v3)		\
     92 	HALF_ROUND(v0,v1,v2,v3,13,16);		\
     93 	HALF_ROUND(v2,v1,v0,v3,17,21);		\
     94 	HALF_ROUND(v0,v1,v2,v3,13,16);		\
     95 	HALF_ROUND(v2,v1,v0,v3,17,21);
     96 
     97 
     98 uint64_t Anope::SipHash24(const void *src, unsigned long src_sz, const char key[16])
     99 {
    100 	const uint64_t *_key = (uint64_t *)key;
    101 	uint64_t k0 = _le64toh(_key[0]);
    102 	uint64_t k1 = _le64toh(_key[1]);
    103 	uint64_t b = (uint64_t)src_sz << 56;
    104 	const uint64_t *in = (uint64_t*)src;
    105 
    106 	uint64_t v0 = k0 ^ 0x736f6d6570736575ULL;
    107 	uint64_t v1 = k1 ^ 0x646f72616e646f6dULL;
    108 	uint64_t v2 = k0 ^ 0x6c7967656e657261ULL;
    109 	uint64_t v3 = k1 ^ 0x7465646279746573ULL;
    110 
    111 	while (src_sz >= 8)
    112 	{
    113 		uint64_t mi = _le64toh(*in);
    114 		in += 1; src_sz -= 8;
    115 		v3 ^= mi;
    116 		DOUBLE_ROUND(v0,v1,v2,v3);
    117 		v0 ^= mi;
    118 	}
    119 
    120 	uint64_t t = 0; uint8_t *pt = (uint8_t *)&t; uint8_t *m = (uint8_t *)in;
    121 	switch (src_sz)
    122 	{
    123 		case 7: pt[6] = m[6];
    124 		case 6: pt[5] = m[5];
    125 		case 5: pt[4] = m[4];
    126 		case 4: *((uint32_t*)&pt[0]) = *((uint32_t*)&m[0]); break;
    127 		case 3: pt[2] = m[2];
    128 		case 2: pt[1] = m[1];
    129 		case 1: pt[0] = m[0];
    130 	}
    131 	b |= _le64toh(t);
    132 
    133 	v3 ^= b;
    134 	DOUBLE_ROUND(v0,v1,v2,v3);
    135 	v0 ^= b; v2 ^= 0xff;
    136 	DOUBLE_ROUND(v0,v1,v2,v3);
    137 	DOUBLE_ROUND(v0,v1,v2,v3);
    138 	return (v0 ^ v1) ^ (v2 ^ v3);
    139 }