Source code: cryptix/jce/provider/cipher/Twofish.java
1 /* $Id: Twofish.java,v 1.4 2000/02/12 03:14:31 gelderen Exp $
2 *
3 * Copyright (C) 1997-2000 The Cryptix Foundation Limited.
4 * All rights reserved.
5 *
6 * Use, modification, copying and distribution of this software is subject
7 * the terms and conditions of the Cryptix General Licence. You should have
8 * received a copy of the Cryptix General Licence along with this library;
9 * if not, you can download a copy from http://www.cryptix.org/ .
10 */
11 package cryptix.jce.provider.cipher;
12
13 import java.security.InvalidKeyException;
14 import java.security.Key;
15
16
17 /**
18 * Twofish is an AES candidate algorithm. It is a balanced 128-bit Feistel
19 * cipher, consisting of 16 rounds. In each round, a 64-bit S-box value is
20 * computed from 64 bits of the block, and this value is xored into the other
21 * half of the block. The two half-blocks are then exchanged, and the next
22 * round begins. Before the first round, all input bits are xored with key-
23 * dependent "whitening" subkeys, and after the final round the output bits
24 * are xored with other key-dependent whitening subkeys; these subkeys are
25 * not used anywhere else in the algorithm.<p>
26 *
27 * Twofish was submitted by Bruce Schneier, Doug Whiting, John Kelsey, Chris
28 * Hall and David Wagner.<p>
29 *
30 * Reference:<ol>
31 * <li>TWOFISH2.C -- Optimized C API calls for TWOFISH AES submission,
32 * Version 1.00, April 1998, by Doug Whiting.</ol><p>
33 *
34 * @version $Revision: 1.4 $
35 * @author Raif S. Naffah
36 * @author Jeroen C. van Gelderen (gelderen@cryptix.org)
37 */
38 public final class Twofish extends BlockCipher
39 {
40
41 // Constants
42 //...........................................................................
43
44 private static final int
45 BLOCK_SIZE = 16, // bytes in a data-block
46 ROUNDS = 16;
47
48 private static final int
49 TOTAL_SUBKEYS = 4 + 4 + 2*ROUNDS;
50
51 private static final int
52 SK_BUMP = 0x01010101,
53 SK_ROTL = 9;
54
55 /** Fixed 8x8 permutation S-boxes */
56 private static final byte[][] P = new byte[][]
57 {
58 { // p0
59 (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
60 (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
61 (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
62 (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
63 (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
64 (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
65 (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
66 (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
67 (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
68 (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
69 (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
70 (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
71 (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
72 (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
73 (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
74 (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
75 (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
76 (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
77 (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
78 (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
79 (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
80 (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
81 (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
82 (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
83 (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
84 (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
85 (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
86 (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
87 (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
88 (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
89 (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
90 (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
91 (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
92 (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
93 (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
94 (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
95 (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
96 (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
97 (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
98 (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
99 (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
100 (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
101 (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
102 (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
103 (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
104 (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
105 (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
106 (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
107 (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
108 (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
109 (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
110 (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
111 (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
112 (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
113 (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
114 (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
115 (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
116 (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
117 (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
118 (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
119 (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
120 (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
121 (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
122 (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0
123 },
124 { // p1
125 (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
126 (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
127 (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
128 (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
129 (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
130 (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
131 (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
132 (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
133 (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
134 (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
135 (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
136 (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
137 (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
138 (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
139 (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
140 (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
141 (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
142 (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
143 (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
144 (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
145 (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
146 (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
147 (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
148 (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
149 (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
150 (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
151 (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
152 (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
153 (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
154 (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
155 (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
156 (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
157 (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
158 (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
159 (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
160 (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
161 (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
162 (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
163 (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
164 (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
165 (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
166 (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
167 (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
168 (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
169 (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
170 (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
171 (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
172 (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
173 (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
174 (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
175 (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
176 (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
177 (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
178 (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
179 (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
180 (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
181 (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
182 (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
183 (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
184 (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
185 (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
186 (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
187 (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
188 (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91
189 }
190 };
191
192 /**
193 * Define the fixed p0/p1 permutations used in keyed S-box lookup.
194 * By changing the following constant definitions, the S-boxes will
195 * automatically get changed in the Twofish engine.
196 */
197 private static final int
198 P_00 = 1,
199 P_01 = 0,
200 P_02 = 0,
201 P_03 = P_01 ^ 1,
202 P_04 = 1,
203 P_10 = 0,
204 P_11 = 0,
205 P_12 = 1,
206 P_13 = P_11 ^ 1,
207 P_14 = 0,
208 P_20 = 1,
209 P_21 = 1,
210 P_22 = 0,
211 P_23 = P_21 ^ 1,
212 P_24 = 0,
213 P_30 = 0,
214 P_31 = 1,
215 P_32 = 1,
216 P_33 = P_31 ^ 1,
217 P_34 = 1;
218
219 /** Primitive polynomial for GF(256) */
220 private static final int
221 GF256_FDBK = 0x169,
222 GF256_FDBK_2 = 0x169 / 2,
223 GF256_FDBK_4 = 0x169 / 4;
224
225 /** MDS matrix */
226 private static final int[][] MDS = new int[4][256]; // blank final
227
228 private static final int RS_GF_FDBK = 0x14D; // field generator
229
230
231 // Static code - to intialise the MDS matrix
232 //...........................................................................
233
234 static
235 {
236 // precompute the MDS matrix
237
238 int[] m1 = new int[2];
239 int[] mX = new int[2];
240 int[] mY = new int[2];
241 int i, j;
242 for (i = 0; i < 256; i++)
243 {
244 j = P[0][i] & 0xFF; // compute all the matrix elements
245 m1[0] = j;
246 mX[0] = Mx_X( j ) & 0xFF;
247 mY[0] = Mx_Y( j ) & 0xFF;
248
249 j = P[1][i] & 0xFF;
250 m1[1] = j;
251 mX[1] = Mx_X( j ) & 0xFF;
252 mY[1] = Mx_Y( j ) & 0xFF;
253
254 MDS[0][i] = m1[P_00] << 0 | // fill matrix w/ above elements
255 mX[P_00] << 8 |
256 mY[P_00] << 16 |
257 mY[P_00] << 24;
258 MDS[1][i] = mY[P_10] << 0 |
259 mY[P_10] << 8 |
260 mX[P_10] << 16 |
261 m1[P_10] << 24;
262 MDS[2][i] = mX[P_20] << 0 |
263 mY[P_20] << 8 |
264 m1[P_20] << 16 |
265 mY[P_20] << 24;
266 MDS[3][i] = mX[P_30] << 0 |
267 m1[P_30] << 8 |
268 mY[P_30] << 16 |
269 mX[P_30] << 24;
270 }
271 }
272
273 private static final int LFSR1( int x )
274 {
275 return (x >> 1) ^
276 ((x & 0x01) != 0 ? GF256_FDBK_2 : 0);
277 }
278
279 private static final int LFSR2( int x )
280 {
281 return (x >> 2) ^
282 ((x & 0x02) != 0 ? GF256_FDBK_2 : 0) ^
283 ((x & 0x01) != 0 ? GF256_FDBK_4 : 0);
284 }
285
286 private static final int Mx_1( int x ) { return x; }
287 private static final int Mx_X( int x ) { return x ^ LFSR2(x); }
288 private static final int Mx_Y( int x ) { return x ^ LFSR1(x) ^ LFSR2(x); }
289
290
291 // Instance variables
292 //...........................................................................
293
294 /** Encrypt (false) or decrypt mode (true) */
295 private boolean decrypt;
296
297
298 /** Key dependent S-box */
299 private final int[] sBox = new int[4 * 256];
300
301
302 /** Subkeys */
303 private final int[] subKeys = new int[TOTAL_SUBKEYS];
304
305
306 // Constructor
307 //...........................................................................
308
309 public Twofish()
310 {
311 super(BLOCK_SIZE);
312 }
313
314
315 // BlockCipher abstract method implementation
316 //...........................................................................
317
318 protected void coreInit(Key key, boolean decrypt)
319 throws InvalidKeyException
320 {
321 if( key==null )
322 throw new InvalidKeyException("key: key is null");
323
324 if( !key.getFormat().equalsIgnoreCase("RAW") )
325 throw new InvalidKeyException("key: wrong format, RAW needed");
326
327 byte[] userkey = key.getEncoded();
328 if(userkey == null)
329 throw new InvalidKeyException("RAW bytes missing");
330
331 int len = userkey.length ;
332 if( len != 16 && len != 24 && len!=32 )
333 throw new InvalidKeyException("Invalid user key length");
334
335 this.decrypt = decrypt;
336 makeSubKeys(userkey);
337 }
338
339
340 protected void coreCrypt(byte[] in, int inOffset, byte[] out, int outOffset)
341 {
342 blockCrypt(in, inOffset, out, outOffset);
343 }
344
345
346 // Private methods
347 //...........................................................................
348
349 /**
350 * Expand a user-supplied key material into a session key.
351 *
352 * @param key The 64/128/192/256-bit user-key to use.
353 * @return This cipher's round keys.
354 * @exception InvalidKeyException If the key is invalid.
355 */
356 private final void makeSubKeys(byte[] k)
357 throws InvalidKeyException
358 {
359 int length = k.length;
360 int k64Cnt = length / 8;
361 int[] k32e = new int[4]; // even 32-bit entities
362 int[] k32o = new int[4]; // odd 32-bit entities
363 int[] sBoxKey = new int[4];
364
365 // split user key material into even and odd 32-bit entities and
366 // compute S-box keys using (12, 8) Reed-Solomon code over GF(256)
367 int i, j, offset = 0;
368 for (i = 0, j = k64Cnt-1; i < 4 && offset < length; i++, j--)
369 {
370 k32e[i] = (k[offset++] & 0xFF) |
371 (k[offset++] & 0xFF) << 8 |
372 (k[offset++] & 0xFF) << 16 |
373 (k[offset++] & 0xFF) << 24;
374 k32o[i] = (k[offset++] & 0xFF) |
375 (k[offset++] & 0xFF) << 8 |
376 (k[offset++] & 0xFF) << 16 |
377 (k[offset++] & 0xFF) << 24;
378 sBoxKey[j] = RS_MDS_Encode( k32e[i], k32o[i] ); // reverse order
379 }
380
381 // compute the round decryption subkeys for PHT. these same subkeys
382 // will be used in encryption but will be applied in reverse order.
383 int A, B, q=0;
384 i=0;
385 while(i < TOTAL_SUBKEYS)
386 {
387 A = F32( k64Cnt, q, k32e ); // A uses even key entities
388 q += SK_BUMP;
389
390 B = F32( k64Cnt, q, k32o ); // B uses odd key entities
391 q += SK_BUMP;
392
393 B = B << 8 | B >>> 24;
394
395 A += B;
396 subKeys[i++] = A; // combine with a PHT
397
398 A += B;
399 subKeys[i++] = A << SK_ROTL | A >>> (32-SK_ROTL);
400 }
401
402 // fully expand the table for speed
403 int k0 = sBoxKey[0];
404 int k1 = sBoxKey[1];
405 int k2 = sBoxKey[2];
406 int k3 = sBoxKey[3];
407 int b0, b1, b2, b3;
408 for (i = 0; i < 256; i++)
409 {
410 b0 = b1 = b2 = b3 = i;
411 switch (k64Cnt & 3)
412 {
413 case 1:
414 sBox[ 2*i ] = MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)];
415 sBox[ 2*i+1] = MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)];
416 sBox[0x200+2*i ] = MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)];
417 sBox[0x200+2*i+1] = MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)];
418 break;
419 case 0: // same as 4
420 b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);
421 b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);
422 b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);
423 b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);
424 case 3:
425 b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);
426 b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);
427 b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);
428 b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);
429 case 2: // 128-bit keys
430 sBox[ 2*i ] = MDS[0][
431 (P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF) ^ b0(k0)];
432
433 sBox[ 2*i+1] = MDS[1][
434 (P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF) ^ b1(k0)];
435
436 sBox[0x200+2*i ] = MDS[2][
437 (P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF) ^ b2(k0)];
438
439 sBox[0x200+2*i+1] = MDS[3][
440 (P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF) ^ b3(k0)];
441 }
442 }
443
444 // swap input and output whitening keys when decrypting
445 if(decrypt)
446 for(i=0; i<4; i++)
447 {
448 int t = subKeys[i];
449 subKeys[i] = subKeys[i+4];
450 subKeys[i+4] = t;
451 }
452 }
453
454
455 /**
456 * Encrypt exactly one block of plaintext. Blocks may overlap.
457 *
458 * @param in The plaintext.
459 * @param inOffset Index of in from which to start considering data.
460 * @param sessionKey The session key to use for encryption.
461 * @return The ciphertext generated from a plaintext using the session key.
462 */
463 private final void blockCrypt(byte[] in, int inOffset,
464 byte[] out, int outOffset)
465 {
466 int[] sBox = this.sBox;
467 int[] sKey = this.subKeys;
468
469 int x0 = (in[inOffset++] & 0xFF) |
470 (in[inOffset++] & 0xFF) << 8 |
471 (in[inOffset++] & 0xFF) << 16 |
472 (in[inOffset++] & 0xFF) << 24;
473 int x1 = (in[inOffset++] & 0xFF) |
474 (in[inOffset++] & 0xFF) << 8 |
475 (in[inOffset++] & 0xFF) << 16 |
476 (in[inOffset++] & 0xFF) << 24;
477 int x2 = (in[inOffset++] & 0xFF) |
478 (in[inOffset++] & 0xFF) << 8 |
479 (in[inOffset++] & 0xFF) << 16 |
480 (in[inOffset++] & 0xFF) << 24;
481 int x3 = (in[inOffset++] & 0xFF) |
482 (in[inOffset++] & 0xFF) << 8 |
483 (in[inOffset++] & 0xFF) << 16 |
484 (in[inOffset ] & 0xFF) << 24;
485
486 x0 ^= sKey[0];
487 x1 ^= sKey[1];
488 x2 ^= sKey[2];
489 x3 ^= sKey[3];
490
491 int k, t0, t1;
492 if(decrypt)
493 {
494 k = 39;
495 for (int R = 0; R < ROUNDS; R += 2)
496 {
497 t0 = Fe32( sBox, x0, 0 );
498 t1 = Fe32( sBox, x1, 3 );
499 x3 ^= t0 + 2*t1 + sKey[k--];
500 x3 = x3 >>> 1 | x3 << 31;
501 x2 = x2 << 1 | x2 >>> 31;
502 x2 ^= t0 + t1 + sKey[k--];
503
504 t0 = Fe32( sBox, x2, 0 );
505 t1 = Fe32( sBox, x3, 3 );
506 x1 ^= t0 + 2*t1 + sKey[k--];
507 x1 = x1 >>> 1 | x1 << 31;
508 x0 = x0 << 1 | x0 >>> 31;
509 x0 ^= t0 + t1 + sKey[k--];
510 }
511 }
512 else
513 {
514 k = 8;
515 for (int R = 0; R < ROUNDS; R += 2)
516 {
517 t0 = Fe32( sBox, x0, 0 );
518 t1 = Fe32( sBox, x1, 3 );
519 x2 ^= t0 + t1 + sKey[k++];
520 x2 = x2 >>> 1 | x2 << 31;
521 x3 = x3 << 1 | x3 >>> 31;
522 x3 ^= t0 + 2*t1 + sKey[k++];
523
524 t0 = Fe32( sBox, x2, 0 );
525 t1 = Fe32( sBox, x3, 3 );
526 x0 ^= t0 + t1 + sKey[k++];
527 x0 = x0 >>> 1 | x0 << 31;
528 x1 = x1 << 1 | x1 >>> 31;
529 x1 ^= t0 + 2*t1 + sKey[k++];
530 }
531 }
532
533 x2 ^= sKey[4];
534 x3 ^= sKey[5];
535 x0 ^= sKey[6];
536 x1 ^= sKey[7];
537
538 out[outOffset++] = (byte)(x2 );
539 out[outOffset++] = (byte)(x2 >>> 8);
540 out[outOffset++] = (byte)(x2 >>> 16);
541 out[outOffset++] = (byte)(x2 >>> 24);
542
543 out[outOffset++] = (byte)(x3 );
544 out[outOffset++] = (byte)(x3 >>> 8);
545 out[outOffset++] = (byte)(x3 >>> 16);
546 out[outOffset++] = (byte)(x3 >>> 24);
547
548 out[outOffset++] = (byte)(x0 );
549 out[outOffset++] = (byte)(x0 >>> 8);
550 out[outOffset++] = (byte)(x0 >>> 16);
551 out[outOffset++] = (byte)(x0 >>> 24);
552
553 out[outOffset++] = (byte)(x1 );
554 out[outOffset++] = (byte)(x1 >>> 8);
555 out[outOffset++] = (byte)(x1 >>> 16);
556 out[outOffset ] = (byte)(x1 >>> 24);
557 }
558
559
560 // own methods
561 //...........................................................................
562
563 private static final int b0( int x ) { return x & 0xFF; }
564 private static final int b1( int x ) { return (x >>> 8) & 0xFF; }
565 private static final int b2( int x ) { return (x >>> 16) & 0xFF; }
566 private static final int b3( int x ) { return (x >>> 24) & 0xFF; }
567
568 /**
569 * Use (12, 8) Reed-Solomon code over GF(256) to produce a key S-box
570 * 32-bit entity from two key material 32-bit entities.
571 *
572 * @param k0 1st 32-bit entity.
573 * @param k1 2nd 32-bit entity.
574 * @return Remainder polynomial generated using RS code
575 */
576 private static final int RS_MDS_Encode( int k0, int k1)
577 {
578 int r = k1;
579 for (int i = 0; i < 4; i++) // shift 1 byte at a time
580 r = RS_rem( r );
581
582 r ^= k0;
583 for (int i = 0; i < 4; i++)
584 r = RS_rem( r );
585
586 return r;
587 }
588
589 /*
590 * Reed-Solomon code parameters: (12, 8) reversible code:<p>
591 * <pre>
592 * g(x) = x**4 + (a + 1/a) x**3 + a x**2 + (a + 1/a) x + 1
593 * </pre>
594 * where a = primitive root of field generator 0x14D
595 */
596 private static final int RS_rem( int x )
597 {
598 int b = (x >>> 24) & 0xFF;
599 int g2 = ((b << 1) ^ ( (b & 0x80)!=0 ? RS_GF_FDBK : 0 )) & 0xFF;
600 int g3 = (b >>> 1) ^ ( (b & 0x01)!=0 ? (RS_GF_FDBK >>> 1) : 0 ) ^ g2;
601 int result = (x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b;
602 return result;
603 }
604
605 private static final int F32( int k64Cnt, int x, int[] k32 )
606 {
607 int b0 = b0(x);
608 int b1 = b1(x);
609 int b2 = b2(x);
610 int b3 = b3(x);
611 int k0 = k32[0];
612 int k1 = k32[1];
613 int k2 = k32[2];
614 int k3 = k32[3];
615
616 int result = 0;
617 switch (k64Cnt & 3)
618 {
619 case 1:
620 result =
621 MDS[0][(P[P_01][b0] & 0xFF) ^ b0(k0)] ^
622 MDS[1][(P[P_11][b1] & 0xFF) ^ b1(k0)] ^
623 MDS[2][(P[P_21][b2] & 0xFF) ^ b2(k0)] ^
624 MDS[3][(P[P_31][b3] & 0xFF) ^ b3(k0)];
625 break;
626 case 0: // same as 4
627 b0 = (P[P_04][b0] & 0xFF) ^ b0(k3);
628 b1 = (P[P_14][b1] & 0xFF) ^ b1(k3);
629 b2 = (P[P_24][b2] & 0xFF) ^ b2(k3);
630 b3 = (P[P_34][b3] & 0xFF) ^ b3(k3);
631 case 3:
632 b0 = (P[P_03][b0] & 0xFF) ^ b0(k2);
633 b1 = (P[P_13][b1] & 0xFF) ^ b1(k2);
634 b2 = (P[P_23][b2] & 0xFF) ^ b2(k2);
635 b3 = (P[P_33][b3] & 0xFF) ^ b3(k2);
636 case 2: // 128-bit keys (optimize for this case)
637 result =
638 MDS[0][(P[P_01][(P[P_02][b0] & 0xFF) ^ b0(k1)] & 0xFF) ^ b0(k0)] ^
639 MDS[1][(P[P_11][(P[P_12][b1] & 0xFF) ^ b1(k1)] & 0xFF) ^ b1(k0)] ^
640 MDS[2][(P[P_21][(P[P_22][b2] & 0xFF) ^ b2(k1)] & 0xFF) ^ b2(k0)] ^
641 MDS[3][(P[P_31][(P[P_32][b3] & 0xFF) ^ b3(k1)] & 0xFF) ^ b3(k0)];
642 break;
643 }
644 return result;
645 }
646
647
648 private static final int Fe32( int[] sBox, int x, int R )
649 {
650 return sBox[ 2*_b(x, R ) ] ^
651 sBox[ 2*_b(x, R+1) + 1] ^
652 sBox[0x200 + 2*_b(x, R+2) ] ^
653 sBox[0x200 + 2*_b(x, R+3) + 1];
654 }
655
656 private static final int _b( int x, int N )
657 {
658 int result = 0;
659 switch (N%4)
660 {
661 case 0: result = b0(x); break;
662 case 1: result = b1(x); break;
663 case 2: result = b2(x); break;
664 case 3: result = b3(x); break;
665 }
666 return result;
667 }
668 }