1 /* Twofish.java --
2    Copyright (C) 2001, 2002, 2003, 2006, 2010 Free Software Foundation, Inc.
3 
4 This file is a part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 USA
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version.  */
37 
38 
39 package gnu.javax.crypto.cipher;
40 
41 import gnu.java.security.Configuration;
42 import gnu.java.security.Registry;
43 import gnu.java.security.util.Util;
44 
45 import java.security.InvalidKeyException;
46 import java.util.ArrayList;
47 import java.util.Collections;
48 import java.util.Iterator;
49 import java.util.logging.Logger;
50 
51 /**
52  * Twofish is a balanced 128-bit Feistel cipher, consisting of 16 rounds. In
53  * each round, a 64-bit S-box value is computed from 64 bits of the block, and
54  * this value is xored into the other half of the block. The two half-blocks are
55  * then exchanged, and the next round begins. Before the first round, all input
56  * bits are xored with key-dependent "whitening" subkeys, and after the final
57  * round the output bits are xored with other key-dependent whitening subkeys;
58  * these subkeys are not used anywhere else in the algorithm.
59  * <p>
60  * Twofish is designed by Bruce Schneier, Doug Whiting, John Kelsey, Chris
61  * Hall, David Wagner and Niels Ferguson.
62  * <p>
63  * References:
64  * <ol>
65  *    <li><a href="http://www.counterpane.com/twofish-paper.html">Twofish: A
66  *    128-bit Block Cipher</a>.</li>
67  * </ol>
68  */
69 public final class Twofish
70     extends BaseCipher
71 {
72   private static final Logger log = Configuration.DEBUG ?
73                         Logger.getLogger(Twofish.class.getName()) : null;
74   private static final int DEFAULT_BLOCK_SIZE = 16; // in bytes
75   private static final int DEFAULT_KEY_SIZE = 16; // in bytes
76   private static final int MAX_ROUNDS = 16; // max # rounds (for allocating subkeys)
77   private static final int ROUNDS = MAX_ROUNDS;
78   // subkey array indices
79   private static final int INPUT_WHITEN = 0;
80   private static final int OUTPUT_WHITEN = INPUT_WHITEN + DEFAULT_BLOCK_SIZE / 4;
81   private static final int ROUND_SUBKEYS = OUTPUT_WHITEN + DEFAULT_BLOCK_SIZE / 4;
82   private static final int SK_STEP = 0x02020202;
83   private static final int SK_BUMP = 0x01010101;
84   private static final int SK_ROTL = 9;
85   private static final String[] Pm = new String[] {
86       // p0
87       "\uA967\uB3E8\u04FD\uA376\u9A92\u8078\uE4DD\uD138"
88     + "\u0DC6\u3598\u18F7\uEC6C\u4375\u3726\uFA13\u9448"
89     + "\uF2D0\u8B30\u8454\uDF23\u195B\u3D59\uF3AE\uA282"
90     + "\u6301\u832E\uD951\u9B7C\uA6EB\uA5BE\u160C\uE361"
91     + "\uC08C\u3AF5\u732C\u250B\uBB4E\u896B\u536A\uB4F1"
92     + "\uE1E6\uBD45\uE2F4\uB666\uCC95\u0356\uD41C\u1ED7"
93     + "\uFBC3\u8EB5\uE9CF\uBFBA\uEA77\u39AF\u33C9\u6271"
94     + "\u8179\u09AD\u24CD\uF9D8\uE5C5\uB94D\u4408\u86E7"
95     + "\uA11D\uAAED\u0670\uB2D2\u417B\uA011\u31C2\u2790"
96     + "\u20F6\u60FF\u965C\uB1AB\u9E9C\u521B\u5F93\u0AEF"
97     + "\u9185\u49EE\u2D4F\u8F3B\u4787\u6D46\uD63E\u6964"
98     + "\u2ACE\uCB2F\uFC97\u057A\uAC7F\uD51A\u4B0E\uA75A"
99     + "\u2814\u3F29\u883C\u4C02\uB8DA\uB017\u551F\u8A7D"
100     + "\u57C7\u8D74\uB7C4\u9F72\u7E15\u2212\u5807\u9934"
101     + "\u6E50\uDE68\u65BC\uDBF8\uC8A8\u2B40\uDCFE\u32A4"
102     + "\uCA10\u21F0\uD35D\u0F00\u6F9D\u3642\u4A5E\uC1E0",
103       // p1
104       "\u75F3\uC6F4\uDB7B\uFBC8\u4AD3\uE66B\u457D\uE84B"
105     + "\uD632\uD8FD\u3771\uF1E1\u300F\uF81B\u87FA\u063F"
106     + "\u5EBA\uAE5B\u8A00\uBC9D\u6DC1\uB10E\u805D\uD2D5"
107     + "\uA084\u0714\uB590\u2CA3\uB273\u4C54\u9274\u3651"
108     + "\u38B0\uBD5A\uFC60\u6296\u6C42\uF710\u7C28\u278C"
109     + "\u1395\u9CC7\u2446\u3B70\uCAE3\u85CB\u11D0\u93B8"
110     + "\uA683\u20FF\u9F77\uC3CC\u036F\u08BF\u40E7\u2BE2"
111     + "\u790C\uAA82\u413A\uEAB9\uE49A\uA497\u7EDA\u7A17"
112     + "\u6694\uA11D\u3DF0\uDEB3\u0B72\uA71C\uEFD1\u533E"
113     + "\u8F33\u265F\uEC76\u2A49\u8188\uEE21\uC41A\uEBD9"
114     + "\uC539\u99CD\uAD31\u8B01\u1823\uDD1F\u4E2D\uF948"
115     + "\u4FF2\u658E\u785C\u5819\u8DE5\u9857\u677F\u0564"
116     + "\uAF63\uB6FE\uF5B7\u3CA5\uCEE9\u6844\uE04D\u4369"
117     + "\u292E\uAC15\u59A8\u0A9E\u6E47\uDF34\u356A\uCFDC"
118     + "\u22C9\uC09B\u89D4\uEDAB\u12A2\u0D52\uBB02\u2FA9"
119     + "\uD761\u1EB4\u5004\uF6C2\u1625\u8656\u5509\uBE91" };
120   /** Fixed 8x8 permutation S-boxes */
121   private static final byte[][] P = new byte[2][256]; // blank final
122   /**
123    * Define the fixed p0/p1 permutations used in keyed S-box lookup. By
124    * changing the following constant definitions, the S-boxes will
125    * automatically get changed in the Twofish engine.
126    */
127   private static final int P_00 = 1;
128   private static final int P_01 = 0;
129   private static final int P_02 = 0;
130   private static final int P_03 = P_01 ^ 1;
131   private static final int P_04 = 1;
132   private static final int P_10 = 0;
133   private static final int P_11 = 0;
134   private static final int P_12 = 1;
135   private static final int P_13 = P_11 ^ 1;
136   private static final int P_14 = 0;
137   private static final int P_20 = 1;
138   private static final int P_21 = 1;
139   private static final int P_22 = 0;
140   private static final int P_23 = P_21 ^ 1;
141   private static final int P_24 = 0;
142   private static final int P_30 = 0;
143   private static final int P_31 = 1;
144   private static final int P_32 = 1;
145   private static final int P_33 = P_31 ^ 1;
146   private static final int P_34 = 1;
147   /** Primitive polynomial for GF(256) */
148   private static final int GF256_FDBK_2 = 0x169 / 2;
149   private static final int GF256_FDBK_4 = 0x169 / 4;
150   /** MDS matrix */
151   private static final int[][] MDS = new int[4][256]; // blank final
152   private static final int RS_GF_FDBK = 0x14D; // field generator
153   /**
154    * KAT vector (from ecb_vk):
155    * I=183
156    * KEY=0000000000000000000000000000000000000000000002000000000000000000
157    * CT=F51410475B33FBD3DB2117B5C17C82D4
158    */
159   private static final byte[] KAT_KEY = Util.toBytesFromString(
160       "0000000000000000000000000000000000000000000002000000000000000000");
161   private static final byte[] KAT_CT =
162       Util.toBytesFromString("F51410475B33FBD3DB2117B5C17C82D4");
163   /** caches the result of the correctness test, once executed. */
164   private static Boolean valid;
165   static
166     {
167       long time = System.currentTimeMillis();
168       // expand the P arrays
169       int i;
170       char c;
171       for (i = 0; i < 256; i++)
172         {
173           c = Pm[0].charAt(i >>> 1);
174           P[0][i] = (byte)((i & 1) == 0 ? c >>> 8 : c);
175           c = Pm[1].charAt(i >>> 1);
176           P[1][i] = (byte)((i & 1) == 0 ? c >>> 8 : c);
177         }
178       // precompute the MDS matrix
179       int[] m1 = new int[2];
180       int[] mX = new int[2];
181       int[] mY = new int[2];
182       int j;
183       for (i = 0; i < 256; i++)
184         {
185           j = P[0][i] & 0xFF; // compute all the matrix elements
186           m1[0] = j;
187           mX[0] = Mx_X(j) & 0xFF;
188           mY[0] = Mx_Y(j) & 0xFF;
189           j = P[1][i] & 0xFF;
190           m1[1] = j;
191           mX[1] = Mx_X(j) & 0xFF;
192           mY[1] = Mx_Y(j) & 0xFF;
193           MDS[0][i] = m1[P_00] << 0
194                     | mX[P_00] << 8
195                     | mY[P_00] << 16
196                     | mY[P_00] << 24;
197           MDS[1][i] = mY[P_10] << 0
198                     | mY[P_10] << 8
199                     | mX[P_10] << 16
200                     | m1[P_10] << 24;
201           MDS[2][i] = mX[P_20] << 0
202                     | mY[P_20] << 8
203                     | m1[P_20] << 16
204                     | mY[P_20] << 24;
205           MDS[3][i] = mX[P_30] << 0
206                     | m1[P_30] << 8
207                     | mY[P_30] << 16
208                     | mX[P_30] << 24;
209         }
210       time = System.currentTimeMillis() - time;
211       if (Configuration.DEBUG)
212         {
213           log.fine("Static Data");
214           log.fine("MDS[0][]:");
215           StringBuilder sb;
216           for (i = 0; i < 64; i++)
217             {
218               sb = new StringBuilder();
219               for (j = 0; j < 4; j++)
220                 sb.append("0x").append(Util.toString(MDS[0][i * 4 + j])).append(", ");
sb.toString()221               log.fine(sb.toString());
222             }
223           log.fine("MDS[1][]:");
224           for (i = 0; i < 64; i++)
225             {
226               sb = new StringBuilder();
227               for (j = 0; j < 4; j++)
228                 sb.append("0x").append(Util.toString(MDS[1][i * 4 + j])).append(", ");
sb.toString()229               log.fine(sb.toString());
230             }
231           log.fine("MDS[2][]:");
232           for (i = 0; i < 64; i++)
233             {
234               sb = new StringBuilder();
235               for (j = 0; j < 4; j++)
236                 sb.append("0x").append(Util.toString(MDS[2][i * 4 + j])).append(", ");
sb.toString()237               log.fine(sb.toString());
238             }
239           log.fine("MDS[3][]:");
240           for (i = 0; i < 64; i++)
241             {
242               sb = new StringBuilder();
243               for (j = 0; j < 4; j++)
244                 sb.append("0x").append(Util.toString(MDS[3][i * 4 + j])).append(", ");
sb.toString()245               log.fine(sb.toString());
246             }
247           log.fine("Total initialization time: " + time + " ms.");
248         }
249     }
250 
LFSR1(int x)251   private static final int LFSR1(int x)
252   {
253     return (x >> 1) ^ ((x & 0x01) != 0 ? GF256_FDBK_2 : 0);
254   }
255 
LFSR2(int x)256   private static final int LFSR2(int x)
257   {
258     return (x >> 2)
259         ^ ((x & 0x02) != 0 ? GF256_FDBK_2 : 0)
260         ^ ((x & 0x01) != 0 ? GF256_FDBK_4 : 0);
261   }
262 
Mx_X(int x)263   private static final int Mx_X(int x)
264   { // 5B
265     return x ^ LFSR2(x);
266   }
267 
Mx_Y(int x)268   private static final int Mx_Y(int x)
269   { // EF
270     return x ^ LFSR1(x) ^ LFSR2(x);
271   }
272 
273   /** Trivial 0-arguments constructor. */
Twofish()274   public Twofish()
275   {
276     super(Registry.TWOFISH_CIPHER, DEFAULT_BLOCK_SIZE, DEFAULT_KEY_SIZE);
277   }
278 
b0(int x)279   private static final int b0(int x)
280   {
281     return x & 0xFF;
282   }
283 
b1(int x)284   private static final int b1(int x)
285   {
286     return (x >>> 8) & 0xFF;
287   }
288 
b2(int x)289   private static final int b2(int x)
290   {
291     return (x >>> 16) & 0xFF;
292   }
293 
b3(int x)294   private static final int b3(int x)
295   {
296     return (x >>> 24) & 0xFF;
297   }
298 
299   /**
300    * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box 32-bit
301    * entity from two key material 32-bit entities.
302    *
303    * @param k0 1st 32-bit entity.
304    * @param k1 2nd 32-bit entity.
305    * @return remainder polynomial generated using RS code
306    */
RS_MDS_Encode(int k0, int k1)307   private static final int RS_MDS_Encode(int k0, int k1)
308   {
309     int r = k1;
310     int i;
311     for (i = 0; i < 4; i++) // shift 1 byte at a time
312       r = RS_rem(r);
313     r ^= k0;
314     for (i = 0; i < 4; i++)
315       r = RS_rem(r);
316     return r;
317   }
318 
319   /**
320    * Reed-Solomon code parameters: (12, 8) reversible code:<p>
321    * <pre>
322    *   g(x) = x**4 + (a + 1/a) x**3 + a x**2 + (a + 1/a) x + 1
323    * </pre>
324    * where a = primitive root of field generator 0x14D
325    */
RS_rem(int x)326   private static final int RS_rem(int x)
327   {
328     int b = (x >>> 24) & 0xFF;
329     int g2 = ((b << 1) ^ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xFF;
330     int g3 = (b >>> 1) ^ ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0) ^ g2;
331     int result = (x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b;
332     return result;
333   }
334 
F32(int k64Cnt, int x, int[] k32)335   private static final int F32(int k64Cnt, int x, int[] k32)
336   {
337     int b0 = b0(x);
338     int b1 = b1(x);
339     int b2 = b2(x);
340     int b3 = b3(x);
341     int k0 = k32[0];
342     int k1 = k32[1];
343     int k2 = k32[2];
344     int k3 = k32[3];
345     int result = 0;
346     switch (k64Cnt & 3)
347       {
348       case 1:
349         result = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)]
350                ^ MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)]
351                ^ MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)]
352                ^ MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)];
353         break;
354       case 0: // same as 4
355         b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);
356         b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);
357         b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);
358         b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);
359       case 3:
360         b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);
361         b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);
362         b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);
363         b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);
364       case 2: // 128-bit keys (optimize for this case)
365         result = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF) ^ b0(k0)]
366                ^ MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF) ^ b1(k0)]
367                ^ MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF) ^ b2(k0)]
368                ^ MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF) ^ b3(k0)];
369         break;
370       }
371     return result;
372   }
373 
Fe32(int[] sBox, int x, int R)374   private static final int Fe32(int[] sBox, int x, int R)
375   {
376     return sBox[        2 * _b(x, R    )    ]
377          ^ sBox[        2 * _b(x, R + 1) + 1]
378          ^ sBox[0x200 + 2 * _b(x, R + 2)    ]
379          ^ sBox[0x200 + 2 * _b(x, R + 3) + 1];
380   }
381 
_b(int x, int N)382   private static final int _b(int x, int N)
383   {
384     switch (N % 4)
385       {
386       case 0:
387         return x & 0xFF;
388       case 1:
389         return (x >>> 8) & 0xFF;
390       case 2:
391         return (x >>> 16) & 0xFF;
392       default:
393         return x >>> 24;
394       }
395   }
396 
clone()397   public Object clone()
398   {
399     Twofish result = new Twofish();
400     result.currentBlockSize = this.currentBlockSize;
401     return result;
402   }
403 
blockSizes()404   public Iterator blockSizes()
405   {
406     ArrayList al = new ArrayList();
407     al.add(Integer.valueOf(DEFAULT_BLOCK_SIZE));
408     return Collections.unmodifiableList(al).iterator();
409   }
410 
keySizes()411   public Iterator keySizes()
412   {
413     ArrayList al = new ArrayList();
414     al.add(Integer.valueOf(8)); //   64-bit
415     al.add(Integer.valueOf(16)); // 128-bit
416     al.add(Integer.valueOf(24)); // 192-bit
417     al.add(Integer.valueOf(32)); // 256-bit
418     return Collections.unmodifiableList(al).iterator();
419   }
420 
421   /**
422    * Expands a user-supplied key material into a session key for a designated
423    * <i>block size</i>.
424    *
425    * @param k the 64/128/192/256-bit user-key to use.
426    * @param bs the desired block size in bytes.
427    * @return an Object encapsulating the session key.
428    * @exception IllegalArgumentException if the block size is not 16 (128-bit).
429    * @exception InvalidKeyException if the key data is invalid.
430    */
makeKey(byte[] k, int bs)431   public Object makeKey(byte[] k, int bs) throws InvalidKeyException
432   {
433     if (bs != DEFAULT_BLOCK_SIZE)
434       throw new IllegalArgumentException();
435     if (k == null)
436       throw new InvalidKeyException("Empty key");
437     int length = k.length;
438     if (! (length == 8 || length == 16 || length == 24 || length == 32))
439       throw new InvalidKeyException("Incorrect key length");
440     int k64Cnt = length / 8;
441     int subkeyCnt = ROUND_SUBKEYS + 2 * ROUNDS;
442     int[] k32e = new int[4]; // even 32-bit entities
443     int[] k32o = new int[4]; // odd 32-bit entities
444     int[] sBoxKey = new int[4];
445     // split user key material into even and odd 32-bit entities and
446     // compute S-box keys using (12, 8) Reed-Solomon code over GF(256)
447     int i, j, offset = 0;
448     for (i = 0, j = k64Cnt - 1; i < 4 && offset < length; i++, j--)
449       {
450         k32e[i] = (k[offset++] & 0xFF)
451                 | (k[offset++] & 0xFF) << 8
452                 | (k[offset++] & 0xFF) << 16
453                 | (k[offset++] & 0xFF) << 24;
454         k32o[i] = (k[offset++] & 0xFF)
455                 | (k[offset++] & 0xFF) << 8
456                 | (k[offset++] & 0xFF) << 16
457                 | (k[offset++] & 0xFF) << 24;
458         sBoxKey[j] = RS_MDS_Encode(k32e[i], k32o[i]); // reverse order
459       }
460     // compute the round decryption subkeys for PHT. these same subkeys
461     // will be used in encryption but will be applied in reverse order.
462     int q, A, B;
463     int[] subKeys = new int[subkeyCnt];
464     for (i = q = 0; i < subkeyCnt / 2; i++, q += SK_STEP)
465       {
466         A = F32(k64Cnt, q, k32e); // A uses even key entities
467         B = F32(k64Cnt, q + SK_BUMP, k32o); // B uses odd  key entities
468         B = B << 8 | B >>> 24;
469         A += B;
470         subKeys[2 * i] = A; // combine with a PHT
471         A += B;
472         subKeys[2 * i + 1] = A << SK_ROTL | A >>> (32 - SK_ROTL);
473       }
474     // fully expand the table for speed
475     int k0 = sBoxKey[0];
476     int k1 = sBoxKey[1];
477     int k2 = sBoxKey[2];
478     int k3 = sBoxKey[3];
479     int b0, b1, b2, b3;
480     int[] sBox = new int[4 * 256];
481     for (i = 0; i < 256; i++)
482       {
483         b0 = b1 = b2 = b3 = i;
484         switch (k64Cnt & 3)
485           {
486           case 1:
487             sBox[        2 * i    ] = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)];
488             sBox[        2 * i + 1] = MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)];
489             sBox[0x200 + 2 * i    ] = MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)];
490             sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)];
491             break;
492           case 0: // same as 4
493             b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);
494             b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);
495             b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);
496             b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);
497           case 3:
498             b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);
499             b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);
500             b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);
501             b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);
502           case 2: // 128-bit keys
503             sBox[        2 * i    ] = MDS[0][(P[P_01][(P[P_02][b0] & 0xFF)
504                                                       ^ b0(k1)] & 0xFF) ^ b0(k0)];
505             sBox[        2 * i + 1] = MDS[1][(P[P_11][(P[P_12][b1] & 0xFF)
506                                                       ^ b1(k1)] & 0xFF) ^ b1(k0)];
507             sBox[0x200 + 2 * i    ] = MDS[2][(P[P_21][(P[P_22][b2] & 0xFF)
508                                                       ^ b2(k1)] & 0xFF) ^ b2(k0)];
509             sBox[0x200 + 2 * i + 1] = MDS[3][(P[P_31][(P[P_32][b3] & 0xFF)
510                                                       ^ b3(k1)] & 0xFF) ^ b3(k0)];
511           }
512       }
513     if (Configuration.DEBUG)
514       {
515         StringBuilder sb;
516         log.fine("S-box[]:");
517         for (i = 0; i < 64; i++)
518           {
519             sb = new StringBuilder();
520             for (j = 0; j < 4; j++)
521               sb.append("0x").append(Util.toString(sBox[i * 4 + j])).append(", ");
522             log.fine(sb.toString());
523           }
524         log.fine("");
525         for (i = 0; i < 64; i++)
526           {
527             sb = new StringBuilder();
528             for (j = 0; j < 4; j++)
529               sb.append("0x").append(Util.toString(sBox[256 + i * 4 + j])).append(", ");
530             log.fine(sb.toString());
531           }
532         log.fine("");
533         for (i = 0; i < 64; i++)
534           {
535             sb = new StringBuilder();
536             for (j = 0; j < 4; j++)
537               sb.append("0x").append(Util.toString(sBox[512 + i * 4 + j])).append(", ");
538             log.fine(sb.toString());
539           }
540         log.fine("");
541         for (i = 0; i < 64; i++)
542           {
543             sb = new StringBuilder();
544             for (j = 0; j < 4; j++)
545               sb.append("0x").append(Util.toString(sBox[768 + i * 4 + j])).append(", ");
546             log.fine(sb.toString());
547           }
548         log.fine("User (odd, even) keys  --> S-Box keys:");
549         for (i = 0; i < k64Cnt; i++)
550           log.fine("0x" + Util.toString(k32o[i])
551                    + "  0x" + Util.toString(k32e[i])
552                    + " --> 0x" + Util.toString(sBoxKey[k64Cnt - 1 - i]));
553         log.fine("Round keys:");
554         for (i = 0; i < ROUND_SUBKEYS + 2 * ROUNDS; i += 2)
555           log.fine("0x" + Util.toString(subKeys[i])
556                    + "  0x" + Util.toString(subKeys[i + 1]));
557       }
558     return new Object[] { sBox, subKeys };
559   }
560 
encrypt(byte[] in, int inOffset, byte[] out, int outOffset, Object sessionKey, int bs)561   public void encrypt(byte[] in, int inOffset, byte[] out, int outOffset,
562                       Object sessionKey, int bs)
563   {
564     if (bs != DEFAULT_BLOCK_SIZE)
565       throw new IllegalArgumentException();
566     Object[] sk = (Object[]) sessionKey; // extract S-box and session key
567     int[] sBox = (int[]) sk[0];
568     int[] sKey = (int[]) sk[1];
569     if (Configuration.DEBUG)
570       log.fine("PT=" + Util.toString(in, inOffset, bs));
571     int x0 = (in[inOffset++] & 0xFF)
572            | (in[inOffset++] & 0xFF) << 8
573            | (in[inOffset++] & 0xFF) << 16
574            | (in[inOffset++] & 0xFF) << 24;
575     int x1 = (in[inOffset++] & 0xFF)
576            | (in[inOffset++] & 0xFF) << 8
577            | (in[inOffset++] & 0xFF) << 16
578            | (in[inOffset++] & 0xFF) << 24;
579     int x2 = (in[inOffset++] & 0xFF)
580            | (in[inOffset++] & 0xFF) << 8
581            | (in[inOffset++] & 0xFF) << 16
582            | (in[inOffset++] & 0xFF) << 24;
583     int x3 = (in[inOffset++] & 0xFF)
584            | (in[inOffset++] & 0xFF) << 8
585            | (in[inOffset++] & 0xFF) << 16
586            | (in[inOffset++] & 0xFF) << 24;
587     x0 ^= sKey[INPUT_WHITEN];
588     x1 ^= sKey[INPUT_WHITEN + 1];
589     x2 ^= sKey[INPUT_WHITEN + 2];
590     x3 ^= sKey[INPUT_WHITEN + 3];
591     if (Configuration.DEBUG)
592       log.fine("PTw=" + Util.toString(x0) + Util.toString(x1)
593                + Util.toString(x2) + Util.toString(x3));
594     int t0, t1;
595     int k = ROUND_SUBKEYS;
596     for (int R = 0; R < ROUNDS; R += 2)
597       {
598         t0 = Fe32(sBox, x0, 0);
599         t1 = Fe32(sBox, x1, 3);
600         x2 ^= t0 + t1 + sKey[k++];
601         x2 = x2 >>> 1 | x2 << 31;
602         x3 = x3 << 1 | x3 >>> 31;
603         x3 ^= t0 + 2 * t1 + sKey[k++];
604         if (Configuration.DEBUG)
605           log.fine("CT" + (R) + "=" + Util.toString(x0) + Util.toString(x1)
606                    + Util.toString(x2) + Util.toString(x3));
607         t0 = Fe32(sBox, x2, 0);
608         t1 = Fe32(sBox, x3, 3);
609         x0 ^= t0 + t1 + sKey[k++];
610         x0 = x0 >>> 1 | x0 << 31;
611         x1 = x1 << 1 | x1 >>> 31;
612         x1 ^= t0 + 2 * t1 + sKey[k++];
613         if (Configuration.DEBUG)
614           log.fine("CT" + (R + 1) + "=" + Util.toString(x0) + Util.toString(x1)
615                    + Util.toString(x2) + Util.toString(x3));
616       }
617     x2 ^= sKey[OUTPUT_WHITEN];
618     x3 ^= sKey[OUTPUT_WHITEN + 1];
619     x0 ^= sKey[OUTPUT_WHITEN + 2];
620     x1 ^= sKey[OUTPUT_WHITEN + 3];
621     if (Configuration.DEBUG)
622       log.fine("CTw=" + Util.toString(x0) + Util.toString(x1)
623                + Util.toString(x2) + Util.toString(x3));
624     out[outOffset++] = (byte) x2;
625     out[outOffset++] = (byte)(x2 >>> 8);
626     out[outOffset++] = (byte)(x2 >>> 16);
627     out[outOffset++] = (byte)(x2 >>> 24);
628     out[outOffset++] = (byte) x3;
629     out[outOffset++] = (byte)(x3 >>> 8);
630     out[outOffset++] = (byte)(x3 >>> 16);
631     out[outOffset++] = (byte)(x3 >>> 24);
632     out[outOffset++] = (byte) x0;
633     out[outOffset++] = (byte)(x0 >>> 8);
634     out[outOffset++] = (byte)(x0 >>> 16);
635     out[outOffset++] = (byte)(x0 >>> 24);
636     out[outOffset++] = (byte) x1;
637     out[outOffset++] = (byte)(x1 >>> 8);
638     out[outOffset++] = (byte)(x1 >>> 16);
639     out[outOffset  ] = (byte)(x1 >>> 24);
640     if (Configuration.DEBUG)
641       log.fine("CT=" + Util.toString(out, outOffset - 15, 16) + "\n");
642   }
643 
decrypt(byte[] in, int inOffset, byte[] out, int outOffset, Object sessionKey, int bs)644   public void decrypt(byte[] in, int inOffset, byte[] out, int outOffset,
645                       Object sessionKey, int bs)
646   {
647     if (bs != DEFAULT_BLOCK_SIZE)
648       throw new IllegalArgumentException();
649     Object[] sk = (Object[]) sessionKey; // extract S-box and session key
650     int[] sBox = (int[]) sk[0];
651     int[] sKey = (int[]) sk[1];
652     if (Configuration.DEBUG)
653       log.fine("CT=" + Util.toString(in, inOffset, bs));
654     int x2 = (in[inOffset++] & 0xFF)
655            | (in[inOffset++] & 0xFF) << 8
656            | (in[inOffset++] & 0xFF) << 16
657            | (in[inOffset++] & 0xFF) << 24;
658     int x3 = (in[inOffset++] & 0xFF)
659            | (in[inOffset++] & 0xFF) << 8
660            | (in[inOffset++] & 0xFF) << 16
661            | (in[inOffset++] & 0xFF) << 24;
662     int x0 = (in[inOffset++] & 0xFF)
663            | (in[inOffset++] & 0xFF) << 8
664            | (in[inOffset++] & 0xFF) << 16
665            | (in[inOffset++] & 0xFF) << 24;
666     int x1 = (in[inOffset++] & 0xFF)
667            | (in[inOffset++] & 0xFF) << 8
668            | (in[inOffset++] & 0xFF) << 16
669            | (in[inOffset++] & 0xFF) << 24;
670     x2 ^= sKey[OUTPUT_WHITEN];
671     x3 ^= sKey[OUTPUT_WHITEN + 1];
672     x0 ^= sKey[OUTPUT_WHITEN + 2];
673     x1 ^= sKey[OUTPUT_WHITEN + 3];
674     if (Configuration.DEBUG)
675       log.fine("CTw=" + Util.toString(x2) + Util.toString(x3)
676                + Util.toString(x0) + Util.toString(x1));
677     int k = ROUND_SUBKEYS + 2 * ROUNDS - 1;
678     int t0, t1;
679     for (int R = 0; R < ROUNDS; R += 2)
680       {
681         t0 = Fe32(sBox, x2, 0);
682         t1 = Fe32(sBox, x3, 3);
683         x1 ^= t0 + 2 * t1 + sKey[k--];
684         x1 = x1 >>> 1 | x1 << 31;
685         x0 = x0 << 1 | x0 >>> 31;
686         x0 ^= t0 + t1 + sKey[k--];
687         if (Configuration.DEBUG)
688           log.fine("PT" + (ROUNDS - R) + "=" + Util.toString(x2)
689                    + Util.toString(x3) + Util.toString(x0) + Util.toString(x1));
690         t0 = Fe32(sBox, x0, 0);
691         t1 = Fe32(sBox, x1, 3);
692         x3 ^= t0 + 2 * t1 + sKey[k--];
693         x3 = x3 >>> 1 | x3 << 31;
694         x2 = x2 << 1 | x2 >>> 31;
695         x2 ^= t0 + t1 + sKey[k--];
696         if (Configuration.DEBUG)
697           log.fine("PT" + (ROUNDS - R - 1) + "=" + Util.toString(x2)
698                    + Util.toString(x3) + Util.toString(x0) + Util.toString(x1));
699       }
700     x0 ^= sKey[INPUT_WHITEN];
701     x1 ^= sKey[INPUT_WHITEN + 1];
702     x2 ^= sKey[INPUT_WHITEN + 2];
703     x3 ^= sKey[INPUT_WHITEN + 3];
704     if (Configuration.DEBUG)
705       log.fine("PTw=" + Util.toString(x2) + Util.toString(x3)
706                + Util.toString(x0) + Util.toString(x1));
707     out[outOffset++] = (byte) x0;
708     out[outOffset++] = (byte)(x0 >>> 8);
709     out[outOffset++] = (byte)(x0 >>> 16);
710     out[outOffset++] = (byte)(x0 >>> 24);
711     out[outOffset++] = (byte) x1;
712     out[outOffset++] = (byte)(x1 >>> 8);
713     out[outOffset++] = (byte)(x1 >>> 16);
714     out[outOffset++] = (byte)(x1 >>> 24);
715     out[outOffset++] = (byte) x2;
716     out[outOffset++] = (byte)(x2 >>> 8);
717     out[outOffset++] = (byte)(x2 >>> 16);
718     out[outOffset++] = (byte)(x2 >>> 24);
719     out[outOffset++] = (byte) x3;
720     out[outOffset++] = (byte)(x3 >>> 8);
721     out[outOffset++] = (byte)(x3 >>> 16);
722     out[outOffset  ] = (byte)(x3 >>> 24);
723     if (Configuration.DEBUG)
724       log.fine("PT=" + Util.toString(out, outOffset - 15, 16) + "\n");
725   }
726 
selfTest()727   public boolean selfTest()
728   {
729     if (valid == null)
730       {
731         boolean result = super.selfTest(); // do symmetry tests
732         if (result)
733           result = testKat(KAT_KEY, KAT_CT);
734         valid = Boolean.valueOf(result);
735       }
736     return valid.booleanValue();
737   }
738 }
739