001: package org.bouncycastle.crypto.engines;
002:
003: import org.bouncycastle.crypto.BlockCipher;
004: import org.bouncycastle.crypto.CipherParameters;
005: import org.bouncycastle.crypto.DataLengthException;
006: import org.bouncycastle.crypto.params.KeyParameter;
007:
008: /**
009: * A class that provides Twofish encryption operations.
010: *
011: * This Java implementation is based on the Java reference
012: * implementation provided by Bruce Schneier and developed
013: * by Raif S. Naffah.
014: */
015: public final class TwofishEngine implements BlockCipher {
016: private static final byte[][] P = {
017: { // p0
018: (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
019: (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
020: (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
021: (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
022: (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
023: (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
024: (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
025: (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
026: (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
027: (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
028: (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
029: (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
030: (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
031: (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
032: (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
033: (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
034: (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
035: (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
036: (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
037: (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
038: (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
039: (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
040: (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
041: (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
042: (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
043: (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
044: (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
045: (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
046: (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
047: (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
048: (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
049: (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
050: (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
051: (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
052: (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
053: (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
054: (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
055: (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
056: (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
057: (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
058: (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
059: (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
060: (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
061: (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
062: (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
063: (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
064: (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
065: (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
066: (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
067: (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
068: (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
069: (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
070: (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
071: (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
072: (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
073: (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
074: (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
075: (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
076: (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
077: (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
078: (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
079: (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
080: (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
081: (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0 },
082: { // p1
083: (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
084: (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
085: (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
086: (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
087: (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
088: (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
089: (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
090: (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
091: (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
092: (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
093: (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
094: (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
095: (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
096: (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
097: (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
098: (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
099: (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
100: (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
101: (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
102: (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
103: (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
104: (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
105: (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
106: (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
107: (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
108: (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
109: (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
110: (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
111: (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
112: (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
113: (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
114: (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
115: (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
116: (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
117: (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
118: (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
119: (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
120: (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
121: (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
122: (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
123: (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
124: (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
125: (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
126: (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
127: (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
128: (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
129: (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
130: (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
131: (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
132: (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
133: (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
134: (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
135: (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
136: (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
137: (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
138: (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
139: (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
140: (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
141: (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
142: (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
143: (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
144: (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
145: (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
146: (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91 } };
147:
148: /**
149: * Define the fixed p0/p1 permutations used in keyed S-box lookup.
150: * By changing the following constant definitions, the S-boxes will
151: * automatically get changed in the Twofish engine.
152: */
153: private static final int P_00 = 1;
154: private static final int P_01 = 0;
155: private static final int P_02 = 0;
156: private static final int P_03 = P_01 ^ 1;
157: private static final int P_04 = 1;
158:
159: private static final int P_10 = 0;
160: private static final int P_11 = 0;
161: private static final int P_12 = 1;
162: private static final int P_13 = P_11 ^ 1;
163: private static final int P_14 = 0;
164:
165: private static final int P_20 = 1;
166: private static final int P_21 = 1;
167: private static final int P_22 = 0;
168: private static final int P_23 = P_21 ^ 1;
169: private static final int P_24 = 0;
170:
171: private static final int P_30 = 0;
172: private static final int P_31 = 1;
173: private static final int P_32 = 1;
174: private static final int P_33 = P_31 ^ 1;
175: private static final int P_34 = 1;
176:
177: /* Primitive polynomial for GF(256) */
178: private static final int GF256_FDBK = 0x169;
179: private static final int GF256_FDBK_2 = GF256_FDBK / 2;
180: private static final int GF256_FDBK_4 = GF256_FDBK / 4;
181:
182: private static final int RS_GF_FDBK = 0x14D; // field generator
183:
184: //====================================
185: // Useful constants
186: //====================================
187:
188: private static final int ROUNDS = 16;
189: private static final int MAX_ROUNDS = 16; // bytes = 128 bits
190: private static final int BLOCK_SIZE = 16; // bytes = 128 bits
191: private static final int MAX_KEY_BITS = 256;
192:
193: private static final int INPUT_WHITEN = 0;
194: private static final int OUTPUT_WHITEN = INPUT_WHITEN + BLOCK_SIZE
195: / 4; // 4
196: private static final int ROUND_SUBKEYS = OUTPUT_WHITEN + BLOCK_SIZE
197: / 4;// 8
198:
199: private static final int TOTAL_SUBKEYS = ROUND_SUBKEYS + 2
200: * MAX_ROUNDS;// 40
201:
202: private static final int SK_STEP = 0x02020202;
203: private static final int SK_BUMP = 0x01010101;
204: private static final int SK_ROTL = 9;
205:
206: private boolean encrypting = false;
207:
208: private int[] gMDS0 = new int[MAX_KEY_BITS];
209: private int[] gMDS1 = new int[MAX_KEY_BITS];
210: private int[] gMDS2 = new int[MAX_KEY_BITS];
211: private int[] gMDS3 = new int[MAX_KEY_BITS];
212:
213: /**
214: * gSubKeys[] and gSBox[] are eventually used in the
215: * encryption and decryption methods.
216: */
217: private int[] gSubKeys;
218: private int[] gSBox;
219:
220: private int k64Cnt = 0;
221:
222: private byte[] workingKey = null;
223:
224: public TwofishEngine() {
225: // calculate the MDS matrix
226: int[] m1 = new int[2];
227: int[] mX = new int[2];
228: int[] mY = new int[2];
229: int j;
230:
231: for (int i = 0; i < MAX_KEY_BITS; i++) {
232: j = P[0][i] & 0xff;
233: m1[0] = j;
234: mX[0] = Mx_X(j) & 0xff;
235: mY[0] = Mx_Y(j) & 0xff;
236:
237: j = P[1][i] & 0xff;
238: m1[1] = j;
239: mX[1] = Mx_X(j) & 0xff;
240: mY[1] = Mx_Y(j) & 0xff;
241:
242: gMDS0[i] = m1[P_00] | mX[P_00] << 8 | mY[P_00] << 16
243: | mY[P_00] << 24;
244:
245: gMDS1[i] = mY[P_10] | mY[P_10] << 8 | mX[P_10] << 16
246: | m1[P_10] << 24;
247:
248: gMDS2[i] = mX[P_20] | mY[P_20] << 8 | m1[P_20] << 16
249: | mY[P_20] << 24;
250:
251: gMDS3[i] = mX[P_30] | m1[P_30] << 8 | mY[P_30] << 16
252: | mX[P_30] << 24;
253: }
254: }
255:
256: /**
257: * initialise a Twofish cipher.
258: *
259: * @param encrypting whether or not we are for encryption.
260: * @param params the parameters required to set up the cipher.
261: * @exception IllegalArgumentException if the params argument is
262: * inappropriate.
263: */
264: public void init(boolean encrypting, CipherParameters params) {
265: if (params instanceof KeyParameter) {
266: this .encrypting = encrypting;
267: this .workingKey = ((KeyParameter) params).getKey();
268: this .k64Cnt = (this .workingKey.length / 8); // pre-padded ?
269: setKey(this .workingKey);
270:
271: return;
272: }
273:
274: throw new IllegalArgumentException(
275: "invalid parameter passed to Twofish init - "
276: + params.getClass().getName());
277: }
278:
279: public String getAlgorithmName() {
280: return "Twofish";
281: }
282:
283: public final int processBlock(byte[] in, int inOff, byte[] out,
284: int outOff) {
285: if (workingKey == null) {
286: throw new IllegalStateException("Twofish not initialised");
287: }
288:
289: if ((inOff + BLOCK_SIZE) > in.length) {
290: throw new DataLengthException("input buffer too short");
291: }
292:
293: if ((outOff + BLOCK_SIZE) > out.length) {
294: throw new DataLengthException("output buffer too short");
295: }
296:
297: if (encrypting) {
298: encryptBlock(in, inOff, out, outOff);
299: } else {
300: decryptBlock(in, inOff, out, outOff);
301: }
302:
303: return BLOCK_SIZE;
304: }
305:
306: public void reset() {
307: if (this .workingKey != null) {
308: setKey(this .workingKey);
309: }
310: }
311:
312: public int getBlockSize() {
313: return BLOCK_SIZE;
314: }
315:
316: //==================================
317: // Private Implementation
318: //==================================
319:
320: private void setKey(byte[] key) {
321: int[] k32e = new int[MAX_KEY_BITS / 64]; // 4
322: int[] k32o = new int[MAX_KEY_BITS / 64]; // 4
323:
324: int[] sBoxKeys = new int[MAX_KEY_BITS / 64]; // 4
325: gSubKeys = new int[TOTAL_SUBKEYS];
326:
327: if (k64Cnt < 1) {
328: throw new IllegalArgumentException(
329: "Key size less than 64 bits");
330: }
331:
332: if (k64Cnt > 4) {
333: throw new IllegalArgumentException(
334: "Key size larger than 256 bits");
335: }
336:
337: /*
338: * k64Cnt is the number of 8 byte blocks (64 chunks)
339: * that are in the input key. The input key is a
340: * maximum of 32 bytes (256 bits), so the range
341: * for k64Cnt is 1..4
342: */
343: for (int i = 0; i < k64Cnt; i++) {
344: int p = i * 8;
345:
346: k32e[i] = BytesTo32Bits(key, p);
347: k32o[i] = BytesTo32Bits(key, p + 4);
348:
349: sBoxKeys[k64Cnt - 1 - i] = RS_MDS_Encode(k32e[i], k32o[i]);
350: }
351:
352: int q, A, B;
353: for (int i = 0; i < TOTAL_SUBKEYS / 2; i++) {
354: q = i * SK_STEP;
355: A = F32(q, k32e);
356: B = F32(q + SK_BUMP, k32o);
357: B = B << 8 | B >>> 24;
358: A += B;
359: gSubKeys[i * 2] = A;
360: A += B;
361: gSubKeys[i * 2 + 1] = A << SK_ROTL | A >>> (32 - SK_ROTL);
362: }
363:
364: /*
365: * fully expand the table for speed
366: */
367: int k0 = sBoxKeys[0];
368: int k1 = sBoxKeys[1];
369: int k2 = sBoxKeys[2];
370: int k3 = sBoxKeys[3];
371: int b0, b1, b2, b3;
372: gSBox = new int[4 * MAX_KEY_BITS];
373: for (int i = 0; i < MAX_KEY_BITS; i++) {
374: b0 = b1 = b2 = b3 = i;
375: switch (k64Cnt & 3) {
376: case 1:
377: gSBox[i * 2] = gMDS0[(P[P_01][b0] & 0xff) ^ b0(k0)];
378: gSBox[i * 2 + 1] = gMDS1[(P[P_11][b1] & 0xff) ^ b1(k0)];
379: gSBox[i * 2 + 0x200] = gMDS2[(P[P_21][b2] & 0xff)
380: ^ b2(k0)];
381: gSBox[i * 2 + 0x201] = gMDS3[(P[P_31][b3] & 0xff)
382: ^ b3(k0)];
383: break;
384: case 0: /* 256 bits of key */
385: b0 = (P[P_04][b0] & 0xff) ^ b0(k3);
386: b1 = (P[P_14][b1] & 0xff) ^ b1(k3);
387: b2 = (P[P_24][b2] & 0xff) ^ b2(k3);
388: b3 = (P[P_34][b3] & 0xff) ^ b3(k3);
389: case 3:
390: b0 = (P[P_03][b0] & 0xff) ^ b0(k2);
391: b1 = (P[P_13][b1] & 0xff) ^ b1(k2);
392: b2 = (P[P_23][b2] & 0xff) ^ b2(k2);
393: b3 = (P[P_33][b3] & 0xff) ^ b3(k2);
394: case 2:
395: gSBox[i * 2] = gMDS0[(P[P_01][(P[P_02][b0] & 0xff)
396: ^ b0(k1)] & 0xff)
397: ^ b0(k0)];
398: gSBox[i * 2 + 1] = gMDS1[(P[P_11][(P[P_12][b1] & 0xff)
399: ^ b1(k1)] & 0xff)
400: ^ b1(k0)];
401: gSBox[i * 2 + 0x200] = gMDS2[(P[P_21][(P[P_22][b2] & 0xff)
402: ^ b2(k1)] & 0xff)
403: ^ b2(k0)];
404: gSBox[i * 2 + 0x201] = gMDS3[(P[P_31][(P[P_32][b3] & 0xff)
405: ^ b3(k1)] & 0xff)
406: ^ b3(k0)];
407: break;
408: }
409: }
410:
411: /*
412: * the function exits having setup the gSBox with the
413: * input key material.
414: */
415: }
416:
417: /**
418: * Encrypt the given input starting at the given offset and place
419: * the result in the provided buffer starting at the given offset.
420: * The input will be an exact multiple of our blocksize.
421: *
422: * encryptBlock uses the pre-calculated gSBox[] and subKey[]
423: * arrays.
424: */
425: private void encryptBlock(byte[] src, int srcIndex, byte[] dst,
426: int dstIndex) {
427: int x0 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[INPUT_WHITEN];
428: int x1 = BytesTo32Bits(src, srcIndex + 4)
429: ^ gSubKeys[INPUT_WHITEN + 1];
430: int x2 = BytesTo32Bits(src, srcIndex + 8)
431: ^ gSubKeys[INPUT_WHITEN + 2];
432: int x3 = BytesTo32Bits(src, srcIndex + 12)
433: ^ gSubKeys[INPUT_WHITEN + 3];
434:
435: int k = ROUND_SUBKEYS;
436: int t0, t1;
437: for (int r = 0; r < ROUNDS; r += 2) {
438: t0 = Fe32_0(x0);
439: t1 = Fe32_3(x1);
440: x2 ^= t0 + t1 + gSubKeys[k++];
441: x2 = x2 >>> 1 | x2 << 31;
442: x3 = (x3 << 1 | x3 >>> 31) ^ (t0 + 2 * t1 + gSubKeys[k++]);
443:
444: t0 = Fe32_0(x2);
445: t1 = Fe32_3(x3);
446: x0 ^= t0 + t1 + gSubKeys[k++];
447: x0 = x0 >>> 1 | x0 << 31;
448: x1 = (x1 << 1 | x1 >>> 31) ^ (t0 + 2 * t1 + gSubKeys[k++]);
449: }
450:
451: Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], dst, dstIndex);
452: Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], dst,
453: dstIndex + 4);
454: Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], dst,
455: dstIndex + 8);
456: Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], dst,
457: dstIndex + 12);
458: }
459:
460: /**
461: * Decrypt the given input starting at the given offset and place
462: * the result in the provided buffer starting at the given offset.
463: * The input will be an exact multiple of our blocksize.
464: */
465: private void decryptBlock(byte[] src, int srcIndex, byte[] dst,
466: int dstIndex) {
467: int x2 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[OUTPUT_WHITEN];
468: int x3 = BytesTo32Bits(src, srcIndex + 4)
469: ^ gSubKeys[OUTPUT_WHITEN + 1];
470: int x0 = BytesTo32Bits(src, srcIndex + 8)
471: ^ gSubKeys[OUTPUT_WHITEN + 2];
472: int x1 = BytesTo32Bits(src, srcIndex + 12)
473: ^ gSubKeys[OUTPUT_WHITEN + 3];
474:
475: int k = ROUND_SUBKEYS + 2 * ROUNDS - 1;
476: int t0, t1;
477: for (int r = 0; r < ROUNDS; r += 2) {
478: t0 = Fe32_0(x2);
479: t1 = Fe32_3(x3);
480: x1 ^= t0 + 2 * t1 + gSubKeys[k--];
481: x0 = (x0 << 1 | x0 >>> 31) ^ (t0 + t1 + gSubKeys[k--]);
482: x1 = x1 >>> 1 | x1 << 31;
483:
484: t0 = Fe32_0(x0);
485: t1 = Fe32_3(x1);
486: x3 ^= t0 + 2 * t1 + gSubKeys[k--];
487: x2 = (x2 << 1 | x2 >>> 31) ^ (t0 + t1 + gSubKeys[k--]);
488: x3 = x3 >>> 1 | x3 << 31;
489: }
490:
491: Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], dst, dstIndex);
492: Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], dst,
493: dstIndex + 4);
494: Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], dst,
495: dstIndex + 8);
496: Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], dst,
497: dstIndex + 12);
498: }
499:
500: /*
501: * TODO: This can be optimised and made cleaner by combining
502: * the functionality in this function and applying it appropriately
503: * to the creation of the subkeys during key setup.
504: */
505: private final int F32(int x, int[] k32) {
506: int b0 = b0(x);
507: int b1 = b1(x);
508: int b2 = b2(x);
509: int b3 = b3(x);
510: int k0 = k32[0];
511: int k1 = k32[1];
512: int k2 = k32[2];
513: int k3 = k32[3];
514:
515: int result = 0;
516: switch (k64Cnt & 3) {
517: case 1:
518: result = gMDS0[(P[P_01][b0] & 0xff) ^ b0(k0)]
519: ^ gMDS1[(P[P_11][b1] & 0xff) ^ b1(k0)]
520: ^ gMDS2[(P[P_21][b2] & 0xff) ^ b2(k0)]
521: ^ gMDS3[(P[P_31][b3] & 0xff) ^ b3(k0)];
522: break;
523: case 0: /* 256 bits of key */
524: b0 = (P[P_04][b0] & 0xff) ^ b0(k3);
525: b1 = (P[P_14][b1] & 0xff) ^ b1(k3);
526: b2 = (P[P_24][b2] & 0xff) ^ b2(k3);
527: b3 = (P[P_34][b3] & 0xff) ^ b3(k3);
528: case 3:
529: b0 = (P[P_03][b0] & 0xff) ^ b0(k2);
530: b1 = (P[P_13][b1] & 0xff) ^ b1(k2);
531: b2 = (P[P_23][b2] & 0xff) ^ b2(k2);
532: b3 = (P[P_33][b3] & 0xff) ^ b3(k2);
533: case 2:
534: result = gMDS0[(P[P_01][(P[P_02][b0] & 0xff) ^ b0(k1)] & 0xff)
535: ^ b0(k0)]
536: ^ gMDS1[(P[P_11][(P[P_12][b1] & 0xff) ^ b1(k1)] & 0xff)
537: ^ b1(k0)]
538: ^ gMDS2[(P[P_21][(P[P_22][b2] & 0xff) ^ b2(k1)] & 0xff)
539: ^ b2(k0)]
540: ^ gMDS3[(P[P_31][(P[P_32][b3] & 0xff) ^ b3(k1)] & 0xff)
541: ^ b3(k0)];
542: break;
543: }
544: return result;
545: }
546:
547: /**
548: * Use (12, 8) Reed-Solomon code over GF(256) to produce
549: * a key S-box 32-bit entity from 2 key material 32-bit
550: * entities.
551: *
552: * @param k0 first 32-bit entity
553: * @param k1 second 32-bit entity
554: * @return Remainder polynomial generated using RS code
555: */
556: private final int RS_MDS_Encode(int k0, int k1) {
557: int r = k1;
558: for (int i = 0; i < 4; i++) // shift 1 byte at a time
559: {
560: r = RS_rem(r);
561: }
562: r ^= k0;
563: for (int i = 0; i < 4; i++) {
564: r = RS_rem(r);
565: }
566:
567: return r;
568: }
569:
570: /**
571: * Reed-Solomon code parameters: (12,8) reversible code:<p>
572: * <pre>
573: * g(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
574: * </pre>
575: * where a = primitive root of field generator 0x14D
576: */
577: private final int RS_rem(int x) {
578: int b = (x >>> 24) & 0xff;
579: int g2 = ((b << 1) ^ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
580: int g3 = ((b >>> 1) ^ ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0))
581: ^ g2;
582: return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
583: }
584:
585: private final int LFSR1(int x) {
586: return (x >> 1) ^ (((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
587: }
588:
589: private final int LFSR2(int x) {
590: return (x >> 2) ^ (((x & 0x02) != 0) ? GF256_FDBK_2 : 0)
591: ^ (((x & 0x01) != 0) ? GF256_FDBK_4 : 0);
592: }
593:
594: private final int Mx_X(int x) {
595: return x ^ LFSR2(x);
596: } // 5B
597:
598: private final int Mx_Y(int x) {
599: return x ^ LFSR1(x) ^ LFSR2(x);
600: } // EF
601:
602: private final int b0(int x) {
603: return x & 0xff;
604: }
605:
606: private final int b1(int x) {
607: return (x >>> 8) & 0xff;
608: }
609:
610: private final int b2(int x) {
611: return (x >>> 16) & 0xff;
612: }
613:
614: private final int b3(int x) {
615: return (x >>> 24) & 0xff;
616: }
617:
618: private final int Fe32_0(int x) {
619: return gSBox[0x000 + 2 * (x & 0xff)]
620: ^ gSBox[0x001 + 2 * ((x >>> 8) & 0xff)]
621: ^ gSBox[0x200 + 2 * ((x >>> 16) & 0xff)]
622: ^ gSBox[0x201 + 2 * ((x >>> 24) & 0xff)];
623: }
624:
625: private final int Fe32_3(int x) {
626: return gSBox[0x000 + 2 * ((x >>> 24) & 0xff)]
627: ^ gSBox[0x001 + 2 * (x & 0xff)]
628: ^ gSBox[0x200 + 2 * ((x >>> 8) & 0xff)]
629: ^ gSBox[0x201 + 2 * ((x >>> 16) & 0xff)];
630: }
631:
632: private final int BytesTo32Bits(byte[] b, int p) {
633: return ((b[p] & 0xff)) | ((b[p + 1] & 0xff) << 8)
634: | ((b[p + 2] & 0xff) << 16) | ((b[p + 3] & 0xff) << 24);
635: }
636:
637: private final void Bits32ToBytes(int in, byte[] b, int offset) {
638: b[offset] = (byte) in;
639: b[offset + 1] = (byte) (in >> 8);
640: b[offset + 2] = (byte) (in >> 16);
641: b[offset + 3] = (byte) (in >> 24);
642: }
643: }
|