]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/siphash24.c
Merge pull request #28301 from berrange/cvm-lockdown
[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
99534007 75 const uint8_t *in = ASSERT_PTR(_in);
17010c23 76 const uint8_t *end = in + inlen;
6059dab8
LP
77 size_t left = state->inlen & 7;
78 uint64_t m;
17010c23 79
17010c23 80 assert(state);
708684ef 81
6059dab8 82 /* Update total length */
17010c23 83 state->inlen += inlen;
9bf3b535 84
6059dab8 85 /* If padding exists, fill it out */
17010c23 86 if (left > 0) {
6059dab8
LP
87 for ( ; in < end && left < 8; in ++, left ++)
88 state->padding |= ((uint64_t) *in) << (left * 8);
2c4cc3bd 89
17010c23 90 if (in == end && left < 8)
6059dab8 91 /* We did not have enough input to fill out the padding completely */
17010c23 92 return;
2c4cc3bd 93
d6601495 94#if ENABLE_DEBUG_SIPHASH
17010c23
TG
95 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
96 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
97 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
98 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
99 printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding);
2c4cc3bd 100#endif
6059dab8 101
17010c23
TG
102 state->v3 ^= state->padding;
103 sipround(state);
104 sipround(state);
105 state->v0 ^= state->padding;
2c4cc3bd 106
17010c23
TG
107 state->padding = 0;
108 }
2c4cc3bd 109
6059dab8 110 end -= (state->inlen % sizeof(uint64_t));
2c4cc3bd 111
6059dab8 112 for ( ; in < end; in += 8) {
8dd85afe 113 m = unaligned_read_le64(in);
d6601495 114#if ENABLE_DEBUG_SIPHASH
17010c23
TG
115 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
116 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
117 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
118 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
119 printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m);
9bf3b535 120#endif
17010c23
TG
121 state->v3 ^= m;
122 sipround(state);
123 sipround(state);
124 state->v0 ^= m;
125 }
9bf3b535 126
17010c23 127 left = state->inlen & 7;
6059dab8
LP
128 switch (left) {
129 case 7:
130 state->padding |= ((uint64_t) in[6]) << 48;
4831981d 131 _fallthrough_;
6059dab8
LP
132 case 6:
133 state->padding |= ((uint64_t) in[5]) << 40;
4831981d 134 _fallthrough_;
6059dab8
LP
135 case 5:
136 state->padding |= ((uint64_t) in[4]) << 32;
4831981d 137 _fallthrough_;
6059dab8
LP
138 case 4:
139 state->padding |= ((uint64_t) in[3]) << 24;
4831981d 140 _fallthrough_;
6059dab8
LP
141 case 3:
142 state->padding |= ((uint64_t) in[2]) << 16;
4831981d 143 _fallthrough_;
6059dab8
LP
144 case 2:
145 state->padding |= ((uint64_t) in[1]) << 8;
4831981d 146 _fallthrough_;
6059dab8
LP
147 case 1:
148 state->padding |= ((uint64_t) in[0]);
4831981d 149 _fallthrough_;
6059dab8
LP
150 case 0:
151 break;
17010c23 152 }
f2936011
TG
153}
154
933f9cae 155uint64_t siphash24_finalize(struct siphash *state) {
17010c23 156 uint64_t b;
9bf3b535 157
6059dab8
LP
158 assert(state);
159
160 b = state->padding | (((uint64_t) state->inlen) << 56);
161
d6601495 162#if ENABLE_DEBUG_SIPHASH
6059dab8
LP
163 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
164 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
165 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
166 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
17010c23 167 printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding);
9bf3b535 168#endif
6059dab8 169
17010c23
TG
170 state->v3 ^= b;
171 sipround(state);
172 sipround(state);
173 state->v0 ^= b;
f2936011 174
d6601495 175#if ENABLE_DEBUG_SIPHASH
17010c23
TG
176 printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0);
177 printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1);
178 printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2);
179 printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3);
9bf3b535 180#endif
17010c23 181 state->v2 ^= 0xff;
c7b68d84 182
17010c23
TG
183 sipround(state);
184 sipround(state);
185 sipround(state);
186 sipround(state);
0cb3c286 187
933f9cae 188 return state->v0 ^ state->v1 ^ state->v2 ^ state->v3;
c7b68d84
TG
189}
190
3042bbeb 191uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[static 16]) {
17010c23 192 struct siphash state;
9e77e048 193
6059dab8
LP
194 assert(in);
195 assert(k);
196
17010c23 197 siphash24_init(&state, k);
6059dab8 198 siphash24_compress(in, inlen, &state);
933f9cae
DM
199
200 return siphash24_finalize(&state);
9bf3b535 201}