ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/spritz/spritz++.h
Revision: 1.2
Committed: Fri Jan 9 09:12:18 2015 UTC (9 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.1: +3 -0 lines
Log Message:
*** empty log message ***

File Contents

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