… | |
… | |
43 | struct spritz |
43 | struct spritz |
44 | { |
44 | { |
45 | enum { N = 256 }; |
45 | enum { N = 256 }; |
46 | |
46 | |
47 | uint8_t a, i, j, k, z, w; |
47 | uint8_t a, i, j, k, z, w; |
48 | uint8_t S[N]; |
48 | 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 | } |
49 | |
55 | |
50 | spritz () |
56 | spritz () |
51 | { |
57 | { |
52 | a = |
58 | a = |
53 | i = |
59 | i = |
… | |
… | |
56 | z = 0; |
62 | z = 0; |
57 | w = 1; |
63 | w = 1; |
58 | |
64 | |
59 | uint_fast8_t v = N - 1; |
65 | uint_fast8_t v = N - 1; |
60 | do |
66 | do |
61 | S[v] = v; |
67 | S(v) = v; |
62 | while (v--); |
68 | while (v--); |
63 | } |
69 | } |
64 | |
70 | |
65 | void update () |
71 | void update () |
66 | { |
72 | { |
67 | i += w; |
73 | i += w; |
68 | j = k + S[j + S[i]]; |
74 | j = k + S(j + S(i)); |
69 | k = k + i + S[j]; |
75 | k = k + i + S(j); |
70 | swap (S[i], S[j]); |
76 | swap (S(i), S(j)); |
71 | } |
77 | } |
72 | |
78 | |
73 | void whip (uint_fast16_t r) |
79 | void whip (uint_fast16_t r) |
74 | { |
80 | { |
75 | while (r--) |
81 | while (r--) |
… | |
… | |
86 | } |
92 | } |
87 | |
93 | |
88 | void crush () |
94 | void crush () |
89 | { |
95 | { |
90 | for (uint_fast16_t v = 0; v < (N >> 1); ++v) |
96 | for (uint_fast16_t v = 0; v < (N >> 1); ++v) |
91 | if (S[v] > S[N - 1 - v]) |
97 | if (S(v) > S(N - 1 - v)) |
92 | swap (S[v], S[N - 1 - v]); |
98 | swap (S(v), S(N - 1 - v)); |
93 | } |
99 | } |
94 | |
100 | |
95 | void shuffle () |
101 | void shuffle () |
96 | { |
102 | { |
97 | whip (2 * N); crush (); |
103 | whip (2 * N); crush (); |
… | |
… | |
109 | |
115 | |
110 | void absorb_nibble (uint8_t x) |
116 | void absorb_nibble (uint8_t x) |
111 | { |
117 | { |
112 | shuffle_absorb (); |
118 | shuffle_absorb (); |
113 | |
119 | |
114 | swap (S[a], S[(N >> 1) + x]); |
120 | swap (S(a), S((N >> 1) + x)); |
115 | ++a; |
121 | ++a; |
116 | } |
122 | } |
117 | |
123 | |
118 | void absorb_byte (uint8_t b) |
124 | void absorb_byte (uint8_t b) |
119 | { |
125 | { |
… | |
… | |
149 | shuffle (); |
155 | shuffle (); |
150 | } |
156 | } |
151 | |
157 | |
152 | uint8_t output () |
158 | uint8_t output () |
153 | { |
159 | { |
154 | return S[j + S[i + S[z + k]]]; |
160 | return z = S(j + S(i + S(z + k))); |
155 | } |
161 | } |
156 | |
162 | |
157 | // slightly faster internal helper, drip without squeeze preparation |
163 | // slightly faster internal helper, drip without squeeze preparation |
158 | uint8_t drip_nosqueeze () |
164 | uint8_t drip_nosqueeze () |
159 | { |
165 | { |
… | |
… | |
293 | |
299 | |
294 | // call mac() at most once at the end |
300 | // call mac() at most once at the end |
295 | using spritz_mac::mac; |
301 | using spritz_mac::mac; |
296 | }; |
302 | }; |
297 | |
303 | |
298 | struct spritz_drbg : protected spritz |
304 | struct spritz_prng : protected spritz |
299 | { |
305 | { |
300 | // seed optional, can be done via put |
306 | // seed optional, can be done via put |
301 | spritz_drbg (const void *S = 0, size_t S_len = 0) |
307 | spritz_prng (const void *S = 0, size_t S_len = 0) |
302 | { |
308 | { |
303 | absorb (S, S_len); |
309 | absorb (S, S_len); |
304 | } |
310 | } |
305 | |
311 | |
306 | // add additional entropy |
312 | // add additional entropy |
307 | void put (const void *S, size_t S_len) |
313 | void add (const void *S, size_t S_len) |
308 | { |
314 | { |
309 | absorb (S, S_len); |
315 | absorb (S, S_len); |
310 | } |
316 | } |
311 | |
317 | |
312 | // get random bytes |
318 | // get random bytes |