check in latest versions
[IRC.git] / Robust / src / Benchmarks / Prefetch / threadv1.0 / section2 / crypt / IDEATest.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 *                  Original version of this code by                       *
16 *                 Gabriel Zachmann (zach@igd.fhg.de)                      *
17 *                                                                         *
18 *      This version copyright (c) The University of Edinburgh, 2001.      *
19 *                         All rights reserved.                            *
20 *                                                                         *
21 **************************************************************************/
22 /**************************************************************************
23 *                       Ported for DSTM Benchmark                         *
24 **************************************************************************/
25
26
27 /**
28 * Class IDEATest
29 *
30 * This test performs IDEA encryption then decryption. IDEA stands
31 * for International Data Encryption Algorithm. The test is based
32 * on code presented in Applied Cryptography by Bruce Schnier,
33 * which was based on code developed by Xuejia Lai and James L.
34 * Massey.
35
36 **/
37
38 package crypt;
39
40 import java.util.*;
41 import jgfutil.*; 
42
43 class IDEATest
44 {
45
46 // Declare class data. Byte buffer plain1 holds the original
47 // data for encryption, crypt1 holds the encrypted data, and
48 // plain2 holds the decrypted data, which should match plain1
49 // byte for byte.
50
51 int array_rows; 
52
53 byte [] plain1;       // Buffer for plaintext data.
54 byte [] crypt1;       // Buffer for encrypted data.
55 byte [] plain2;       // Buffer for decrypted data.
56
57 short [] userkey;     // Key for encryption/decryption.
58 int [] Z;             // Encryption subkey (userkey derived).
59 int [] DK;            // Decryption subkey (userkey derived).
60
61
62
63 void Do()
64 {
65    
66     IDEARunner th[] = new IDEARunner [JGFCryptBench.nthreads];
67   
68     // Start the stopwatch.       
69   JGFInstrumentor.startTimer("Section2:Crypt:Kernel");          
70
71   // Encrypt plain1.
72   for(int i=1;i<JGFCryptBench.nthreads;i++) {
73             th[i] = new IDEARunner(i,plain1,crypt1,Z);
74             th[i].start();
75         }       
76
77         th[0] = new IDEARunner(0,plain1,crypt1,Z);
78         th[0].start();
79
80
81         for(int i=1;i<JGFCryptBench.nthreads;i++) {
82           th[i].join();
83         }     
84   
85         // Decrypt.
86         for(int i=1;i<JGFCryptBench.nthreads;i++) {
87             th[i] = new IDEARunner(i,crypt1,plain2,DK);
88             th[i].start();
89         }       
90
91         th[0] = new IDEARunner(0,crypt1,plain2,DK);
92         th[0].start();
93   
94
95         for(int i=1;i<JGFCryptBench.nthreads;i++) {
96           th[i].join();
97         }
98
99
100   // Stop the stopwatch.
101   JGFInstrumentor.stopTimer("Section2:Crypt:Kernel");
102
103 }
104
105 /*
106 * buildTestData
107 *
108 * Builds the data used for the test -- each time the test is run.
109 */
110
111 void buildTestData()
112 {
113
114
115     // Create three byte arrays that will be used (and reused) for
116     // encryption/decryption operations.
117
118     plain1 = new byte [array_rows];
119     crypt1 = new byte [array_rows];
120     plain2 = new byte [array_rows];
121
122
123     Random rndnum = new Random(136506717L);  // Create random number generator.
124
125
126     // Allocate three arrays to hold keys: userkey is the 128-bit key.
127     // Z is the set of 16-bit encryption subkeys derived from userkey,
128     // while DK is the set of 16-bit decryption subkeys also derived
129     // from userkey. NOTE: The 16-bit values are stored here in
130     // 32-bit int arrays so that the values may be used in calculations
131     // as if they are unsigned. Each 64-bit block of plaintext goes
132     // through eight processing rounds involving six of the subkeys
133     // then a final output transform with four of the keys; (8 * 6)
134     // + 4 = 52 subkeys.
135
136     userkey = new short [8];  // User key has 8 16-bit shorts.
137     Z = new int [52];         // Encryption subkey (user key derived).
138     DK = new int [52];        // Decryption subkey (user key derived).
139
140     // Generate user key randomly; eight 16-bit values in an array.
141
142     for (int i = 0; i < 8; i++)
143     {
144         // Again, the random number function returns int. Converting
145         // to a short type preserves the bit pattern in the lower 16
146         // bits of the int and discards the rest.
147
148       userkey[i] = (short) rndnum.nextInt();
149     }
150
151     // Compute encryption and decryption subkeys.
152
153     calcEncryptKey();
154     calcDecryptKey();
155
156     // Fill plain1 with "text."
157     for (int i = 0; i < array_rows; i++)
158     {
159       plain1[i] = (byte) i; 
160
161       // Converting to a byte
162       // type preserves the bit pattern in the lower 8 bits of the
163       // int and discards the rest.
164     }
165 }
166
167 /*
168 * calcEncryptKey
169 *
170 * Builds the 52 16-bit encryption subkeys Z[] from the user key and
171 * stores in 32-bit int array. The routing corrects an error in the
172 * source code in the Schnier book. Basically, the sense of the 7-
173 * and 9-bit shifts are reversed. It still works reversed, but would
174 * encrypted code would not decrypt with someone else's IDEA code.
175 */
176
177 private void calcEncryptKey()
178 {
179     int j;                       // Utility variable.
180
181     for (int i = 0; i < 52; i++) // Zero out the 52-int Z array.
182         Z[i] = 0;
183
184     for (int i = 0; i < 8; i++)  // First 8 subkeys are userkey itself.
185     {
186         Z[i] = userkey[i] & 0xffff;     // Convert "unsigned"
187                                         // short to int.
188     }
189
190     // Each set of 8 subkeys thereafter is derived from left rotating
191     // the whole 128-bit key 25 bits to left (once between each set of
192     // eight keys and then before the last four). Instead of actually
193     // rotating the whole key, this routine just grabs the 16 bits
194     // that are 25 bits to the right of the corresponding subkey
195     // eight positions below the current subkey. That 16-bit extent
196     // straddles two array members, so bits are shifted left in one
197     // member and right (with zero fill) in the other. For the last
198     // two subkeys in any group of eight, those 16 bits start to
199     // wrap around to the first two members of the previous eight.
200
201     for (int i = 8; i < 52; i++)
202     {
203         j = i % 8;
204         if (j < 6)
205         {
206             Z[i] = ((Z[i -7]>>>9) | (Z[i-6]<<7)) // Shift and combine.
207                     & 0xFFFF;                    // Just 16 bits.
208             continue;                            // Next iteration.
209         }
210
211         if (j == 6)    // Wrap to beginning for second chunk.
212         {
213             Z[i] = ((Z[i -7]>>>9) | (Z[i-14]<<7))
214                     & 0xFFFF;
215             continue;
216         }
217
218          // j == 7 so wrap to beginning for both chunks.
219
220         Z[i] = ((Z[i -15]>>>9) | (Z[i-14]<<7))
221                     & 0xFFFF;
222     }
223 }
224
225 /*
226 * calcDecryptKey
227 *
228 * Builds the 52 16-bit encryption subkeys DK[] from the encryption-
229 * subkeys Z[]. DK[] is a 32-bit int array holding 16-bit values as
230 * unsigned.
231 */
232
233 private void calcDecryptKey()
234 {
235     int j, k;                 // Index counters.
236     int t1, t2, t3;           // Temps to hold decrypt subkeys.
237
238     t1 = inv(Z[0]);           // Multiplicative inverse (mod x10001).
239     t2 = - Z[1] & 0xffff;     // Additive inverse, 2nd encrypt subkey.
240     t3 = - Z[2] & 0xffff;     // Additive inverse, 3rd encrypt subkey.
241
242     DK[51] = inv(Z[3]);       // Multiplicative inverse (mod x10001).
243     DK[50] = t3;
244     DK[49] = t2;
245     DK[48] = t1;
246
247     j = 47;                   // Indices into temp and encrypt arrays.
248     k = 4;
249     for (int i = 0; i < 7; i++)
250     {
251         t1 = Z[k++];
252         DK[j--] = Z[k++];
253         DK[j--] = t1;
254         t1 = inv(Z[k++]);
255         t2 = -Z[k++] & 0xffff;
256         t3 = -Z[k++] & 0xffff;
257         DK[j--] = inv(Z[k++]);
258         DK[j--] = t2;
259         DK[j--] = t3;
260         DK[j--] = t1;
261     }
262
263     t1 = Z[k++];
264     DK[j--] = Z[k++];
265     DK[j--] = t1;
266     t1 = inv(Z[k++]);
267     t2 = -Z[k++] & 0xffff;
268     t3 = -Z[k++] & 0xffff;
269     DK[j--] = inv(Z[k++]);
270     DK[j--] = t3;
271     DK[j--] = t2;
272     DK[j--] = t1;
273 }
274
275
276
277
278
279 /*
280 * mul
281 *
282 * Performs multiplication, modulo (2**16)+1. This code is structured
283 * on the assumption that untaken branches are cheaper than taken
284 * branches, and that the compiler doesn't schedule branches.
285 * Java: Must work with 32-bit int and one 64-bit long to keep
286 * 16-bit values and their products "unsigned." The routine assumes
287 * that both a and b could fit in 16 bits even though they come in
288 * as 32-bit ints. Lots of "& 0xFFFF" masks here to keep things 16-bit.
289 * Also, because the routine stores mod (2**16)+1 results in a 2**16
290 * space, the result is truncated to zero whenever the result would
291 * zero, be 2**16. And if one of the multiplicands is 0, the result
292 * is not zero, but (2**16) + 1 minus the other multiplicand (sort
293 * of an additive inverse mod 0x10001).
294
295 * NOTE: The java conversion of this routine works correctly, but
296 * is half the speed of using Java's modulus division function (%)
297 * on the multiplication with a 16-bit masking of the result--running
298 * in the Symantec Caje IDE. So it's not called for now; the test
299 * uses Java % instead.
300 */
301
302 private int mul(int a, int b)
303 {
304     int ret;
305     long p;             // Large enough to catch 16-bit multiply
306                         // without hitting sign bit.
307     if (a != 0)
308     {
309         if(b != 0)
310         {
311             p = (long) a * b;
312             b = (int) p & 0xFFFF;       // Lower 16 bits.
313             a = (int) p >>> 16;         // Upper 16 bits.
314             if (b < a)
315               return (b - a + 1) & 0xFFFF;
316             else
317               return (b - a) & 0xFFFF;
318         }
319         else
320             return ((1 - a) & 0xFFFF);  // If b = 0, then same as
321                                         // 0x10001 - a.
322     }
323     else                                // If a = 0, then return
324         return((1 - b) & 0xFFFF);       // same as 0x10001 - b.
325 }
326
327 /*
328 * inv
329 *
330 * Compute multiplicative inverse of x, modulo (2**16)+1 using
331 * extended Euclid's GCD (greatest common divisor) algorithm.
332 * It is unrolled twice to avoid swapping the meaning of
333 * the registers. And some subtracts are changed to adds.
334 * Java: Though it uses signed 32-bit ints, the interpretation
335 * of the bits within is strictly unsigned 16-bit.
336 */
337
338 private int inv(int x)
339 {
340     int t0, t1;
341     int q, y;
342
343     if (x <= 1)             // Assumes positive x.
344         return(x);          // 0 and 1 are self-inverse.
345
346     t1 = 0x10001 / x;       // (2**16+1)/x; x is >= 2, so fits 16 bits.
347     y = 0x10001 % x;
348     if (y == 1)
349         return((1 - t1) & 0xFFFF);
350
351     t0 = 1;
352     do {
353         q = x / y;
354         x = x % y;
355         t0 += q * t1;
356         if (x == 1) return(t0);
357         q = y / x;
358         y = y % x;
359         t1 += q * t0;
360     } while (y != 1);
361
362     return((1 - t1) & 0xFFFF);
363 }
364
365 /*
366 * freeTestData
367 *
368 * Nulls arrays and forces garbage collection to free up memory.
369 */
370
371 void freeTestData()
372 {
373     plain1 = null;
374     crypt1 = null;
375     plain2 = null;
376     userkey = null;
377     Z = null;
378     DK = null;
379
380     //System.gc();                // Force garbage collection.
381 }
382
383
384 }
385
386
387
388 class IDEARunner extends Thread {
389
390     int id,key[];
391     byte text1[],text2[];
392
393     public IDEARunner(int id, byte [] text1, byte [] text2, int [] key) {
394         this.id = id;
395         this.text1=text1;
396         this.text2=text2;
397         this.key=key;
398     }
399 /*
400 * run()
401 *
402 * IDEA encryption/decryption algorithm. It processes plaintext in
403 * 64-bit blocks, one at a time, breaking the block into four 16-bit
404 * unsigned subblocks. It goes through eight rounds of processing
405 * using 6 new subkeys each time, plus four for last step. The source
406 * text is in array text1, the destination text goes into array text2
407 * The routine represents 16-bit subblocks and subkeys as type int so
408 * that they can be treated more easily as unsigned. Multiplication
409 * modulo 0x10001 interprets a zero sub-block as 0x10000; it must to
410 * fit in 16 bits.
411 */
412  
413     public void run() {
414                 int ilow, iupper, slice, tslice, ttslice;  
415
416         tslice = text1.length / 8;
417         ttslice = (tslice + JGFCryptBench.nthreads-1) / JGFCryptBench.nthreads;
418         slice = ttslice*8;
419
420         ilow = id*slice;
421         iupper = (id+1)*slice;
422         if(iupper > text1.length) iupper = text1.length;
423
424 int i1 = ilow;                 // Index into first text array.
425 int i2 = ilow;                 // Index into second text array.
426 int ik;                     // Index into key array.
427 int x1, x2, x3, x4, t1, t2; // Four "16-bit" blocks, two temps.
428 int r;                      // Eight rounds of processing.
429
430  for (int i =ilow ; i <iupper ; i +=8)
431 {
432
433     ik = 0;                 // Restart key index.
434     r = 8;                  // Eight rounds of processing.
435
436     // Load eight plain1 bytes as four 16-bit "unsigned" integers.
437     // Masking with 0xff prevents sign extension with cast to int.
438
439     x1 = text1[i1++] & 0xff;          // Build 16-bit x1 from 2 bytes,
440     x1 |= (text1[i1++] & 0xff) << 8;  // assuming low-order byte first.
441     x2 = text1[i1++] & 0xff;
442     x2 |= (text1[i1++] & 0xff) << 8;
443     x3 = text1[i1++] & 0xff;
444     x3 |= (text1[i1++] & 0xff) << 8;
445     x4 = text1[i1++] & 0xff;
446     x4 |= (text1[i1++] & 0xff) << 8;
447
448     do {
449         // 1) Multiply (modulo 0x10001), 1st text sub-block
450         // with 1st key sub-block.
451
452         x1 = (int) ((long) x1 * key[ik++] % 0x10001L & 0xffff);
453
454         // 2) Add (modulo 0x10000), 2nd text sub-block
455         // with 2nd key sub-block.
456
457         x2 = x2 + key[ik++] & 0xffff;
458
459         // 3) Add (modulo 0x10000), 3rd text sub-block
460         // with 3rd key sub-block.
461
462         x3 = x3 + key[ik++] & 0xffff;
463
464         // 4) Multiply (modulo 0x10001), 4th text sub-block
465         // with 4th key sub-block.
466
467         x4 = (int) ((long) x4 * key[ik++] % 0x10001L & 0xffff);
468
469         // 5) XOR results from steps 1 and 3.
470
471         t2 = x1 ^ x3;
472
473         // 6) XOR results from steps 2 and 4.
474         // Included in step 8.
475
476         // 7) Multiply (modulo 0x10001), result of step 5
477         // with 5th key sub-block.
478
479         t2 = (int) ((long) t2 * key[ik++] % 0x10001L & 0xffff);
480
481         // 8) Add (modulo 0x10000), results of steps 6 and 7.
482
483         t1 = t2 + (x2 ^ x4) & 0xffff;
484
485         // 9) Multiply (modulo 0x10001), result of step 8
486         // with 6th key sub-block.
487
488         t1 = (int) ((long) t1 * key[ik++] % 0x10001L & 0xffff);
489
490         // 10) Add (modulo 0x10000), results of steps 7 and 9.
491
492         t2 = t1 + t2 & 0xffff;
493
494         // 11) XOR results from steps 1 and 9.
495
496         x1 ^= t1;
497
498         // 14) XOR results from steps 4 and 10. (Out of order).
499
500         x4 ^= t2;
501
502         // 13) XOR results from steps 2 and 10. (Out of order).
503
504         t2 ^= x2;
505
506         // 12) XOR results from steps 3 and 9. (Out of order).
507
508         x2 = x3 ^ t1;
509
510         x3 = t2;        // Results of x2 and x3 now swapped.
511
512     } while(--r != 0);  // Repeats seven more rounds.
513
514     // Final output transform (4 steps).
515
516     // 1) Multiply (modulo 0x10001), 1st text-block
517     // with 1st key sub-block.
518
519     x1 = (int) ((long) x1 * key[ik++] % 0x10001L & 0xffff);
520
521     // 2) Add (modulo 0x10000), 2nd text sub-block
522     // with 2nd key sub-block. It says x3, but that is to undo swap
523     // of subblocks 2 and 3 in 8th processing round.
524
525     x3 = x3 + key[ik++] & 0xffff;
526
527     // 3) Add (modulo 0x10000), 3rd text sub-block
528     // with 3rd key sub-block. It says x2, but that is to undo swap
529     // of subblocks 2 and 3 in 8th processing round.
530
531     x2 = x2 + key[ik++] & 0xffff;
532
533     // 4) Multiply (modulo 0x10001), 4th text-block
534     // with 4th key sub-block.
535
536     x4 = (int) ((long) x4 * key[ik++] % 0x10001L & 0xffff);
537
538     // Repackage from 16-bit sub-blocks to 8-bit byte array text2.
539
540     text2[i2++] = (byte) x1;
541     text2[i2++] = (byte) (x1 >>> 8);
542     text2[i2++] = (byte) x3;                // x3 and x2 are switched
543     text2[i2++] = (byte) (x3 >>> 8);        // only in name.
544     text2[i2++] = (byte) x2;
545     text2[i2++] = (byte) (x2 >>> 8);
546     text2[i2++] = (byte) x4;
547     text2[i2++] = (byte) (x4 >>> 8);
548
549 }   // End for loop.
550
551     }   // End routine.
552
553 }  // End of class
554
555
556
557
558
559
560
561
562