]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/siphash24.c
basic/extract-word,man: clarify "correction" of invalid escapes
[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 <stdio.h>
21
22 #include "macro.h"
23 #include "siphash24.h"
24 #include "unaligned.h"
25
26 static inline uint64_t rotate_left(uint64_t x, uint8_t b) {
27 assert(b < 64);
28
29 return (x << b) | (x >> (64 - b));
30 }
31
32 static inline void sipround(struct siphash *state) {
33 assert(state);
34
35 state->v0 += state->v1;
36 state->v1 = rotate_left(state->v1, 13);
37 state->v1 ^= state->v0;
38 state->v0 = rotate_left(state->v0, 32);
39 state->v2 += state->v3;
40 state->v3 = rotate_left(state->v3, 16);
41 state->v3 ^= state->v2;
42 state->v0 += state->v3;
43 state->v3 = rotate_left(state->v3, 21);
44 state->v3 ^= state->v0;
45 state->v2 += state->v1;
46 state->v1 = rotate_left(state->v1, 17);
47 state->v1 ^= state->v2;
48 state->v2 = rotate_left(state->v2, 32);
49 }
50
51 void siphash24_init(struct siphash *state, const uint8_t k[16]) {
52 uint64_t k0, k1;
53
54 assert(state);
55 assert(k);
56
57 k0 = unaligned_read_le64(k);
58 k1 = unaligned_read_le64(k + 8);
59
60 *state = (struct siphash) {
61 /* "somepseudorandomlygeneratedbytes" */
62 .v0 = 0x736f6d6570736575ULL ^ k0,
63 .v1 = 0x646f72616e646f6dULL ^ k1,
64 .v2 = 0x6c7967656e657261ULL ^ k0,
65 .v3 = 0x7465646279746573ULL ^ k1,
66 .padding = 0,
67 .inlen = 0,
68 };
69 }
70
71 void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
72
73 const uint8_t *in = _in;
74 const uint8_t *end = in + inlen;
75 size_t left = state->inlen & 7;
76 uint64_t m;
77
78 assert(in);
79 assert(state);
80
81 /* Update total length */
82 state->inlen += inlen;
83
84 /* If padding exists, fill it out */
85 if (left > 0) {
86 for ( ; in < end && left < 8; in ++, left ++)
87 state->padding |= ((uint64_t) *in) << (left * 8);
88
89 if (in == end && left < 8)
90 /* We did not have enough input to fill out the padding completely */
91 return;
92
93 #ifdef DEBUG
94 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
95 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
96 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
97 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
98 printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding);
99 #endif
100
101 state->v3 ^= state->padding;
102 sipround(state);
103 sipround(state);
104 state->v0 ^= state->padding;
105
106 state->padding = 0;
107 }
108
109 end -= (state->inlen % sizeof(uint64_t));
110
111 for ( ; in < end; in += 8) {
112 m = unaligned_read_le64(in);
113 #ifdef DEBUG
114 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
115 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
116 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
117 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
118 printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m);
119 #endif
120 state->v3 ^= m;
121 sipround(state);
122 sipround(state);
123 state->v0 ^= m;
124 }
125
126 left = state->inlen & 7;
127 switch (left) {
128 case 7:
129 state->padding |= ((uint64_t) in[6]) << 48;
130 case 6:
131 state->padding |= ((uint64_t) in[5]) << 40;
132 case 5:
133 state->padding |= ((uint64_t) in[4]) << 32;
134 case 4:
135 state->padding |= ((uint64_t) in[3]) << 24;
136 case 3:
137 state->padding |= ((uint64_t) in[2]) << 16;
138 case 2:
139 state->padding |= ((uint64_t) in[1]) << 8;
140 case 1:
141 state->padding |= ((uint64_t) in[0]);
142 case 0:
143 break;
144 }
145 }
146
147 uint64_t siphash24_finalize(struct siphash *state) {
148 uint64_t b;
149
150 assert(state);
151
152 b = state->padding | (((uint64_t) state->inlen) << 56);
153
154 #ifdef DEBUG
155 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
156 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
157 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
158 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
159 printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
160 #endif
161
162 state->v3 ^= b;
163 sipround(state);
164 sipround(state);
165 state->v0 ^= b;
166
167 #ifdef DEBUG
168 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
169 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
170 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
171 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
172 #endif
173 state->v2 ^= 0xff;
174
175 sipround(state);
176 sipround(state);
177 sipround(state);
178 sipround(state);
179
180 return state->v0 ^ state->v1 ^ state->v2 ^ state->v3;
181 }
182
183 uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) {
184 struct siphash state;
185
186 assert(in);
187 assert(k);
188
189 siphash24_init(&state, k);
190 siphash24_compress(in, inlen, &state);
191
192 return siphash24_finalize(&state);
193 }