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