1 |
/* spritz.c */ |
2 |
/* (C)2015 Marc Alexander Lehmann, all rights reserved */ |
3 |
|
4 |
#include "spritz.h" |
5 |
|
6 |
#include <assert.h> |
7 |
|
8 |
void |
9 |
spritz_init (spritz_state *s) |
10 |
{ |
11 |
s->a = |
12 |
s->i = |
13 |
s->j = |
14 |
s->k = |
15 |
s->z = 0; |
16 |
s->w = 1; |
17 |
|
18 |
uint_fast8_t v = spritz_N - 1; |
19 |
do |
20 |
s->S[v] = v; |
21 |
while (v--); |
22 |
} |
23 |
|
24 |
void |
25 |
spritz_update (spritz_state *s) |
26 |
{ |
27 |
s->i += s->w; |
28 |
s->j = s->k + s->S[s->j + s->S[s->i]]; |
29 |
s->k = s->k + s->i + s->S[s->j]; |
30 |
SPRITZ_SWAP (s->S[s->i], s->S[s->j]); |
31 |
} |
32 |
|
33 |
void |
34 |
spritz_whip (spritz_state *s, uint_fast16_t r) |
35 |
{ |
36 |
while (r--) |
37 |
spritz_update (s); |
38 |
|
39 |
s->w += 2; |
40 |
} |
41 |
|
42 |
#define SPRITZ_SWAP(a,b) { uint8_t ss_c = (a); (a) = (b); (b) = ss_c; } |
43 |
|
44 |
void |
45 |
spritz_crush (spritz_state *s) |
46 |
{ |
47 |
uint_fast16_t v; |
48 |
|
49 |
for (v = 0; v < (spritz_N >> 1); ++v) |
50 |
if (s->S[v] > s->S[spritz_N - 1 - v]) |
51 |
SPRITZ_SWAP (s->S[v], s->S[spritz_N - 1 - v]); |
52 |
} |
53 |
|
54 |
void |
55 |
spritz_shuffle (spritz_state *s) |
56 |
{ |
57 |
spritz_whip (s, 2 * spritz_N); spritz_crush (s); |
58 |
spritz_whip (s, 2 * spritz_N); spritz_crush (s); |
59 |
spritz_whip (s, 2 * spritz_N); |
60 |
|
61 |
s->a = 0; |
62 |
} |
63 |
|
64 |
static void |
65 |
spritz_shuffle_absorb (spritz_state *s) |
66 |
{ |
67 |
if (s->a == (spritz_N >> 1)) |
68 |
spritz_shuffle (s); |
69 |
} |
70 |
|
71 |
void |
72 |
spritz_absorb_nibble (spritz_state *s, uint8_t x) |
73 |
{ |
74 |
spritz_shuffle_absorb (s); |
75 |
|
76 |
SPRITZ_SWAP (s->S[s->a], s->S[(spritz_N >> 1) + x]); |
77 |
++s->a; |
78 |
} |
79 |
|
80 |
static void |
81 |
spritz_absorb_byte (spritz_state *s, uint8_t b) |
82 |
{ |
83 |
spritz_absorb_nibble (s, b & 15); |
84 |
spritz_absorb_nibble (s, b >> 4); |
85 |
} |
86 |
|
87 |
void |
88 |
spritz_absorb (spritz_state *s, const void *I, size_t I_len) |
89 |
{ |
90 |
uint8_t *i = (uint8_t *)I; |
91 |
|
92 |
while (I_len--) |
93 |
spritz_absorb_byte (s, *i++); |
94 |
} |
95 |
|
96 |
void |
97 |
spritz_absorb_stop (spritz_state *s) |
98 |
{ |
99 |
spritz_shuffle_absorb (s); |
100 |
|
101 |
++s->a; |
102 |
} |
103 |
|
104 |
// commonly used helper function |
105 |
void |
106 |
spritz_absorb_and_stop (spritz_state *s, const void *I, size_t I_len) |
107 |
{ |
108 |
spritz_absorb (s, I, I_len); |
109 |
spritz_absorb_stop (s); |
110 |
} |
111 |
|
112 |
static void |
113 |
spritz_shuffle_squeeze (spritz_state *s) |
114 |
{ |
115 |
if (s->a) |
116 |
spritz_shuffle (s); |
117 |
} |
118 |
|
119 |
uint8_t |
120 |
spritz_output (spritz_state *s) |
121 |
{ |
122 |
return s->S[s->j + s->S[s->i + s->S[s->z + s->k]]]; |
123 |
} |
124 |
|
125 |
// slightly faster internal helper, drip without squeeze preparation |
126 |
static uint8_t |
127 |
spritz_drip_nosqueeze (spritz_state *s) |
128 |
{ |
129 |
spritz_update (s); |
130 |
return spritz_output (s); |
131 |
} |
132 |
|
133 |
void |
134 |
spritz_squeeze (spritz_state *s, void *P, size_t P_len) |
135 |
{ |
136 |
spritz_shuffle_squeeze (s); |
137 |
|
138 |
uint8_t *p = (uint8_t *)P; |
139 |
|
140 |
while (P_len--) |
141 |
*p++ = spritz_drip_nosqueeze (s); |
142 |
} |
143 |
|
144 |
uint8_t |
145 |
spritz_drip (spritz_state *s) |
146 |
{ |
147 |
spritz_shuffle_squeeze (s); |
148 |
|
149 |
return spritz_drip_nosqueeze (s); |
150 |
} |
151 |
|
152 |
void |
153 |
spritz_xor_init (spritz_state *s, const void *K, size_t K_len, const void *IV, size_t IV_len) |
154 |
{ |
155 |
spritz_init (s); |
156 |
|
157 |
spritz_absorb (s, K, K_len); |
158 |
|
159 |
if (IV) |
160 |
{ |
161 |
spritz_absorb_stop (s); |
162 |
spritz_absorb (s, IV, IV_len); |
163 |
} |
164 |
|
165 |
spritz_shuffle_squeeze (s); |
166 |
} |
167 |
|
168 |
void |
169 |
spritz_xor_crypt (spritz_state *s, const void *I, void *O, size_t len) |
170 |
{ |
171 |
const uint8_t *i = (const uint8_t *)I; |
172 |
uint8_t *o = ( uint8_t *)O; |
173 |
|
174 |
while (len--) |
175 |
*o++ = *i++ ^ spritz_drip_nosqueeze (s); |
176 |
} |
177 |
|
178 |
void |
179 |
spritz_hash_finish (spritz_state *s, void *H, size_t H_len) |
180 |
{ |
181 |
spritz_absorb_stop (s); |
182 |
assert (H_len <= 0xff); |
183 |
spritz_absorb_byte (s, H_len); |
184 |
|
185 |
spritz_squeeze (s, H, H_len); |
186 |
} |
187 |
|
188 |
void |
189 |
spritz_mac_init (spritz_state *s, const void *K, size_t K_len) |
190 |
{ |
191 |
spritz_init (s); |
192 |
spritz_absorb_and_stop (s, K, K_len); |
193 |
} |
194 |
|
195 |
void |
196 |
spritz_aead_init (spritz_state *s, const void *K, size_t K_len) |
197 |
{ |
198 |
spritz_mac_init (s, K, K_len); |
199 |
} |
200 |
|
201 |
void |
202 |
spritz_aead_crypt (spritz_state *s, const void *I, void *O, size_t len) |
203 |
{ |
204 |
const uint8_t *i = (const uint8_t *)I; |
205 |
uint8_t *o = ( uint8_t *)O; |
206 |
|
207 |
uint8_t x[spritz_N >> 2]; |
208 |
|
209 |
while (len) |
210 |
{ |
211 |
uint_fast8_t j; |
212 |
uint8_t l = len > sizeof (x) ? sizeof (x) : len; |
213 |
len -= l; |
214 |
|
215 |
spritz_squeeze (s, x, l); |
216 |
|
217 |
for (j = 0; j < l; ++j) |
218 |
spritz_absorb_byte (s, *o++ = *i++ ^ x[j]); |
219 |
} |
220 |
} |
221 |
|
222 |
void |
223 |
spritz_prng_init (spritz_state *s, const void *S, size_t S_len) |
224 |
{ |
225 |
spritz_init (s); |
226 |
spritz_absorb (s, S, S_len); |
227 |
} |
228 |
|