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

# User Rev Content
1 root 1.3 /* 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 root 1.2
39 root 1.1 #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 root 1.4 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 root 1.1
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 root 1.4 S(v) = v;
68 root 1.1 while (v--);
69     }
70    
71     void update ()
72     {
73     i += w;
74 root 1.4 j = k + S(j + S(i));
75     k = k + i + S(j);
76     swap (S(i), S(j));
77 root 1.1 }
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 root 1.4 if (S(v) > S(N - 1 - v))
98     swap (S(v), S(N - 1 - v));
99 root 1.1 }
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 root 1.4 swap (S(a), S((N >> 1) + x));
121 root 1.1 ++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 root 1.4 return z = S(j + S(i + S(z + k)));
161 root 1.1 }
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 root 1.4 struct spritz_prng : protected spritz
305 root 1.1 {
306     // seed optional, can be done via put
307 root 1.4 spritz_prng (const void *S = 0, size_t S_len = 0)
308 root 1.1 {
309     absorb (S, S_len);
310     }
311    
312     // add additional entropy
313 root 1.4 void add (const void *S, size_t S_len)
314 root 1.1 {
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