18e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrompackage org.bouncycastle.crypto.engines;
28e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
38e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstromimport org.bouncycastle.crypto.BlockCipher;
48e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstromimport org.bouncycastle.crypto.CipherParameters;
58e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstromimport org.bouncycastle.crypto.DataLengthException;
6a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstromimport org.bouncycastle.crypto.OutputLengthException;
78e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstromimport org.bouncycastle.crypto.params.KeyParameter;
88e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
98e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom/**
108e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom * A class that provides Twofish encryption operations.
118e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom *
128e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom * This Java implementation is based on the Java reference
138e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom * implementation provided by Bruce Schneier and developed
148e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom * by Raif S. Naffah.
158e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom */
168e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrompublic final class TwofishEngine
178e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    implements BlockCipher
188e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom{
198e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final byte[][] P =  {
208e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {  // p0
218e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
228e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
238e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
248e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
258e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
268e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
278e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
288e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
298e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
308e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
318e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
328e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
338e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
348e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
358e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
368e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
378e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
388e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
398e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
408e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
418e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
428e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
438e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
448e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
458e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
468e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
478e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
488e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
498e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
508e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
518e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
528e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
538e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
548e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
558e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
568e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
578e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
588e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
598e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
608e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
618e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
628e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
638e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
648e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
658e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
668e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
678e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
688e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
698e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
708e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
718e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
728e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
738e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
748e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
758e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
768e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
778e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
788e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
798e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
808e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
818e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
828e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
838e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
848e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0 },
858e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {  // p1
868e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
878e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
888e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
898e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
908e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
918e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
928e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
938e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
948e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
958e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
968e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
978e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
988e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
998e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
1008e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
1018e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
1028e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
1038e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
1048e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
1058e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
1068e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
1078e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
1088e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
1098e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
1108e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
1118e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
1128e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
1138e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
1148e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
1158e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
1168e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
1178e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
1188e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
1198e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
1208e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
1218e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
1228e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
1238e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
1248e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
1258e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
1268e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
1278e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
1288e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
1298e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
1308e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
1318e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
1328e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
1338e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
1348e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
1358e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
1368e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
1378e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
1388e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
1398e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
1408e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
1418e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
1428e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
1438e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
1448e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
1458e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
1468e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
1478e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
1488e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
1498e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91  }
1508e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    };
1518e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
1528e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    /**
1538e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    * Define the fixed p0/p1 permutations used in keyed S-box lookup.
1548e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    * By changing the following constant definitions, the S-boxes will
1558e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    * automatically get changed in the Twofish engine.
1568e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    */
1578e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_00 = 1;
1588e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_01 = 0;
1598e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_02 = 0;
1608e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_03 = P_01 ^ 1;
1618e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_04 = 1;
1628e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
1638e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_10 = 0;
1648e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_11 = 0;
1658e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_12 = 1;
1668e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_13 = P_11 ^ 1;
1678e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_14 = 0;
1688e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
1698e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_20 = 1;
1708e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_21 = 1;
1718e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_22 = 0;
1728e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_23 = P_21 ^ 1;
1738e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_24 = 0;
1748e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
1758e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_30 = 0;
1768e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_31 = 1;
1778e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_32 = 1;
1788e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_33 = P_31 ^ 1;
1798e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int P_34 = 1;
1808e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
1818e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    /* Primitive polynomial for GF(256) */
1828e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int GF256_FDBK =   0x169;
1838e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int GF256_FDBK_2 = GF256_FDBK / 2;
1848e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int GF256_FDBK_4 = GF256_FDBK / 4;
1858e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
1868e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int RS_GF_FDBK = 0x14D; // field generator
1878e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
1888e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    //====================================
1898e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    // Useful constants
1908e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    //====================================
1918e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
1928e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int    ROUNDS = 16;
1938e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int    MAX_ROUNDS = 16;  // bytes = 128 bits
1948e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int    BLOCK_SIZE = 16;  // bytes = 128 bits
1958e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int    MAX_KEY_BITS = 256;
1968e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
1978e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int    INPUT_WHITEN=0;
1988e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int    OUTPUT_WHITEN=INPUT_WHITEN+BLOCK_SIZE/4; // 4
1998e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int    ROUND_SUBKEYS=OUTPUT_WHITEN+BLOCK_SIZE/4;// 8
2008e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2018e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int    TOTAL_SUBKEYS=ROUND_SUBKEYS+2*MAX_ROUNDS;// 40
2028e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2038e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int    SK_STEP = 0x02020202;
2048e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int    SK_BUMP = 0x01010101;
2058e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private static final int    SK_ROTL = 9;
2068e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2078e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private boolean encrypting = false;
2088e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2098e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int[] gMDS0 = new int[MAX_KEY_BITS];
2108e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int[] gMDS1 = new int[MAX_KEY_BITS];
2118e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int[] gMDS2 = new int[MAX_KEY_BITS];
2128e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int[] gMDS3 = new int[MAX_KEY_BITS];
2138e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2148e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    /**
2158e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * gSubKeys[] and gSBox[] are eventually used in the
2168e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * encryption and decryption methods.
2178e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     */
2188e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int[] gSubKeys;
2198e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int[] gSBox;
2208e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2218e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int k64Cnt = 0;
2228e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2238e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private byte[] workingKey = null;
2248e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2258e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    public TwofishEngine()
2268e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
2278e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        // calculate the MDS matrix
2288e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int[] m1 = new int[2];
2298e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int[] mX = new int[2];
2308e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int[] mY = new int[2];
2318e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int j;
2328e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2338e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        for (int i=0; i< MAX_KEY_BITS ; i++)
2348e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
2358e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            j = P[0][i] & 0xff;
2368e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            m1[0] = j;
2378e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            mX[0] = Mx_X(j) & 0xff;
2388e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            mY[0] = Mx_Y(j) & 0xff;
2398e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2408e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            j = P[1][i] & 0xff;
2418e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            m1[1] = j;
2428e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            mX[1] = Mx_X(j) & 0xff;
2438e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            mY[1] = Mx_Y(j) & 0xff;
2448e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2458e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            gMDS0[i] = m1[P_00]       | mX[P_00] <<  8 |
2468e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                         mY[P_00] << 16 | mY[P_00] << 24;
2478e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2488e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            gMDS1[i] = mY[P_10]       | mY[P_10] <<  8 |
2498e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                         mX[P_10] << 16 | m1[P_10] << 24;
2508e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2518e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            gMDS2[i] = mX[P_20]       | mY[P_20] <<  8 |
2528e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                         m1[P_20] << 16 | mY[P_20] << 24;
2538e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2548e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            gMDS3[i] = mX[P_30]       | m1[P_30] <<  8 |
2558e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                         mY[P_30] << 16 | mX[P_30] << 24;
2568e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
2578e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
2588e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2598e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    /**
2608e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * initialise a Twofish cipher.
2618e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     *
2628e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * @param encrypting whether or not we are for encryption.
2638e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * @param params the parameters required to set up the cipher.
2648e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * @exception IllegalArgumentException if the params argument is
2658e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * inappropriate.
2668e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     */
2678e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    public void init(
2688e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        boolean             encrypting,
2698e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        CipherParameters    params)
2708e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
2718e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        if (params instanceof KeyParameter)
2728e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
2738e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            this.encrypting = encrypting;
2748e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            this.workingKey = ((KeyParameter)params).getKey();
2758e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            this.k64Cnt = (this.workingKey.length / 8); // pre-padded ?
2768e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            setKey(this.workingKey);
2778e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2788e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            return;
2798e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
2808e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2818e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        throw new IllegalArgumentException("invalid parameter passed to Twofish init - " + params.getClass().getName());
2828e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
2838e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2848e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    public String getAlgorithmName()
2858e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
2868e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return "Twofish";
2878e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
2888e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
2898e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    public int processBlock(
2908e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        byte[] in,
2918e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int inOff,
2928e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        byte[] out,
2938e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int outOff)
2948e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
2958e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        if (workingKey == null)
2968e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
2978e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            throw new IllegalStateException("Twofish not initialised");
2988e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
2998e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3008e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        if ((inOff + BLOCK_SIZE) > in.length)
3018e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
3028e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            throw new DataLengthException("input buffer too short");
3038e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
3048e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3058e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        if ((outOff + BLOCK_SIZE) > out.length)
3068e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
307a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom            throw new OutputLengthException("output buffer too short");
3088e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
3098e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3108e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        if (encrypting)
3118e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
3128e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            encryptBlock(in, inOff, out, outOff);
3138e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
3148e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        else
3158e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
3168e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            decryptBlock(in, inOff, out, outOff);
3178e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
3188e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3198e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return BLOCK_SIZE;
3208e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
3218e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3228e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    public void reset()
3238e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
3248e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        if (this.workingKey != null)
3258e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
3268e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            setKey(this.workingKey);
3278e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
3288e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
3298e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3308e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    public int getBlockSize()
3318e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
3328e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return BLOCK_SIZE;
3338e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
3348e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3358e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    //==================================
3368e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    // Private Implementation
3378e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    //==================================
3388e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3398e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private void setKey(byte[] key)
3408e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
3418e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int[] k32e = new int[MAX_KEY_BITS/64]; // 4
3428e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int[] k32o = new int[MAX_KEY_BITS/64]; // 4
3438e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3448e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int[] sBoxKeys = new int[MAX_KEY_BITS/64]; // 4
3458e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        gSubKeys = new int[TOTAL_SUBKEYS];
3468e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3478e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        if (k64Cnt < 1)
3488e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
3498e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            throw new IllegalArgumentException("Key size less than 64 bits");
3508e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
3518e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3528e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        if (k64Cnt > 4)
3538e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
3548e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            throw new IllegalArgumentException("Key size larger than 256 bits");
3558e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
3568e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3578e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        /*
3588e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom         * k64Cnt is the number of 8 byte blocks (64 chunks)
3598e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom         * that are in the input key.  The input key is a
3608e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom         * maximum of 32 bytes (256 bits), so the range
3618e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom         * for k64Cnt is 1..4
3628e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom         */
3638e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        for (int i=0; i<k64Cnt ; i++)
3648e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
3658e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            int p = i* 8;
3668e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3678e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            k32e[i] = BytesTo32Bits(key, p);
3688e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            k32o[i] = BytesTo32Bits(key, p+4);
3698e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3708e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            sBoxKeys[k64Cnt-1-i] = RS_MDS_Encode(k32e[i], k32o[i]);
3718e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
3728e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3738e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int q,A,B;
3748e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        for (int i=0; i < TOTAL_SUBKEYS / 2 ; i++)
3758e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
3768e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            q = i*SK_STEP;
3778e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            A = F32(q,         k32e);
3788e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            B = F32(q+SK_BUMP, k32o);
3798e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            B = B << 8 | B >>> 24;
3808e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            A += B;
3818e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            gSubKeys[i*2] = A;
3828e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            A += B;
3838e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            gSubKeys[i*2 + 1] = A << SK_ROTL | A >>> (32-SK_ROTL);
3848e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
3858e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
3868e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        /*
3878e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom         * fully expand the table for speed
3888e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom         */
3898e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int k0 = sBoxKeys[0];
3908e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int k1 = sBoxKeys[1];
3918e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int k2 = sBoxKeys[2];
3928e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int k3 = sBoxKeys[3];
3938e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int b0, b1, b2, b3;
3948e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        gSBox = new int[4*MAX_KEY_BITS];
3958e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        for (int i=0; i<MAX_KEY_BITS; i++)
3968e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
3978e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            b0 = b1 = b2 = b3 = i;
3988e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            switch (k64Cnt & 3)
3998e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            {
4008e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                case 1:
4018e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    gSBox[i*2]       = gMDS0[(P[P_01][b0] & 0xff) ^ b0(k0)];
4028e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    gSBox[i*2+1]     = gMDS1[(P[P_11][b1] & 0xff) ^ b1(k0)];
4038e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    gSBox[i*2+0x200] = gMDS2[(P[P_21][b2] & 0xff) ^ b2(k0)];
4048e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    gSBox[i*2+0x201] = gMDS3[(P[P_31][b3] & 0xff) ^ b3(k0)];
4058e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                break;
4064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                case 0: // 256 bits of key
4078e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    b0 = (P[P_04][b0] & 0xff) ^ b0(k3);
4088e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    b1 = (P[P_14][b1] & 0xff) ^ b1(k3);
4098e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    b2 = (P[P_24][b2] & 0xff) ^ b2(k3);
4108e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    b3 = (P[P_34][b3] & 0xff) ^ b3(k3);
4114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    // fall through, having pre-processed b[0]..b[3] with k32[3]
4124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                case 3: // 192 bits of key
4138e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    b0 = (P[P_03][b0] & 0xff) ^ b0(k2);
4148e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    b1 = (P[P_13][b1] & 0xff) ^ b1(k2);
4158e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    b2 = (P[P_23][b2] & 0xff) ^ b2(k2);
4168e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    b3 = (P[P_33][b3] & 0xff) ^ b3(k2);
4174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    // fall through, having pre-processed b[0]..b[3] with k32[2]
4184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                case 2: // 128 bits of key
4198e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    gSBox[i*2]   = gMDS0[(P[P_01]
4208e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                        [(P[P_02][b0] & 0xff) ^ b0(k1)] & 0xff) ^ b0(k0)];
4218e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    gSBox[i*2+1] = gMDS1[(P[P_11]
4228e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                        [(P[P_12][b1] & 0xff) ^ b1(k1)] & 0xff) ^ b1(k0)];
4238e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    gSBox[i*2+0x200] = gMDS2[(P[P_21]
4248e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                        [(P[P_22][b2] & 0xff) ^ b2(k1)] & 0xff) ^ b2(k0)];
4258e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                    gSBox[i*2+0x201] = gMDS3[(P[P_31]
4268e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                        [(P[P_32][b3] & 0xff) ^ b3(k1)] & 0xff) ^ b3(k0)];
4278e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                break;
4288e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            }
4298e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
4308e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
4318e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        /*
4328e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom         * the function exits having setup the gSBox with the
4338e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom         * input key material.
4348e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom         */
4358e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
4368e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
4378e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    /**
4388e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * Encrypt the given input starting at the given offset and place
4398e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * the result in the provided buffer starting at the given offset.
4408e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * The input will be an exact multiple of our blocksize.
4418e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     *
4428e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * encryptBlock uses the pre-calculated gSBox[] and subKey[]
4438e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * arrays.
4448e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     */
4458e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private void encryptBlock(
4468e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        byte[] src,
4478e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int srcIndex,
4488e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        byte[] dst,
4498e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int dstIndex)
4508e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
4518e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int x0 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[INPUT_WHITEN];
4528e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int x1 = BytesTo32Bits(src, srcIndex + 4) ^ gSubKeys[INPUT_WHITEN + 1];
4538e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int x2 = BytesTo32Bits(src, srcIndex + 8) ^ gSubKeys[INPUT_WHITEN + 2];
4548e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int x3 = BytesTo32Bits(src, srcIndex + 12) ^ gSubKeys[INPUT_WHITEN + 3];
4558e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
4568e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int k = ROUND_SUBKEYS;
4578e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int t0, t1;
4588e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        for (int r = 0; r < ROUNDS; r +=2)
4598e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
4608e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            t0 = Fe32_0(x0);
4618e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            t1 = Fe32_3(x1);
4628e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x2 ^= t0 + t1 + gSubKeys[k++];
4638e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x2 = x2 >>>1 | x2 << 31;
4648e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x3 = (x3 << 1 | x3 >>> 31) ^ (t0 + 2*t1 + gSubKeys[k++]);
4658e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
4668e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            t0 = Fe32_0(x2);
4678e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            t1 = Fe32_3(x3);
4688e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x0 ^= t0 + t1 + gSubKeys[k++];
4698e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x0 = x0 >>>1 | x0 << 31;
4708e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x1 = (x1 << 1 | x1 >>> 31) ^ (t0 + 2*t1 + gSubKeys[k++]);
4718e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
4728e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
4738e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], dst, dstIndex);
4748e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], dst, dstIndex + 4);
4758e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], dst, dstIndex + 8);
4768e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], dst, dstIndex + 12);
4778e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
4788e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
4798e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    /**
4808e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * Decrypt the given input starting at the given offset and place
4818e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * the result in the provided buffer starting at the given offset.
4828e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * The input will be an exact multiple of our blocksize.
4838e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     */
4848e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private void decryptBlock(
4858e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        byte[] src,
4868e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int srcIndex,
4878e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        byte[] dst,
4888e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int dstIndex)
4898e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
4908e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int x2 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[OUTPUT_WHITEN];
4918e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int x3 = BytesTo32Bits(src, srcIndex+4) ^ gSubKeys[OUTPUT_WHITEN + 1];
4928e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int x0 = BytesTo32Bits(src, srcIndex+8) ^ gSubKeys[OUTPUT_WHITEN + 2];
4938e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int x1 = BytesTo32Bits(src, srcIndex+12) ^ gSubKeys[OUTPUT_WHITEN + 3];
4948e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
4958e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int k = ROUND_SUBKEYS + 2 * ROUNDS -1 ;
4968e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int t0, t1;
4978e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        for (int r = 0; r< ROUNDS ; r +=2)
4988e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
4998e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            t0 = Fe32_0(x2);
5008e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            t1 = Fe32_3(x3);
5018e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x1 ^= t0 + 2*t1 + gSubKeys[k--];
5028e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x0 = (x0 << 1 | x0 >>> 31) ^ (t0 + t1 + gSubKeys[k--]);
5038e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x1 = x1 >>>1 | x1 << 31;
5048e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
5058e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            t0 = Fe32_0(x0);
5068e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            t1 = Fe32_3(x1);
5078e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x3 ^= t0 + 2*t1 + gSubKeys[k--];
5088e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x2 = (x2 << 1 | x2 >>> 31) ^ (t0 + t1 + gSubKeys[k--]);
5098e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            x3 = x3 >>>1 | x3 << 31;
5108e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
5118e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
5128e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], dst, dstIndex);
5138e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], dst, dstIndex + 4);
5148e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], dst, dstIndex + 8);
5158e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], dst, dstIndex + 12);
5168e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
5178e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
5188e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    /*
5198e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * TODO:  This can be optimised and made cleaner by combining
5208e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * the functionality in this function and applying it appropriately
5218e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * to the creation of the subkeys during key setup.
5228e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     */
5238e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int F32(int x, int[] k32)
5248e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
5258e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int b0 = b0(x);
5268e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int b1 = b1(x);
5278e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int b2 = b2(x);
5288e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int b3 = b3(x);
5298e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int k0 = k32[0];
5308e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int k1 = k32[1];
5318e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int k2 = k32[2];
5328e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int k3 = k32[3];
5338e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
5348e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int result = 0;
5358e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        switch (k64Cnt & 3)
5368e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
5378e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            case 1:
5388e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                result = gMDS0[(P[P_01][b0] & 0xff) ^ b0(k0)] ^
5398e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                         gMDS1[(P[P_11][b1] & 0xff) ^ b1(k0)] ^
5408e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                         gMDS2[(P[P_21][b2] & 0xff) ^ b2(k0)] ^
5418e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                         gMDS3[(P[P_31][b3] & 0xff) ^ b3(k0)];
5428e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                break;
5438e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            case 0: /* 256 bits of key */
5448e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                b0 = (P[P_04][b0] & 0xff) ^ b0(k3);
5458e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                b1 = (P[P_14][b1] & 0xff) ^ b1(k3);
5468e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                b2 = (P[P_24][b2] & 0xff) ^ b2(k3);
5478e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                b3 = (P[P_34][b3] & 0xff) ^ b3(k3);
5488e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            case 3:
5498e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                b0 = (P[P_03][b0] & 0xff) ^ b0(k2);
5508e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                b1 = (P[P_13][b1] & 0xff) ^ b1(k2);
5518e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                b2 = (P[P_23][b2] & 0xff) ^ b2(k2);
5528e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                b3 = (P[P_33][b3] & 0xff) ^ b3(k2);
5538e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            case 2:
5548e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                result =
5558e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                gMDS0[(P[P_01][(P[P_02][b0]&0xff)^b0(k1)]&0xff)^b0(k0)] ^
5568e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                gMDS1[(P[P_11][(P[P_12][b1]&0xff)^b1(k1)]&0xff)^b1(k0)] ^
5578e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                gMDS2[(P[P_21][(P[P_22][b2]&0xff)^b2(k1)]&0xff)^b2(k0)] ^
5588e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                gMDS3[(P[P_31][(P[P_32][b3]&0xff)^b3(k1)]&0xff)^b3(k0)];
5598e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            break;
5608e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
5618e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return result;
5628e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
5638e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
5648e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    /**
5658e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * Use (12, 8) Reed-Solomon code over GF(256) to produce
5668e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * a key S-box 32-bit entity from 2 key material 32-bit
5678e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * entities.
5688e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     *
5698e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * @param    k0 first 32-bit entity
5708e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * @param    k1 second 32-bit entity
5718e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * @return     Remainder polynomial generated using RS code
5728e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     */
5738e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int RS_MDS_Encode(int k0, int k1)
5748e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
5758e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int r = k1;
5768e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        for (int i = 0 ; i < 4 ; i++) // shift 1 byte at a time
5778e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
5788e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            r = RS_rem(r);
5798e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
5808e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        r ^= k0;
5818e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        for (int i=0 ; i < 4 ; i++)
5828e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        {
5838e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom            r = RS_rem(r);
5848e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        }
5858e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
5868e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return r;
5878e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
5888e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
5898e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    /**
5908e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * Reed-Solomon code parameters: (12,8) reversible code:<p>
5918e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * <pre>
5928e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * g(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
5938e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * </pre>
5948e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     * where a = primitive root of field generator 0x14D
5958e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom     */
5968e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int RS_rem(int x)
5978e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
5988e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int b = (x >>> 24) & 0xff;
5998e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int g2 = ((b << 1) ^
6008e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                 ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
6018e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        int g3 = ((b >>> 1) ^
6028e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                 ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0)) ^ g2 ;
6038e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
6048e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
6058e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6068e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int LFSR1(int x)
6078e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6088e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return (x >> 1) ^
6098e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                (((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
6108e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
6118e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6128e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int LFSR2(int x)
6138e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6148e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return (x >> 2) ^
6158e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                (((x & 0x02) != 0) ? GF256_FDBK_2 : 0) ^
6168e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom                (((x & 0x01) != 0) ? GF256_FDBK_4 : 0);
6178e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
6188e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6198e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int Mx_X(int x)
6208e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6218e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return x ^ LFSR2(x);
6228e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    } // 5B
6238e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6248e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int Mx_Y(int x)
6258e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6268e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return x ^ LFSR1(x) ^ LFSR2(x);
6278e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    } // EF
6288e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6298e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int b0(int x)
6308e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6318e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return x & 0xff;
6328e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
6338e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6348e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int b1(int x)
6358e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6368e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return (x >>> 8) & 0xff;
6378e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
6388e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6398e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int b2(int x)
6408e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6418e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return (x >>> 16) & 0xff;
6428e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
6438e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6448e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int b3(int x)
6458e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6468e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return (x >>> 24) & 0xff;
6478e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
6488e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6498e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int Fe32_0(int x)
6508e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6518e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return gSBox[ 0x000 + 2*(x & 0xff) ] ^
6528e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom               gSBox[ 0x001 + 2*((x >>> 8) & 0xff) ] ^
6538e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom               gSBox[ 0x200 + 2*((x >>> 16) & 0xff) ] ^
6548e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom               gSBox[ 0x201 + 2*((x >>> 24) & 0xff) ];
6558e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
6568e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6578e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int Fe32_3(int x)
6588e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6598e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return gSBox[ 0x000 + 2*((x >>> 24) & 0xff) ] ^
6608e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom               gSBox[ 0x001 + 2*(x & 0xff) ] ^
6618e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom               gSBox[ 0x200 + 2*((x >>> 8) & 0xff) ] ^
6628e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom               gSBox[ 0x201 + 2*((x >>> 16) & 0xff) ];
6638e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
6648e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6658e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private int BytesTo32Bits(byte[] b, int p)
6668e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6678e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        return ((b[p] & 0xff)) |
6688e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom             ((b[p+1] & 0xff) << 8) |
6698e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom             ((b[p+2] & 0xff) << 16) |
6708e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom             ((b[p+3] & 0xff) << 24);
6718e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
6728e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom
6738e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    private void Bits32ToBytes(int in,  byte[] b, int offset)
6748e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    {
6758e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        b[offset] = (byte)in;
6768e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        b[offset + 1] = (byte)(in >> 8);
6778e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        b[offset + 2] = (byte)(in >> 16);
6788e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom        b[offset + 3] = (byte)(in >> 24);
6798e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom    }
6808e551503a8d09fb57fd4efe9a2aa0392e7ba56e9Brian Carlstrom}
681