]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/siphash24.c
headers: add spdx tags to imported files with a known license
[thirdparty/systemd.git] / src / basic / siphash24.c
CommitLineData
448e7440
ZJS
1/* SPDX-License-Identifier: CC0-1.0 */
2
9bf3b535
LP
3/*
4 SipHash reference C implementation
5
6 Written in 2012 by
7 Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
8 Daniel J. Bernstein <djb@cr.yp.to>
9
10 To the extent possible under law, the author(s) have dedicated all copyright
11 and related and neighboring rights to this software to the public domain
12 worldwide. This software is distributed without any warranty.
13
14 You should have received a copy of the CC0 Public Domain Dedication along with
448e7440 15 this software. If not, see <https://creativecommons.org/publicdomain/zero/1.0/>.
9bf3b535
LP
16
17 (Minimal changes made by Lennart Poettering, to make clean for inclusion in systemd)
17010c23
TG
18 (Refactored by Tom Gundersen to split up in several functions and follow systemd
19 coding style)
9bf3b535 20*/
17010c23 21
ac9b215d
TJ
22#include <stdio.h>
23
11c3a366 24#include "macro.h"
93cc7779 25#include "siphash24.h"
8dd85afe 26#include "unaligned.h"
17010c23 27
a1e92eee 28static uint64_t rotate_left(uint64_t x, uint8_t b) {
17010c23
TG
29 assert(b < 64);
30
31 return (x << b) | (x >> (64 - b));
32}
9bf3b535 33
a1e92eee 34static void sipround(struct siphash *state) {
17010c23
TG
35 assert(state);
36
37 state->v0 += state->v1;
38 state->v1 = rotate_left(state->v1, 13);
39 state->v1 ^= state->v0;
40 state->v0 = rotate_left(state->v0, 32);
41 state->v2 += state->v3;
42 state->v3 = rotate_left(state->v3, 16);
43 state->v3 ^= state->v2;
44 state->v0 += state->v3;
45 state->v3 = rotate_left(state->v3, 21);
46 state->v3 ^= state->v0;
47 state->v2 += state->v1;
48 state->v1 = rotate_left(state->v1, 17);
49 state->v1 ^= state->v2;
50 state->v2 = rotate_left(state->v2, 32);
51}
9bf3b535 52
3042bbeb 53void siphash24_init(struct siphash *state, const uint8_t k[static 16]) {
17010c23
TG
54 uint64_t k0, k1;
55
56 assert(state);
57 assert(k);
58
4de91d7e
LP
59 k0 = unaligned_read_le64(k);
60 k1 = unaligned_read_le64(k + 8);
17010c23 61
6059dab8
LP
62 *state = (struct siphash) {
63 /* "somepseudorandomlygeneratedbytes" */
64 .v0 = 0x736f6d6570736575ULL ^ k0,
65 .v1 = 0x646f72616e646f6dULL ^ k1,
66 .v2 = 0x6c7967656e657261ULL ^ k0,
67 .v3 = 0x7465646279746573ULL ^ k1,
68 .padding = 0,
69 .inlen = 0,
70 };
708684ef
TG
71}
72
7c57f504 73void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) {
6059dab8 74
17010c23
TG
75 const uint8_t *in = _in;
76 const uint8_t *end = in + inlen;
6059dab8
LP
77 size_t left = state->inlen & 7;
78 uint64_t m;
17010c23
TG
79
80 assert(in);
81 assert(state);
708684ef 82
6059dab8 83 /* Update total length */
17010c23 84 state->inlen += inlen;
9bf3b535 85
6059dab8 86 /* If padding exists, fill it out */
17010c23 87 if (left > 0) {
6059dab8
LP
88 for ( ; in < end && left < 8; in ++, left ++)
89 state->padding |= ((uint64_t) *in) << (left * 8);
2c4cc3bd 90
17010c23 91 if (in == end && left < 8)
6059dab8 92 /* We did not have enough input to fill out the padding completely */
17010c23 93 return;
2c4cc3bd 94
d6601495 95#if ENABLE_DEBUG_SIPHASH
17010c23
TG
96 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
97 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
98 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
99 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
100 printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding);
2c4cc3bd 101#endif
6059dab8 102
17010c23
TG
103 state->v3 ^= state->padding;
104 sipround(state);
105 sipround(state);
106 state->v0 ^= state->padding;
2c4cc3bd 107
17010c23
TG
108 state->padding = 0;
109 }
2c4cc3bd 110
6059dab8 111 end -= (state->inlen % sizeof(uint64_t));
2c4cc3bd 112
6059dab8 113 for ( ; in < end; in += 8) {
8dd85afe 114 m = unaligned_read_le64(in);
d6601495 115#if ENABLE_DEBUG_SIPHASH
17010c23
TG
116 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
117 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
118 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
119 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
120 printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m);
9bf3b535 121#endif
17010c23
TG
122 state->v3 ^= m;
123 sipround(state);
124 sipround(state);
125 state->v0 ^= m;
126 }
9bf3b535 127
17010c23 128 left = state->inlen & 7;
6059dab8
LP
129 switch (left) {
130 case 7:
131 state->padding |= ((uint64_t) in[6]) << 48;
4831981d 132 _fallthrough_;
6059dab8
LP
133 case 6:
134 state->padding |= ((uint64_t) in[5]) << 40;
4831981d 135 _fallthrough_;
6059dab8
LP
136 case 5:
137 state->padding |= ((uint64_t) in[4]) << 32;
4831981d 138 _fallthrough_;
6059dab8
LP
139 case 4:
140 state->padding |= ((uint64_t) in[3]) << 24;
4831981d 141 _fallthrough_;
6059dab8
LP
142 case 3:
143 state->padding |= ((uint64_t) in[2]) << 16;
4831981d 144 _fallthrough_;
6059dab8
LP
145 case 2:
146 state->padding |= ((uint64_t) in[1]) << 8;
4831981d 147 _fallthrough_;
6059dab8
LP
148 case 1:
149 state->padding |= ((uint64_t) in[0]);
4831981d 150 _fallthrough_;
6059dab8
LP
151 case 0:
152 break;
17010c23 153 }
f2936011
TG
154}
155
933f9cae 156uint64_t siphash24_finalize(struct siphash *state) {
17010c23 157 uint64_t b;
9bf3b535 158
6059dab8
LP
159 assert(state);
160
161 b = state->padding | (((uint64_t) state->inlen) << 56);
162
d6601495 163#if ENABLE_DEBUG_SIPHASH
6059dab8
LP
164 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
165 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
166 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
167 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
17010c23 168 printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
9bf3b535 169#endif
6059dab8 170
17010c23
TG
171 state->v3 ^= b;
172 sipround(state);
173 sipround(state);
174 state->v0 ^= b;
f2936011 175
d6601495 176#if ENABLE_DEBUG_SIPHASH
17010c23
TG
177 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
178 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
179 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
180 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
9bf3b535 181#endif
17010c23 182 state->v2 ^= 0xff;
c7b68d84 183
17010c23
TG
184 sipround(state);
185 sipround(state);
186 sipround(state);
187 sipround(state);
0cb3c286 188
933f9cae 189 return state->v0 ^ state->v1 ^ state->v2 ^ state->v3;
c7b68d84
TG
190}
191
3042bbeb 192uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[static 16]) {
17010c23 193 struct siphash state;
9e77e048 194
6059dab8
LP
195 assert(in);
196 assert(k);
197
17010c23 198 siphash24_init(&state, k);
6059dab8 199 siphash24_compress(in, inlen, &state);
933f9cae
DM
200
201 return siphash24_finalize(&state);
9bf3b535 202}