| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | SipHash reference C implementation | ||
| 3 | |||
| 4 | Copyright (c) 2012-2021 Jean-Philippe Aumasson | ||
| 5 | <jeanphilippe.aumasson@gmail.com> | ||
| 6 | Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to> | ||
| 7 | |||
| 8 | To the extent possible under law, the author(s) have dedicated all copyright | ||
| 9 | and related and neighboring rights to this software to the public domain | ||
| 10 | worldwide. This software is distributed without any warranty. | ||
| 11 | |||
| 12 | You should have received a copy of the CC0 Public Domain Dedication along | ||
| 13 | with | ||
| 14 | this software. If not, see | ||
| 15 | <http://creativecommons.org/publicdomain/zero/1.0/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | // clang-format off | ||
| 19 | #include "siphash.h" | ||
| 20 | |||
| 21 | #include <cassert> | ||
| 22 | #include <cstdint> | ||
| 23 | #include <cstdio> | ||
| 24 | |||
| 25 | /* default: SipHash-2-4 */ | ||
| 26 | #ifndef cROUNDS | ||
| 27 | #define cROUNDS 2 | ||
| 28 | #endif | ||
| 29 | #ifndef dROUNDS | ||
| 30 | #define dROUNDS 4 | ||
| 31 | #endif | ||
| 32 | |||
| 33 | #define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) | ||
| 34 | |||
| 35 | #define U32TO8_LE(p, v) \ | ||
| 36 | (p)[0] = (uint8_t)((v)); \ | ||
| 37 | (p)[1] = (uint8_t)((v) >> 8); \ | ||
| 38 | (p)[2] = (uint8_t)((v) >> 16); \ | ||
| 39 | (p)[3] = (uint8_t)((v) >> 24); | ||
| 40 | |||
| 41 | #define U64TO8_LE(p, v) \ | ||
| 42 | U32TO8_LE((p), (uint32_t)((v))); \ | ||
| 43 | U32TO8_LE((p) + 4, (uint32_t)((v) >> 32)); | ||
| 44 | |||
| 45 | #define U8TO64_LE(p) \ | ||
| 46 | (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \ | ||
| 47 | ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \ | ||
| 48 | ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \ | ||
| 49 | ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56)) | ||
| 50 | |||
| 51 | #define SIPROUND \ | ||
| 52 | do { \ | ||
| 53 | v0 += v1; \ | ||
| 54 | v1 = ROTL(v1, 13); \ | ||
| 55 | v1 ^= v0; \ | ||
| 56 | v0 = ROTL(v0, 32); \ | ||
| 57 | v2 += v3; \ | ||
| 58 | v3 = ROTL(v3, 16); \ | ||
| 59 | v3 ^= v2; \ | ||
| 60 | v0 += v3; \ | ||
| 61 | v3 = ROTL(v3, 21); \ | ||
| 62 | v3 ^= v0; \ | ||
| 63 | v2 += v1; \ | ||
| 64 | v1 = ROTL(v1, 17); \ | ||
| 65 | v1 ^= v2; \ | ||
| 66 | v2 = ROTL(v2, 32); \ | ||
| 67 | } while (0) | ||
| 68 | |||
| 69 | #ifdef DEBUG | ||
| 70 | #define TRACE \ | ||
| 71 | do { \ | ||
| 72 | printf("(%3zu) v0 %016" PRIx64 "\n", inlen, v0); \ | ||
| 73 | printf("(%3zu) v1 %016" PRIx64 "\n", inlen, v1); \ | ||
| 74 | printf("(%3zu) v2 %016" PRIx64 "\n", inlen, v2); \ | ||
| 75 | printf("(%3zu) v3 %016" PRIx64 "\n", inlen, v3); \ | ||
| 76 | } while (0) | ||
| 77 | #else | ||
| 78 | #define TRACE | ||
| 79 | #endif | ||
| 80 | |||
| 81 | int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out, | ||
| 82 | const size_t outlen) { | ||
| 83 | |||
| 84 | 59 | const unsigned char *ni = (const unsigned char *)in; | |
| 85 | 59 | const unsigned char *kk = (const unsigned char *)k; | |
| 86 | |||
| 87 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
59 | assert((outlen == 8) || (outlen == 16)); |
| 88 | 59 | uint64_t v0 = UINT64_C(0x736f6d6570736575); | |
| 89 | 59 | uint64_t v1 = UINT64_C(0x646f72616e646f6d); | |
| 90 | 59 | uint64_t v2 = UINT64_C(0x6c7967656e657261); | |
| 91 | 59 | uint64_t v3 = UINT64_C(0x7465646279746573); | |
| 92 | 59 | uint64_t k0 = U8TO64_LE(kk); | |
| 93 | 59 | uint64_t k1 = U8TO64_LE(kk + 8); | |
| 94 | uint64_t m; | ||
| 95 | int i; | ||
| 96 | 59 | const unsigned char *end = ni + inlen - (inlen % sizeof(uint64_t)); | |
| 97 | 59 | const int left = inlen & 7; | |
| 98 | 59 | uint64_t b = ((uint64_t)inlen) << 56; | |
| 99 | 59 | v3 ^= k1; | |
| 100 | 59 | v2 ^= k0; | |
| 101 | 59 | v1 ^= k1; | |
| 102 | 59 | v0 ^= k0; | |
| 103 | |||
| 104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | if (outlen == 16) |
| 105 | ✗ | v1 ^= 0xee; | |
| 106 | |||
| 107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | for (; ni != end; ni += 8) { |
| 108 | ✗ | m = U8TO64_LE(ni); | |
| 109 | ✗ | v3 ^= m; | |
| 110 | |||
| 111 | TRACE; | ||
| 112 | ✗ | for (i = 0; i < cROUNDS; ++i) | |
| 113 | ✗ | SIPROUND; | |
| 114 | |||
| 115 | ✗ | v0 ^= m; | |
| 116 | } | ||
| 117 | |||
| 118 |
1/9✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 59 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
59 | switch (left) { |
| 119 | ✗ | case 7: | |
| 120 | ✗ | b |= ((uint64_t)ni[6]) << 48; | |
| 121 | /* FALLTHRU */ | ||
| 122 | ✗ | case 6: | |
| 123 | ✗ | b |= ((uint64_t)ni[5]) << 40; | |
| 124 | /* FALLTHRU */ | ||
| 125 | ✗ | case 5: | |
| 126 | ✗ | b |= ((uint64_t)ni[4]) << 32; | |
| 127 | /* FALLTHRU */ | ||
| 128 | ✗ | case 4: | |
| 129 | ✗ | b |= ((uint64_t)ni[3]) << 24; | |
| 130 | /* FALLTHRU */ | ||
| 131 | ✗ | case 3: | |
| 132 | ✗ | b |= ((uint64_t)ni[2]) << 16; | |
| 133 | /* FALLTHRU */ | ||
| 134 | ✗ | case 2: | |
| 135 | ✗ | b |= ((uint64_t)ni[1]) << 8; | |
| 136 | /* FALLTHRU */ | ||
| 137 | 59 | case 1: | |
| 138 | 59 | b |= ((uint64_t)ni[0]); | |
| 139 | 59 | break; | |
| 140 | ✗ | case 0: | |
| 141 | ✗ | break; | |
| 142 | } | ||
| 143 | |||
| 144 | 59 | v3 ^= b; | |
| 145 | |||
| 146 | TRACE; | ||
| 147 |
2/2✓ Branch 0 taken 118 times.
✓ Branch 1 taken 59 times.
|
177 | for (i = 0; i < cROUNDS; ++i) |
| 148 | 118 | SIPROUND; | |
| 149 | |||
| 150 | 59 | v0 ^= b; | |
| 151 | |||
| 152 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | if (outlen == 16) |
| 153 | ✗ | v2 ^= 0xee; | |
| 154 | else | ||
| 155 | 59 | v2 ^= 0xff; | |
| 156 | |||
| 157 | TRACE; | ||
| 158 |
2/2✓ Branch 0 taken 236 times.
✓ Branch 1 taken 59 times.
|
295 | for (i = 0; i < dROUNDS; ++i) |
| 159 | 236 | SIPROUND; | |
| 160 | |||
| 161 | 59 | b = v0 ^ v1 ^ v2 ^ v3; | |
| 162 | 59 | U64TO8_LE(out, b); | |
| 163 | |||
| 164 |
1/2✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
|
59 | if (outlen == 8) |
| 165 | 59 | return 0; | |
| 166 | |||
| 167 | ✗ | v1 ^= 0xdd; | |
| 168 | |||
| 169 | TRACE; | ||
| 170 | ✗ | for (i = 0; i < dROUNDS; ++i) | |
| 171 | ✗ | SIPROUND; | |
| 172 | |||
| 173 | ✗ | b = v0 ^ v1 ^ v2 ^ v3; | |
| 174 | ✗ | U64TO8_LE(out + 8, b); | |
| 175 | |||
| 176 | ✗ | return 0; | |
| 177 | } | ||
| 178 | |||
| 179 | // clang-format on | ||
| 180 |