ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/spritz/spritz.c
Revision: 1.7
Committed: Sat Jan 10 13:02:26 2015 UTC (9 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-1_02, rel-1_0, rel-1_01, HEAD
Changes since 1.6: +3 -3 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /* spritz.c, spritz C implementation
2 *
3 * Copyright (c) 2015 Marc Alexander Lehmann <libev@schmorp.de>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without modifica-
7 * tion, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
18 * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
20 * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
24 * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
25 * OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * Alternatively, the contents of this file may be used under the terms of
28 * the GNU General Public License ("GPL") version 2 or any later version,
29 * in which case the provisions of the GPL are applicable instead of
30 * the above. If you wish to allow the use of your version of this file
31 * only under the terms of the GPL and not to allow others to use your
32 * version of this file under the BSD license, indicate your decision
33 * by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL. If you do not delete the
35 * provisions above, a recipient may use your version of this file under
36 * either the BSD or the GPL.
37 */
38
39 #include "spritz.h"
40
41 #include <assert.h>
42
43 /*****************************************************************************/
44
45 #define SPRITZ_SWAP(a,b) { uint8_t ss_c = (a); (a) = (b); (b) = ss_c; }
46
47 void
48 spritz_init (spritz_state *s)
49 {
50 s->a =
51 s->i =
52 s->j =
53 s->k =
54 s->z = 0;
55 s->w = 1;
56
57 uint_fast8_t v = spritz_N - 1;
58 do
59 s->S[v] = v;
60 while (v--);
61 }
62
63 void
64 spritz_update (spritz_state *s)
65 {
66 s->i = s->i + s->w;
67 s->j = s->k + s->S[(uint8_t)(s->j + s->S[s->i])];
68 s->k = s->k + s->i + s->S[s->j];
69 SPRITZ_SWAP (s->S[s->i], s->S[s->j]);
70 }
71
72 void
73 spritz_whip (spritz_state *s, uint_fast16_t r)
74 {
75 while (r--)
76 spritz_update (s);
77
78 s->w += 2;
79 }
80
81 void
82 spritz_crush (spritz_state *s)
83 {
84 uint_fast16_t v;
85
86 for (v = 0; v < (spritz_N >> 1); ++v)
87 if (s->S[v] > s->S[spritz_N - 1 - v])
88 SPRITZ_SWAP (s->S[v], s->S[spritz_N - 1 - v]);
89 }
90
91 void
92 spritz_shuffle (spritz_state *s)
93 {
94 spritz_whip (s, 2 * spritz_N); spritz_crush (s);
95 spritz_whip (s, 2 * spritz_N); spritz_crush (s);
96 spritz_whip (s, 2 * spritz_N);
97
98 s->a = 0;
99 }
100
101 static void
102 spritz_shuffle_absorb (spritz_state *s)
103 {
104 if (s->a == (spritz_N >> 1))
105 spritz_shuffle (s);
106 }
107
108 static void
109 spritz_absorb_nibble (spritz_state *s, uint8_t x)
110 {
111 spritz_shuffle_absorb (s);
112
113 SPRITZ_SWAP (s->S[s->a], s->S[(uint8_t)((spritz_N >> 1) + x)]);
114 ++s->a;
115 }
116
117 static void
118 spritz_absorb_byte (spritz_state *s, uint8_t b)
119 {
120 spritz_absorb_nibble (s, b & 15);
121 spritz_absorb_nibble (s, b >> 4);
122 }
123
124 void
125 spritz_absorb (spritz_state *s, const void *I, size_t I_len)
126 {
127 uint8_t *i = (uint8_t *)I;
128
129 while (I_len--)
130 spritz_absorb_byte (s, *i++);
131 }
132
133 void
134 spritz_absorb_stop (spritz_state *s)
135 {
136 spritz_shuffle_absorb (s);
137
138 ++s->a;
139 }
140
141 void
142 spritz_absorb_and_stop (spritz_state *s, const void *I, size_t I_len)
143 {
144 spritz_absorb (s, I, I_len);
145 spritz_absorb_stop (s);
146 }
147
148 static void
149 spritz_shuffle_squeeze (spritz_state *s)
150 {
151 if (s->a)
152 spritz_shuffle (s);
153 }
154
155 uint8_t
156 spritz_output (spritz_state *s)
157 {
158 uint8_t r = s->z + s->k;
159
160 r = s->i + s->S[r];
161 r = s->j + s->S[r];
162
163 return s->z = s->S[r];
164 }
165
166 /* slightly faster internal helper, drip without squeeze preparation */
167 static uint8_t
168 spritz_drip_nosqueeze (spritz_state *s)
169 {
170 spritz_update (s);
171 return spritz_output (s);
172 }
173
174 void
175 spritz_squeeze (spritz_state *s, void *P, size_t P_len)
176 {
177 spritz_shuffle_squeeze (s);
178
179 uint8_t *p = (uint8_t *)P;
180
181 while (P_len--)
182 *p++ = spritz_drip_nosqueeze (s);
183 }
184
185 uint8_t
186 spritz_drip (spritz_state *s)
187 {
188 spritz_shuffle_squeeze (s);
189
190 return spritz_drip_nosqueeze (s);
191 }
192
193 /*****************************************************************************/
194
195 void
196 spritz_cipher_init (spritz_state *s, const void *K, size_t K_len, const void *IV, size_t IV_len)
197 {
198 spritz_init (s);
199
200 spritz_absorb (s, K, K_len);
201
202 if (IV)
203 {
204 spritz_absorb_stop (s);
205 spritz_absorb (s, IV, IV_len);
206 }
207
208 spritz_shuffle_squeeze (s);
209 }
210
211 void
212 spritz_cipher_encrypt (spritz_state *s, const void *I, void *O, size_t len)
213 {
214 const uint8_t *i = (const uint8_t *)I;
215 uint8_t *o = ( uint8_t *)O;
216
217 while (len--)
218 *o++ = *i++ + spritz_drip_nosqueeze (s);
219 }
220
221 void
222 spritz_cipher_decrypt (spritz_state *s, const void *I, void *O, size_t len)
223 {
224 const uint8_t *i = (const uint8_t *)I;
225 uint8_t *o = ( uint8_t *)O;
226
227 while (len--)
228 *o++ = *i++ - spritz_drip_nosqueeze (s);
229 }
230
231 /*****************************************************************************/
232
233 void
234 spritz_cipher_xor_crypt (spritz_state *s, const void *I, void *O, size_t len)
235 {
236 const uint8_t *i = (const uint8_t *)I;
237 uint8_t *o = ( uint8_t *)O;
238
239 while (len--)
240 *o++ = *i++ ^ spritz_drip_nosqueeze (s);
241 }
242
243 /*****************************************************************************/
244
245 void
246 spritz_hash_finish (spritz_state *s, void *H, size_t H_len)
247 {
248 spritz_absorb_stop (s);
249 assert (H_len <= 0xff);
250 spritz_absorb_byte (s, H_len);
251
252 spritz_squeeze (s, H, H_len);
253 }
254
255 /*****************************************************************************/
256
257 void
258 spritz_mac_init (spritz_state *s, const void *K, size_t K_len)
259 {
260 spritz_init (s);
261 spritz_absorb_and_stop (s, K, K_len);
262 }
263
264 /*****************************************************************************/
265
266 void
267 spritz_aead_encrypt (spritz_state *s, const void *I, void *O, size_t len)
268 {
269 const uint8_t *i = (const uint8_t *)I;
270 uint8_t *o = ( uint8_t *)O;
271
272 while (len)
273 {
274 uint_fast8_t j;
275 uint8_t x[spritz_aead_blocksize];
276 uint8_t l = len > sizeof (x) ? sizeof (x) : len;
277 len -= l;
278
279 spritz_squeeze (s, x, l);
280
281 for (j = 0; j < l; ++j)
282 {
283 *o = *i++ + x[j];
284 spritz_absorb_byte (s, *o);
285 ++o;
286 }
287 }
288 }
289
290 void
291 spritz_aead_decrypt (spritz_state *s, const void *I, void *O, size_t len)
292 {
293 const uint8_t *i = (const uint8_t *)I;
294 uint8_t *o = ( uint8_t *)O;
295
296 while (len)
297 {
298 uint_fast8_t j;
299 uint8_t x[spritz_aead_blocksize];
300 uint8_t l = len > sizeof (x) ? sizeof (x) : len;
301 len -= l;
302
303 spritz_squeeze (s, x, l);
304
305 for (j = 0; j < l; ++j)
306 {
307 spritz_absorb_byte (s, *i);
308 *o = *i++ - x[j];
309 ++o;
310 }
311 }
312 }
313
314 /*****************************************************************************/
315
316 void
317 spritz_aead_xor_crypt (spritz_state *s, const void *I, void *O, size_t len)
318 {
319 const uint8_t *i = (const uint8_t *)I;
320 uint8_t *o = ( uint8_t *)O;
321
322 while (len)
323 {
324 uint_fast8_t j;
325 uint8_t x[spritz_aead_blocksize];
326 uint8_t l = len > sizeof (x) ? sizeof (x) : len;
327 len -= l;
328
329 spritz_squeeze (s, x, l);
330
331 for (j = 0; j < l; ++j)
332 spritz_absorb_byte (s, *o++ = *i++ ^ x[j]);
333 }
334 }
335
336 /*****************************************************************************/
337
338 void
339 spritz_prng_init (spritz_state *s, const void *S, size_t S_len)
340 {
341 spritz_init (s);
342 spritz_absorb (s, S, S_len);
343 }
344