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, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.2: +37 -2 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     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