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