Change tabbing for everything....
[IRC.git] / Robust / src / Benchmarks / Prefetch / Crypt / dsm / crypt / JGFCryptBench.java
1 /**************************************************************************
2  *                                                                         *
3  *         Java Grande Forum Benchmark Suite - Thread Version 1.0          *
4  *                                                                         *
5  *                            produced by                                  *
6  *                                                                         *
7  *                  Java Grande Benchmarking Project                       *
8  *                                                                         *
9  *                                at                                       *
10  *                                                                         *
11  *                Edinburgh Parallel Computing Centre                      *
12  *                                                                         * 
13  *                email: epcc-javagrande@epcc.ed.ac.uk                     *
14  *                                                                         *
15  *                                                                         *
16  *      This version copyright (c) The University of Edinburgh, 2001.      *
17  *                         All rights reserved.                            *
18  *                                                                         *
19  **************************************************************************/
20 /**************************************************************************
21  *                       Ported for DSTM Benchmark                         *
22  **************************************************************************/
23
24 public class JGFCryptBench { 
25
26   private int size; 
27   private int datasizes[];
28   int array_rows; 
29
30   byte [] plain1;       // Buffer for plaintext data.
31   byte [] crypt1;       // Buffer for encrypted data.
32   byte [] plain2;       // Buffer for decrypted data.
33
34   short [] userkey;     // Key for encryption/decryption.
35   int [] Z;             // Encryption subkey (userkey derived).
36   int [] DK;            // Decryption subkey (userkey derived).
37
38
39   //
40   // buildTestData
41   //Builds the data used for the test -- each time the test is run.
42   void buildTestData()
43   {
44
45
46     // Create three byte arrays that will be used (and reused) for
47     // encryption/decryption operations.
48
49
50     plain1 = global new byte [array_rows];
51     crypt1 = global new byte [array_rows];
52     plain2 = global new byte [array_rows];
53
54
55     Random rndnum = global new Random(136506717L);  // Create random number generator.
56
57
58     // Allocate three arrays to hold keys: userkey is the 128-bit key.
59     // Z is the set of 16-bit encryption subkeys derived from userkey,
60     // while DK is the set of 16-bit decryption subkeys also derived
61     // from userkey. NOTE: The 16-bit values are stored here in
62     // 32-bit int arrays so that the values may be used in calculations
63     // as if they are unsigned. Each 64-bit block of plaintext goes
64     // through eight processing rounds involving six of the subkeys
65     // then a final output transform with four of the keys; (8 * 6)
66     // + 4 = 52 subkeys.
67
68     userkey = global new short [8];  // User key has 8 16-bit shorts.
69     Z = global new int [52];         // Encryption subkey (user key derived).
70     DK = global new int [52];        // Decryption subkey (user key derived).
71
72     // Generate user key randomly; eight 16-bit values in an array.
73
74     for (int i = 0; i < 8; i++)
75     {
76       // Again, the random number function returns int. Converting
77       // to a short type preserves the bit pattern in the lower 16
78       // bits of the int and discards the rest.
79
80       userkey[i] = (short) rndnum.nextInt();
81     }
82
83     // Compute encryption and decryption subkeys.
84
85     calcEncryptKey();
86     calcDecryptKey();
87
88     // Fill plain1 with "text."
89     for (int i = 0; i < array_rows; i++)
90     {
91       plain1[i] = (byte) i; 
92
93       // Converting to a byte
94       // type preserves the bit pattern in the lower 8 bits of the
95       // int and discards the rest.
96     }
97   }
98
99
100   // calcEncryptKey
101
102   // Builds the 52 16-bit encryption subkeys Z[] from the user key and
103   //stores in 32-bit int array. The routing corrects an error in the
104   //source code in the Schnier book. Basically, the sense of the 7-
105   //and 9-bit shifts are reversed. It still works reversed, but would
106   //encrypted code would not decrypt with someone else's IDEA code.
107   //
108
109   private void calcEncryptKey()
110   {
111     int j;                       // Utility variable.
112
113     for (int i = 0; i < 52; i++) // Zero out the 52-int Z array.
114       Z[i] = 0;
115
116     for (int i = 0; i < 8; i++)  // First 8 subkeys are userkey itself.
117     {
118       Z[i] = userkey[i] & 0xffff;     // Convert "unsigned"
119       // short to int.
120     }
121
122     // Each set of 8 subkeys thereafter is derived from left rotating
123     // the whole 128-bit key 25 bits to left (once between each set of
124     // eight keys and then before the last four). Instead of actually
125     // rotating the whole key, this routine just grabs the 16 bits
126     // that are 25 bits to the right of the corresponding subkey
127     // eight positions below the current subkey. That 16-bit extent
128     // straddles two array members, so bits are shifted left in one
129     // member and right (with zero fill) in the other. For the last
130     // two subkeys in any group of eight, those 16 bits start to
131     // wrap around to the first two members of the previous eight.
132
133     for (int i = 8; i < 52; i++)
134     {
135       int flag1 = 0;
136       j = i % 8;
137       if (j < 6)
138       {
139         Z[i] = ((Z[i -7]>>>9) | (Z[i-6]<<7)) // Shift and combine.
140           & 0xFFFF;                    // Just 16 bits.
141         //continue;                            // Next iteration.
142         flag1 = 1;
143       }
144
145       if(flag1 == 0) {
146         int flag2 = 0;
147
148         if (j == 6)    // Wrap to beginning for second chunk.
149         {
150           Z[i] = ((Z[i -7]>>>9) | (Z[i-14]<<7))
151             & 0xFFFF;
152           //continue;
153           flag2 = 1;
154         }
155
156         if(flag2 == 0) {
157           // j == 7 so wrap to beginning for both chunks.
158           Z[i] = ((Z[i -15]>>>9) | (Z[i-14]<<7))
159             & 0xFFFF;
160         }
161       }
162     }
163   }
164
165   //
166   //calcDecryptKey
167   //
168   //Builds the 52 16-bit encryption subkeys DK[] from the encryption-
169   //subkeys Z[]. DK[] is a 32-bit int array holding 16-bit values as
170   //unsigned.
171   //
172
173   private void calcDecryptKey()
174   {
175     int j, k;                 // Index counters.
176     int t1, t2, t3;           // Temps to hold decrypt subkeys.
177
178     t1 = inv(Z[0]);           // Multiplicative inverse (mod x10001).
179     t2 = - Z[1] & 0xffff;     // Additive inverse, 2nd encrypt subkey.
180     t3 = - Z[2] & 0xffff;     // Additive inverse, 3rd encrypt subkey.
181
182     DK[51] = inv(Z[3]);       // Multiplicative inverse (mod x10001).
183     DK[50] = t3;
184     DK[49] = t2;
185     DK[48] = t1;
186
187     j = 47;                   // Indices into temp and encrypt arrays.
188     k = 4;
189     for (int i = 0; i < 7; i++)
190     {
191       t1 = Z[k++];
192       DK[j--] = Z[k++];
193       DK[j--] = t1;
194       t1 = inv(Z[k++]);
195       t2 = -Z[k++] & 0xffff;
196       t3 = -Z[k++] & 0xffff;
197       DK[j--] = inv(Z[k++]);
198       DK[j--] = t2;
199       DK[j--] = t3;
200       DK[j--] = t1;
201     }
202
203     t1 = Z[k++];
204     DK[j--] = Z[k++];
205     DK[j--] = t1;
206     t1 = inv(Z[k++]);
207     t2 = -Z[k++] & 0xffff;
208     t3 = -Z[k++] & 0xffff;
209     DK[j--] = inv(Z[k++]);
210     DK[j--] = t3;
211     DK[j--] = t2;
212     DK[j--] = t1;
213   }
214
215
216   //
217   //mul
218   //
219   // Performs multiplication, modulo (2**16)+1. This code is structured
220   // on the assumption that untaken branches are cheaper than taken
221   // branches, and that the compiler doesn't schedule branches.
222   // Java: Must work with 32-bit int and one 64-bit long to keep
223   // 16-bit values and their products "unsigned." The routine assumes
224   // that both a and b could fit in 16 bits even though they come in
225   // as 32-bit ints. Lots of "& 0xFFFF" masks here to keep things 16-bit.
226   // Also, because the routine stores mod (2**16)+1 results in a 2**16
227   // space, the result is truncated to zero whenever the result would
228   // zero, be 2**16. And if one of the multiplicands is 0, the result
229   // is not zero, but (2**16) + 1 minus the other multiplicand (sort
230   // of an additive inverse mod 0x10001).
231
232   // NOTE: The java conversion of this routine works correctly, but
233   // is half the speed of using Java's modulus division function (%)
234   // on the multiplication with a 16-bit masking of the result--running
235   // in the Symantec Caje IDE. So it's not called for now; the test
236   // uses Java % instead.
237   //
238
239   private int mul(int a, int b)
240   {
241     int ret;
242     long p;             // Large enough to catch 16-bit multiply
243     // without hitting sign bit.
244     if (a != 0)
245     {
246       if(b != 0)
247       {
248         p = (long) a * b;
249         b = (int) p & 0xFFFF;       // Lower 16 bits.
250         a = (int) p >>> 16;         // Upper 16 bits.
251         if (b < a)
252           return (b - a + 1) & 0xFFFF;
253         else
254           return (b - a) & 0xFFFF;
255       }
256       else
257         return ((1 - a) & 0xFFFF);  // If b = 0, then same as
258       // 0x10001 - a.
259     }
260     else                                // If a = 0, then return
261       return((1 - b) & 0xFFFF);       // same as 0x10001 - b.
262   }
263
264   //
265   // inv
266   //
267   // Compute multiplicative inverse of x, modulo (2**16)+1 using
268   // extended Euclid's GCD (greatest common divisor) algorithm.
269   // It is unrolled twice to avoid swapping the meaning of
270   // the registers. And some subtracts are changed to adds.
271   // Java: Though it uses signed 32-bit ints, the interpretation
272   // of the bits within is strictly unsigned 16-bit.
273   //
274
275   private int inv(int x)
276   {
277     int t0, t1;
278     int q, y;
279
280     if (x <= 1)             // Assumes positive x.
281       return(x);          // 0 and 1 are self-inverse.
282
283     t1 = 0x10001 / x;       // (2**16+1)/x; x is >= 2, so fits 16 bits.
284     y = 0x10001 % x;
285     if (y == 1)
286       return((1 - t1) & 0xFFFF);
287
288     t0 = 1;
289     do {
290       q = x / y;
291       x = x % y;
292       t0 += q * t1;
293       if (x == 1) return(t0);
294       q = y / x;
295       y = y % x;
296       t1 += q * t0;
297     } while (y != 1);
298
299     return((1 - t1) & 0xFFFF);
300   }
301
302   //
303   // freeTestData
304   //
305   // Nulls arrays and forces garbage collection to free up memory.
306   //
307
308   void freeTestData(int array_rows)
309   {
310     for(int i = 0; i<array_rows; i++) {
311       plain1[i] = (byte) 0;
312       crypt1[i] = (byte) 0;
313       plain2[i] = (byte) 0;
314     }
315
316     for(int i = 0; i<8; i++) {
317       userkey[i] = (short) 0;
318     }
319
320     for(int i = 0; i<52; i++) {
321       Z[i] = 0;
322       DK[i] = 0;
323     }
324
325     //System.gc();                // Force garbage collection.
326   }
327
328
329   public JGFCryptBench()
330   {
331     datasizes = global new int[3];
332     datasizes[0] = 3000000;
333     datasizes[1] = 20000000;
334     datasizes[2] = 50000000;
335   }
336
337
338   public void JGFsetsize(int size){
339     this.size = size;
340   }
341
342   public void JGFinitialise(){
343     array_rows = datasizes[size];
344     buildTestData();
345   }
346
347   /*
348   public void JGFkernel(){
349     Do(); 
350   }
351   */
352
353   public void JGFvalidate(){
354     boolean error;
355
356     error = false; 
357     for (int i = 0; i < array_rows; i++){
358       error = (plain1 [i] != plain2 [i]); 
359       if (error){
360         //System.printString("Validation failed");
361         //System.printString("Original Byte " + i + " = " + plain1[i]); 
362         //System.printString("Encrypted Byte " + i + " = " + crypt1[i]); 
363         //System.printString("Decrypted Byte " + i + " = " + plain2[i]); 
364         return;
365         //break;
366       }
367     }
368   }
369
370
371   public void JGFtidyup(){
372     freeTestData(array_rows); 
373   }  
374
375   /*
376   public void JGFrun(int size){
377     instr.addTimer("Section2:Crypt:Kernel", "Kbyte",size);
378     JGFsetsize(size); 
379     JGFinitialise(); 
380     JGFkernel(); 
381     JGFvalidate(); 
382     JGFtidyup(); 
383     instr.addOpsToTimer("Section2:Crypt:Kernel", (2*array_rows)/1000.); 
384     instr.printTimer("Section2:Crypt:Kernel"); 
385   }
386   */
387 }