ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/spritz/spritz++.h
Revision: 1.4
Committed: Sat Jan 10 04:14:21 2015 UTC (9 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-1_02, rel-1_0, rel-0_2, rel-1_01, HEAD
Changes since 1.3: +18 -12 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /* spritz++, C++ header-only 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 <assert.h>
40 #include <stdint.h>
41 #include <sys/types.h>
42
43 struct spritz
44 {
45 enum { N = 256 };
46
47 uint8_t a, i, j, k, z, w;
48 uint8_t s[N];
49
50 // helper to reduce index to uint8_t
51 uint8_t &S (uint8_t i)
52 {
53 return s[i];
54 }
55
56 spritz ()
57 {
58 a =
59 i =
60 j =
61 k =
62 z = 0;
63 w = 1;
64
65 uint_fast8_t v = N - 1;
66 do
67 S(v) = v;
68 while (v--);
69 }
70
71 void update ()
72 {
73 i += w;
74 j = k + S(j + S(i));
75 k = k + i + S(j);
76 swap (S(i), S(j));
77 }
78
79 void whip (uint_fast16_t r)
80 {
81 while (r--)
82 update ();
83
84 w += 2;
85 }
86
87 static void swap (uint8_t &a, uint8_t &b)
88 {
89 uint8_t c = a;
90 a = b;
91 b = c;
92 }
93
94 void crush ()
95 {
96 for (uint_fast16_t v = 0; v < (N >> 1); ++v)
97 if (S(v) > S(N - 1 - v))
98 swap (S(v), S(N - 1 - v));
99 }
100
101 void shuffle ()
102 {
103 whip (2 * N); crush ();
104 whip (2 * N); crush ();
105 whip (2 * N);
106
107 a = 0;
108 }
109
110 void shuffle_absorb ()
111 {
112 if (a == (N >> 1))
113 shuffle ();
114 }
115
116 void absorb_nibble (uint8_t x)
117 {
118 shuffle_absorb ();
119
120 swap (S(a), S((N >> 1) + x));
121 ++a;
122 }
123
124 void absorb_byte (uint8_t b)
125 {
126 absorb_nibble (b & 15);
127 absorb_nibble (b >> 4);
128 }
129
130 void absorb (const void *I, size_t I_len)
131 {
132 uint8_t *i = (uint8_t *)I;
133
134 while (I_len--)
135 absorb_byte (*i++);
136 }
137
138 void absorb_stop ()
139 {
140 shuffle_absorb ();
141
142 ++a;
143 }
144
145 // commonly used helper function
146 void absorb_stop (const void *I, size_t I_len)
147 {
148 absorb (I, I_len);
149 absorb_stop ();
150 }
151
152 void shuffle_squeeze ()
153 {
154 if (a)
155 shuffle ();
156 }
157
158 uint8_t output ()
159 {
160 return z = S(j + S(i + S(z + k)));
161 }
162
163 // slightly faster internal helper, drip without squeeze preparation
164 uint8_t drip_nosqueeze ()
165 {
166 update ();
167 return output ();
168 }
169
170 void squeeze (void *P, size_t P_len)
171 {
172 shuffle_squeeze ();
173
174 uint8_t *p = (uint8_t *)P;
175
176 while (P_len--)
177 *p++ = drip_nosqueeze ();
178 }
179
180 uint8_t drip ()
181 {
182 shuffle_squeeze ();
183
184 return drip_nosqueeze ();
185 }
186 };
187
188 // what follows is wrappers that make using spritz easier and less error-prone
189
190 // spritz-xor variant of cipher
191 struct spritz_xor : protected spritz
192 {
193 // key K required, IV optional
194 spritz_xor (const void *K, size_t K_len, const void *IV = 0, size_t IV_len = 0)
195 {
196 absorb (K, K_len);
197
198 if (IV)
199 {
200 absorb_stop ();
201 absorb (IV, IV_len);
202 }
203
204 shuffle_squeeze ();
205 }
206
207 // can be called multiple times/incrementally
208 // can work inplace
209 // works for both encryption and decryption
210 void crypt (const void *I, void *O, size_t len)
211 {
212 const uint8_t *i = (const uint8_t *)I;
213 uint8_t *o = ( uint8_t *)O;
214
215 while (len--)
216 *o++ = *i++ ^ drip_nosqueeze ();
217 }
218 };
219
220 struct spritz_hash : protected spritz
221 {
222 spritz_hash ()
223 {
224 }
225
226 // can be called multiple times/incrementally
227 void add (const void *M, size_t M_len)
228 {
229 absorb (M, M_len);
230 }
231
232 // must be called at most once at the end
233 void hash (void *H, size_t H_len)
234 {
235 absorb_stop ();
236 assert (H_len <= 0xff);
237 absorb_byte (H_len);
238
239 squeeze (H, H_len);
240 }
241 };
242
243 struct spritz_mac : protected spritz_hash
244 {
245 spritz_mac (const void *K, size_t K_len)
246 {
247 absorb_stop (K, K_len);
248 }
249
250 // use add to incrementally add data
251 using spritz_hash::add;
252
253 // must be called at most once at the end
254 void mac (void *H, size_t H_len)
255 {
256 hash (H, H_len);
257 }
258 };
259
260 struct spritz_aead : protected spritz_mac
261 {
262 spritz_aead (const void *K, size_t K_len)
263 : spritz_mac (K, K_len)
264 {
265 }
266
267 // must be called after construction, before data
268 void nonce (const void *N, size_t N_len)
269 {
270 absorb_stop (N, N_len);
271 }
272
273 // must be called after nonce, before crypt
274 void associated_data (const void *D, size_t D_len)
275 {
276 absorb_stop (D, D_len);
277 }
278
279 // must be called after data, only once, before mac
280 // works for both encryption and decryption
281 void crypt (const void *I, void *O, size_t len)
282 {
283 const uint8_t *i = (const uint8_t *)I;
284 uint8_t *o = ( uint8_t *)O;
285
286 uint8_t x[N >> 2];
287
288 while (len)
289 {
290 uint8_t l = len > sizeof (x) ? sizeof (x) : len;
291 len -= l;
292
293 squeeze (x, l);
294
295 for (uint_fast8_t j = 0; j < l; ++j)
296 absorb_byte (*o++ = *i++ ^ x[j]);
297 }
298 }
299
300 // call mac() at most once at the end
301 using spritz_mac::mac;
302 };
303
304 struct spritz_prng : protected spritz
305 {
306 // seed optional, can be done via put
307 spritz_prng (const void *S = 0, size_t S_len = 0)
308 {
309 absorb (S, S_len);
310 }
311
312 // add additional entropy
313 void add (const void *S, size_t S_len)
314 {
315 absorb (S, S_len);
316 }
317
318 // get random bytes
319 void get (void *R, size_t R_len)
320 {
321 squeeze (R, R_len);
322 }
323 };
324