]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/siphash24.c
missing include added for build with -DDEBUG (#3424)
[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
TG
25
26static inline uint64_t rotate_left(uint64_t x, uint8_t b) {
27 assert(b < 64);
28
29 return (x << b) | (x >> (64 - b));
30}
9bf3b535 31
17010c23
TG
32static 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}
9bf3b535 50
0cb3c286 51void siphash24_init(struct siphash *state, const uint8_t k[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
TG
92
93#ifdef DEBUG
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);
9bf3b535 113#ifdef DEBUG
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;
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;
17010c23 144 }
f2936011
TG
145}
146
933f9cae 147uint64_t siphash24_finalize(struct siphash *state) {
17010c23 148 uint64_t b;
9bf3b535 149
6059dab8
LP
150 assert(state);
151
152 b = state->padding | (((uint64_t) state->inlen) << 56);
153
9bf3b535 154#ifdef DEBUG
6059dab8
LP
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);
17010c23 159 printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
9bf3b535 160#endif
6059dab8 161
17010c23
TG
162 state->v3 ^= b;
163 sipround(state);
164 sipround(state);
165 state->v0 ^= b;
f2936011 166
9bf3b535 167#ifdef DEBUG
17010c23
TG
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);
9bf3b535 172#endif
17010c23 173 state->v2 ^= 0xff;
c7b68d84 174
17010c23
TG
175 sipround(state);
176 sipround(state);
177 sipround(state);
178 sipround(state);
0cb3c286 179
933f9cae 180 return state->v0 ^ state->v1 ^ state->v2 ^ state->v3;
c7b68d84
TG
181}
182
6059dab8 183uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) {
17010c23 184 struct siphash state;
9e77e048 185
6059dab8
LP
186 assert(in);
187 assert(k);
188
17010c23 189 siphash24_init(&state, k);
6059dab8 190 siphash24_compress(in, inlen, &state);
933f9cae
DM
191
192 return siphash24_finalize(&state);
9bf3b535 193}