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

# Content
1 /* spritz++ */
2 /* (C)2015 Marc Alexander Lehmann, all rights reserved */
3
4 #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