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