]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/siphash24.c
path-util: rework find_binary(), fsck_exists() and mkfs_exists()
[thirdparty/systemd.git] / src / basic / siphash24.c
1 /*
2 SipHash reference C implementation
3
4 Written in 2012 by
5 Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
6 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 with
13 this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
14
15 (Minimal changes made by Lennart Poettering, to make clean for inclusion in systemd)
16 (Refactored by Tom Gundersen to split up in several functions and follow systemd
17 coding style)
18 */
19
20 #include "sparse-endian.h"
21
22 #include "siphash24.h"
23 #include "util.h"
24
25 static inline uint64_t rotate_left(uint64_t x, uint8_t b) {
26 assert(b < 64);
27
28 return (x << b) | (x >> (64 - b));
29 }
30
31 static inline void sipround(struct siphash *state) {
32 assert(state);
33
34 state->v0 += state->v1;
35 state->v1 = rotate_left(state->v1, 13);
36 state->v1 ^= state->v0;
37 state->v0 = rotate_left(state->v0, 32);
38 state->v2 += state->v3;
39 state->v3 = rotate_left(state->v3, 16);
40 state->v3 ^= state->v2;
41 state->v0 += state->v3;
42 state->v3 = rotate_left(state->v3, 21);
43 state->v3 ^= state->v0;
44 state->v2 += state->v1;
45 state->v1 = rotate_left(state->v1, 17);
46 state->v1 ^= state->v2;
47 state->v2 = rotate_left(state->v2, 32);
48 }
49
50 void siphash24_init(struct siphash *state, const uint8_t k[16]) {
51 uint64_t k0, k1;
52
53 assert(state);
54 assert(k);
55
56 k0 = le64toh(*(le64_t*) k);
57 k1 = le64toh(*(le64_t*) (k + 8));
58
59 /* "somepseudorandomlygeneratedbytes" */
60 state->v0 = 0x736f6d6570736575ULL ^ k0;
61 state->v1 = 0x646f72616e646f6dULL ^ k1;
62 state->v2 = 0x6c7967656e657261ULL ^ k0;
63 state->v3 = 0x7465646279746573ULL ^ k1;
64 state->padding = 0;
65 state->inlen = 0;
66 }
67
68 void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
69 uint64_t m;
70 const uint8_t *in = _in;
71 const uint8_t *end = in + inlen;
72 unsigned left = state->inlen & 7;
73
74 assert(in);
75 assert(state);
76
77 /* update total length */
78 state->inlen += inlen;
79
80 /* if padding exists, fill it out */
81 if (left > 0) {
82 for ( ; in < end && left < 8; in ++, left ++ )
83 state->padding |= ( ( uint64_t )*in ) << (left * 8);
84
85 if (in == end && left < 8)
86 /* we did not have enough input to fill out the padding completely */
87 return;
88
89 #ifdef DEBUG
90 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
91 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
92 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
93 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
94 printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding);
95 #endif
96 state->v3 ^= state->padding;
97 sipround(state);
98 sipround(state);
99 state->v0 ^= state->padding;
100
101 state->padding = 0;
102 }
103
104 end -= ( state->inlen % sizeof (uint64_t) );
105
106 for ( ; in < end; in += 8 ) {
107 m = le64toh(*(le64_t*) in);
108 #ifdef DEBUG
109 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
110 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
111 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
112 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
113 printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m);
114 #endif
115 state->v3 ^= m;
116 sipround(state);
117 sipround(state);
118 state->v0 ^= m;
119 }
120
121 left = state->inlen & 7;
122
123 switch(left)
124 {
125 case 7: state->padding |= ((uint64_t) in[6]) << 48;
126
127 case 6: state->padding |= ((uint64_t) in[5]) << 40;
128
129 case 5: state->padding |= ((uint64_t) in[4]) << 32;
130
131 case 4: state->padding |= ((uint64_t) in[3]) << 24;
132
133 case 3: state->padding |= ((uint64_t) in[2]) << 16;
134
135 case 2: state->padding |= ((uint64_t) in[1]) << 8;
136
137 case 1: state->padding |= ((uint64_t) in[0]); break;
138
139 case 0: break;
140 }
141 }
142
143 void siphash24_finalize(uint8_t out[8], struct siphash *state) {
144 uint64_t b;
145
146 b = state->padding | (( ( uint64_t )state->inlen ) << 56);
147 #ifdef DEBUG
148 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t)state->v0);
149 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t)state->v1);
150 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t)state->v2);
151 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t)state->v3);
152 printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
153 #endif
154 state->v3 ^= b;
155 sipround(state);
156 sipround(state);
157 state->v0 ^= b;
158
159 #ifdef DEBUG
160 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
161 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
162 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
163 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
164 #endif
165 state->v2 ^= 0xff;
166
167 sipround(state);
168 sipround(state);
169 sipround(state);
170 sipround(state);
171
172 *(le64_t*)out = htole64(state->v0 ^ state->v1 ^ state->v2 ^ state->v3);
173 }
174
175 /* SipHash-2-4 */
176 void siphash24(uint8_t out[8], const void *_in, size_t inlen, const uint8_t k[16]) {
177 struct siphash state;
178
179 siphash24_init(&state, k);
180 siphash24_compress(_in, inlen, &state);
181 siphash24_finalize(out, &state);
182 }