Home | History | Annotate | Download | only in engines
      1 package org.bouncycastle.crypto.engines;
      2 
      3 import org.bouncycastle.crypto.BlockCipher;
      4 import org.bouncycastle.crypto.CipherParameters;
      5 import org.bouncycastle.crypto.DataLengthException;
      6 import org.bouncycastle.crypto.OutputLengthException;
      7 import org.bouncycastle.crypto.params.KeyParameter;
      8 import org.bouncycastle.util.Arrays;
      9 import 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  */
     34 public 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 
    170 private 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