1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.crypto.engines;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.BlockCipher;
4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.CipherParameters;
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.DataLengthException;
6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.KeyParameter;
7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/**
9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * an implementation of the AES (Rijndael), from FIPS-197.
10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <p>
11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam *
13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam *
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * There are three levels of tradeoff of speed vs memory
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Because java has no preprocessor, they are written as three separate classes from which to choose
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam *
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * and 4 for decryption.
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam *
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * adding 12 rotate operations per round to compute the values contained in the other tables from
24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * the contents of the first.
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam *
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * The slowest version uses no static tables at all and computes the values in each round.
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <p>
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * This file contains the middle performance version with 2Kbytes of static tables for round precomputation.
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam *
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class AESEngine
32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    implements BlockCipher
33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // The S box
35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final byte[] S = {
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197,
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)48,   (byte)1, (byte)103,  (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)202, (byte)130, (byte)201, (byte)125, (byte)250,  (byte)89,  (byte)71, (byte)240,
39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)183, (byte)253, (byte)147,  (byte)38,  (byte)54,  (byte)63, (byte)247, (byte)204,
41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216,  (byte)49,  (byte)21,
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)4, (byte)199,  (byte)35, (byte)195,  (byte)24, (byte)150,   (byte)5, (byte)154,
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)7,  (byte)18, (byte)128, (byte)226, (byte)235,  (byte)39, (byte)178, (byte)117,
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)9, (byte)131,  (byte)44,  (byte)26,  (byte)27, (byte)110,  (byte)90, (byte)160,
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)82,  (byte)59, (byte)214, (byte)179,  (byte)41, (byte)227,  (byte)47, (byte)132,
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)83, (byte)209,   (byte)0, (byte)237,  (byte)32, (byte)252, (byte)177,  (byte)91,
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)106, (byte)203, (byte)190,  (byte)57,  (byte)74,  (byte)76,  (byte)88, (byte)207,
48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)208, (byte)239, (byte)170, (byte)251,  (byte)67,  (byte)77,  (byte)51, (byte)133,
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)69, (byte)249,   (byte)2, (byte)127,  (byte)80,  (byte)60, (byte)159, (byte)168,
50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)81, (byte)163,  (byte)64, (byte)143, (byte)146, (byte)157,  (byte)56, (byte)245,
51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)188, (byte)182, (byte)218,  (byte)33,  (byte)16, (byte)255, (byte)243, (byte)210,
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)205,  (byte)12,  (byte)19, (byte)236,  (byte)95, (byte)151,  (byte)68,  (byte)23,
53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)196, (byte)167, (byte)126,  (byte)61, (byte)100,  (byte)93,  (byte)25, (byte)115,
54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)96, (byte)129,  (byte)79, (byte)220,  (byte)34,  (byte)42, (byte)144, (byte)136,
55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)70, (byte)238, (byte)184,  (byte)20, (byte)222,  (byte)94,  (byte)11, (byte)219,
56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)224,  (byte)50,  (byte)58,  (byte)10,  (byte)73,   (byte)6,  (byte)36,  (byte)92,
57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)194, (byte)211, (byte)172,  (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)231, (byte)200,  (byte)55, (byte)109, (byte)141, (byte)213,  (byte)78, (byte)169,
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)108,  (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174,   (byte)8,
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)186, (byte)120,  (byte)37,  (byte)46,  (byte)28, (byte)166, (byte)180, (byte)198,
61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)232, (byte)221, (byte)116,  (byte)31,  (byte)75, (byte)189, (byte)139, (byte)138,
62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)112,  (byte)62, (byte)181, (byte)102,  (byte)72,   (byte)3, (byte)246,  (byte)14,
63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)97,  (byte)53,  (byte)87, (byte)185, (byte)134, (byte)193,  (byte)29, (byte)158,
64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)225, (byte)248, (byte)152,  (byte)17, (byte)105, (byte)217, (byte)142, (byte)148,
65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)155,  (byte)30, (byte)135, (byte)233, (byte)206,  (byte)85,  (byte)40, (byte)223,
66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)140, (byte)161, (byte)137,  (byte)13, (byte)191, (byte)230,  (byte)66, (byte)104,
67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)65, (byte)153,  (byte)45,  (byte)15, (byte)176,  (byte)84, (byte)187,  (byte)22,
68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    };
69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // The inverse S-box
71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final byte[] Si = {
72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)82,   (byte)9, (byte)106, (byte)213,  (byte)48,  (byte)54, (byte)165,  (byte)56,
73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)191,  (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)124, (byte)227,  (byte)57, (byte)130, (byte)155,  (byte)47, (byte)255, (byte)135,
75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)52, (byte)142,  (byte)67,  (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)84, (byte)123, (byte)148,  (byte)50, (byte)166, (byte)194,  (byte)35,  (byte)61,
77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)238,  (byte)76, (byte)149,  (byte)11,  (byte)66, (byte)250, (byte)195,  (byte)78,
78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)8,  (byte)46, (byte)161, (byte)102,  (byte)40, (byte)217,  (byte)36, (byte)178,
79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)118,  (byte)91, (byte)162,  (byte)73, (byte)109, (byte)139, (byte)209,  (byte)37,
80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152,  (byte)22,
81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)212, (byte)164,  (byte)92, (byte)204,  (byte)93, (byte)101, (byte)182, (byte)146,
82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)108, (byte)112,  (byte)72,  (byte)80, (byte)253, (byte)237, (byte)185, (byte)218,
83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)94,  (byte)21,  (byte)70,  (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)144, (byte)216, (byte)171,   (byte)0, (byte)140, (byte)188, (byte)211,  (byte)10,
85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)247, (byte)228,  (byte)88,   (byte)5, (byte)184, (byte)179,  (byte)69,   (byte)6,
86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)208,  (byte)44,  (byte)30, (byte)143, (byte)202,  (byte)63,  (byte)15,   (byte)2,
87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)193, (byte)175, (byte)189,   (byte)3,   (byte)1,  (byte)19, (byte)138, (byte)107,
88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)58, (byte)145,  (byte)17,  (byte)65,  (byte)79, (byte)103, (byte)220, (byte)234,
89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)150, (byte)172, (byte)116,  (byte)34, (byte)231, (byte)173,  (byte)53, (byte)133,
91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)226, (byte)249,  (byte)55, (byte)232,  (byte)28, (byte)117, (byte)223, (byte)110,
92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)71, (byte)241,  (byte)26, (byte)113,  (byte)29,  (byte)41, (byte)197, (byte)137,
93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)111, (byte)183,  (byte)98,  (byte)14, (byte)170,  (byte)24, (byte)190,  (byte)27,
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)252,  (byte)86,  (byte)62,  (byte)75, (byte)198, (byte)210, (byte)121,  (byte)32,
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205,  (byte)90, (byte)244,
96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)31, (byte)221, (byte)168,  (byte)51, (byte)136,   (byte)7, (byte)199,  (byte)49,
97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)177,  (byte)18,  (byte)16,  (byte)89,  (byte)39, (byte)128, (byte)236,  (byte)95,
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)96,  (byte)81, (byte)127, (byte)169,  (byte)25, (byte)181,  (byte)74,  (byte)13,
99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)160, (byte)224,  (byte)59,  (byte)77, (byte)174,  (byte)42, (byte)245, (byte)176,
101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)200, (byte)235, (byte)187,  (byte)60, (byte)131,  (byte)83, (byte)153,  (byte)97,
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)23,  (byte)43,   (byte)4, (byte)126, (byte)186, (byte)119, (byte)214,  (byte)38,
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        (byte)225, (byte)105,  (byte)20,  (byte)99,  (byte)85,  (byte)33,  (byte)12, (byte)125,
104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        };
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // vector used in calculating key schedule (powers of x in GF(256))
107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int[] rcon = {
108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam         0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam         0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // precomputation tables of calculations for rounds
112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int[] T0 =
113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x3a16162c};
166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamprivate static final int[] Tinv0 =
168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
177b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
178b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
179b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
181b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
184b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
185b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
186b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
187b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
188b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
189b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
190b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
192b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
193b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
194b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
195b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
196b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
197b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
198b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
199b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
200b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
201b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
202b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
203b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
204b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
206b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
207b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
209b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
211b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
212b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
213b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
214b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
219b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     0x4257b8d0};
221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int shift(
223b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     r,
224b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     shift)
225b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
226b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (r >>> shift) | (r << -shift);
227b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
228b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
229b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
230b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
231b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int m1 = 0x80808080;
232b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int m2 = 0x7f7f7f7f;
233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int m3 = 0x0000001b;
234b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
235b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int FFmulX(int x)
236b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
237b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
238b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
239b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /*
241b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam       The following defines provide alternative definitions of FFmulX that might
242b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam       give improved performance if a fast 32-bit multiply is not available.
243b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
244b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam       private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
245b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam       private static final int  m4 = 0x1b1b1b1b;
246b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam       private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
247b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
248b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    */
249b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
250b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int inv_mcol(int x)
251b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
252b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int f2 = FFmulX(x);
253b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int f4 = FFmulX(f2);
254b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int f8 = FFmulX(f4);
255b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int f9 = x ^ f8;
256b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
257b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
258b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
259b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
260b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int subWord(int x)
261b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
262b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
263b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
264b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
265b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
266b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Calculate the necessary round keys
267b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * The number of calculations depends on key size and block size
268b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
269b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * This code is written assuming those are the only possible values
270b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
271b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int[][] generateWorkingKey(
272b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    byte[] key,
273b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                                    boolean forEncryption)
274b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
275b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int         KC = key.length / 4;  // key length in words
276b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int         t;
277b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
278b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
279b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
280b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalArgumentException("Key length not 128/192/256 bits.");
281b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
282b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
283b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ROUNDS = KC + 6;  // This is not always true for the generalized Rijndael that allows larger block sizes
284b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int[][] W = new int[ROUNDS+1][4];   // 4 words in a block
285b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
286b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
287b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // copy the key into the round key array
288b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
289b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
290b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        t = 0;
291b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int i = 0;
292b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (i < key.length)
293b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
294b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
295b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                i+=4;
296b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                t++;
297b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
298b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
299b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
300b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // while not enough round key material calculated
301b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // calculate new values
302b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
303b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int k = (ROUNDS + 1) << 2;
304b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (i = KC; (i < k); i++)
305b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
306b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                int temp = W[(i-1)>>2][(i-1)&3];
307b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if ((i % KC) == 0)
308b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
309b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    temp = subWord(shift(temp, 8)) ^ rcon[(i / KC)-1];
310b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
311b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                else if ((KC > 6) && ((i % KC) == 4))
312b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
313b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    temp = subWord(temp);
314b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
315b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
316b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
317b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
318b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
319b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (!forEncryption)
320b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
321b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            for (int j = 1; j < ROUNDS; j++)
322b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
323b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                for (i = 0; i < 4; i++)
324b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
325b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    W[j][i] = inv_mcol(W[j][i]);
326b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
327b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
328b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
329b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
330b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return W;
331b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
332b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
333b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int         ROUNDS;
334b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int[][]     WorkingKey = null;
335b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int         C0, C1, C2, C3;
336b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private boolean     forEncryption;
337b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
338b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int BLOCK_SIZE = 16;
339b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
340b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
341b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * default constructor - 128 bit block size.
342b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
343b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public AESEngine()
344b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
345b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
346b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
347b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
348b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * initialise an AES cipher.
349b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
350b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param forEncryption whether or not we are for encryption.
351b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param params the parameters required to set up the cipher.
352b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @exception IllegalArgumentException if the params argument is
353b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * inappropriate.
354b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
355b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void init(
356b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        boolean           forEncryption,
357b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        CipherParameters  params)
358b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
359b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (params instanceof KeyParameter)
360b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
361b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption);
362b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            this.forEncryption = forEncryption;
363b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return;
364b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
365b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
366b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throw new IllegalArgumentException("invalid parameter passed to AES init - " + params.getClass().getName());
367b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
368b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
369b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public String getAlgorithmName()
370b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
371b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return "AES";
372b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
373b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
374b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public int getBlockSize()
375b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
376b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return BLOCK_SIZE;
377b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
378b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
379b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public int processBlock(
380b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[] in,
381b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int inOff,
382b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[] out,
383b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int outOff)
384b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
385b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (WorkingKey == null)
386b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
387b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IllegalStateException("AES engine not initialised");
388b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
389b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
390b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if ((inOff + (32 / 2)) > in.length)
391b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
392b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new DataLengthException("input buffer too short");
393b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
394b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
395b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if ((outOff + (32 / 2)) > out.length)
396b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
397b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new DataLengthException("output buffer too short");
398b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
399b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
400b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (forEncryption)
401b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
402b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            unpackBlock(in, inOff);
403b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            encryptBlock(WorkingKey);
404b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            packBlock(out, outOff);
405b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
406b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else
407b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
408b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            unpackBlock(in, inOff);
409b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            decryptBlock(WorkingKey);
410b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            packBlock(out, outOff);
411b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
412b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
413b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return BLOCK_SIZE;
414b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
415b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
416b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void reset()
417b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
418b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
419b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
420c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private void unpackBlock(
421b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]      bytes,
422b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int         off)
423b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
424b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     index = off;
425b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
426b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C0 = (bytes[index++] & 0xff);
427b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C0 |= (bytes[index++] & 0xff) << 8;
428b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C0 |= (bytes[index++] & 0xff) << 16;
429b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C0 |= bytes[index++] << 24;
430b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
431b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C1 = (bytes[index++] & 0xff);
432b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C1 |= (bytes[index++] & 0xff) << 8;
433b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C1 |= (bytes[index++] & 0xff) << 16;
434b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C1 |= bytes[index++] << 24;
435b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
436b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C2 = (bytes[index++] & 0xff);
437b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C2 |= (bytes[index++] & 0xff) << 8;
438b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C2 |= (bytes[index++] & 0xff) << 16;
439b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C2 |= bytes[index++] << 24;
440b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
441b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C3 = (bytes[index++] & 0xff);
442b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C3 |= (bytes[index++] & 0xff) << 8;
443b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C3 |= (bytes[index++] & 0xff) << 16;
444b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C3 |= bytes[index++] << 24;
445b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
446b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
447c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private void packBlock(
448b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]      bytes,
449b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int         off)
450b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
451b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     index = off;
452b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
453b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)C0;
454b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C0 >> 8);
455b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C0 >> 16);
456b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C0 >> 24);
457b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
458b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)C1;
459b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C1 >> 8);
460b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C1 >> 16);
461b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C1 >> 24);
462b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
463b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)C2;
464b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C2 >> 8);
465b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C2 >> 16);
466b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C2 >> 24);
467b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
468b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)C3;
469b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C3 >> 8);
470b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C3 >> 16);
471b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        bytes[index++] = (byte)(C3 >> 24);
472b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
473b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
474b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
475c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private void encryptBlock(int[][] KW)
476b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
477b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int r, r0, r1, r2, r3;
478b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
479b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C0 ^= KW[0][0];
480b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C1 ^= KW[0][1];
481b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C2 ^= KW[0][2];
482b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C3 ^= KW[0][3];
483b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
484b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        r = 1;
485b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
486b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (r < ROUNDS - 1)
487b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
488b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            r0 = T0[C0&255] ^ shift(T0[(C1>>8)&255], 24) ^ shift(T0[(C2>>16)&255],16) ^ shift(T0[(C3>>24)&255],8) ^ KW[r][0];
489b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            r1 = T0[C1&255] ^ shift(T0[(C2>>8)&255], 24) ^ shift(T0[(C3>>16)&255], 16) ^ shift(T0[(C0>>24)&255], 8) ^ KW[r][1];
490b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            r2 = T0[C2&255] ^ shift(T0[(C3>>8)&255], 24) ^ shift(T0[(C0>>16)&255], 16) ^ shift(T0[(C1>>24)&255], 8) ^ KW[r][2];
491b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            r3 = T0[C3&255] ^ shift(T0[(C0>>8)&255], 24) ^ shift(T0[(C1>>16)&255], 16) ^ shift(T0[(C2>>24)&255], 8) ^ KW[r++][3];
492b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            C0 = T0[r0&255] ^ shift(T0[(r1>>8)&255], 24) ^ shift(T0[(r2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
493b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            C1 = T0[r1&255] ^ shift(T0[(r2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(r0>>24)&255], 8) ^ KW[r][1];
494b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            C2 = T0[r2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(r0>>16)&255], 16) ^ shift(T0[(r1>>24)&255], 8) ^ KW[r][2];
495b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            C3 = T0[r3&255] ^ shift(T0[(r0>>8)&255], 24) ^ shift(T0[(r1>>16)&255], 16) ^ shift(T0[(r2>>24)&255], 8) ^ KW[r++][3];
496b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
497b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
498b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        r0 = T0[C0&255] ^ shift(T0[(C1>>8)&255], 24) ^ shift(T0[(C2>>16)&255], 16) ^ shift(T0[(C3>>24)&255], 8) ^ KW[r][0];
499b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        r1 = T0[C1&255] ^ shift(T0[(C2>>8)&255], 24) ^ shift(T0[(C3>>16)&255], 16) ^ shift(T0[(C0>>24)&255], 8) ^ KW[r][1];
500b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        r2 = T0[C2&255] ^ shift(T0[(C3>>8)&255], 24) ^ shift(T0[(C0>>16)&255], 16) ^ shift(T0[(C1>>24)&255], 8) ^ KW[r][2];
501b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        r3 = T0[C3&255] ^ shift(T0[(C0>>8)&255], 24) ^ shift(T0[(C1>>16)&255], 16) ^ shift(T0[(C2>>24)&255], 8) ^ KW[r++][3];
502b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
503b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // the final round's table is a simple function of S so we don't use a whole other four tables for it
504b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
505b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
506b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
507b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
508b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
509b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
510b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
511b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
512c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private void decryptBlock(int[][] KW)
513b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
514b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int r, r0, r1, r2, r3;
515b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
516b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C0 ^= KW[ROUNDS][0];
517b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C1 ^= KW[ROUNDS][1];
518b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C2 ^= KW[ROUNDS][2];
519b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C3 ^= KW[ROUNDS][3];
520b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
521b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        r = ROUNDS-1;
522b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
523b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        while (r>1)
524b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
525b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            r0 = Tinv0[C0&255] ^ shift(Tinv0[(C3>>8)&255], 24) ^ shift(Tinv0[(C2>>16)&255], 16) ^ shift(Tinv0[(C1>>24)&255], 8) ^ KW[r][0];
526b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            r1 = Tinv0[C1&255] ^ shift(Tinv0[(C0>>8)&255], 24) ^ shift(Tinv0[(C3>>16)&255], 16) ^ shift(Tinv0[(C2>>24)&255], 8) ^ KW[r][1];
527b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            r2 = Tinv0[C2&255] ^ shift(Tinv0[(C1>>8)&255], 24) ^ shift(Tinv0[(C0>>16)&255], 16) ^ shift(Tinv0[(C3>>24)&255], 8) ^ KW[r][2];
528b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            r3 = Tinv0[C3&255] ^ shift(Tinv0[(C2>>8)&255], 24) ^ shift(Tinv0[(C1>>16)&255], 16) ^ shift(Tinv0[(C0>>24)&255], 8) ^ KW[r--][3];
529b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            C0 = Tinv0[r0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(r2>>16)&255], 16) ^ shift(Tinv0[(r1>>24)&255], 8) ^ KW[r][0];
530b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            C1 = Tinv0[r1&255] ^ shift(Tinv0[(r0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(r2>>24)&255], 8) ^ KW[r][1];
531b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            C2 = Tinv0[r2&255] ^ shift(Tinv0[(r1>>8)&255], 24) ^ shift(Tinv0[(r0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
532b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            C3 = Tinv0[r3&255] ^ shift(Tinv0[(r2>>8)&255], 24) ^ shift(Tinv0[(r1>>16)&255], 16) ^ shift(Tinv0[(r0>>24)&255], 8) ^ KW[r--][3];
533b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
534b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
535b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        r0 = Tinv0[C0&255] ^ shift(Tinv0[(C3>>8)&255], 24) ^ shift(Tinv0[(C2>>16)&255], 16) ^ shift(Tinv0[(C1>>24)&255], 8) ^ KW[r][0];
536b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        r1 = Tinv0[C1&255] ^ shift(Tinv0[(C0>>8)&255], 24) ^ shift(Tinv0[(C3>>16)&255], 16) ^ shift(Tinv0[(C2>>24)&255], 8) ^ KW[r][1];
537b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        r2 = Tinv0[C2&255] ^ shift(Tinv0[(C1>>8)&255], 24) ^ shift(Tinv0[(C0>>16)&255], 16) ^ shift(Tinv0[(C3>>24)&255], 8) ^ KW[r][2];
538c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        r3 = Tinv0[C3&255] ^ shift(Tinv0[(C2>>8)&255], 24) ^ shift(Tinv0[(C1>>16)&255], 16) ^ shift(Tinv0[(C0>>24)&255], 8) ^ KW[r][3];
539b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
540b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // the final round's table is a simple function of Si so we don't use a whole other four tables for it
541b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
542b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
543b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
544b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
545b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
546b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
547b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
548