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