/src/libzip/lib/siphash.c
Line | Count | Source |
1 | | /* |
2 | | SipHash reference C implementation |
3 | | |
4 | | Copyright (c) 2012-2022 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 | | #include "siphash.h" |
19 | | |
20 | | #include <string.h> |
21 | | |
22 | | /* default: SipHash-2-4 */ |
23 | | #ifndef cROUNDS |
24 | 233k | #define cROUNDS 2 |
25 | | #endif |
26 | | #ifndef dROUNDS |
27 | 177k | #define dROUNDS 4 |
28 | | #endif |
29 | | |
30 | 1.78M | #define ROTL(x, b) (zip_uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) |
31 | | |
32 | | #define U32TO8_LE(p, v) \ |
33 | 71.0k | (p)[0] = (zip_uint8_t)((v)); \ |
34 | 71.0k | (p)[1] = (zip_uint8_t)((v) >> 8); \ |
35 | 71.0k | (p)[2] = (zip_uint8_t)((v) >> 16); \ |
36 | 71.0k | (p)[3] = (zip_uint8_t)((v) >> 24); |
37 | | |
38 | | #define U64TO8_LE(p, v) \ |
39 | 35.5k | U32TO8_LE((p), (zip_uint32_t)((v))); \ |
40 | 35.5k | U32TO8_LE((p) + 4, (zip_uint32_t)((v) >> 32)); |
41 | | |
42 | 113k | #define U8TO64_LE(p) (((zip_uint64_t)((p)[0])) | ((zip_uint64_t)((p)[1]) << 8) | ((zip_uint64_t)((p)[2]) << 16) | ((zip_uint64_t)((p)[3]) << 24) | ((zip_uint64_t)((p)[4]) << 32) | ((zip_uint64_t)((p)[5]) << 40) | ((zip_uint64_t)((p)[6]) << 48) | ((zip_uint64_t)((p)[7]) << 56)) |
43 | | |
44 | | #define SIPROUND \ |
45 | 297k | do { \ |
46 | 297k | v0 += v1; \ |
47 | 297k | v1 = ROTL(v1, 13); \ |
48 | 297k | v1 ^= v0; \ |
49 | 297k | v0 = ROTL(v0, 32); \ |
50 | 297k | v2 += v3; \ |
51 | 297k | v3 = ROTL(v3, 16); \ |
52 | 297k | v3 ^= v2; \ |
53 | 297k | v0 += v3; \ |
54 | 297k | v3 = ROTL(v3, 21); \ |
55 | 297k | v3 ^= v0; \ |
56 | 297k | v2 += v1; \ |
57 | 297k | v1 = ROTL(v1, 17); \ |
58 | 297k | v1 ^= v2; \ |
59 | 297k | v2 = ROTL(v2, 32); \ |
60 | 297k | } while (0) |
61 | | |
62 | | /* |
63 | | Computes a SipHash value |
64 | | */ |
65 | 35.5k | zip_uint64_t siphash(const zip_uint8_t *data, const zip_uint8_t *key) { |
66 | 35.5k | const zip_uint8_t *ni = data; |
67 | 35.5k | const zip_uint8_t *kk = key; |
68 | 35.5k | size_t inlen = strlen((const char *)data); |
69 | 35.5k | zip_uint64_t out; |
70 | | |
71 | 35.5k | zip_uint64_t v0 = UINT64_C(0x736f6d6570736575); |
72 | 35.5k | zip_uint64_t v1 = UINT64_C(0x646f72616e646f6d); |
73 | 35.5k | zip_uint64_t v2 = UINT64_C(0x6c7967656e657261); |
74 | 35.5k | zip_uint64_t v3 = UINT64_C(0x7465646279746573); |
75 | 35.5k | zip_uint64_t k0 = U8TO64_LE(kk); |
76 | 35.5k | zip_uint64_t k1 = U8TO64_LE(kk + 8); |
77 | 35.5k | zip_uint64_t m; |
78 | 35.5k | int i; |
79 | 35.5k | const unsigned char *end = ni + inlen - (inlen % sizeof(zip_uint64_t)); |
80 | 35.5k | const int left = inlen & 7; |
81 | 35.5k | zip_uint64_t b = ((zip_uint64_t)inlen) << 56; |
82 | 35.5k | v3 ^= k1; |
83 | 35.5k | v2 ^= k0; |
84 | 35.5k | v1 ^= k1; |
85 | 35.5k | v0 ^= k0; |
86 | | |
87 | 77.9k | for (; ni != end; ni += 8) { |
88 | 42.4k | m = U8TO64_LE(ni); |
89 | 42.4k | v3 ^= m; |
90 | | |
91 | 127k | for (i = 0; i < cROUNDS; ++i) { |
92 | 84.8k | SIPROUND; |
93 | 84.8k | } |
94 | | |
95 | 42.4k | v0 ^= m; |
96 | 42.4k | } |
97 | | |
98 | 35.5k | switch (left) { |
99 | 1.67k | case 7: |
100 | 1.67k | b |= ((zip_uint64_t)ni[6]) << 48; |
101 | | /* FALLTHRU */ |
102 | 2.45k | case 6: |
103 | 2.45k | b |= ((zip_uint64_t)ni[5]) << 40; |
104 | | /* FALLTHRU */ |
105 | 5.76k | case 5: |
106 | 5.76k | b |= ((zip_uint64_t)ni[4]) << 32; |
107 | | /* FALLTHRU */ |
108 | 6.31k | case 4: |
109 | 6.31k | b |= ((zip_uint64_t)ni[3]) << 24; |
110 | | /* FALLTHRU */ |
111 | 6.92k | case 3: |
112 | 6.92k | b |= ((zip_uint64_t)ni[2]) << 16; |
113 | | /* FALLTHRU */ |
114 | 7.85k | case 2: |
115 | 7.85k | b |= ((zip_uint64_t)ni[1]) << 8; |
116 | | /* FALLTHRU */ |
117 | 8.69k | case 1: |
118 | 8.69k | b |= ((zip_uint64_t)ni[0]); |
119 | 8.69k | break; |
120 | 26.8k | case 0: |
121 | 26.8k | break; |
122 | 35.5k | } |
123 | | |
124 | 35.5k | v3 ^= b; |
125 | | |
126 | 106k | for (i = 0; i < cROUNDS; ++i) { |
127 | 71.0k | SIPROUND; |
128 | 71.0k | } |
129 | | |
130 | 35.5k | v0 ^= b; |
131 | | |
132 | 35.5k | v2 ^= 0xff; |
133 | | |
134 | 177k | for (i = 0; i < dROUNDS; ++i) { |
135 | 142k | SIPROUND; |
136 | 142k | } |
137 | | |
138 | 35.5k | b = v0 ^ v1 ^ v2 ^ v3; |
139 | 35.5k | U64TO8_LE((zip_uint8_t *)&out, b); |
140 | | |
141 | 35.5k | return out; |
142 | 35.5k | } |