chiark / gitweb /
Fix service file to match installed elogind binary location
[elogind.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 #if 1 /// let's add a diagnostic push to silence -Wimplicit-fallthrough to elogind
72 #  ifdef __GNUC__
73 #    pragma GCC diagnostic push
74 #    pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
75 #  endif // __GNUC__
76 #endif // 1
77 void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
78
79         const uint8_t *in = _in;
80         const uint8_t *end = in + inlen;
81         size_t left = state->inlen & 7;
82         uint64_t m;
83
84         assert(in);
85         assert(state);
86
87         /* Update total length */
88         state->inlen += inlen;
89
90         /* If padding exists, fill it out */
91         if (left > 0) {
92                 for ( ; in < end && left < 8; in ++, left ++)
93                         state->padding |= ((uint64_t) *in) << (left * 8);
94
95                 if (in == end && left < 8)
96                         /* We did not have enough input to fill out the padding completely */
97                         return;
98
99 #ifdef DEBUG
100                 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
101                 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
102                 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
103                 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
104                 printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding);
105 #endif
106
107                 state->v3 ^= state->padding;
108                 sipround(state);
109                 sipround(state);
110                 state->v0 ^= state->padding;
111
112                 state->padding = 0;
113         }
114
115         end -= (state->inlen % sizeof(uint64_t));
116
117         for ( ; in < end; in += 8) {
118                 m = unaligned_read_le64(in);
119 #ifdef DEBUG
120                 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
121                 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
122                 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
123                 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
124                 printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m);
125 #endif
126                 state->v3 ^= m;
127                 sipround(state);
128                 sipround(state);
129                 state->v0 ^= m;
130         }
131
132         left = state->inlen & 7;
133         switch (left) {
134                 case 7:
135                         state->padding |= ((uint64_t) in[6]) << 48;
136                         /* fall through */
137                 case 6:
138                         state->padding |= ((uint64_t) in[5]) << 40;
139                         /* fall through */
140                 case 5:
141                         state->padding |= ((uint64_t) in[4]) << 32;
142                         /* fall through */
143                 case 4:
144                         state->padding |= ((uint64_t) in[3]) << 24;
145                         /* fall through */
146                 case 3:
147                         state->padding |= ((uint64_t) in[2]) << 16;
148                         /* fall through */
149                 case 2:
150                         state->padding |= ((uint64_t) in[1]) <<  8;
151                         /* fall through */
152                 case 1:
153                         state->padding |= ((uint64_t) in[0]);
154                         /* fall through */
155                 case 0:
156                         break;
157         }
158 }
159 #if 1 /// end diagnostic push in elogind
160 #  ifdef __GNUC__
161 #    pragma GCC diagnostic pop
162 #  endif // __GNUC__
163 #endif // 1
164
165 uint64_t siphash24_finalize(struct siphash *state) {
166         uint64_t b;
167
168         assert(state);
169
170         b = state->padding | (((uint64_t) state->inlen) << 56);
171
172 #ifdef DEBUG
173         printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
174         printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
175         printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
176         printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
177         printf("(%3zu) padding   %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
178 #endif
179
180         state->v3 ^= b;
181         sipround(state);
182         sipround(state);
183         state->v0 ^= b;
184
185 #ifdef DEBUG
186         printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
187         printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
188         printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
189         printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
190 #endif
191         state->v2 ^= 0xff;
192
193         sipround(state);
194         sipround(state);
195         sipround(state);
196         sipround(state);
197
198         return state->v0 ^ state->v1 ^ state->v2  ^ state->v3;
199 }
200
201 uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) {
202         struct siphash state;
203
204         assert(in);
205         assert(k);
206
207         siphash24_init(&state, k);
208         siphash24_compress(in, inlen, &state);
209
210         return siphash24_finalize(&state);
211 }