Home | History | Annotate | Download | only in crypto
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../../include/fxcrt/fx_basic.h"
      8 #include "../../../include/fdrm/fx_crypt.h"
      9 #ifdef __cplusplus
     10 extern "C" {
     11 #endif
     12 #define MAX_NR 14
     13 #define MAX_NK 8
     14 #define MAX_NB 8
     15 #define mulby2(x) ( ((x&0x7F) << 1) ^ (x & 0x80 ? 0x1B : 0) )
     16 #define GET_32BIT_MSB_FIRST(cp) \
     17     (((unsigned long)(unsigned char)(cp)[3]) | \
     18      ((unsigned long)(unsigned char)(cp)[2] << 8) | \
     19      ((unsigned long)(unsigned char)(cp)[1] << 16) | \
     20      ((unsigned long)(unsigned char)(cp)[0] << 24))
     21 #define PUT_32BIT_MSB_FIRST(cp, value) do { \
     22         (cp)[3] = (value); \
     23         (cp)[2] = (value) >> 8; \
     24         (cp)[1] = (value) >> 16; \
     25         (cp)[0] = (value) >> 24; } while (0)
     26 struct AESContext {
     27     unsigned int keysched[(MAX_NR + 1) * MAX_NB];
     28     unsigned int invkeysched[(MAX_NR + 1) * MAX_NB];
     29     void (*encrypt) (AESContext * ctx, unsigned int * block);
     30     void (*decrypt) (AESContext * ctx, unsigned int * block);
     31     unsigned int iv[MAX_NB];
     32     int Nb, Nr;
     33 };
     34 static const unsigned char Sbox[256] = {
     35     0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
     36     0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
     37     0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
     38     0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
     39     0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
     40     0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
     41     0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
     42     0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
     43     0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
     44     0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
     45     0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
     46     0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
     47     0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
     48     0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
     49     0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
     50     0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
     51     0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
     52     0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
     53     0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
     54     0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
     55     0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
     56     0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
     57     0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
     58     0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
     59     0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
     60     0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
     61     0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
     62     0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
     63     0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
     64     0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
     65     0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
     66     0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
     67 };
     68 static const unsigned char Sboxinv[256] = {
     69     0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
     70     0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
     71     0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
     72     0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
     73     0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
     74     0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
     75     0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
     76     0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
     77     0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
     78     0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
     79     0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
     80     0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
     81     0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
     82     0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
     83     0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
     84     0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
     85     0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
     86     0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
     87     0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
     88     0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
     89     0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
     90     0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
     91     0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
     92     0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
     93     0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
     94     0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
     95     0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
     96     0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
     97     0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
     98     0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
     99     0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
    100     0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
    101 };
    102 static const unsigned int E0[256] = {
    103     0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d,
    104     0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554,
    105     0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d,
    106     0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a,
    107     0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87,
    108     0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b,
    109     0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea,
    110     0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b,
    111     0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a,
    112     0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f,
    113     0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108,
    114     0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f,
    115     0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e,
    116     0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5,
    117     0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d,
    118     0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f,
    119     0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e,
    120     0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb,
    121     0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce,
    122     0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497,
    123     0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c,
    124     0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed,
    125     0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b,
    126     0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a,
    127     0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16,
    128     0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594,
    129     0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81,
    130     0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3,
    131     0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a,
    132     0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504,
    133     0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163,
    134     0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d,
    135     0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f,
    136     0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739,
    137     0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47,
    138     0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,
    139     0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f,
    140     0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883,
    141     0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c,
    142     0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76,
    143     0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e,
    144     0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4,
    145     0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6,
    146     0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b,
    147     0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7,
    148     0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0,
    149     0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25,
    150     0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
    151     0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72,
    152     0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651,
    153     0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21,
    154     0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85,
    155     0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa,
    156     0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12,
    157     0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0,
    158     0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9,
    159     0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133,
    160     0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7,
    161     0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920,
    162     0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a,
    163     0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17,
    164     0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8,
    165     0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11,
    166     0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a,
    167 };
    168 static const unsigned int E1[256] = {
    169     0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b,
    170     0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5,
    171     0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b,
    172     0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676,
    173     0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d,
    174     0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0,
    175     0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf,
    176     0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0,
    177     0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626,
    178     0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc,
    179     0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1,
    180     0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515,
    181     0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3,
    182     0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a,
    183     0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2,
    184     0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575,
    185     0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a,
    186     0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0,
    187     0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3,
    188     0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484,
    189     0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded,
    190     0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b,
    191     0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939,
    192     0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf,
    193     0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb,
    194     0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585,
    195     0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f,
    196     0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8,
    197     0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f,
    198     0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5,
    199     0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121,
    200     0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2,
    201     0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec,
    202     0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717,
    203     0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d,
    204     0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373,
    205     0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc,
    206     0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888,
    207     0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414,
    208     0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb,
    209     0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a,
    210     0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c,
    211     0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262,
    212     0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979,
    213     0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d,
    214     0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9,
    215     0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea,
    216     0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808,
    217     0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e,
    218     0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6,
    219     0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f,
    220     0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a,
    221     0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666,
    222     0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e,
    223     0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9,
    224     0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e,
    225     0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111,
    226     0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494,
    227     0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9,
    228     0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf,
    229     0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d,
    230     0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868,
    231     0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f,
    232     0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616,
    233 };
    234 static const unsigned int E2[256] = {
    235     0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b,
    236     0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5,
    237     0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b,
    238     0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76,
    239     0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d,
    240     0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0,
    241     0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af,
    242     0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0,
    243     0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26,
    244     0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc,
    245     0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1,
    246     0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15,
    247     0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3,
    248     0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a,
    249     0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2,
    250     0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75,
    251     0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a,
    252     0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0,
    253     0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3,
    254     0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384,
    255     0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed,
    256     0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b,
    257     0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239,
    258     0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf,
    259     0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb,
    260     0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185,
    261     0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f,
    262     0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8,
    263     0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f,
    264     0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5,
    265     0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221,
    266     0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2,
    267     0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec,
    268     0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17,
    269     0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d,
    270     0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673,
    271     0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc,
    272     0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88,
    273     0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814,
    274     0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb,
    275     0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a,
    276     0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c,
    277     0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462,
    278     0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279,
    279     0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d,
    280     0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9,
    281     0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea,
    282     0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008,
    283     0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e,
    284     0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6,
    285     0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f,
    286     0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a,
    287     0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66,
    288     0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e,
    289     0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9,
    290     0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e,
    291     0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211,
    292     0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394,
    293     0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9,
    294     0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df,
    295     0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d,
    296     0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068,
    297     0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f,
    298     0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16,
    299 };
    300 static const unsigned int E3[256] = {
    301     0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6,
    302     0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491,
    303     0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56,
    304     0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec,
    305     0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa,
    306     0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb,
    307     0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45,
    308     0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b,
    309     0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c,
    310     0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83,
    311     0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9,
    312     0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a,
    313     0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d,
    314     0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f,
    315     0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf,
    316     0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea,
    317     0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34,
    318     0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b,
    319     0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d,
    320     0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713,
    321     0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1,
    322     0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6,
    323     0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72,
    324     0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85,
    325     0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed,
    326     0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411,
    327     0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe,
    328     0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b,
    329     0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05,
    330     0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1,
    331     0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342,
    332     0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf,
    333     0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3,
    334     0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e,
    335     0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a,
    336     0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6,
    337     0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3,
    338     0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b,
    339     0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28,
    340     0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad,
    341     0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14,
    342     0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8,
    343     0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4,
    344     0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2,
    345     0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da,
    346     0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049,
    347     0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf,
    348     0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810,
    349     0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c,
    350     0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197,
    351     0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e,
    352     0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f,
    353     0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc,
    354     0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c,
    355     0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069,
    356     0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927,
    357     0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322,
    358     0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733,
    359     0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9,
    360     0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5,
    361     0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a,
    362     0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0,
    363     0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e,
    364     0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c,
    365 };
    366 static const unsigned int D0[256] = {
    367     0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96,
    368     0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393,
    369     0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25,
    370     0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f,
    371     0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1,
    372     0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6,
    373     0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da,
    374     0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844,
    375     0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd,
    376     0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4,
    377     0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45,
    378     0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94,
    379     0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7,
    380     0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a,
    381     0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5,
    382     0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c,
    383     0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1,
    384     0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a,
    385     0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75,
    386     0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051,
    387     0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46,
    388     0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff,
    389     0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77,
    390     0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb,
    391     0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000,
    392     0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e,
    393     0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927,
    394     0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a,
    395     0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e,
    396     0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16,
    397     0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d,
    398     0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8,
    399     0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd,
    400     0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34,
    401     0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163,
    402     0xd731dcca, 0x42638510, 0x13972240, 0x84c61120,
    403     0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d,
    404     0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0,
    405     0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422,
    406     0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef,
    407     0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36,
    408     0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4,
    409     0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662,
    410     0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5,
    411     0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3,
    412     0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b,
    413     0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8,
    414     0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6,
    415     0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6,
    416     0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0,
    417     0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815,
    418     0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f,
    419     0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df,
    420     0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f,
    421     0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e,
    422     0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713,
    423     0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89,
    424     0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c,
    425     0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf,
    426     0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86,
    427     0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f,
    428     0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541,
    429     0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190,
    430     0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742,
    431 };
    432 static const unsigned int D1[256] = {
    433     0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e,
    434     0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303,
    435     0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c,
    436     0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3,
    437     0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0,
    438     0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9,
    439     0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259,
    440     0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8,
    441     0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971,
    442     0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a,
    443     0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f,
    444     0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b,
    445     0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8,
    446     0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab,
    447     0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708,
    448     0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682,
    449     0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2,
    450     0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe,
    451     0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb,
    452     0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10,
    453     0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd,
    454     0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015,
    455     0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e,
    456     0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee,
    457     0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000,
    458     0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72,
    459     0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39,
    460     0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e,
    461     0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91,
    462     0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a,
    463     0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17,
    464     0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9,
    465     0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60,
    466     0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e,
    467     0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1,
    468     0xcad731dc, 0x10426385, 0x40139722, 0x2084c611,
    469     0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1,
    470     0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3,
    471     0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964,
    472     0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390,
    473     0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b,
    474     0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf,
    475     0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46,
    476     0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af,
    477     0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512,
    478     0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb,
    479     0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a,
    480     0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8,
    481     0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c,
    482     0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266,
    483     0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8,
    484     0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6,
    485     0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604,
    486     0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551,
    487     0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41,
    488     0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647,
    489     0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c,
    490     0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1,
    491     0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737,
    492     0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db,
    493     0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340,
    494     0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95,
    495     0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1,
    496     0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857,
    497 };
    498 static const unsigned int D2[256] = {
    499     0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27,
    500     0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3,
    501     0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502,
    502     0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562,
    503     0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe,
    504     0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3,
    505     0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552,
    506     0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9,
    507     0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9,
    508     0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce,
    509     0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253,
    510     0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908,
    511     0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b,
    512     0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655,
    513     0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337,
    514     0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16,
    515     0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69,
    516     0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6,
    517     0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6,
    518     0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e,
    519     0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6,
    520     0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050,
    521     0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9,
    522     0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8,
    523     0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000,
    524     0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a,
    525     0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d,
    526     0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436,
    527     0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b,
    528     0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12,
    529     0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b,
    530     0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e,
    531     0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f,
    532     0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb,
    533     0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4,
    534     0xdccad731, 0x85104263, 0x22401397, 0x112084c6,
    535     0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729,
    536     0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1,
    537     0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9,
    538     0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233,
    539     0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4,
    540     0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad,
    541     0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e,
    542     0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3,
    543     0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25,
    544     0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b,
    545     0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f,
    546     0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15,
    547     0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0,
    548     0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2,
    549     0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7,
    550     0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791,
    551     0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496,
    552     0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665,
    553     0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b,
    554     0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6,
    555     0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13,
    556     0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47,
    557     0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7,
    558     0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844,
    559     0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3,
    560     0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d,
    561     0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456,
    562     0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8,
    563 };
    564 static const unsigned int D3[256] = {
    565     0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a,
    566     0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b,
    567     0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5,
    568     0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5,
    569     0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d,
    570     0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b,
    571     0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95,
    572     0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e,
    573     0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27,
    574     0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d,
    575     0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562,
    576     0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9,
    577     0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752,
    578     0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66,
    579     0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3,
    580     0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced,
    581     0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e,
    582     0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4,
    583     0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4,
    584     0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd,
    585     0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d,
    586     0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60,
    587     0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767,
    588     0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79,
    589     0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000,
    590     0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c,
    591     0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736,
    592     0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24,
    593     0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b,
    594     0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c,
    595     0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12,
    596     0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814,
    597     0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3,
    598     0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b,
    599     0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8,
    600     0x31dccad7, 0x63851042, 0x97224013, 0xc6112084,
    601     0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7,
    602     0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077,
    603     0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247,
    604     0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22,
    605     0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698,
    606     0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f,
    607     0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254,
    608     0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582,
    609     0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf,
    610     0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb,
    611     0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883,
    612     0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef,
    613     0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629,
    614     0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035,
    615     0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533,
    616     0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17,
    617     0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4,
    618     0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46,
    619     0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb,
    620     0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d,
    621     0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb,
    622     0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a,
    623     0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73,
    624     0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678,
    625     0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2,
    626     0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff,
    627     0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064,
    628     0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0,
    629 };
    630 #define ADD_ROUND_KEY_4 (block[0]^=*keysched++, block[1]^=*keysched++, \
    631                          block[2]^=*keysched++, block[3]^=*keysched++)
    632 #define ADD_ROUND_KEY_6 (block[0]^=*keysched++, block[1]^=*keysched++, \
    633                          block[2]^=*keysched++, block[3]^=*keysched++, \
    634                          block[4]^=*keysched++, block[5]^=*keysched++)
    635 #define ADD_ROUND_KEY_8 (block[0]^=*keysched++, block[1]^=*keysched++, \
    636                          block[2]^=*keysched++, block[3]^=*keysched++, \
    637                          block[4]^=*keysched++, block[5]^=*keysched++, \
    638                          block[6]^=*keysched++, block[7]^=*keysched++)
    639 #define MOVEWORD(i) ( block[i] = newstate[i] )
    640 #undef MAKEWORD
    641 #define MAKEWORD(i) ( newstate[i] = (E0[(block[i] >> 24) & 0xFF] ^ \
    642                                      E1[(block[(i+C1)%Nb] >> 16) & 0xFF] ^ \
    643                                      E2[(block[(i+C2)%Nb] >> 8) & 0xFF] ^ \
    644                                      E3[block[(i+C3)%Nb] & 0xFF]) )
    645 #define LASTWORD(i) ( newstate[i] = (Sbox[(block[i] >> 24) & 0xFF] << 24) | \
    646                                     (Sbox[(block[(i+C1)%Nb] >> 16) & 0xFF] << 16) | \
    647                                     (Sbox[(block[(i+C2)%Nb] >>  8) & 0xFF] <<  8) | \
    648                                     (Sbox[(block[(i+C3)%Nb]      ) & 0xFF]      ) )
    649 static void aes_encrypt_nb_4(AESContext * ctx, unsigned int * block)
    650 {
    651     int i;
    652     static const int C1 = 1, C2 = 2, C3 = 3, Nb = 4;
    653     unsigned int *keysched = ctx->keysched;
    654     unsigned int newstate[4];
    655     for (i = 0; i < ctx->Nr - 1; i++) {
    656         ADD_ROUND_KEY_4;
    657         MAKEWORD(0);
    658         MAKEWORD(1);
    659         MAKEWORD(2);
    660         MAKEWORD(3);
    661         MOVEWORD(0);
    662         MOVEWORD(1);
    663         MOVEWORD(2);
    664         MOVEWORD(3);
    665     }
    666     ADD_ROUND_KEY_4;
    667     LASTWORD(0);
    668     LASTWORD(1);
    669     LASTWORD(2);
    670     LASTWORD(3);
    671     MOVEWORD(0);
    672     MOVEWORD(1);
    673     MOVEWORD(2);
    674     MOVEWORD(3);
    675     ADD_ROUND_KEY_4;
    676 }
    677 static void aes_encrypt_nb_6(AESContext * ctx, unsigned int * block)
    678 {
    679     int i;
    680     static const int C1 = 1, C2 = 2, C3 = 3, Nb = 6;
    681     unsigned int *keysched = ctx->keysched;
    682     unsigned int newstate[6];
    683     for (i = 0; i < ctx->Nr - 1; i++) {
    684         ADD_ROUND_KEY_6;
    685         MAKEWORD(0);
    686         MAKEWORD(1);
    687         MAKEWORD(2);
    688         MAKEWORD(3);
    689         MAKEWORD(4);
    690         MAKEWORD(5);
    691         MOVEWORD(0);
    692         MOVEWORD(1);
    693         MOVEWORD(2);
    694         MOVEWORD(3);
    695         MOVEWORD(4);
    696         MOVEWORD(5);
    697     }
    698     ADD_ROUND_KEY_6;
    699     LASTWORD(0);
    700     LASTWORD(1);
    701     LASTWORD(2);
    702     LASTWORD(3);
    703     LASTWORD(4);
    704     LASTWORD(5);
    705     MOVEWORD(0);
    706     MOVEWORD(1);
    707     MOVEWORD(2);
    708     MOVEWORD(3);
    709     MOVEWORD(4);
    710     MOVEWORD(5);
    711     ADD_ROUND_KEY_6;
    712 }
    713 static void aes_encrypt_nb_8(AESContext * ctx, unsigned int * block)
    714 {
    715     int i;
    716     static const int C1 = 1, C2 = 3, C3 = 4, Nb = 8;
    717     unsigned int *keysched = ctx->keysched;
    718     unsigned int newstate[8];
    719     for (i = 0; i < ctx->Nr - 1; i++) {
    720         ADD_ROUND_KEY_8;
    721         MAKEWORD(0);
    722         MAKEWORD(1);
    723         MAKEWORD(2);
    724         MAKEWORD(3);
    725         MAKEWORD(4);
    726         MAKEWORD(5);
    727         MAKEWORD(6);
    728         MAKEWORD(7);
    729         MOVEWORD(0);
    730         MOVEWORD(1);
    731         MOVEWORD(2);
    732         MOVEWORD(3);
    733         MOVEWORD(4);
    734         MOVEWORD(5);
    735         MOVEWORD(6);
    736         MOVEWORD(7);
    737     }
    738     ADD_ROUND_KEY_8;
    739     LASTWORD(0);
    740     LASTWORD(1);
    741     LASTWORD(2);
    742     LASTWORD(3);
    743     LASTWORD(4);
    744     LASTWORD(5);
    745     LASTWORD(6);
    746     LASTWORD(7);
    747     MOVEWORD(0);
    748     MOVEWORD(1);
    749     MOVEWORD(2);
    750     MOVEWORD(3);
    751     MOVEWORD(4);
    752     MOVEWORD(5);
    753     MOVEWORD(6);
    754     MOVEWORD(7);
    755     ADD_ROUND_KEY_8;
    756 }
    757 #undef MAKEWORD
    758 #undef LASTWORD
    759 #define MAKEWORD(i) ( newstate[i] = (D0[(block[i] >> 24) & 0xFF] ^ \
    760                                      D1[(block[(i+C1)%Nb] >> 16) & 0xFF] ^ \
    761                                      D2[(block[(i+C2)%Nb] >> 8) & 0xFF] ^ \
    762                                      D3[block[(i+C3)%Nb] & 0xFF]) )
    763 #define LASTWORD(i) (newstate[i] = (Sboxinv[(block[i] >> 24) & 0xFF] << 24) | \
    764                                    (Sboxinv[(block[(i+C1)%Nb] >> 16) & 0xFF] << 16) | \
    765                                    (Sboxinv[(block[(i+C2)%Nb] >>  8) & 0xFF] <<  8) | \
    766                                    (Sboxinv[(block[(i+C3)%Nb]      ) & 0xFF]      ) )
    767 static void aes_decrypt_nb_4(AESContext * ctx, unsigned int * block)
    768 {
    769     int i;
    770     static const int C1 = 4 - 1, C2 = 4 - 2, C3 = 4 - 3, Nb = 4;
    771     unsigned int *keysched = ctx->invkeysched;
    772     unsigned int newstate[4];
    773     for (i = 0; i < ctx->Nr - 1; i++) {
    774         ADD_ROUND_KEY_4;
    775         MAKEWORD(0);
    776         MAKEWORD(1);
    777         MAKEWORD(2);
    778         MAKEWORD(3);
    779         MOVEWORD(0);
    780         MOVEWORD(1);
    781         MOVEWORD(2);
    782         MOVEWORD(3);
    783     }
    784     ADD_ROUND_KEY_4;
    785     LASTWORD(0);
    786     LASTWORD(1);
    787     LASTWORD(2);
    788     LASTWORD(3);
    789     MOVEWORD(0);
    790     MOVEWORD(1);
    791     MOVEWORD(2);
    792     MOVEWORD(3);
    793     ADD_ROUND_KEY_4;
    794 }
    795 static void aes_decrypt_nb_6(AESContext * ctx, unsigned int * block)
    796 {
    797     int i;
    798     static const int C1 = 6 - 1, C2 = 6 - 2, C3 = 6 - 3, Nb = 6;
    799     unsigned int *keysched = ctx->invkeysched;
    800     unsigned int newstate[6];
    801     for (i = 0; i < ctx->Nr - 1; i++) {
    802         ADD_ROUND_KEY_6;
    803         MAKEWORD(0);
    804         MAKEWORD(1);
    805         MAKEWORD(2);
    806         MAKEWORD(3);
    807         MAKEWORD(4);
    808         MAKEWORD(5);
    809         MOVEWORD(0);
    810         MOVEWORD(1);
    811         MOVEWORD(2);
    812         MOVEWORD(3);
    813         MOVEWORD(4);
    814         MOVEWORD(5);
    815     }
    816     ADD_ROUND_KEY_6;
    817     LASTWORD(0);
    818     LASTWORD(1);
    819     LASTWORD(2);
    820     LASTWORD(3);
    821     LASTWORD(4);
    822     LASTWORD(5);
    823     MOVEWORD(0);
    824     MOVEWORD(1);
    825     MOVEWORD(2);
    826     MOVEWORD(3);
    827     MOVEWORD(4);
    828     MOVEWORD(5);
    829     ADD_ROUND_KEY_6;
    830 }
    831 static void aes_decrypt_nb_8(AESContext * ctx, unsigned int * block)
    832 {
    833     int i;
    834     static const int C1 = 8 - 1, C2 = 8 - 3, C3 = 8 - 4, Nb = 8;
    835     unsigned int *keysched = ctx->invkeysched;
    836     unsigned int newstate[8];
    837     for (i = 0; i < ctx->Nr - 1; i++) {
    838         ADD_ROUND_KEY_8;
    839         MAKEWORD(0);
    840         MAKEWORD(1);
    841         MAKEWORD(2);
    842         MAKEWORD(3);
    843         MAKEWORD(4);
    844         MAKEWORD(5);
    845         MAKEWORD(6);
    846         MAKEWORD(7);
    847         MOVEWORD(0);
    848         MOVEWORD(1);
    849         MOVEWORD(2);
    850         MOVEWORD(3);
    851         MOVEWORD(4);
    852         MOVEWORD(5);
    853         MOVEWORD(6);
    854         MOVEWORD(7);
    855     }
    856     ADD_ROUND_KEY_8;
    857     LASTWORD(0);
    858     LASTWORD(1);
    859     LASTWORD(2);
    860     LASTWORD(3);
    861     LASTWORD(4);
    862     LASTWORD(5);
    863     LASTWORD(6);
    864     LASTWORD(7);
    865     MOVEWORD(0);
    866     MOVEWORD(1);
    867     MOVEWORD(2);
    868     MOVEWORD(3);
    869     MOVEWORD(4);
    870     MOVEWORD(5);
    871     MOVEWORD(6);
    872     MOVEWORD(7);
    873     ADD_ROUND_KEY_8;
    874 }
    875 #undef MAKEWORD
    876 #undef LASTWORD
    877 static void aes_setup(AESContext * ctx, int blocklen,
    878                       const unsigned char *key, int keylen)
    879 {
    880     int i, j, Nk, rconst;
    881     ASSERT(blocklen == 16 || blocklen == 24 || blocklen == 32);
    882     ASSERT(keylen == 16 || keylen == 24 || keylen == 32);
    883     Nk = keylen / 4;
    884     ctx->Nb = blocklen / 4;
    885     ctx->Nr = 6 + (ctx->Nb > Nk ? ctx->Nb : Nk);
    886     if (ctx->Nb == 8) {
    887         ctx->encrypt = aes_encrypt_nb_8, ctx->decrypt = aes_decrypt_nb_8;
    888     } else if (ctx->Nb == 6) {
    889         ctx->encrypt = aes_encrypt_nb_6, ctx->decrypt = aes_decrypt_nb_6;
    890     } else if (ctx->Nb == 4) {
    891         ctx->encrypt = aes_encrypt_nb_4, ctx->decrypt = aes_decrypt_nb_4;
    892     }
    893     rconst = 1;
    894     for (i = 0; i < (ctx->Nr + 1) * ctx->Nb; i++) {
    895         if (i < Nk) {
    896             ctx->keysched[i] = GET_32BIT_MSB_FIRST(key + 4 * i);
    897         } else {
    898             unsigned int temp = ctx->keysched[i - 1];
    899             if (i % Nk == 0) {
    900                 int a, b, c, d;
    901                 a = (temp >> 16) & 0xFF;
    902                 b = (temp >> 8) & 0xFF;
    903                 c = (temp >> 0) & 0xFF;
    904                 d = (temp >> 24) & 0xFF;
    905                 temp = Sbox[a] ^ rconst;
    906                 temp = (temp << 8) | Sbox[b];
    907                 temp = (temp << 8) | Sbox[c];
    908                 temp = (temp << 8) | Sbox[d];
    909                 rconst = mulby2(rconst);
    910             } else if (i % Nk == 4 && Nk > 6) {
    911                 int a, b, c, d;
    912                 a = (temp >> 24) & 0xFF;
    913                 b = (temp >> 16) & 0xFF;
    914                 c = (temp >> 8) & 0xFF;
    915                 d = (temp >> 0) & 0xFF;
    916                 temp = Sbox[a];
    917                 temp = (temp << 8) | Sbox[b];
    918                 temp = (temp << 8) | Sbox[c];
    919                 temp = (temp << 8) | Sbox[d];
    920             }
    921             ctx->keysched[i] = ctx->keysched[i - Nk] ^ temp;
    922         }
    923     }
    924     for (i = 0; i <= ctx->Nr; i++) {
    925         for (j = 0; j < ctx->Nb; j++) {
    926             unsigned int temp;
    927             temp = ctx->keysched[(ctx->Nr - i) * ctx->Nb + j];
    928             if (i != 0 && i != ctx->Nr) {
    929                 int a, b, c, d;
    930                 a = (temp >> 24) & 0xFF;
    931                 b = (temp >> 16) & 0xFF;
    932                 c = (temp >> 8) & 0xFF;
    933                 d = (temp >> 0) & 0xFF;
    934                 temp = D0[Sbox[a]];
    935                 temp ^= D1[Sbox[b]];
    936                 temp ^= D2[Sbox[c]];
    937                 temp ^= D3[Sbox[d]];
    938             }
    939             ctx->invkeysched[i * ctx->Nb + j] = temp;
    940         }
    941     }
    942 }
    943 static void aes_decrypt(AESContext * ctx, unsigned int * block)
    944 {
    945     ctx->decrypt(ctx, block);
    946 }
    947 static void aes_decrypt_cbc(unsigned char *dest, const unsigned char *src, int len, AESContext * ctx)
    948 {
    949     unsigned int iv[4], x[4], ct[4];
    950     int i;
    951     ASSERT((len & 15) == 0);
    952     FXSYS_memcpy32(iv, ctx->iv, sizeof(iv));
    953     while (len > 0) {
    954         for (i = 0; i < 4; i++) {
    955             x[i] = ct[i] = GET_32BIT_MSB_FIRST(src + 4 * i);
    956         }
    957         aes_decrypt(ctx, x);
    958         for (i = 0; i < 4; i++) {
    959             PUT_32BIT_MSB_FIRST(dest + 4 * i, iv[i] ^ x[i]);
    960             iv[i] = ct[i];
    961         }
    962         dest += 16;
    963         src += 16;
    964         len -= 16;
    965     }
    966     FXSYS_memcpy32(ctx->iv, iv, sizeof(iv));
    967 }
    968 static void aes_encrypt(AESContext * ctx, unsigned int * block)
    969 {
    970     ctx->encrypt(ctx, block);
    971 }
    972 static void aes_encrypt_cbc(unsigned char *dest, const unsigned char *src, int len, AESContext * ctx)
    973 {
    974     unsigned int iv[4];
    975     int i;
    976     ASSERT((len & 15) == 0);
    977     FXSYS_memcpy32(iv, ctx->iv, sizeof(iv));
    978     while (len > 0) {
    979         for (i = 0; i < 4; i++) {
    980             iv[i] ^= GET_32BIT_MSB_FIRST(src + 4 * i);
    981         }
    982         aes_encrypt(ctx, iv);
    983         for (i = 0; i < 4; i++) {
    984             PUT_32BIT_MSB_FIRST(dest + 4 * i, iv[i]);
    985         }
    986         dest += 16;
    987         src += 16;
    988         len -= 16;
    989     }
    990     FXSYS_memcpy32(ctx->iv, iv, sizeof(iv));
    991 }
    992 void CRYPT_AESSetKey(FX_LPVOID context, FX_DWORD blocklen, FX_LPCBYTE key, FX_DWORD keylen, FX_BOOL bEncrypt)
    993 {
    994     aes_setup((AESContext*)context, blocklen, key, keylen);
    995 }
    996 void CRYPT_AESSetIV(FX_LPVOID context, FX_LPCBYTE iv)
    997 {
    998     int i;
    999     for (i = 0; i < ((AESContext*)context)->Nb; i++) {
   1000         ((AESContext*)context)->iv[i] = GET_32BIT_MSB_FIRST(iv + 4 * i);
   1001     }
   1002 }
   1003 void CRYPT_AESDecrypt(FX_LPVOID context, FX_LPBYTE dest, FX_LPCBYTE src, FX_DWORD len)
   1004 {
   1005     aes_decrypt_cbc(dest, src, len, (AESContext*)context);
   1006 }
   1007 void CRYPT_AESEncrypt(FX_LPVOID context, FX_LPBYTE dest, FX_LPCBYTE src, FX_DWORD len)
   1008 {
   1009     aes_encrypt_cbc(dest, src, len, (AESContext*)context);
   1010 }
   1011 #ifdef __cplusplus
   1012 };
   1013 #endif
   1014