1 #include "rand-blackrock.h"
2 #include "pixie-timer.h"
3 #include "unusedparm.h"
4 #include "util-malloc.h"
5 #include "string_s.h"
6 #include <stdint.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <math.h>
11 #include <ctype.h>
12 #include <time.h>
13 
14 #if defined(_MSC_VER)
15 #define inline _inline
16 #endif
17 
18 /*
19  * Expanded DES S-boxes
20  */
21 static const uint32_t SB1[64] =
22 {
23     0x01010400, 0x00000000, 0x00010000, 0x01010404,
24     0x01010004, 0x00010404, 0x00000004, 0x00010000,
25     0x00000400, 0x01010400, 0x01010404, 0x00000400,
26     0x01000404, 0x01010004, 0x01000000, 0x00000004,
27     0x00000404, 0x01000400, 0x01000400, 0x00010400,
28     0x00010400, 0x01010000, 0x01010000, 0x01000404,
29     0x00010004, 0x01000004, 0x01000004, 0x00010004,
30     0x00000000, 0x00000404, 0x00010404, 0x01000000,
31     0x00010000, 0x01010404, 0x00000004, 0x01010000,
32     0x01010400, 0x01000000, 0x01000000, 0x00000400,
33     0x01010004, 0x00010000, 0x00010400, 0x01000004,
34     0x00000400, 0x00000004, 0x01000404, 0x00010404,
35     0x01010404, 0x00010004, 0x01010000, 0x01000404,
36     0x01000004, 0x00000404, 0x00010404, 0x01010400,
37     0x00000404, 0x01000400, 0x01000400, 0x00000000,
38     0x00010004, 0x00010400, 0x00000000, 0x01010004
39 };
40 
41 static const uint32_t SB2[64] =
42 {
43     0x80108020, 0x80008000, 0x00008000, 0x00108020,
44     0x00100000, 0x00000020, 0x80100020, 0x80008020,
45     0x80000020, 0x80108020, 0x80108000, 0x80000000,
46     0x80008000, 0x00100000, 0x00000020, 0x80100020,
47     0x00108000, 0x00100020, 0x80008020, 0x00000000,
48     0x80000000, 0x00008000, 0x00108020, 0x80100000,
49     0x00100020, 0x80000020, 0x00000000, 0x00108000,
50     0x00008020, 0x80108000, 0x80100000, 0x00008020,
51     0x00000000, 0x00108020, 0x80100020, 0x00100000,
52     0x80008020, 0x80100000, 0x80108000, 0x00008000,
53     0x80100000, 0x80008000, 0x00000020, 0x80108020,
54     0x00108020, 0x00000020, 0x00008000, 0x80000000,
55     0x00008020, 0x80108000, 0x00100000, 0x80000020,
56     0x00100020, 0x80008020, 0x80000020, 0x00100020,
57     0x00108000, 0x00000000, 0x80008000, 0x00008020,
58     0x80000000, 0x80100020, 0x80108020, 0x00108000
59 };
60 
61 static const uint32_t SB3[64] =
62 {
63     0x00000208, 0x08020200, 0x00000000, 0x08020008,
64     0x08000200, 0x00000000, 0x00020208, 0x08000200,
65     0x00020008, 0x08000008, 0x08000008, 0x00020000,
66     0x08020208, 0x00020008, 0x08020000, 0x00000208,
67     0x08000000, 0x00000008, 0x08020200, 0x00000200,
68     0x00020200, 0x08020000, 0x08020008, 0x00020208,
69     0x08000208, 0x00020200, 0x00020000, 0x08000208,
70     0x00000008, 0x08020208, 0x00000200, 0x08000000,
71     0x08020200, 0x08000000, 0x00020008, 0x00000208,
72     0x00020000, 0x08020200, 0x08000200, 0x00000000,
73     0x00000200, 0x00020008, 0x08020208, 0x08000200,
74     0x08000008, 0x00000200, 0x00000000, 0x08020008,
75     0x08000208, 0x00020000, 0x08000000, 0x08020208,
76     0x00000008, 0x00020208, 0x00020200, 0x08000008,
77     0x08020000, 0x08000208, 0x00000208, 0x08020000,
78     0x00020208, 0x00000008, 0x08020008, 0x00020200
79 };
80 
81 static const uint32_t SB4[64] =
82 {
83     0x00802001, 0x00002081, 0x00002081, 0x00000080,
84     0x00802080, 0x00800081, 0x00800001, 0x00002001,
85     0x00000000, 0x00802000, 0x00802000, 0x00802081,
86     0x00000081, 0x00000000, 0x00800080, 0x00800001,
87     0x00000001, 0x00002000, 0x00800000, 0x00802001,
88     0x00000080, 0x00800000, 0x00002001, 0x00002080,
89     0x00800081, 0x00000001, 0x00002080, 0x00800080,
90     0x00002000, 0x00802080, 0x00802081, 0x00000081,
91     0x00800080, 0x00800001, 0x00802000, 0x00802081,
92     0x00000081, 0x00000000, 0x00000000, 0x00802000,
93     0x00002080, 0x00800080, 0x00800081, 0x00000001,
94     0x00802001, 0x00002081, 0x00002081, 0x00000080,
95     0x00802081, 0x00000081, 0x00000001, 0x00002000,
96     0x00800001, 0x00002001, 0x00802080, 0x00800081,
97     0x00002001, 0x00002080, 0x00800000, 0x00802001,
98     0x00000080, 0x00800000, 0x00002000, 0x00802080
99 };
100 
101 static const uint32_t SB5[64] =
102 {
103     0x00000100, 0x02080100, 0x02080000, 0x42000100,
104     0x00080000, 0x00000100, 0x40000000, 0x02080000,
105     0x40080100, 0x00080000, 0x02000100, 0x40080100,
106     0x42000100, 0x42080000, 0x00080100, 0x40000000,
107     0x02000000, 0x40080000, 0x40080000, 0x00000000,
108     0x40000100, 0x42080100, 0x42080100, 0x02000100,
109     0x42080000, 0x40000100, 0x00000000, 0x42000000,
110     0x02080100, 0x02000000, 0x42000000, 0x00080100,
111     0x00080000, 0x42000100, 0x00000100, 0x02000000,
112     0x40000000, 0x02080000, 0x42000100, 0x40080100,
113     0x02000100, 0x40000000, 0x42080000, 0x02080100,
114     0x40080100, 0x00000100, 0x02000000, 0x42080000,
115     0x42080100, 0x00080100, 0x42000000, 0x42080100,
116     0x02080000, 0x00000000, 0x40080000, 0x42000000,
117     0x00080100, 0x02000100, 0x40000100, 0x00080000,
118     0x00000000, 0x40080000, 0x02080100, 0x40000100
119 };
120 
121 static const uint32_t SB6[64] =
122 {
123     0x20000010, 0x20400000, 0x00004000, 0x20404010,
124     0x20400000, 0x00000010, 0x20404010, 0x00400000,
125     0x20004000, 0x00404010, 0x00400000, 0x20000010,
126     0x00400010, 0x20004000, 0x20000000, 0x00004010,
127     0x00000000, 0x00400010, 0x20004010, 0x00004000,
128     0x00404000, 0x20004010, 0x00000010, 0x20400010,
129     0x20400010, 0x00000000, 0x00404010, 0x20404000,
130     0x00004010, 0x00404000, 0x20404000, 0x20000000,
131     0x20004000, 0x00000010, 0x20400010, 0x00404000,
132     0x20404010, 0x00400000, 0x00004010, 0x20000010,
133     0x00400000, 0x20004000, 0x20000000, 0x00004010,
134     0x20000010, 0x20404010, 0x00404000, 0x20400000,
135     0x00404010, 0x20404000, 0x00000000, 0x20400010,
136     0x00000010, 0x00004000, 0x20400000, 0x00404010,
137     0x00004000, 0x00400010, 0x20004010, 0x00000000,
138     0x20404000, 0x20000000, 0x00400010, 0x20004010
139 };
140 
141 static const uint32_t SB7[64] =
142 {
143     0x00200000, 0x04200002, 0x04000802, 0x00000000,
144     0x00000800, 0x04000802, 0x00200802, 0x04200800,
145     0x04200802, 0x00200000, 0x00000000, 0x04000002,
146     0x00000002, 0x04000000, 0x04200002, 0x00000802,
147     0x04000800, 0x00200802, 0x00200002, 0x04000800,
148     0x04000002, 0x04200000, 0x04200800, 0x00200002,
149     0x04200000, 0x00000800, 0x00000802, 0x04200802,
150     0x00200800, 0x00000002, 0x04000000, 0x00200800,
151     0x04000000, 0x00200800, 0x00200000, 0x04000802,
152     0x04000802, 0x04200002, 0x04200002, 0x00000002,
153     0x00200002, 0x04000000, 0x04000800, 0x00200000,
154     0x04200800, 0x00000802, 0x00200802, 0x04200800,
155     0x00000802, 0x04000002, 0x04200802, 0x04200000,
156     0x00200800, 0x00000000, 0x00000002, 0x04200802,
157     0x00000000, 0x00200802, 0x04200000, 0x00000800,
158     0x04000002, 0x04000800, 0x00000800, 0x00200002
159 };
160 
161 static const uint32_t SB8[64] =
162 {
163     0x10001040, 0x00001000, 0x00040000, 0x10041040,
164     0x10000000, 0x10001040, 0x00000040, 0x10000000,
165     0x00040040, 0x10040000, 0x10041040, 0x00041000,
166     0x10041000, 0x00041040, 0x00001000, 0x00000040,
167     0x10040000, 0x10000040, 0x10001000, 0x00001040,
168     0x00041000, 0x00040040, 0x10040040, 0x10041000,
169     0x00001040, 0x00000000, 0x00000000, 0x10040040,
170     0x10000040, 0x10001000, 0x00041040, 0x00040000,
171     0x00041040, 0x00040000, 0x10041000, 0x00001000,
172     0x00000040, 0x10040040, 0x00001000, 0x00041040,
173     0x10001000, 0x00000040, 0x10000040, 0x10040000,
174     0x10040040, 0x10000000, 0x00040000, 0x10001040,
175     0x00000000, 0x10041040, 0x00040040, 0x10000040,
176     0x10040000, 0x10001000, 0x10001040, 0x00000000,
177     0x10041040, 0x00041000, 0x00041000, 0x00001040,
178     0x00001040, 0x00040040, 0x10000000, 0x10041000
179 };
180 /***************************************************************************
181  * It's an s-box. You gotta have an s-box
182  ***************************************************************************/
183 const unsigned char sbox2[] = {
184 0x91, 0x58, 0xb3, 0x31, 0x6c, 0x33, 0xda, 0x88,
185 0x57, 0xdd, 0x8c, 0xf2, 0x29, 0x5a, 0x08, 0x9f,
186 0x49, 0x34, 0xce, 0x99, 0x9e, 0xbf, 0x0f, 0x81,
187 0xd4, 0x2f, 0x92, 0x3f, 0x95, 0xf5, 0x23, 0x00,
188 0x0d, 0x3e, 0xa8, 0x90, 0x98, 0xdd, 0x20, 0x00,
189 0x03, 0x69, 0x0a, 0xca, 0xba, 0x12, 0x08, 0x41,
190 0x6e, 0xb9, 0x86, 0xe4, 0x50, 0xf0, 0x84, 0xe2,
191 0xb3, 0xb3, 0xc8, 0xb5, 0xb2, 0x2d, 0x18, 0x70,
192 
193 0x0a, 0xd7, 0x92, 0x90, 0x9e, 0x1e, 0x0c, 0x1f,
194 0x08, 0xe8, 0x06, 0xfd, 0x85, 0x2f, 0xaa, 0x5d,
195 0xcf, 0xf9, 0xe3, 0x55, 0xb9, 0xfe, 0xa6, 0x7f,
196 0x44, 0x3b, 0x4a, 0x4f, 0xc9, 0x2f, 0xd2, 0xd3,
197 0x8e, 0xdc, 0xae, 0xba, 0x4f, 0x02, 0xb4, 0x76,
198 0xba, 0x64, 0x2d, 0x07, 0x9e, 0x08, 0xec, 0xbd,
199 0x52, 0x29, 0x07, 0xbb, 0x9f, 0xb5, 0x58, 0x6f,
200 0x07, 0x55, 0xb0, 0x34, 0x74, 0x9f, 0x05, 0xb2,
201 
202 0xdf, 0xa9, 0xc6, 0x2a, 0xa3, 0x5d, 0xff, 0x10,
203 0x40, 0xb3, 0xb7, 0xb4, 0x63, 0x6e, 0xf4, 0x3e,
204 0xee, 0xf6, 0x49, 0x52, 0xe3, 0x11, 0xb3, 0xf1,
205 0xfb, 0x60, 0x48, 0xa1, 0xa4, 0x19, 0x7a, 0x2e,
206 0x90, 0x28, 0x90, 0x8d, 0x5e, 0x8c, 0x8c, 0xc4,
207 0xf2, 0x4a, 0xf6, 0xb2, 0x19, 0x83, 0xea, 0xed,
208 0x6d, 0xba, 0xfe, 0xd8, 0xb6, 0xa3, 0x5a, 0xb4,
209 0x48, 0xfa, 0xbe, 0x5c, 0x69, 0xac, 0x3c, 0x8f,
210 
211 0x63, 0xaf, 0xa4, 0x42, 0x25, 0x50, 0xab, 0x65,
212 0x80, 0x65, 0xb9, 0xfb, 0xc7, 0xf2, 0x2d, 0x5c,
213 0xe3, 0x4c, 0xa4, 0xa6, 0x8e, 0x07, 0x9c, 0xeb,
214 0x41, 0x93, 0x65, 0x44, 0x4a, 0x86, 0xc1, 0xf6,
215 0x2c, 0x97, 0xfd, 0xf4, 0x6c, 0xdc, 0xe1, 0xe0,
216 0x28, 0xd9, 0x89, 0x7b, 0x09, 0xe2, 0xa0, 0x38,
217 0x74, 0x4a, 0xa6, 0x5e, 0xd2, 0xe2, 0x4d, 0xf3,
218 0xf4, 0xc6, 0xbc, 0xa2, 0x51, 0x58, 0xe8, 0xae,
219 
220 0x91, 0x58, 0xb3, 0x31, 0x6c, 0x33, 0xda, 0x88,
221 };
222 
223 
224 /****************************************************************************
225  * Given a number, figure out the nearest power-of-two (16,32,64,128,etc.)
226  * that can hold that number. We do this so that we can convert multiplies
227  * into shifts.
228  ****************************************************************************/
229 static uint64_t
next_power_of_two(uint64_t num)230 next_power_of_two(uint64_t num)
231 {
232     uint64_t power_of_two = 1;
233 
234     num++;
235 
236     while ((uint64_t)(1ULL << power_of_two) < num)
237         power_of_two++;
238 
239     return (1ULL << power_of_two);
240 }
241 static uint64_t
bit_count(uint64_t num)242 bit_count(uint64_t num)
243 {
244     uint64_t bits = 0;
245 
246     while ((num >> bits) > 1)
247         bits++;
248 
249     return bits;
250 }
251 
252 /***************************************************************************
253  ***************************************************************************/
254 void
blackrock2_init(struct BlackRock * br,uint64_t range,uint64_t seed,unsigned rounds)255 blackrock2_init(struct BlackRock *br, uint64_t range, uint64_t seed, unsigned rounds)
256 {
257     uint64_t a;
258     uint64_t b;
259 
260     a = next_power_of_two(
261                                 (uint64_t)sqrt(range * 1.0)
262                           );
263     b = next_power_of_two(range/a);
264 
265     //printf("a=%llu b=%llu seed = 0x%llu\n", a, b, seed);
266 
267     br->range = range;
268 
269     br->a = a;
270     br->a_bits = bit_count(br->a);
271     br->a_mask = br->a - 1ULL;
272 
273     br->b = b;
274     br->b_bits = bit_count(br->b);
275     br->b_mask = br->b - 1ULL;
276 
277     //printf("a: 0x%llx / %llu\n", br->a_mask, br->a_bits);
278     //printf("b: 0x%llx / %llu\n", br->b_mask, br->b_bits);
279 
280     br->rounds = rounds;
281     br->seed = seed;
282     br->range = range;
283 }
284 
285 
286 /***************************************************************************
287  * The inner round/mixer function. In DES, it's a series of S-box lookups,
288  * which
289  ***************************************************************************/
290 static inline uint64_t
ROUND(uint64_t r,uint64_t R,uint64_t seed)291 ROUND(uint64_t r, uint64_t R, uint64_t seed)
292 {
293 #define GETBYTE(R,n) ((uint64_t)(((((R)>>(n*8ULL)))&0xFFULL)))
294 #if 0
295     uint64_t r0, r1, r2, r3;
296 #endif
297     uint64_t T, Y;
298 
299     T = R ^ ((seed>>r) | (seed<<(64-r)));
300 
301 
302     if (r & 1) {
303         Y = SB8[ (T      ) & 0x3F ] ^              \
304              SB6[ (T >>  8) & 0x3F ] ^              \
305              SB4[ (T >> 16) & 0x3F ] ^              \
306              SB2[ (T >> 24) & 0x3F ];               \
307     } else {
308         Y = SB7[ (T      ) & 0x3F ] ^              \
309              SB5[ (T >>  8) & 0x3F ] ^              \
310              SB3[ (T >> 16) & 0x3F ] ^              \
311              SB1[ (T >> 24) & 0x3F ];
312     }
313     return Y;
314 #if 0
315     r0 = sbox2[GETBYTE(R,0)]<< 6 | sbox2[GETBYTE(R,1)]<< 0;
316     r1 = sbox2[GETBYTE(R,2)]<< 6 | sbox2[GETBYTE(R,5)]<< 0;
317     r2 = sbox2[GETBYTE(R,4)]<< 6 | sbox2[GETBYTE(R,5)]<< 0;
318     r3 = sbox2[GETBYTE(R,6)]<< 6 | sbox2[GETBYTE(R,7)]<< 0;
319 
320     R = r0 ^ (r1<<12) * (r2 << 24) ^ (r3 << 36) * r;
321 
322     return R;
323     /*return((uint64_t)sbox2[GETBYTE(R,7ULL)]<< 0ULL)
324         | ((uint64_t)sbox2[GETBYTE(R,6ULL)]<< 8ULL)
325         | ((uint64_t)sbox2[GETBYTE(R,5ULL)]<<16ULL)
326         | ((uint64_t)sbox2[GETBYTE(R,4ULL)]<<24ULL)
327         | ((uint64_t)sbox2[GETBYTE(R,3ULL)]<<32ULL)
328         | ((uint64_t)sbox2[GETBYTE(R,2ULL)]<<40ULL)
329         | ((uint64_t)sbox2[GETBYTE(R,1ULL)]<<48ULL)
330         | ((uint64_t)sbox2[GETBYTE(R,0ULL)]<<56ULL)
331         ;*/
332     return R;
333 #endif
334 }
335 
336 
337 /***************************************************************************
338  ***************************************************************************/
339 static inline uint64_t
ENCRYPT(unsigned r,uint64_t a_bits,uint64_t a_mask,uint64_t b_bits,uint64_t b_mask,uint64_t m,uint64_t seed)340 ENCRYPT(unsigned r, uint64_t a_bits, uint64_t a_mask, uint64_t b_bits, uint64_t b_mask, uint64_t m, uint64_t seed)
341 {
342     uint64_t L, R;
343     unsigned j = 1;
344     uint64_t tmp;
345 
346     UNUSEDPARM(b_bits);
347 
348     L = m & a_mask;
349     R = m >> a_bits;
350 
351     for (j=1; j<=r; j++) {
352         tmp = (L + ROUND(j, R, seed)) & a_mask;
353         L = R;
354         R = tmp;
355         j++;
356 
357         tmp = (L + ROUND(j, R, seed)) & b_mask;
358         L = R;
359         R = tmp;
360     }
361 
362     if ((j-1) & 1) {
363         return (L << (a_bits)) + R;
364     } else {
365         return (R << (a_bits)) + L;
366     }
367 }
368 static inline uint64_t
DECRYPT(unsigned r,uint64_t a,uint64_t b,uint64_t m,uint64_t seed)369 DECRYPT(unsigned r, uint64_t a, uint64_t b, uint64_t m, uint64_t seed)
370 {
371     uint64_t L, R;
372     unsigned j;
373     uint64_t tmp;
374 
375     if (r & 1) {
376         R = m % a;
377         L = m / a;
378     } else {
379         L = m % a;
380         R = m / a;
381     }
382 
383     for (j=r; j>=1; j--) {
384         if (j & 1) {
385             tmp = ROUND(j, L, seed);
386             if (tmp > R) {
387                 tmp = (tmp - R);
388                 tmp = a - (tmp%a);
389                 if (tmp == a)
390                     tmp = 0;
391             } else {
392                 tmp = (R - tmp);
393                 tmp %= a;
394             }
395         } else {
396             tmp = ROUND(j, L, seed);
397             if (tmp > R) {
398                 tmp = (tmp - R);
399                 tmp = b - (tmp%b);
400                 if (tmp == b)
401                     tmp = 0;
402             } else {
403                 tmp = (R - tmp);
404                 tmp %= b;
405             }
406         }
407         R = L;
408         L = tmp;
409     }
410     return a * R + L;
411 }
412 
413 /***************************************************************************
414  ***************************************************************************/
415 uint64_t
blackrock2_shuffle(const struct BlackRock * br,uint64_t m)416 blackrock2_shuffle(const struct BlackRock *br, uint64_t m)
417 {
418     uint64_t c;
419 
420     c = ENCRYPT(br->rounds, br->a_bits, br->a_mask, br->b_bits, br->b_mask, m, br->seed);
421     while (c >= br->range)
422         c = ENCRYPT(br->rounds, br->a_bits, br->a_mask, br->b_bits, br->b_mask, c, br->seed);
423 
424     return c;
425 }
426 
427 /***************************************************************************
428  ***************************************************************************/
429 uint64_t
blackrock2_unshuffle(const struct BlackRock * br,uint64_t m)430 blackrock2_unshuffle(const struct BlackRock *br, uint64_t m)
431 {
432     uint64_t c;
433 
434     c = DECRYPT(br->rounds, br->a, br->b, m, br->seed);
435     while (c >= br->range)
436         c = DECRYPT(br->rounds, br->a, br->b,  c, br->seed);
437 
438     return c;
439 }
440 
441 
442 /***************************************************************************
443  * This function called only during selftest/regression-test.
444  ***************************************************************************/
445 static unsigned
verify(struct BlackRock * br,uint64_t max)446 verify(struct BlackRock *br, uint64_t max)
447 {
448     unsigned char *list;
449     uint64_t i;
450     unsigned is_success = 1;
451     uint64_t range = br->range;
452 
453     /* Allocate a list of 1-byte counters */
454     list = CALLOC(1, (size_t)((range<max)?range:max));
455 
456     /* For all numbers in the range, verify increment the counter for the
457      * the output. */
458     for (i=0; i<range; i++) {
459         uint64_t x = blackrock2_shuffle(br, i);
460         if (x < max)
461             list[x]++;
462     }
463 
464     /* Now check the output to make sure that every counter is set exactly
465      * to the value of '1'. */
466     for (i=0; i<max && i<range; i++) {
467         if (list[i] != 1)
468             is_success = 0;
469     }
470 
471     free(list);
472 
473     return is_success;
474 }
475 
476 /***************************************************************************
477  * Benchmarks the crypto function.
478  ***************************************************************************/
479 void
blackrock2_benchmark(unsigned rounds)480 blackrock2_benchmark(unsigned rounds)
481 {
482     struct BlackRock br;
483     uint64_t range = 0x010356789123ULL;
484     uint64_t i;
485     uint64_t result = 0;
486     uint64_t start, stop;
487     static const uint64_t ITERATIONS = 5000000ULL;
488 
489     printf("-- blackrock-2 -- \n");
490     printf("rounds = %u\n", rounds);
491     blackrock2_init(&br, range, 1, rounds);
492 /*printf("range = 0x%10" PRIx64 "\n", range);
493 printf("rangex= 0x%10" PRIx64 "\n", br.a*br.b);
494 printf("    a = 0x%10" PRIx64 "\n", br.a);
495 printf("    b = 0x%10" PRIx64 "\n", br.b);*/
496 
497     /*
498      * Time the the algorithm
499      */
500     start = pixie_nanotime();
501     for (i=0; i<ITERATIONS; i++) {
502         result += blackrock2_shuffle(&br, i);
503     }
504     stop = pixie_nanotime();
505 
506     /*
507      * Print the results
508      */
509     if (result) {
510         double elapsed = ((double)(stop - start))/(1000000000.0);
511         double rate = ITERATIONS/elapsed;
512 
513         rate /= 1000000.0;
514 
515         printf("iterations/second = %5.3f-million\n", rate);
516 
517     }
518 
519     printf("\n");
520 
521 }
522 
523 /***************************************************************************
524  ***************************************************************************/
525 int
blackrock2_selftest(void)526 blackrock2_selftest(void)
527 {
528     uint64_t i;
529     int is_success = 0;
530     uint64_t range;
531 
532     /* @marshray
533      * Basic test of decryption. I take the index, encrypt it, then decrypt it,
534      * which means I should get the original index back again. Only, it's not
535      * working. The decryption fails. The reason it's failing is obvious -- I'm
536      * just not seeing it though. The error is probably in the 'unfe()'
537      * function above.
538      */
539     {
540         struct BlackRock br;
541         uint64_t result, result2;
542         blackrock2_init(&br, 1000, 0, 6);
543 
544         for (i=0; i<10; i++) {
545             result = blackrock2_shuffle(&br, i);
546             result2 = blackrock2_unshuffle(&br, result);
547             if (i != result2)
548                 return 1; /*fail*/
549         }
550 
551     }
552 
553 
554     range = 3015 * 3;
555 
556     for (i=0; i<5; i++) {
557         struct BlackRock br;
558 
559         range += 11 + i;
560         range *= 1 + i;
561 
562         blackrock2_init(&br, range, time(0), 6);
563 
564         is_success = verify(&br, range);
565 
566         if (!is_success) {
567             fprintf(stderr, "BLACKROCK: randomization failed\n");
568             return 1; /*fail*/
569         }
570     }
571 
572     return 0; /*success*/
573 }
574