001/*
002 * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023// Checkstyle: stop
024
025package com.oracle.graal.jtt.hotpath;
026
027import java.util.*;
028
029import org.junit.*;
030
031import com.oracle.graal.jtt.*;
032
033public class HP_idea extends JTTTest {
034
035    public boolean test() {
036        buildTestData();
037        Do();
038        return verify();
039    }
040
041    // Declare class data. Byte buffer plain1 holds the original
042    // data for encryption, crypt1 holds the encrypted data, and
043    // plain2 holds the decrypted data, which should match plain1
044    // byte for byte.
045
046    int array_rows;
047
048    byte[] plain1; // Buffer for plaintext data.
049    byte[] crypt1; // Buffer for encrypted data.
050    byte[] plain2; // Buffer for decrypted data.
051
052    short[] userkey; // Key for encryption/decryption.
053    int[] Z; // Encryption subkey (userkey derived).
054    int[] DK; // Decryption subkey (userkey derived).
055
056    void Do() {
057        cipher_idea(plain1, crypt1, Z); // Encrypt plain1.
058        cipher_idea(crypt1, plain2, DK); // Decrypt.
059    }
060
061    /*
062     * buildTestData
063     *
064     * Builds the data used for the test -- each time the test is run.
065     */
066
067    void buildTestData() {
068        // Create three byte arrays that will be used (and reused) for
069        // encryption/decryption operations.
070
071        plain1 = new byte[array_rows];
072        crypt1 = new byte[array_rows];
073        plain2 = new byte[array_rows];
074
075        Random rndnum = new Random(136506717L); // Create random number generator.
076
077        // Allocate three arrays to hold keys: userkey is the 128-bit key.
078        // Z is the set of 16-bit encryption subkeys derived from userkey,
079        // while DK is the set of 16-bit decryption subkeys also derived
080        // from userkey. NOTE: The 16-bit values are stored here in
081        // 32-bit int arrays so that the values may be used in calculations
082        // as if they are unsigned. Each 64-bit block of plaintext goes
083        // through eight processing rounds involving six of the subkeys
084        // then a final output transform with four of the keys; (8 * 6)
085        // + 4 = 52 subkeys.
086
087        userkey = new short[8]; // User key has 8 16-bit shorts.
088        Z = new int[52]; // Encryption subkey (user key derived).
089        DK = new int[52]; // Decryption subkey (user key derived).
090
091        // Generate user key randomly; eight 16-bit values in an array.
092
093        for (int i = 0; i < 8; i++) {
094            // Again, the random number function returns int. Converting
095            // to a short type preserves the bit pattern in the lower 16
096            // bits of the int and discards the rest.
097
098            userkey[i] = (short) rndnum.nextInt();
099        }
100
101        // Compute encryption and decryption subkeys.
102
103        calcEncryptKey();
104        calcDecryptKey();
105
106        // Fill plain1 with "text."
107        for (int i = 0; i < array_rows; i++) {
108            plain1[i] = (byte) i;
109
110            // Converting to a byte
111            // type preserves the bit pattern in the lower 8 bits of the
112            // int and discards the rest.
113        }
114    }
115
116    /*
117     * calcEncryptKey
118     *
119     * Builds the 52 16-bit encryption subkeys Z[] from the user key and stores in 32-bit int array.
120     * The routing corrects an error in the source code in the Schnier book. Basically, the sense of
121     * the 7- and 9-bit shifts are reversed. It still works reversed, but would encrypted code would
122     * not decrypt with someone else's IDEA code.
123     */
124
125    private void calcEncryptKey() {
126        int j; // Utility variable.
127
128        for (int i = 0; i < 52; i++) {
129            // Zero out the 52-int Z array.
130            Z[i] = 0;
131        }
132
133        for (int i = 0; i < 8; i++) // First 8 subkeys are userkey itself.
134        {
135            Z[i] = userkey[i] & 0xffff; // Convert "unsigned"
136            // short to int.
137        }
138
139        // Each set of 8 subkeys thereafter is derived from left rotating
140        // the whole 128-bit key 25 bits to left (once between each set of
141        // eight keys and then before the last four). Instead of actually
142        // rotating the whole key, this routine just grabs the 16 bits
143        // that are 25 bits to the right of the corresponding subkey
144        // eight positions below the current subkey. That 16-bit extent
145        // straddles two array members, so bits are shifted left in one
146        // member and right (with zero fill) in the other. For the last
147        // two subkeys in any group of eight, those 16 bits start to
148        // wrap around to the first two members of the previous eight.
149
150        for (int i = 8; i < 52; i++) {
151            j = i % 8;
152            if (j < 6) {
153                Z[i] = ((Z[i - 7] >>> 9) | (Z[i - 6] << 7)) // Shift and combine.
154                & 0xFFFF; // Just 16 bits.
155                continue; // Next iteration.
156            }
157
158            if (j == 6) // Wrap to beginning for second chunk.
159            {
160                Z[i] = ((Z[i - 7] >>> 9) | (Z[i - 14] << 7)) & 0xFFFF;
161                continue;
162            }
163
164            // j == 7 so wrap to beginning for both chunks.
165
166            Z[i] = ((Z[i - 15] >>> 9) | (Z[i - 14] << 7)) & 0xFFFF;
167        }
168    }
169
170    /*
171     * calcDecryptKey
172     *
173     * Builds the 52 16-bit encryption subkeys DK[] from the encryption- subkeys Z[]. DK[] is a
174     * 32-bit int array holding 16-bit values as unsigned.
175     */
176
177    private void calcDecryptKey() {
178        int j, k; // Index counters.
179        int t1, t2, t3; // Temps to hold decrypt subkeys.
180
181        t1 = inv(Z[0]); // Multiplicative inverse (mod x10001).
182        t2 = -Z[1] & 0xffff; // Additive inverse, 2nd encrypt subkey.
183        t3 = -Z[2] & 0xffff; // Additive inverse, 3rd encrypt subkey.
184
185        DK[51] = inv(Z[3]); // Multiplicative inverse (mod x10001).
186        DK[50] = t3;
187        DK[49] = t2;
188        DK[48] = t1;
189
190        j = 47; // Indices into temp and encrypt arrays.
191        k = 4;
192        for (int i = 0; i < 7; i++) {
193            t1 = Z[k++];
194            DK[j--] = Z[k++];
195            DK[j--] = t1;
196            t1 = inv(Z[k++]);
197            t2 = -Z[k++] & 0xffff;
198            t3 = -Z[k++] & 0xffff;
199            DK[j--] = inv(Z[k++]);
200            DK[j--] = t2;
201            DK[j--] = t3;
202            DK[j--] = t1;
203        }
204
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--] = t3;
213        DK[j--] = t2;
214        DK[j--] = t1;
215    }
216
217    /*
218     * cipher_idea
219     *
220     * IDEA encryption/decryption algorithm. It processes plaintext in 64-bit blocks, one at a time,
221     * breaking the block into four 16-bit unsigned subblocks. It goes through eight rounds of
222     * processing using 6 new subkeys each time, plus four for last step. The source text is in
223     * array text1, the destination text goes into array text2 The routine represents 16-bit
224     * subblocks and subkeys as type int so that they can be treated more easily as unsigned.
225     * Multiplication modulo 0x10001 interprets a zero sub-block as 0x10000; it must to fit in 16
226     * bits.
227     */
228
229    @SuppressWarnings("static-method")
230    private void cipher_idea(byte[] text1, byte[] text2, int[] key) {
231
232        int i1 = 0; // Index into first text array.
233        int i2 = 0; // Index into second text array.
234        int ik; // Index into key array.
235        int x1, x2, x3, x4, t1, t2; // Four "16-bit" blocks, two temps.
236        int r; // Eight rounds of processing.
237
238        for (int i = 0; i < text1.length; i += 8) {
239
240            ik = 0; // Restart key index.
241            r = 8; // Eight rounds of processing.
242
243            // Load eight plain1 bytes as four 16-bit "unsigned" integers.
244            // Masking with 0xff prevents sign extension with cast to int.
245
246            x1 = text1[i1++] & 0xff; // Build 16-bit x1 from 2 bytes,
247            x1 |= (text1[i1++] & 0xff) << 8; // assuming low-order byte first.
248            x2 = text1[i1++] & 0xff;
249            x2 |= (text1[i1++] & 0xff) << 8;
250            x3 = text1[i1++] & 0xff;
251            x3 |= (text1[i1++] & 0xff) << 8;
252            x4 = text1[i1++] & 0xff;
253            x4 |= (text1[i1++] & 0xff) << 8;
254
255            do {
256                // 1) Multiply (modulo 0x10001), 1st text sub-block
257                // with 1st key sub-block.
258
259                x1 = (int) ((long) x1 * key[ik++] % 0x10001L & 0xffff);
260
261                // 2) Add (modulo 0x10000), 2nd text sub-block
262                // with 2nd key sub-block.
263
264                x2 = x2 + key[ik++] & 0xffff;
265
266                // 3) Add (modulo 0x10000), 3rd text sub-block
267                // with 3rd key sub-block.
268
269                x3 = x3 + key[ik++] & 0xffff;
270
271                // 4) Multiply (modulo 0x10001), 4th text sub-block
272                // with 4th key sub-block.
273
274                x4 = (int) ((long) x4 * key[ik++] % 0x10001L & 0xffff);
275
276                // 5) XOR results from steps 1 and 3.
277
278                t2 = x1 ^ x3;
279
280                // 6) XOR results from steps 2 and 4.
281                // Included in step 8.
282
283                // 7) Multiply (modulo 0x10001), result of step 5
284                // with 5th key sub-block.
285
286                t2 = (int) ((long) t2 * key[ik++] % 0x10001L & 0xffff);
287
288                // 8) Add (modulo 0x10000), results of steps 6 and 7.
289
290                t1 = t2 + (x2 ^ x4) & 0xffff;
291
292                // 9) Multiply (modulo 0x10001), result of step 8
293                // with 6th key sub-block.
294
295                t1 = (int) ((long) t1 * key[ik++] % 0x10001L & 0xffff);
296
297                // 10) Add (modulo 0x10000), results of steps 7 and 9.
298
299                t2 = t1 + t2 & 0xffff;
300
301                // 11) XOR results from steps 1 and 9.
302
303                x1 ^= t1;
304
305                // 14) XOR results from steps 4 and 10. (Out of order).
306
307                x4 ^= t2;
308
309                // 13) XOR results from steps 2 and 10. (Out of order).
310
311                t2 ^= x2;
312
313                // 12) XOR results from steps 3 and 9. (Out of order).
314
315                x2 = x3 ^ t1;
316
317                x3 = t2; // Results of x2 and x3 now swapped.
318
319            } while (--r != 0); // Repeats seven more rounds.
320
321            // Final output transform (4 steps).
322
323            // 1) Multiply (modulo 0x10001), 1st text-block
324            // with 1st key sub-block.
325
326            x1 = (int) ((long) x1 * key[ik++] % 0x10001L & 0xffff);
327
328            // 2) Add (modulo 0x10000), 2nd text sub-block
329            // with 2nd key sub-block. It says x3, but that is to undo swap
330            // of subblocks 2 and 3 in 8th processing round.
331
332            x3 = x3 + key[ik++] & 0xffff;
333
334            // 3) Add (modulo 0x10000), 3rd text sub-block
335            // with 3rd key sub-block. It says x2, but that is to undo swap
336            // of subblocks 2 and 3 in 8th processing round.
337
338            x2 = x2 + key[ik++] & 0xffff;
339
340            // 4) Multiply (modulo 0x10001), 4th text-block
341            // with 4th key sub-block.
342
343            x4 = (int) ((long) x4 * key[ik++] % 0x10001L & 0xffff);
344
345            // Repackage from 16-bit sub-blocks to 8-bit byte array text2.
346
347            text2[i2++] = (byte) x1;
348            text2[i2++] = (byte) (x1 >>> 8);
349            text2[i2++] = (byte) x3; // x3 and x2 are switched
350            text2[i2++] = (byte) (x3 >>> 8); // only in name.
351            text2[i2++] = (byte) x2;
352            text2[i2++] = (byte) (x2 >>> 8);
353            text2[i2++] = (byte) x4;
354            text2[i2++] = (byte) (x4 >>> 8);
355
356        } // End for loop.
357
358    } // End routine.
359
360    /*
361     * mul
362     *
363     * Performs multiplication, modulo (2**16)+1. This code is structured on the assumption that
364     * untaken branches are cheaper than taken branches, and that the compiler doesn't schedule
365     * branches. Java: Must work with 32-bit int and one 64-bit long to keep 16-bit values and their
366     * products "unsigned." The routine assumes that both a and b could fit in 16 bits even though
367     * they come in as 32-bit ints. Lots of "& 0xFFFF" masks here to keep things 16-bit. Also,
368     * because the routine stores mod (2**16)+1 results in a 2**16 space, the result is truncated to
369     * zero whenever the result would zero, be 2**16. And if one of the multiplicands is 0, the
370     * result is not zero, but (2**16) + 1 minus the other multiplicand (sort of an additive inverse
371     * mod 0x10001).
372     *
373     * NOTE: The java conversion of this routine works correctly, but is half the speed of using
374     * Java's modulus division function (%) on the multiplication with a 16-bit masking of the
375     * result--running in the Symantec Caje IDE. So it's not called for now; the test uses Java %
376     * instead.
377     */
378
379    /*
380     * private int mul(int a, int b) throws ArithmeticException { long p; // Large enough to catch
381     * 16-bit multiply // without hitting sign bit. if (a != 0) { if (b != 0) { p = (long) a * b; b
382     * = (int) p & 0xFFFF; // Lower 16 bits. a = (int) p >>> 16; // Upper 16 bits.
383     *
384     * return (b - a + (b < a ? 1 : 0) & 0xFFFF); } else return ((1 - a) & 0xFFFF); // If b = 0,
385     * then same as // 0x10001 - a. } else // If a = 0, then return return((1 - b) & 0xFFFF); //
386     * same as 0x10001 - b. }
387     */
388
389    /*
390     * inv
391     *
392     * Compute multiplicative inverse of x, modulo (2**16)+1 using extended Euclid's GCD (greatest
393     * common divisor) algorithm. It is unrolled twice to avoid swapping the meaning of the
394     * registers. And some subtracts are changed to adds. Java: Though it uses signed 32-bit ints,
395     * the interpretation of the bits within is strictly unsigned 16-bit.
396     */
397
398    public int inv(int x) {
399        int x2 = x;
400        int t0, t1;
401        int q, y;
402
403        if (x2 <= 1) {
404            return (x2); // 0 and 1 are self-inverse.
405        }
406
407        t1 = 0x10001 / x2; // (2**16+1)/x; x is >= 2, so fits 16 bits.
408        y = 0x10001 % x2;
409        if (y == 1) {
410            return ((1 - t1) & 0xFFFF);
411        }
412
413        t0 = 1;
414        do {
415            q = x2 / y;
416            x2 = x2 % y;
417            t0 += q * t1;
418            if (x2 == 1) {
419                return (t0);
420            }
421            q = y / x2;
422            y = y % x2;
423            t1 += q * t0;
424        } while (y != 1);
425
426        return ((1 - t1) & 0xFFFF);
427    }
428
429    boolean verify() {
430        boolean error;
431        for (int i = 0; i < array_rows; i++) {
432            error = (plain1[i] != plain2[i]);
433            if (error) {
434                return false;
435            }
436        }
437        return true;
438    }
439
440    /*
441     * freeTestData
442     *
443     * Nulls arrays and forces garbage collection to free up memory.
444     */
445
446    void freeTestData() {
447        plain1 = null;
448        crypt1 = null;
449        plain2 = null;
450        userkey = null;
451        Z = null;
452        DK = null;
453    }
454
455    public HP_idea() {
456        array_rows = 3000;
457    }
458
459    @Test
460    public void run0() throws Throwable {
461        runTest("test");
462    }
463
464    @Test
465    public void runInv() {
466        runTest("inv", 724);
467    }
468}