Branch data Line data Source code
1 : : // Copyright (c) 2016-2020 The Bitcoin Core developers 2 : : // Distributed under the MIT software license, see the accompanying 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : : 5 : : #include <crypto/siphash.h> 6 : : 7 : : #define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) 8 : : 9 : : #define SIPROUND do { \ 10 : : v0 += v1; v1 = ROTL(v1, 13); v1 ^= v0; \ 11 : : v0 = ROTL(v0, 32); \ 12 : : v2 += v3; v3 = ROTL(v3, 16); v3 ^= v2; \ 13 : : v0 += v3; v3 = ROTL(v3, 21); v3 ^= v0; \ 14 : : v2 += v1; v1 = ROTL(v1, 17); v1 ^= v2; \ 15 : : v2 = ROTL(v2, 32); \ 16 : : } while (0) 17 : : 18 : 26912 : CSipHasher::CSipHasher(uint64_t k0, uint64_t k1) 19 : : { 20 : 26912 : v[0] = 0x736f6d6570736575ULL ^ k0; 21 : 26912 : v[1] = 0x646f72616e646f6dULL ^ k1; 22 : 26912 : v[2] = 0x6c7967656e657261ULL ^ k0; 23 : 26912 : v[3] = 0x7465646279746573ULL ^ k1; 24 : 26912 : count = 0; 25 : 26912 : tmp = 0; 26 : 26912 : } 27 : : 28 : 46508 : CSipHasher& CSipHasher::Write(uint64_t data) 29 : : { 30 : 46508 : uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; 31 : : 32 [ + - ]: 46508 : assert(count % 8 == 0); 33 : : 34 : 46508 : v3 ^= data; 35 : 46508 : SIPROUND; 36 : 46508 : SIPROUND; 37 : 46508 : v0 ^= data; 38 : : 39 : 46508 : v[0] = v0; 40 : 46508 : v[1] = v1; 41 : 46508 : v[2] = v2; 42 : 46508 : v[3] = v3; 43 : : 44 : 46508 : count += 8; 45 : 46508 : return *this; 46 : : } 47 : : 48 : 18816 : CSipHasher& CSipHasher::Write(Span<const unsigned char> data) 49 : : { 50 : 18816 : uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; 51 : 18816 : uint64_t t = tmp; 52 : 18816 : uint8_t c = count; 53 : : 54 [ + + ]: 151756 : while (data.size() > 0) { 55 : 132940 : t |= uint64_t{data.front()} << (8 * (c % 8)); 56 : 132940 : c++; 57 [ + + ]: 132940 : if ((c & 7) == 0) { 58 : 10336 : v3 ^= t; 59 : 10336 : SIPROUND; 60 : 10336 : SIPROUND; 61 : 10336 : v0 ^= t; 62 : 10336 : t = 0; 63 : 10336 : } 64 : 132940 : data = data.subspan(1); 65 : : } 66 : : 67 : 18816 : v[0] = v0; 68 : 18816 : v[1] = v1; 69 : 18816 : v[2] = v2; 70 : 18816 : v[3] = v3; 71 : 18816 : count = c; 72 : 18816 : tmp = t; 73 : : 74 : 18816 : return *this; 75 : : } 76 : : 77 : 26033 : uint64_t CSipHasher::Finalize() const 78 : : { 79 : 26033 : uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3]; 80 : : 81 : 26033 : uint64_t t = tmp | (((uint64_t)count) << 56); 82 : : 83 : 26033 : v3 ^= t; 84 : 26033 : SIPROUND; 85 : 26033 : SIPROUND; 86 : 26033 : v0 ^= t; 87 : 26033 : v2 ^= 0xFF; 88 : 26033 : SIPROUND; 89 : 26033 : SIPROUND; 90 : 26033 : SIPROUND; 91 : 26033 : SIPROUND; 92 : 26033 : return v0 ^ v1 ^ v2 ^ v3; 93 : : } 94 : : 95 : 2 : uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val) 96 : : { 97 : : /* Specialized implementation for efficiency */ 98 : 2 : uint64_t d = val.GetUint64(0); 99 : : 100 : 2 : uint64_t v0 = 0x736f6d6570736575ULL ^ k0; 101 : 2 : uint64_t v1 = 0x646f72616e646f6dULL ^ k1; 102 : 2 : uint64_t v2 = 0x6c7967656e657261ULL ^ k0; 103 : 2 : uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d; 104 : : 105 : 2 : SIPROUND; 106 : 2 : SIPROUND; 107 : 2 : v0 ^= d; 108 : 2 : d = val.GetUint64(1); 109 : 2 : v3 ^= d; 110 : 2 : SIPROUND; 111 : 2 : SIPROUND; 112 : 2 : v0 ^= d; 113 : 2 : d = val.GetUint64(2); 114 : 2 : v3 ^= d; 115 : 2 : SIPROUND; 116 : 2 : SIPROUND; 117 : 2 : v0 ^= d; 118 : 2 : d = val.GetUint64(3); 119 : 2 : v3 ^= d; 120 : 2 : SIPROUND; 121 : 2 : SIPROUND; 122 : 2 : v0 ^= d; 123 : 2 : v3 ^= (uint64_t{4}) << 59; 124 : 2 : SIPROUND; 125 : 2 : SIPROUND; 126 : 2 : v0 ^= (uint64_t{4}) << 59; 127 : 2 : v2 ^= 0xFF; 128 : 2 : SIPROUND; 129 : 2 : SIPROUND; 130 : 2 : SIPROUND; 131 : 2 : SIPROUND; 132 : 2 : return v0 ^ v1 ^ v2 ^ v3; 133 : : } 134 : : 135 : 0 : uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra) 136 : : { 137 : : /* Specialized implementation for efficiency */ 138 : 0 : uint64_t d = val.GetUint64(0); 139 : : 140 : 0 : uint64_t v0 = 0x736f6d6570736575ULL ^ k0; 141 : 0 : uint64_t v1 = 0x646f72616e646f6dULL ^ k1; 142 : 0 : uint64_t v2 = 0x6c7967656e657261ULL ^ k0; 143 : 0 : uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d; 144 : : 145 : 0 : SIPROUND; 146 : 0 : SIPROUND; 147 : 0 : v0 ^= d; 148 : 0 : d = val.GetUint64(1); 149 : 0 : v3 ^= d; 150 : 0 : SIPROUND; 151 : 0 : SIPROUND; 152 : 0 : v0 ^= d; 153 : 0 : d = val.GetUint64(2); 154 : 0 : v3 ^= d; 155 : 0 : SIPROUND; 156 : 0 : SIPROUND; 157 : 0 : v0 ^= d; 158 : 0 : d = val.GetUint64(3); 159 : 0 : v3 ^= d; 160 : 0 : SIPROUND; 161 : 0 : SIPROUND; 162 : 0 : v0 ^= d; 163 : 0 : d = ((uint64_t{36}) << 56) | extra; 164 : 0 : v3 ^= d; 165 : 0 : SIPROUND; 166 : 0 : SIPROUND; 167 : 0 : v0 ^= d; 168 : 0 : v2 ^= 0xFF; 169 : 0 : SIPROUND; 170 : 0 : SIPROUND; 171 : 0 : SIPROUND; 172 : 0 : SIPROUND; 173 : 0 : return v0 ^ v1 ^ v2 ^ v3; 174 : : }