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

File Contents

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