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