]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/siphash24.c
util: make siphash24_compress_boolean() inline
[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
ac9b215d
TJ
20#include <stdio.h>
21
11c3a366 22#include "macro.h"
93cc7779 23#include "siphash24.h"
8dd85afe 24#include "unaligned.h"
17010c23 25
a1e92eee 26static uint64_t rotate_left(uint64_t x, uint8_t b) {
17010c23
TG
27 assert(b < 64);
28
29 return (x << b) | (x >> (64 - b));
30}
9bf3b535 31
a1e92eee 32static void sipround(struct siphash *state) {
17010c23
TG
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}
9bf3b535 50
3042bbeb 51void siphash24_init(struct siphash *state, const uint8_t k[static 16]) {
17010c23
TG
52 uint64_t k0, k1;
53
54 assert(state);
55 assert(k);
56
4de91d7e
LP
57 k0 = unaligned_read_le64(k);
58 k1 = unaligned_read_le64(k + 8);
17010c23 59
6059dab8
LP
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 };
708684ef
TG
69}
70
7c57f504 71void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
6059dab8 72
17010c23
TG
73 const uint8_t *in = _in;
74 const uint8_t *end = in + inlen;
6059dab8
LP
75 size_t left = state->inlen & 7;
76 uint64_t m;
17010c23
TG
77
78 assert(in);
79 assert(state);
708684ef 80
6059dab8 81 /* Update total length */
17010c23 82 state->inlen += inlen;
9bf3b535 83
6059dab8 84 /* If padding exists, fill it out */
17010c23 85 if (left > 0) {
6059dab8
LP
86 for ( ; in < end && left < 8; in ++, left ++)
87 state->padding |= ((uint64_t) *in) << (left * 8);
2c4cc3bd 88
17010c23 89 if (in == end && left < 8)
6059dab8 90 /* We did not have enough input to fill out the padding completely */
17010c23 91 return;
2c4cc3bd 92
d6601495 93#if ENABLE_DEBUG_SIPHASH
17010c23
TG
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);
2c4cc3bd 99#endif
6059dab8 100
17010c23
TG
101 state->v3 ^= state->padding;
102 sipround(state);
103 sipround(state);
104 state->v0 ^= state->padding;
2c4cc3bd 105
17010c23
TG
106 state->padding = 0;
107 }
2c4cc3bd 108
6059dab8 109 end -= (state->inlen % sizeof(uint64_t));
2c4cc3bd 110
6059dab8 111 for ( ; in < end; in += 8) {
8dd85afe 112 m = unaligned_read_le64(in);
d6601495 113#if ENABLE_DEBUG_SIPHASH
17010c23
TG
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);
9bf3b535 119#endif
17010c23
TG
120 state->v3 ^= m;
121 sipround(state);
122 sipround(state);
123 state->v0 ^= m;
124 }
9bf3b535 125
17010c23 126 left = state->inlen & 7;
6059dab8
LP
127 switch (left) {
128 case 7:
129 state->padding |= ((uint64_t) in[6]) << 48;
4831981d 130 _fallthrough_;
6059dab8
LP
131 case 6:
132 state->padding |= ((uint64_t) in[5]) << 40;
4831981d 133 _fallthrough_;
6059dab8
LP
134 case 5:
135 state->padding |= ((uint64_t) in[4]) << 32;
4831981d 136 _fallthrough_;
6059dab8
LP
137 case 4:
138 state->padding |= ((uint64_t) in[3]) << 24;
4831981d 139 _fallthrough_;
6059dab8
LP
140 case 3:
141 state->padding |= ((uint64_t) in[2]) << 16;
4831981d 142 _fallthrough_;
6059dab8
LP
143 case 2:
144 state->padding |= ((uint64_t) in[1]) << 8;
4831981d 145 _fallthrough_;
6059dab8
LP
146 case 1:
147 state->padding |= ((uint64_t) in[0]);
4831981d 148 _fallthrough_;
6059dab8
LP
149 case 0:
150 break;
17010c23 151 }
f2936011
TG
152}
153
933f9cae 154uint64_t siphash24_finalize(struct siphash *state) {
17010c23 155 uint64_t b;
9bf3b535 156
6059dab8
LP
157 assert(state);
158
159 b = state->padding | (((uint64_t) state->inlen) << 56);
160
d6601495 161#if ENABLE_DEBUG_SIPHASH
6059dab8
LP
162 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
163 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
164 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
165 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
17010c23 166 printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
9bf3b535 167#endif
6059dab8 168
17010c23
TG
169 state->v3 ^= b;
170 sipround(state);
171 sipround(state);
172 state->v0 ^= b;
f2936011 173
d6601495 174#if ENABLE_DEBUG_SIPHASH
17010c23
TG
175 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
176 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
177 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
178 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
9bf3b535 179#endif
17010c23 180 state->v2 ^= 0xff;
c7b68d84 181
17010c23
TG
182 sipround(state);
183 sipround(state);
184 sipround(state);
185 sipround(state);
0cb3c286 186
933f9cae 187 return state->v0 ^ state->v1 ^ state->v2 ^ state->v3;
c7b68d84
TG
188}
189
3042bbeb 190uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[static 16]) {
17010c23 191 struct siphash state;
9e77e048 192
6059dab8
LP
193 assert(in);
194 assert(k);
195
17010c23 196 siphash24_init(&state, k);
6059dab8 197 siphash24_compress(in, inlen, &state);
933f9cae
DM
198
199 return siphash24_finalize(&state);
9bf3b535 200}