c version output message not matching input, did a C vs Java test of the >> and ...
[IRC.git] / Robust / src / Benchmarks / oooJava / C-crypt / crypt.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <sys/time.h>
4
5
6 long currentTimeMillis() {
7   struct timeval* t;
8   gettimeofday( t, NULL );
9   double micros = (double)t->tv_usec;
10   double millis = micros / 1000.0;
11   return (long) millis;
12 }
13
14
15 void buildTestData();
16
17 void calcEncryptKey();
18 void calcDecryptKey();
19
20 int mul( int a, int b );
21 int inv( int x );
22
23 void kernel();
24
25 void cipher_idea( char* text1, char* text2, int* key );
26
27
28 int size;
29 int* datasizes;
30 int array_rows;
31
32 char* plain1; // Buffer for plaintext 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 int problem_size = 2;
39
40
41 void main( int argc, char** argv ) {
42     
43   long startT;
44   long endT;
45   
46   datasizes = malloc( 4*sizeof(int) );
47   datasizes[0] = 3000000;
48   datasizes[1] = 20000000;
49   datasizes[2] = 50000000;
50   datasizes[3] = 1000000000;
51
52   if( argc > 1 ) {
53     problem_size = atoi( argv[1] );
54   }
55   
56   startT=currentTimeMillis();
57
58   array_rows = datasizes[problem_size];
59   buildTestData();
60   
61   endT=currentTimeMillis();
62   
63   kernel();
64   
65   printf( "init=%d\n", endT-startT );
66 }
67
68
69 // buildTestData
70 // Builds the data used for the test -- each time the test is run.
71 void buildTestData() {
72   
73   int i;
74
75   // Create three byte arrays that will be used (and reused) for
76   // encryption/decryption operations.
77
78   plain1 = malloc( array_rows*sizeof( char ) );
79   
80   srand( 136506717 );
81
82   // Allocate three arrays to hold keys: userkey is the 128-bit key.
83   // Z is the set of 16-bit encryption subkeys derived from userkey,
84   // while DK is the set of 16-bit decryption subkeys also derived
85   // from userkey. NOTE: The 16-bit values are stored here in
86   // 32-bit int arrays so that the values may be used in calculations
87   // as if they are unsigned. Each 64-bit block of plaintext goes
88   // through eight processing rounds involving six of the subkeys
89   // then a final output transform with four of the keys; (8 * 6)
90   // + 4 = 52 subkeys.
91
92   userkey = malloc( 8*sizeof( short ) ); // User key has 8 16-bit shorts.
93   Z = malloc( 52*sizeof( int ) ); // Encryption subkey (user key derived).
94   DK = malloc( 52*sizeof( int ) ); // Decryption subkey (user key derived).
95
96   // Generate user key randomly; eight 16-bit values in an array.
97
98   for( i = 0; i < 8; i++ ) {
99     // Again, the random number function returns int. Converting
100     // to a short type preserves the bit pattern in the lower 16
101     // bits of the int and discards the rest.
102     
103     userkey[i] = (short) rand();
104   }
105
106   // Compute encryption and decryption subkeys.
107
108   calcEncryptKey();
109   calcDecryptKey();
110
111   // Fill plain1 with "text."
112   for( i = 0; i < array_rows; i++ ) {
113     plain1[i] = (char) i;
114
115     // Converting to a byte
116     // type preserves the bit pattern in the lower 8 bits of the
117     // int and discards the rest.
118   }
119 }
120
121
122
123 void calcEncryptKey() {
124   // Builds the 52 16-bit encryption subkeys Z[] from the user key and
125   // stores in 32-bit int array. The routing corrects an error in the
126   // source code in the Schnier book. Basically, the sense of the 7-
127   // and 9-bit shifts are reversed. It still works reversed, but would
128   // encrypted code would not decrypt with someone else's IDEA code.
129   //
130   int i;
131   int j; // Utility variables.
132   int flag1;
133   int flag2;
134
135   for( i = 0; i < 52; i++ ) {
136     // Zero out the 52-int Z array.
137     Z[i] = 0;
138   }
139
140   for( i = 0; i < 8; i++ ) { // First 8 subkeys are userkey itself.
141     Z[i] = userkey[i] & 0xffff; // Convert "unsigned"
142     // short to int.
143   }
144
145   // Each set of 8 subkeys thereafter is derived from left rotating
146   // the whole 128-bit key 25 bits to left (once between each set of
147   // eight keys and then before the last four). Instead of actually
148   // rotating the whole key, this routine just grabs the 16 bits
149   // that are 25 bits to the right of the corresponding subkey
150   // eight positions below the current subkey. That 16-bit extent
151   // straddles two array members, so bits are shifted left in one
152   // member and right (with zero fill) in the other. For the last
153   // two subkeys in any group of eight, those 16 bits start to
154   // wrap around to the first two members of the previous eight.
155
156   for( i = 8; i < 52; i++ ) {
157     flag1 = 0;
158     j = i % 8;
159     if (j < 6) {
160       Z[i] = ((Z[i - 7] >> 9) | (Z[i - 6] << 7)) // Shift and combine.
161         & 0xFFFF; // Just 16 bits.
162       // continue; // Next iteration.
163       flag1 = 1;
164     }
165
166     if (flag1 == 0) {
167       flag2 = 0;
168
169       if (j == 6) { // Wrap to beginning for second chunk.        
170         Z[i] = ((Z[i - 7] >> 9) | (Z[i - 14] << 7)) & 0xFFFF;
171         // continue;
172         flag2 = 1;
173       }
174
175       if (flag2 == 0) {
176         // j == 7 so wrap to beginning for both chunks.
177         Z[i] = ((Z[i - 15] >> 9) | (Z[i - 14] << 7)) & 0xFFFF;
178       }
179     }
180   }
181 }
182
183
184 void calcDecryptKey() {
185   // Builds the 52 16-bit encryption subkeys DK[] from the encryption-
186   // subkeys Z[]. DK[] is a 32-bit int array holding 16-bit values as
187   // unsigned.
188   //
189
190   int i, j, k; // Index counters.
191   int t1, t2, t3; // Temps to hold decrypt subkeys.
192
193   t1 = inv(Z[0]); // Multiplicative inverse (mod x10001).
194   t2 = -Z[1] & 0xffff; // Additive inverse, 2nd encrypt subkey.
195   t3 = -Z[2] & 0xffff; // Additive inverse, 3rd encrypt subkey.
196   
197   DK[51] = inv(Z[3]); // Multiplicative inverse (mod x10001).
198   DK[50] = t3;
199   DK[49] = t2;
200   DK[48] = t1;
201
202   j = 47; // Indices into temp and encrypt arrays.
203   k = 4;
204   for( i = 0; i < 7; i++ ) {
205     t1 = Z[k++];
206     DK[j--] = Z[k++];
207     DK[j--] = t1;
208     t1 = inv(Z[k++]);
209     t2 = -Z[k++] & 0xffff;
210     t3 = -Z[k++] & 0xffff;
211     DK[j--] = inv(Z[k++]);
212     DK[j--] = t2;
213     DK[j--] = t3;
214     DK[j--] = t1;
215   }
216
217   t1 = Z[k++];
218   DK[j--] = Z[k++];
219   DK[j--] = t1;
220   t1 = inv(Z[k++]);
221   t2 = -Z[k++] & 0xffff;
222   t3 = -Z[k++] & 0xffff;
223   DK[j--] = inv(Z[k++]);
224   DK[j--] = t3;
225   DK[j--] = t2;
226   DK[j--] = t1;  
227 }
228
229
230
231 int mul( int a, int b ) {
232   // Performs multiplication, modulo (2**16)+1. This code is structured
233   // on the assumption that untaken branches are cheaper than taken
234   // branches, and that the compiler doesn't schedule branches.
235   // Java: Must work with 32-bit int and one 64-bit long to keep
236   // 16-bit values and their products "unsigned." The routine assumes
237   // that both a and b could fit in 16 bits even though they come in
238   // as 32-bit ints. Lots of "& 0xFFFF" masks here to keep things 16-bit.
239   // Also, because the routine stores mod (2**16)+1 results in a 2**16
240   // space, the result is truncated to zero whenever the result would
241   // zero, be 2**16. And if one of the multiplicands is 0, the result
242   // is not zero, but (2**16) + 1 minus the other multiplicand (sort
243   // of an additive inverse mod 0x10001).
244
245   // NOTE: The java conversion of this routine works correctly, but
246   // is half the speed of using Java's modulus division function (%)
247   // on the multiplication with a 16-bit masking of the result--running
248   // in the Symantec Caje IDE. So it's not called for now; the test
249   // uses Java % instead.
250   //
251
252   int ret;
253   long p; // Large enough to catch 16-bit multiply
254   // without hitting sign bit.
255   if (a != 0) {
256     if (b != 0) {
257       p = (long) a * b;
258       b = (int) p & 0xFFFF; // Lower 16 bits.
259       a = (int) p >> 16; // Upper 16 bits.
260       if (b < a)
261         return (b - a + 1) & 0xFFFF;
262       else
263         return (b - a) & 0xFFFF;
264     } else
265       return ((1 - a) & 0xFFFF); // If b = 0, then same as
266     // 0x10001 - a.
267   } else
268     // If a = 0, then return
269     return ((1 - b) & 0xFFFF); // same as 0x10001 - b.
270 }
271
272
273
274
275 int inv( int x ) {
276   // Compute multiplicative inverse of x, modulo (2**16)+1 using
277   // extended Euclid's GCD (greatest common divisor) algorithm.
278   // It is unrolled twice to avoid swapping the meaning of
279   // the registers. And some subtracts are changed to adds.
280   // Java: Though it uses signed 32-bit ints, the interpretation
281   // of the bits within is strictly unsigned 16-bit.
282   //
283
284   int t0, t1;
285   int q, y;
286
287   if (x <= 1) // Assumes positive x.
288     return (x); // 0 and 1 are self-inverse.
289
290   t1 = 0x10001 / x; // (2**16+1)/x; x is >= 2, so fits 16 bits.
291   y = 0x10001 % x;
292   if (y == 1)
293     return ((1 - t1) & 0xFFFF);
294
295   t0 = 1;
296   do {
297     q = x / y;
298     x = x % y;
299     t0 += q * t1;
300     if (x == 1)
301       return (t0);
302     q = y / x;
303     y = y % x;
304     t1 += q * t0;
305   } while (y != 1);
306   
307   return ((1 - t1) & 0xFFFF);
308 }
309
310
311
312 void kernel() {
313   int i;
314   int error;
315
316   char* crypt1 = malloc( array_rows*sizeof( char ) );
317   char* plain2 = malloc( array_rows*sizeof( char ) );
318
319   cipher_idea(plain1, crypt1, Z);     // Encrypt plain1.
320   cipher_idea(crypt1, plain2, DK);    // Decrypt.
321
322   error = 0; 
323   for( i = 0; i < array_rows; i++ ){
324     error = (plain1 [i] != plain2 [i]); 
325     if (error){
326       printf("Validation failed\n");
327       printf("Original  Byte %d = %c\n", i, plain1[i]);
328       printf("Encrypted Byte %d = %c\n", i, crypt1[i]); 
329       printf("Decrypted Byte %d = %c\n", i, plain2[i]); 
330       return;
331     }
332   }
333   printf("Validation Success\n");
334 }
335
336
337
338
339 void cipher_idea( char* text1, char* text2, int* key ) {
340   // IDEA encryption/decryption algorithm. It processes plaintext in
341   // 64-bit blocks, one at a time, breaking the block into four 16-bit
342   // unsigned subblocks. It goes through eight rounds of processing
343   // using 6 new subkeys each time, plus four for last step. The source
344   // text is in array text1, the destination text goes into array text2
345   // The routine represents 16-bit subblocks and subkeys as type int so
346   // that they can be treated more easily as unsigned. Multiplication
347   // modulo 0x10001 interprets a zero sub-block as 0x10000; it must to
348   // fit in 16 bits.
349   //
350   int i;
351   int i1 = 0;                 // Index into first text array.
352   int i2 = 0;                 // Index into second text array.
353   int ik;                     // Index into key array.
354   int x1, x2, x3, x4, t1, t2; // Four "16-bit" blocks, two temps.
355   int r;                      // Eight rounds of processing.
356
357   for( i = 0; i < array_rows; i += 8 )
358     {
359
360       ik = 0;                 // Restart key index.
361       r = 8;                  // Eight rounds of processing.
362
363       // Load eight plain1 bytes as four 16-bit "unsigned" integers.
364       // Masking with 0xff prevents sign extension with cast to int.
365
366       x1 = text1[i1++] & 0xff;          // Build 16-bit x1 from 2 bytes,
367       x1 |= (text1[i1++] & 0xff) << 8;  // assuming low-order byte first.
368       x2 = text1[i1++] & 0xff;
369       x2 |= (text1[i1++] & 0xff) << 8;
370       x3 = text1[i1++] & 0xff;
371       x3 |= (text1[i1++] & 0xff) << 8;
372       x4 = text1[i1++] & 0xff;
373       x4 |= (text1[i1++] & 0xff) << 8;
374
375       do {
376         // 1) Multiply (modulo 0x10001), 1st text sub-block
377         // with 1st key sub-block.
378
379         x1 = (int) ((long) x1 * key[ik++] % 0x10001L & 0xffff);
380
381         // 2) Add (modulo 0x10000), 2nd text sub-block
382         // with 2nd key sub-block.
383
384         x2 = x2 + key[ik++] & 0xffff;
385
386         // 3) Add (modulo 0x10000), 3rd text sub-block
387         // with 3rd key sub-block.
388
389         x3 = x3 + key[ik++] & 0xffff;
390
391         // 4) Multiply (modulo 0x10001), 4th text sub-block
392         // with 4th key sub-block.
393
394         x4 = (int) ((long) x4 * key[ik++] % 0x10001L & 0xffff);
395
396         // 5) XOR results from steps 1 and 3.
397
398         t2 = x1 ^ x3;
399
400         // 6) XOR results from steps 2 and 4.
401         // Included in step 8.
402
403         // 7) Multiply (modulo 0x10001), result of step 5
404         // with 5th key sub-block.
405
406         t2 = (int) ((long) t2 * key[ik++] % 0x10001L & 0xffff);
407
408         // 8) Add (modulo 0x10000), results of steps 6 and 7.
409
410         t1 = t2 + (x2 ^ x4) & 0xffff;
411
412         // 9) Multiply (modulo 0x10001), result of step 8
413         // with 6th key sub-block.
414
415         t1 = (int) ((long) t1 * key[ik++] % 0x10001L & 0xffff);
416
417         // 10) Add (modulo 0x10000), results of steps 7 and 9.
418
419         t2 = t1 + t2 & 0xffff;
420
421         // 11) XOR results from steps 1 and 9.
422
423         x1 ^= t1;
424
425         // 14) XOR results from steps 4 and 10. (Out of order).
426
427         x4 ^= t2;
428
429         // 13) XOR results from steps 2 and 10. (Out of order).
430
431         t2 ^= x2;
432
433         // 12) XOR results from steps 3 and 9. (Out of order).
434
435         x2 = x3 ^ t1;
436
437         x3 = t2;        // Results of x2 and x3 now swapped.
438
439       } while(--r != 0);  // Repeats seven more rounds.
440
441       // Final output transform (4 steps).
442
443       // 1) Multiply (modulo 0x10001), 1st text-block
444       // with 1st key sub-block.
445
446       x1 = (int) ((long) x1 * key[ik++] % 0x10001L & 0xffff);
447
448       // 2) Add (modulo 0x10000), 2nd text sub-block
449       // with 2nd key sub-block. It says x3, but that is to undo swap
450       // of subblocks 2 and 3 in 8th processing round.
451
452       x3 = x3 + key[ik++] & 0xffff;
453
454       // 3) Add (modulo 0x10000), 3rd text sub-block
455       // with 3rd key sub-block. It says x2, but that is to undo swap
456       // of subblocks 2 and 3 in 8th processing round.
457
458       x2 = x2 + key[ik++] & 0xffff;
459
460       // 4) Multiply (modulo 0x10001), 4th text-block
461       // with 4th key sub-block.
462
463       x4 = (int) ((long) x4 * key[ik++] % 0x10001L & 0xffff);
464
465       // Repackage from 16-bit sub-blocks to 8-bit byte array text2.
466
467       text2[i2++] = (char) x1;
468       text2[i2++] = (char) (x1 >> 8);
469       text2[i2++] = (char) x3;                // x3 and x2 are switched
470       text2[i2++] = (char) (x3 >> 8);        // only in name.
471       text2[i2++] = (char) x2;
472       text2[i2++] = (char) (x2 >> 8);
473       text2[i2++] = (char) x4;
474       text2[i2++] = (char) (x4 >> 8);
475
476     }   // End for loop.
477
478 }   // End routine.