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