Thread: About aes

  1. #1
    Registered User
    Join Date
    Oct 2006
    Posts
    8

    About aes

    Hi Everybody,

    I am an electronics engineer. I want to an application with a microcontroller and I need your helps.

    I have some questions.

    1-) How I can load a data to AES (Rinjdael)source code with c. I have to use with c .


    Source code is here : http://svn.saddi.com/rijndael/branch...ndael-fst-3.0/


    please help me.

  2. #2
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    How I can load a data to AES (Rinjdael)source code with c. I have to use with c .
    By "load" do you mean encrypting and decrypting data using the Rijndael methods? If so, I can provide some assistance. I have a similar situation where I use the Rijndael Electronic Code Book (ECB) for encrypting /decrypting data sent to/from a networked security controller. Thus, if your using the ECB method, I can provide some useful C code.

  3. #3
    Registered User
    Join Date
    Oct 2006
    Posts
    8
    Yes, I mean by '' load '' encrypting and decrypting data using the Rijndael method. I need a C code that using AES rijindael 128 bit.

    When you send the code, Please tell how i can use it.

    Thanks a lot.

  4. #4
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    The code below came from my Rijndael class. It has to be compiled as C++. But it can be converted to plain C by addressing the syntactical issues. Also, the only two functions that should be of concern to you are the Encrypt and Decrypt functions. All the other functions are unique to my implementation and are not relevant to the Rijndael encryption/decryption. So, the "cleaning up" of the code, I'll delegate to you.

    Good luck!

    EDIT: This is a 128 bit Electronic Code Book (ECB) Rijndael implementation
    Code:
    // Module name: Rijndael.cpp
    #include <windows.h>
    #include <stdio.h>
    #include "Rijndael.h"
    
    const int sm_alog[256] =
    {
        1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 
        95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 
        229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, 
        83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, 
        76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 
        131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 
        181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, 
        254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, 
        251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 
        195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 
        159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 
        155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, 
        252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, 
        69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 
        18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 
        57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1
    };
    
    const int sm_log[256] =
    {
        0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, 
        100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, 
        125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120, 
        101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142, 
        150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 
        102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 
        126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186, 
        43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87, 
        175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, 
        44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, 
        127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, 
        204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157, 
        151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, 
        83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 
        68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 
        103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7
    };
    
    const char sm_S[256] =
    {
        99, 124, 119, 123, -14, 107, 111, -59, 48, 1, 103, 43, -2, -41, -85, 118, 
        -54, -126, -55, 125, -6, 89, 71, -16, -83, -44, -94, -81, -100, -92, 114, -64, 
        -73, -3, -109, 38, 54, 63, -9, -52, 52, -91, -27, -15, 113, -40, 49, 21, 
        4, -57, 35, -61, 24, -106, 5, -102, 7, 18, -128, -30, -21, 39, -78, 117, 
        9, -125, 44, 26, 27, 110, 90, -96, 82, 59, -42, -77, 41, -29, 47, -124, 
        83, -47, 0, -19, 32, -4, -79, 91, 106, -53, -66, 57, 74, 76, 88, -49, 
        -48, -17, -86, -5, 67, 77, 51, -123, 69, -7, 2, 127, 80, 60, -97, -88, 
        81, -93, 64, -113, -110, -99, 56, -11, -68, -74, -38, 33, 16, -1, -13, -46, 
        -51, 12, 19, -20, 95, -105, 68, 23, -60, -89, 126, 61, 100, 93, 25, 115, 
        96, -127, 79, -36, 34, 42, -112, -120, 70, -18, -72, 20, -34, 94, 11, -37, 
        -32, 50, 58, 10, 73, 6, 36, 92, -62, -45, -84, 98, -111, -107, -28, 121, 
        -25, -56, 55, 109, -115, -43, 78, -87, 108, 86, -12, -22, 101, 122, -82, 8, 
        -70, 120, 37, 46, 28, -90, -76, -58, -24, -35, 116, 31, 75, -67, -117, -118, 
        112, 62, -75, 102, 72, 3, -10, 14, 97, 53, 87, -71, -122, -63, 29, -98, 
        -31, -8, -104, 17, 105, -39, -114, -108, -101, 30, -121, -23, -50, 85, 40, -33, 
        -116, -95, -119, 13, -65, -26, 66, 104, 65, -103, 45, 15, -80, 84, -69, 22
    };
    
    const char sm_Si[256] =
    {
        82, 9, 106, -43, 48, 54, -91, 56, -65, 64, -93, -98, -127, -13, -41, -5, 
        124, -29, 57, -126, -101, 47, -1, -121, 52, -114, 67, 68, -60, -34, -23, -53, 
        84, 123, -108, 50, -90, -62, 35, 61, -18, 76, -107, 11, 66, -6, -61, 78, 
        8, 46, -95, 102, 40, -39, 36, -78, 118, 91, -94, 73, 109, -117, -47, 37, 
        114, -8, -10, 100, -122, 104, -104, 22, -44, -92, 92, -52, 93, 101, -74, -110, 
        108, 112, 72, 80, -3, -19, -71, -38, 94, 21, 70, 87, -89, -115, -99, -124, 
        -112, -40, -85, 0, -116, -68, -45, 10, -9, -28, 88, 5, -72, -77, 69, 6, 
        -48, 44, 30, -113, -54, 63, 15, 2, -63, -81, -67, 3, 1, 19, -118, 107, 
        58, -111, 17, 65, 79, 103, -36, -22, -105, -14, -49, -50, -16, -76, -26, 115, 
        -106, -84, 116, 34, -25, -83, 53, -123, -30, -7, 55, -24, 28, 117, -33, 110, 
        71, -15, 26, 113, 29, 41, -59, -119, 111, -73, 98, 14, -86, 24, -66, 27, 
        -4, 86, 62, 75, -58, -46, 121, 32, -102, -37, -64, -2, 120, -51, 90, -12, 
        31, -35, -88, 51, -120, 7, -57, 49, -79, 18, 16, 89, 39, -128, -20, 95, 
        96, 81, 127, -87, 25, -75, 74, 13, 45, -27, 122, -97, -109, -55, -100, -17, 
        -96, -32, 59, 77, -82, 42, -11, -80, -56, -21, -69, 60, -125, 83, -103, 97, 
        23, 43, 4, 126, -70, 119, -42, 38, -31, 105, 20, 99, 85, 33, 12, 125
    };
    
    const int sm_T1[256] =
    {
        -966564955, -126059388, -294160487, -159679603, 
        -855539, -697603139, -563122255, -1849309868, 
        1613770832, 33620227, -832084055, 1445669757, 
        -402719207, -1244145822, 1303096294, -327780710, 
        -1882535355, 528646813, -1983264448, -92439161, 
        -268764651, -1302767125, -1907931191, -68095989, 
        1101901292, -1277897625, 1604494077, 1169141738, 
        597466303, 1403299063, -462261610, -1681866661, 
        1974974402, -503448292, 1033081774, 1277568618, 
        1815492186, 2118074177, -168298750, -2083730353, 
        1748251740, 1369810420, -773462732, -101584632, 
        -495881837, -1411852173, 1647391059, 706024767, 
        134480908, -1782069422, 1176707941, -1648114850, 
        806885416, 932615841, 168101135, 798661301, 
        235341577, 605164086, 461406363, -538779075, 
        -840176858, 1311188841, 2142417613, -361400929, 
        302582043, 495158174, 1479289972, 874125870, 
        907746093, -596742478, -1269146898, 1537253627, 
        -1538108682, 1983593293, -1210657183, 2108928974, 
        1378429307, -572267714, 1580150641, 327451799, 
        -1504488459, -1177431704, 0, -1041371860, 
        1075847264, -469959649, 2041688520, -1235526675, 
        -731223362, -1916023994, 1740553945, 1916352843, 
        -1807070498, -1739830060, -1336387352, -2049978550, 
        -1143943061, -974131414, 1336584933, -302253290, 
        -2042412091, -1706209833, 1714631509, 293963156, 
        -1975171633, -369493744, 67240454, -25198719, 
        -1605349136, 2017213508, 631218106, 1269344483, 
        -1571728909, 1571005438, -2143272768, 93294474, 
        1066570413, 563977660, 1882732616, -235539196, 
        1673313503, 2008463041, -1344611723, 1109467491, 
        537923632, -436207846, -34344178, -1076702611, 
        -2117218996, 403442708, 638784309, -1007883217, 
        -1101045791, 899127202, -2008791860, 773265209, 
        -1815821225, 1437050866, -58818942, 2050833735, 
        -932944724, -1168286233, 840505643, -428641387, 
        -1067425632, 427917720, -1638969391, -1545806721, 
        1143087718, 1412049534, 999329963, 193497219, 
        -1941551414, -940642775, 1807268051, 672404540, 
        -1478566279, -1134666014, 369822493, -1378100362, 
        -606019525, 1681011286, 1949973070, 336202270, 
        -1840690725, 201721354, 1210328172, -1201906460, 
        -1614626211, -1110191250, 1135389935, -1000185178, 
        965841320, 831886756, -739974089, -226920053, 
        -706222286, -1949775805, 1849112409, -630362697, 
        26054028, -1311386268, -1672589614, 1235855840, 
        -663982924, -1403627782, -202050553, -806688219, 
        -899324497, -193299826, 1202630377, 268961816, 
        1874508501, -260540280, 1243948399, 1546530418, 
        941366308, 1470539505, 1941222599, -1748580783, 
        -873928669, -1579295364, -395021156, 1042226977, 
        -1773450275, 1639824860, 227249030, 260737669, 
        -529502064, 2084453954, 1907733956, -865704278, 
        -1874310952, 100860677, -134810111, 470683154, 
        -1033805405, 1781871967, -1370007559, 1773779408, 
        394692241, -1715355304, 974986535, 664706745, 
        -639508168, -336005101, 731420851, 571543859, 
        -764843589, -1445340816, 126783113, 865375399, 
        765172662, 1008606754, 361203602, -907417312, 
        -2016489911, -1437248001, 1344809080, -1512054918, 
        59542671, 1503764984, 160008576, 437062935, 
        1707065306, -672733647, -2076032314, -798463816, 
        -2109652541, 697932208, 1512910199, 504303377, 
        2075177163, -1470868228, 1841019862, 739644986
    };
    
    const int sm_T2[256] =
    {
        -1513725085, -2064089988, -1712425097, -1913226373, 
        234877682, -1110021269, -1310822545, 1418839493, 
        1348481072, 50462977, -1446090905, 2102799147, 
        434634494, 1656084439, -431117397, -1695779210, 
        1167051466, -1658879358, 1082771913, -2013627011, 
        368048890, -340633255, -913422521, 201060592, 
        -331240019, 1739838676, -44064094, -364531793, 
        -1088185188, -145513308, -1763413390, 1536934080, 
        -1032472649, 484572669, -1371696237, 1783375398, 
        1517041206, 1098792767, 49674231, 1334037708, 
        1550332980, -195975771, 886171109, 150598129, 
        -1813876367, 1940642008, 1398944049, 1059722517, 
        201851908, 1385547719, 1699095331, 1587397571, 
        674240536, -1590192490, 252314885, -1255171430, 
        151914247, 908333586, -1692696448, 1038082786, 
        651029483, 1766729511, -847269198, -1612024459, 
        454166793, -1642232957, 1951935532, 775166490, 
        758520603, -1294176658, -290170278, -77881184, 
        -157003182, 1299594043, 1639438038, -830622797, 
        2068982057, 1054729187, 1901997871, -1760328572, 
        -173649069, 1757008337, 0, 750906861, 
        1614815264, 535035132, -931548751, -306816165, 
        -1093375382, 1183697867, -647512386, 1265776953, 
        -560706998, -728216500, -391096232, 1250283471, 
        1807470800, 717615087, -447763798, 384695291, 
        -981056701, -677753523, 1432761139, -1810791035, 
        -813021883, 283769337, 100925954, -2114027649, 
        -257929136, 1148730428, -1171939425, -481580888, 
        -207466159, -27417693, -1065336768, -1979347057, 
        -1388342638, -1138647651, 1215313976, 82966005, 
        -547111748, -1049119050, 1974459098, 1665278241, 
        807407632, 451280895, 251524083, 1841287890, 
        1283575245, 337120268, 891687699, 801369324, 
        -507617441, -1573546089, -863484860, 959321879, 
        1469301956, -229267545, -2097381762, 1199193405, 
        -1396153244, -407216803, 724703513, -1780059277, 
        -1598005152, -1743158911, -778154161, 2141445340, 
        1715741218, 2119445034, -1422159728, -2096396152, 
        -896776634, 700968686, -747915080, 1009259540, 
        2041044702, -490971554, 487983883, 1991105499, 
        1004265696, 1449407026, 1316239930, 504629770, 
        -611169975, 168560134, 1816667172, -457679780, 
        1570751170, 1857934291, -280777556, -1497079198, 
        -1472622191, -1540254315, 936633572, -1947043463, 
        852879335, 1133234376, 1500395319, -1210421907, 
        -1946055283, 1689376213, -761508274, -532043351, 
        -1260884884, -89369002, 133428468, 634383082, 
        -1345690267, -1896580486, -381178194, 403703816, 
        -714097990, -1997506440, 1867130149, 1918643758, 
        607656988, -245913946, -948718412, 1368901318, 
        600565992, 2090982877, -1662487436, 557719327, 
        -577352885, -597574211, -2045932661, -2062579062, 
        -1864339344, 1115438654, -999180875, -1429445018, 
        -661632952, 84280067, 33027830, 303828494, 
        -1547542175, 1600795957, -106014889, -798377543, 
        -1860729210, 1486471617, 658119965, -1188585826, 
        953803233, 334231800, -1288988520, 857870609, 
        -1143838359, 1890179545, -1995993458, -1489791852, 
        -1238525029, 574365214, -1844082809, 550103529, 
        1233637070, -5614251, 2018519080, 2057691103, 
        -1895592820, -128343647, -2146858615, 387583245, 
        -630865985, 836232934, -964410814, -1194301336, 
        -1014873791, -1339450983, 2002398509, 287182607, 
        -881086288, -56077228, -697451589, 975967766
    };
    
    const int sm_T3[256] =
    {
        1671808611, 2089089148, 2006576759, 2072901243, 
        -233963534, 1807603307, 1873927791, -984313403, 
        810573872, 16974337, 1739181671, 729634347, 
        -31856642, -681396777, -1410970197, 1989864566, 
        -901410870, -2103631998, -918517303, 2106063485, 
        -99225606, 1508618841, 1204391495, -267650064, 
        -1377025619, -731401260, -1560453214, -1343601233, 
        -1665195108, -1527295068, 1922491506, -1067738176, 
        -1211992649, -48438787, -1817297517, 644500518, 
        911895606, 1061256767, -150800905, -867204148, 
        878471220, -1510714971, -449523227, -251069967, 
        1905517169, -663508008, 827548209, 356461077, 
        67897348, -950889017, 593839651, -1017209405, 
        405286936, -1767819370, 84871685, -1699401830, 
        118033927, 305538066, -2137318528, -499261470, 
        -349778453, 661212711, -1295155278, 1973414517, 
        152769033, -2086789757, 745822252, 439235610, 
        455947803, 1857215598, 1525593178, -1594139744, 
        1391895634, 994932283, -698239018, -1278313037, 
        695947817, -482419229, 795958831, -2070473852, 
        1408607827, -781665839, 0, -315833875, 
        543178784, -65018884, -1312261711, 1542305371, 
        1790891114, -884568629, -1093048386, 961245753, 
        1256100938, 1289001036, 1491644504, -817199665, 
        -798245936, -282409489, -1427812438, -82383365, 
        1137018435, 1305975373, 861234739, -2053893755, 
        1171229253, -116332039, 33948674, 2139225727, 
        1357946960, 1011120188, -1615190625, -1461498968, 
        1374921297, -1543610973, 1086357568, -1886780017, 
        -1834139758, -1648615011, 944271416, -184225291, 
        -1126210628, -1228834890, -629821478, 560153121, 
        271589392, -15014401, -217121293, -764559406, 
        -850624051, 202643468, 322250259, -332413972, 
        1608629855, -1750977129, 1154254916, 389623319, 
        -1000893500, -1477290585, 2122513534, 1028094525, 
        1689045092, 1575467613, 422261273, 1939203699, 
        1621147744, -2120738431, 1339137615, -595614756, 
        577127458, 712922154, -1867826288, -2004677752, 
        1187679302, -299251730, -1194103880, 339486740, 
        -562452514, 1591917662, 186455563, -612979237, 
        -532948000, 844522546, 978220090, 169743370, 
        1239126601, 101321734, 611076132, 1558493276, 
        -1034051646, -747717165, -1393605716, 1655096418, 
        -1851246191, -1784401515, -466103324, 2039214713, 
        -416098841, -935097400, 928607799, 1840765549, 
        -1920204403, -714821163, 1322425422, -1444918871, 
        1823791212, 1459268694, -200805388, -366620694, 
        1706019429, 2056189050, -1360443474, 135794696, 
        -1160417350, 2022240376, 628050469, 779246638, 
        472135708, -1494132826, -1261997132, -967731258, 
        -400307224, -579034659, 1956440180, 522272287, 
        1272813131, -1109630531, -1954148981, -1970991222, 
        1888542832, 1044544574, -1245417035, 1722469478, 
        1222152264, 50660867, -167643146, 236067854, 
        1638122081, 895445557, 1475980887, -1177523783, 
        -2037311610, -1051158079, 489110045, -1632032866, 
        -516367903, -132912136, -1733088360, 288563729, 
        1773916777, -646927911, -1903622258, -1800981612, 
        -1682559589, 505560094, -2020469369, -383727127, 
        -834041906, 1442818645, 678973480, -545610273, 
        -1936784500, -1577559647, -1988097655, 219617805, 
        -1076206145, -432941082, 1120306242, 1756942440, 
        1103331905, -1716508263, 762796589, 252780047, 
        -1328841808, 1425844308, -1143575109, 372911126
    };
    
    const int sm_T4[256] =
    {
        1667474886, 2088535288, 2004326894, 2071694838, 
        -219017729, 1802223062, 1869591006, -976923503, 
        808472672, 16843522, 1734846926, 724270422, 
        -16901657, -673750347, -1414797747, 1987484396, 
        -892713585, -2105369313, -909557623, 2105378810, 
        -84273681, 1499065266, 1195886990, -252703749, 
        -1381110719, -724277325, -1566376609, -1347425723, 
        -1667449053, -1532692653, 1920112356, -1061135461, 
        -1212693899, -33743647, -1819038147, 640051788, 
        909531756, 1061110142, -134806795, -859025533, 
        875846760, -1515850671, -437963567, -235861767, 
        1903268834, -656903253, 825316194, 353713962, 
        67374088, -943238507, 589522246, -1010606435, 
        404236336, -1768513225, 84217610, -1701137105, 
        117901582, 303183396, -2139055333, -488489505, 
        -336910643, 656894286, -1296904833, 1970642922, 
        151591698, -2088526307, 741110872, 437923380, 
        454765878, 1852748508, 1515908788, -1600062629, 
        1381168804, 993742198, -690593353, -1280061827, 
        690584402, -471646499, 791638366, -2071685357, 
        1398011302, -774805319, 0, -303223615, 
        538992704, -50585629, -1313748871, 1532751286, 
        1785380564, -875870579, -1094788761, 960056178, 
        1246420628, 1280103576, 1482221744, -808498555, 
        -791647301, -269538619, -1431640753, -67430675, 
        1128514950, 1296947098, 859002214, -2054843375, 
        1162203018, -101117719, 33687044, 2139062782, 
        1347481760, 1010582648, -1616922075, -1465326773, 
        1364325282, -1549533603, 1077985408, -1886418427, 
        -1835881153, -1650607071, 943212656, -168491791, 
        -1128472733, -1229536905, -623217233, 555836226, 
        269496352, -58651, -202174723, -757961281, 
        -842183551, 202118168, 320025894, -320065597, 
        1600119230, -1751670219, 1145359496, 387397934, 
        -993765485, -1482165675, 2122220284, 1027426170, 
        1684319432, 1566435258, 421079858, 1936954854, 
        1616945344, -2122213351, 1330631070, -589529181, 
        572679748, 707427924, -1869567173, -2004319477, 
        1179044492, -286381625, -1195846805, 336870440, 
        -555845209, 1583276732, 185277718, -606374227, 
        -522175525, 842159716, 976899700, 168435220, 
        1229577106, 101059084, 606366792, 1549591736, 
        -1027449441, -741118275, -1397952701, 1650632388, 
        -1852725191, -1785355215, -454805549, 2038008818, 
        -404278571, -926399605, 926374254, 1835907034, 
        -1920103423, -707435343, 1313788572, -1448484791, 
        1819063512, 1448540844, -185333773, -353753649, 
        1701162954, 2054852340, -1364268729, 134748176, 
        -1162160785, 2021165296, 623210314, 774795868, 
        471606328, -1499008681, -1263220877, -960081513, 
        -387439669, -572687199, 1953799400, 522133822, 
        1263263126, -1111630751, -1953790451, -1970633457, 
        1886425312, 1044267644, -1246378895, 1718004428, 
        1212733584, 50529542, -151649801, 235803164, 
        1633788866, 892690282, 1465383342, -1179004823, 
        -2038001385, -1044293479, 488449850, -1633765081, 
        -505333543, -117959701, -1734823125, 286339874, 
        1768537042, -640061271, -1903261433, -1802197197, 
        -1684294099, 505291324, -2021158379, -370597687, 
        -825341561, 1431699370, 673740880, -539002203, 
        -1936945405, -1583220647, -1987477495, 218961690, 
        -1077945755, -421121577, 1111672452, 1751693520, 
        1094828930, -1717981143, 757954394, 252645662, 
        -1330590853, 1414855848, -1145317779, 370555436
    };
    
    const int sm_T5[256] =
    {
        1374988112, 2118214995, 437757123, 975658646, 
        1001089995, 530400753, -1392879445, 1273168787, 
        540080725, -1384747530, -1999866223, -184398811, 
        1340463100, -987051049, 641025152, -1251826801, 
        -558802359, 632953703, 1172967064, 1576976609, 
        -1020300030, -2125664238, -1924753501, 1809054150, 
        59727847, 361929877, -1083344149, -1789765158, 
        -725712083, 1484005843, 1239443753, -1899378620, 
        1975683434, -191989384, -1722270101, 666464733, 
        -1092530250, -259478249, -920605594, 2110667444, 
        1675577880, -451268222, -1756286112, 1649639237, 
        -1318815776, -1150570876, -25059300, -116905068, 
        1883793496, -1891238631, -1797362553, 1383856311, 
        -1418472669, 1917518562, -484470953, 1716890410, 
        -1293211641, 800440835, -2033878118, -751368027, 
        807962610, 599762354, 33778362, -317291940, 
        -1966138325, -1485196142, -217582864, 1315562145, 
        1708848333, 101039829, -785096161, -995688822, 
        875451293, -1561111136, 92987698, -1527321739, 
        193195065, 1080094634, 1584504582, -1116860335, 
        1042385657, -1763899843, -583137874, 1306967366, 
        -1856729675, 1908694277, 67556463, 1615861247, 
        429456164, -692196969, -1992277044, 1742315127, 
        -1326955843, 126454664, -417768648, 2043211483, 
        -1585706425, 2084704233, -125559095, 0, 
        159417987, 841739592, 504459436, 1817866830, 
        -49348613, 260388950, 1034867998, 908933415, 
        168810852, 1750902305, -1688513327, 607530554, 
        202008497, -1822955761, -1259432238, 463180190, 
        -2134850225, 1641816226, 1517767529, 470948374, 
        -493635062, -1063245083, 1008918595, 303765277, 
        235474187, -225720403, 766945465, 337553864, 
        1475418501, -1351284916, -291906117, -1551933187, 
        -150919521, 1551037884, 1147550661, 1543208500, 
        -1958532746, -886847780, -1225917336, -1192955549, 
        -684598070, 1113818384, 328671808, -2067394272, 
        -2058738563, -759480840, -1359400431, -953573011, 
        496906059, -592301837, 226906860, 2009195472, 
        733156972, -1452230247, 294930682, 1206477858, 
        -1459843900, -1594867942, 1451044056, 573804783, 
        -2025238841, -650587711, -1932877058, -1730933962, 
        -1493859889, -1518674392, -625504730, 1068351396, 
        742039012, 1350078989, 1784663195, 1417561698, 
        -158526526, -1864845080, 775550814, -2101104651, 
        -1621262146, 1775276924, 1876241833, -819653965, 
        -928212677, 270040487, -392404114, -616842373, 
        -853116919, 1851332852, -325404927, -2091935064, 
        -426414491, -1426069890, 566021896, -283776794, 
        -1159226407, 1248802510, -358676012, 699432150, 
        832877231, 708780849, -962227152, 899835584, 
        1951317047, -58537306, -527380304, 866637845, 
        -251357110, 1106041591, 2144161806, 395441711, 
        1984812685, 1139781709, -861254316, -459930401, 
        -1630423581, 1282050075, -1054072904, 1181045119, 
        -1654724092, 25965917, -91786125, -83148498, 
        -1285087910, -1831087534, -384805325, 1842759443, 
        -1697160820, 933301370, 1509430414, -351060855, 
        -827774994, -1218328267, -518199827, 2051518780, 
        -1663901863, 1441952575, 404016761, 1942435775, 
        1408749034, 1610459739, -549621996, 2017778566, 
        -894438527, -1184316354, 941896748, -1029488545, 
        371049330, -1126030068, 675039627, -15887039, 
        967311729, 135050206, -659233636, 1683407248, 
        2076935265, -718096784, 1215061108, -793225406
    };
    
    const int sm_T6[256] =
    {
        1347548327, 1400783205, -1021700188, -1774573730, 
        -885281941, -249586363, -1414727080, -1823743229, 
        1428173050, -156404115, -1853305738, 636813900, 
        -61872681, -674944309, -2144979644, -1883938141, 
        1239331162, 1730525723, -1740248562, -513933632, 
        46346101, 310463728, -1551022441, -966011911, 
        -419197089, -1793748324, -339776134, -627748263, 
        768917123, -749177823, 692707433, 1150208456, 
        1786102409, 2029293177, 1805211710, -584599183, 
        -1229004465, 401639597, 1724457132, -1266823622, 
        409198410, -2098914767, 1620529459, 1164071807, 
        -525245321, -2068091986, 486441376, -1795618773, 
        1483753576, 428819965, -2020286868, -1219331080, 
        598438867, -495826174, 1474502543, 711349675, 
        129166120, 53458370, -1702443653, -1512884472, 
        -231724921, -1306280027, -1174273174, 1559041666, 
        730517276, -1834518092, -252508174, -1588696606, 
        -848962828, -721025602, 533804130, -1966823682, 
        -1657524653, -1599933611, 839224033, 1973745387, 
        957055980, -1438621457, 106852767, 1371368976, 
        -113368694, 1033297158, -1361232379, 1179510461, 
        -1248766835, 91341917, 1862534868, -10465259, 
        605657339, -1747534359, -863420349, 2003294622, 
        -1112479678, -2012771957, 954669403, -612775698, 
        1201765386, -377732593, -906460130, 0, 
        -2096529274, 1211247597, -1407315600, 1315723890, 
        -67301633, 1443857720, 507358933, 657861945, 
        1678381017, 560487590, -778347692, 975451694, 
        -1324610969, 261314535, -759894378, -1642357871, 
        1333838021, -1570644960, 1767536459, 370938394, 
        182621114, -440360918, 1128014560, 487725847, 
        185469197, -1376613433, -1188186456, -938205527, 
        -2057834215, 1286567175, -1141990947, -39616672, 
        -1611202266, -1134791947, -985373125, 878443390, 
        1988838185, -590666810, 1756818940, 1673061617, 
        -891866660, 272786309, 1075025698, 545572369, 
        2105887268, -120407235, 296679730, 1841768865, 
        1260232239, -203640272, -334657966, -797457949, 
        1814803222, -1716948807, -99511224, 575138148, 
        -995558260, 446754879, -665420500, -282971248, 
        -947435186, -1042728751, -24327518, 915985419, 
        -811141759, 681933534, 651868046, -1539330625, 
        -466863459, 223377554, -1687527476, 1649704518, 
        -1024029421, -393160520, 1580087799, -175979601, 
        -1096852096, 2087309459, -1452288723, -1278270190, 
        1003007129, -1492117379, 1860738147, 2077965243, 
        164439672, -194094824, 32283319, -1467789414, 
        1709610350, 2125135846, 136428751, -420538904, 
        -642062437, -833982666, -722821367, -701910916, 
        -1355701070, 824852259, 818324884, -1070226842, 
        930369212, -1493400886, -1327460144, 355706840, 
        1257309336, -146674470, 243256656, 790073846, 
        -1921626666, 1296297904, 1422699085, -538667516, 
        -476130891, 457992840, -1195299809, 2135319889, 
        77422314, 1560382517, 1945798516, 788204353, 
        1521706781, 1385356242, 870912086, 325965383, 
        -1936009375, 2050466060, -1906706412, -1981082820, 
        -288446169, 901210569, -304014107, 1014646705, 
        1503449823, 1062597235, 2031621326, -1082931401, 
        -363595827, 1533017514, 350174575, -2038938405, 
        -2117423117, 1052338372, 741876788, 1606591296, 
        1914052035, 213705253, -1960297399, 1107234197, 
        1899603969, -569897805, -1663519516, -1872472383, 
        1635502980, 1893020342, 1950903388, 1120974935
    };
    
    const int sm_T7[256] =
    {
        -1487908364, 1699970625, -1530717673, 1586903591, 
        1808481195, 1173430173, 1487645946, 59984867, 
        -95084496, 1844882806, 1989249228, 1277555970, 
        -671330331, -875051734, 1149249077, -1550863006, 
        1514790577, 459744698, 244860394, -1058972162, 
        1963115311, -267222708, -1750889146, -104436781, 
        1608975247, -1667951214, 2062270317, 1507497298, 
        -2094148418, 567498868, 1764313568, -935031095, 
        -1989511742, 2037970062, 1047239000, 1910319033, 
        1337376481, -1390940024, -1402549984, 984907214, 
        1243112415, 830661914, 861968209, 2135253587, 
        2011214180, -1367032981, -1608712575, 731183368, 
        1750626376, -48656571, 1820824798, -122203525, 
        -752637069, 48394827, -1890065633, -1423284651, 
        671593195, -1039978571, 2073724613, 145085239, 
        -2014171096, -1515052097, 1790575107, -2107839210, 
        472615631, -1265457287, -219090169, -492745111, 
        -187865638, -1093335547, 1646252340, -24460122, 
        1402811438, 1436590835, -516815478, -344611594, 
        -331805821, -274055072, -1626972559, 273792366, 
        -1963377119, 104699613, 95345982, -1119466010, 
        -1917480620, 1560637892, -730921978, 369057872, 
        -81520232, -375925059, 1137477952, -1636341799, 
        1119727848, -1954019447, 1530455833, -287606328, 
        172466556, 266959938, 516552836, 0, 
        -2038232704, -314035669, 1890328081, 1917742170, 
        -262898, 945164165, -719438418, 958871085, 
        -647755249, -1507760036, 1423022939, 775562294, 
        1739656202, -418409641, -1764576018, -1851909221, 
        -984645440, 547512796, 1265195639, 437656594, 
        -1173691757, 719700128, -532464606, 387781147, 
        218828297, -944901493, -1464259146, -1446505442, 
        428169201, 122466165, -574886247, 1627235199, 
        648017665, -172204942, 1002783846, 2117360635, 
        695634755, -958608605, -60246291, -245122844, 
        -590686415, -2062531997, 574624663, 287343814, 
        612205898, 1039717051, 840019705, -1586641111, 
        793451934, 821288114, 1391201670, -472877119, 
        376187827, -1181111952, 1224348052, 1679968233, 
        -1933268740, 1058709744, 752375421, -1863376333, 
        1321699145, -775825096, -1560376118, 188127444, 
        -2117097739, -567761542, -1910056265, -1079754835, 
        -1645990854, -1844621192, -862229921, 1180849278, 
        331544205, -1192718120, -144822727, -1342864701, 
        -2134991011, -1820562992, 766078933, 313773861, 
        -1724135252, 2108100632, 1668212892, -1149510853, 
        2013908262, 418672217, -1224610662, -1700232369, 
        1852171925, -427906305, -821550660, -387518699, 
        -1680229657, 919489135, 164948639, 2094410160, 
        -1297141340, 590424639, -1808742747, 1723872674, 
        -1137216434, -895026046, -793714544, -669699161, 
        -1739919100, -621329940, 1343127501, -164685935, 
        -695372211, -1337113617, 1297403050, 81781910, 
        -1243373871, -2011476886, 532201772, 1367295589, 
        -368796322, 895287692, 1953757831, 1093597963, 
        492483431, -766340389, 1446242576, 1192455638, 
        1636604631, 209336225, 344873464, 1015671571, 
        669961897, -919226527, -437395172, -1321436601, 
        -547775278, 1933530610, -830924780, 935293895, 
        -840281097, -1436852227, 1863638845, -611944380, 
        -209597777, -1002522264, 875313188, 1080017571, 
        -1015933411, 621591778, 1233856572, -1790836979, 
        24197544, -1277294580, -459482956, -1047501738, 
        -2073986101, -1234119374, 1551124588, 1463996600
    };
    
    const int sm_T8[256] =
    {
        -190361519, 1097159550, 396673818, 660510266, 
        -1418998981, -1656360673, -94852180, -486304949, 
        821712160, 1986918061, -864644728, 38544885, 
        -438830001, 718002117, 893681702, 1654886325, 
        -1319482914, -1172609243, -368142267, -20913827, 
        796197571, 1290801793, 1184342925, -738605461, 
        -1889540349, -1835231979, 1836772287, 1381620373, 
        -1098699308, 1948373848, -529979063, -909622130, 
        -1031181707, -1904641804, 1480485785, -1183720153, 
        -514869570, -2001922064, 548169417, -835013507, 
        -548792221, 439452389, 1362321559, 1400849762, 
        1685577905, 1806599355, -2120213250, 137073913, 
        1214797936, 1174215055, -563312748, 2079897426, 
        1943217067, 1258480242, 529487843, 1437280870, 
        -349698126, -1245576401, -981755258, 923313619, 
        679998000, -1079659997, 57326082, 377642221, 
        -820237430, 2041877159, 133361907, 1776460110, 
        -621490843, 96392454, 878845905, -1493267772, 
        777231668, -212492126, -1964953083, -152341084, 
        -2081670901, 1626319424, 1906247262, 1846563261, 
        562755902, -586793578, 1040559837, -423803315, 
        1418573201, -1000536719, 114585348, 1343618912, 
        -1728371687, -1108764714, 1078185097, -643926169, 
        -398279248, -1987344377, 425408743, -923870343, 
        2081048481, 1108339068, -2078357000, 0, 
        -2138668279, 736970802, 292596766, 1517440620, 
        251657213, -2059905521, -1361764803, 758720310, 
        265905162, 1554391400, 1532285339, 908999204, 
        174567692, 1474760595, -292105548, -1684955621, 
        -1060810880, -601841055, 2001430874, 303699484, 
        -1816524062, -1607801408, 585122620, 454499602, 
        151849742, -1949848078, -1230456531, 514443284, 
        -249985705, 1963412655, -1713521682, 2137062819, 
        19308535, 1928707164, 1715193156, -75615141, 
        1126790795, 600235211, -302225226, -453942344, 
        836553431, 1669664834, -1759363053, -971956092, 
        1243905413, -1153566510, -114159186, 698445255, 
        -1641067747, -1305414692, -2041385971, -1042034569, 
        -1290376149, 1891211689, -1807156719, -379313593, 
        -57883480, -264299872, 2100090966, 865136418, 
        1229899655, 953270745, -895287668, -737462632, 
        -176042074, 2061379749, -1215420710, -1379949505, 
        983426092, 2022837584, 1607244650, 2118541908, 
        -1928084746, -658970480, 972512814, -1011878526, 
        1568718495, -795640727, -718427793, 621982671, 
        -1399243832, 410887952, -1671205144, 1002142683, 
        645401037, 1494807662, -1699282452, 1335535747, 
        -1787927066, -1671510, -1127282655, 367585007, 
        -409216582, 1865862730, -1626745622, -1333995991, 
        -1531793615, 1059270954, -1517014842, -1570324427, 
        1320957812, -2100648196, -1865371424, -1479011021, 
        77089521, -321194175, -850391425, -1846137065, 
        1305906550, -273658557, -1437772596, -1778065436, 
        -776608866, 1787304780, 740276417, 1699839814, 
        1592394909, -1942659839, -2022411270, 188821243, 
        1729977011, -606973294, 274084841, -699985043, 
        -681472870, -1593017801, -132870567, 322734571, 
        -1457000754, 1640576439, 484830689, 1202797690, 
        -757114468, -227328171, 349075736, -952647821, 
        -137500077, -39167137, 1030690015, 1155237496, 
        -1342996022, 1757691577, 607398968, -1556062270, 
        499347990, -500888388, 1011452712, 227885567, 
        -1476300487, 213114376, -1260086056, 1455525988, 
        -880516741, 850817237, 1817998408, -1202240816
    };
    
    const int sm_U1[256] =
    {
        0, 235474187, 470948374, 303765277, 
        941896748, 908933415, 607530554, 708780849, 
        1883793496, 2118214995, 1817866830, 1649639237, 
        1215061108, 1181045119, 1417561698, 1517767529, 
        -527380304, -291906117, -58537306, -225720403, 
        -659233636, -692196969, -995688822, -894438527, 
        -1864845080, -1630423581, -1932877058, -2101104651, 
        -1459843900, -1493859889, -1259432238, -1159226407, 
        -616842373, -718096784, -953573011, -920605594, 
        -484470953, -317291940, -15887039, -251357110, 
        -1418472669, -1518674392, -1218328267, -1184316354, 
        -1822955761, -1654724092, -1891238631, -2125664238, 
        1001089995, 899835584, 666464733, 699432150, 
        59727847, 226906860, 530400753, 294930682, 
        1273168787, 1172967064, 1475418501, 1509430414, 
        1942435775, 2110667444, 1876241833, 1641816226, 
        -1384747530, -1551933187, -1318815776, -1083344149, 
        -1789765158, -1688513327, -1992277044, -2025238841, 
        -583137874, -751368027, -1054072904, -819653965, 
        -451268222, -351060855, -116905068, -150919521, 
        1306967366, 1139781709, 1374988112, 1610459739, 
        1975683434, 2076935265, 1775276924, 1742315127, 
        1034867998, 866637845, 566021896, 800440835, 
        92987698, 193195065, 429456164, 395441711, 
        1984812685, 2017778566, 1784663195, 1683407248, 
        1315562145, 1080094634, 1383856311, 1551037884, 
        101039829, 135050206, 437757123, 337553864, 
        1042385657, 807962610, 573804783, 742039012, 
        -1763899843, -1730933962, -1966138325, -2067394272, 
        -1359400431, -1594867942, -1293211641, -1126030068, 
        -426414491, -392404114, -91786125, -191989384, 
        -558802359, -793225406, -1029488545, -861254316, 
        1106041591, 1340463100, 1576976609, 1408749034, 
        2043211483, 2009195472, 1708848333, 1809054150, 
        832877231, 1068351396, 766945465, 599762354, 
        159417987, 126454664, 361929877, 463180190, 
        -1585706425, -1351284916, -1116860335, -1285087910, 
        -1722270101, -1756286112, -2058738563, -1958532746, 
        -785096161, -549621996, -853116919, -1020300030, 
        -384805325, -417768648, -184398811, -83148498, 
        -1697160820, -1797362553, -2033878118, -1999866223, 
        -1561111136, -1392879445, -1092530250, -1326955843, 
        -358676012, -459930401, -158526526, -125559095, 
        -759480840, -592301837, -827774994, -1063245083, 
        2051518780, 1951317047, 1716890410, 1750902305, 
        1113818384, 1282050075, 1584504582, 1350078989, 
        168810852, 67556463, 371049330, 404016761, 
        841739592, 1008918595, 775550814, 540080725, 
        -325404927, -493635062, -259478249, -25059300, 
        -725712083, -625504730, -928212677, -962227152, 
        -1663901863, -1831087534, -2134850225, -1899378620, 
        -1527321739, -1426069890, -1192955549, -1225917336, 
        202008497, 33778362, 270040487, 504459436, 
        875451293, 975658646, 675039627, 641025152, 
        2084704233, 1917518562, 1615861247, 1851332852, 
        1147550661, 1248802510, 1484005843, 1451044056, 
        933301370, 967311729, 733156972, 632953703, 
        260388950, 25965917, 328671808, 496906059, 
        1206477858, 1239443753, 1543208500, 1441952575, 
        2144161806, 1908694277, 1675577880, 1842759443, 
        -684598070, -650587711, -886847780, -987051049, 
        -283776794, -518199827, -217582864, -49348613, 
        -1485196142, -1452230247, -1150570876, -1251826801, 
        -1621262146, -1856729675, -2091935064, -1924753501
    };
    
    const int sm_U2[256] =
    {
        0, 185469197, 370938394, 487725847, 
        741876788, 657861945, 975451694, 824852259, 
        1483753576, 1400783205, 1315723890, 1164071807, 
        1950903388, 2135319889, 1649704518, 1767536459, 
        -1327460144, -1141990947, -1493400886, -1376613433, 
        -1663519516, -1747534359, -1966823682, -2117423117, 
        -393160520, -476130891, -24327518, -175979601, 
        -995558260, -811141759, -759894378, -642062437, 
        2077965243, 1893020342, 1841768865, 1724457132, 
        1474502543, 1559041666, 1107234197, 1257309336, 
        598438867, 681933534, 901210569, 1052338372, 
        261314535, 77422314, 428819965, 310463728, 
        -885281941, -1070226842, -584599183, -701910916, 
        -419197089, -334657966, -249586363, -99511224, 
        -1823743229, -1740248562, -2057834215, -1906706412, 
        -1082931401, -1266823622, -1452288723, -1570644960, 
        -156404115, -39616672, -525245321, -339776134, 
        -627748263, -778347692, -863420349, -947435186, 
        -1361232379, -1512884472, -1195299809, -1278270190, 
        -2098914767, -1981082820, -1795618773, -1611202266, 
        1179510461, 1296297904, 1347548327, 1533017514, 
        1786102409, 1635502980, 2087309459, 2003294622, 
        507358933, 355706840, 136428751, 53458370, 
        839224033, 957055980, 605657339, 790073846, 
        -1921626666, -2038938405, -1687527476, -1872472383, 
        -1588696606, -1438621457, -1219331080, -1134791947, 
        -721025602, -569897805, -1021700188, -938205527, 
        -113368694, -231724921, -282971248, -466863459, 
        1033297158, 915985419, 730517276, 545572369, 
        296679730, 446754879, 129166120, 213705253, 
        1709610350, 1860738147, 1945798516, 2029293177, 
        1239331162, 1120974935, 1606591296, 1422699085, 
        -146674470, -61872681, -513933632, -363595827, 
        -612775698, -797457949, -848962828, -966011911, 
        -1355701070, -1539330625, -1188186456, -1306280027, 
        -2096529274, -2012771957, -1793748324, -1642357871, 
        1201765386, 1286567175, 1371368976, 1521706781, 
        1805211710, 1620529459, 2105887268, 1988838185, 
        533804130, 350174575, 164439672, 46346101, 
        870912086, 954669403, 636813900, 788204353, 
        -1936009375, -2020286868, -1702443653, -1853305738, 
        -1599933611, -1414727080, -1229004465, -1112479678, 
        -722821367, -538667516, -1024029421, -906460130, 
        -120407235, -203640272, -288446169, -440360918, 
        1014646705, 930369212, 711349675, 560487590, 
        272786309, 457992840, 106852767, 223377554, 
        1678381017, 1862534868, 1914052035, 2031621326, 
        1211247597, 1128014560, 1580087799, 1428173050, 
        32283319, 182621114, 401639597, 486441376, 
        768917123, 651868046, 1003007129, 818324884, 
        1503449823, 1385356242, 1333838021, 1150208456, 
        1973745387, 2125135846, 1673061617, 1756818940, 
        -1324610969, -1174273174, -1492117379, -1407315600, 
        -1657524653, -1774573730, -1960297399, -2144979644, 
        -377732593, -495826174, -10465259, -194094824, 
        -985373125, -833982666, -749177823, -665420500, 
        2050466060, 1899603969, 1814803222, 1730525723, 
        1443857720, 1560382517, 1075025698, 1260232239, 
        575138148, 692707433, 878443390, 1062597235, 
        243256656, 91341917, 409198410, 325965383, 
        -891866660, -1042728751, -590666810, -674944309, 
        -420538904, -304014107, -252508174, -67301633, 
        -1834518092, -1716948807, -2068091986, -1883938141, 
        -1096852096, -1248766835, -1467789414, -1551022441, 
    };
    
    const int sm_U3[256] =
    {
        0, 218828297, 437656594, 387781147, 
        875313188, 958871085, 775562294, 590424639, 
        1750626376, 1699970625, 1917742170, 2135253587, 
        1551124588, 1367295589, 1180849278, 1265195639, 
        -793714544, -574886247, -895026046, -944901493, 
        -459482956, -375925059, -24460122, -209597777, 
        -1192718120, -1243373871, -1560376118, -1342864701, 
        -1933268740, -2117097739, -1764576018, -1680229657, 
        -1149510853, -1234119374, -1586641111, -1402549984, 
        -1890065633, -2107839210, -1790836979, -1739919100, 
        -752637069, -567761542, -919226527, -1002522264, 
        -418409641, -368796322, -48656571, -267222708, 
        1808481195, 1723872674, 1910319033, 2094410160, 
        1608975247, 1391201670, 1173430173, 1224348052, 
        59984867, 244860394, 428169201, 344873464, 
        935293895, 984907214, 766078933, 547512796, 
        1844882806, 1627235199, 2011214180, 2062270317, 
        1507497298, 1423022939, 1137477952, 1321699145, 
        95345982, 145085239, 532201772, 313773861, 
        830661914, 1015671571, 731183368, 648017665, 
        -1119466010, -1337113617, -1487908364, -1436852227, 
        -1989511742, -2073986101, -1820562992, -1636341799, 
        -719438418, -669699161, -821550660, -1039978571, 
        -516815478, -331805821, -81520232, -164685935, 
        -695372211, -611944380, -862229921, -1047501738, 
        -492745111, -274055072, -122203525, -172204942, 
        -1093335547, -1277294580, -1530717673, -1446505442, 
        -1963377119, -2014171096, -1863376333, -1645990854, 
        104699613, 188127444, 472615631, 287343814, 
        840019705, 1058709744, 671593195, 621591778, 
        1852171925, 1668212892, 1953757831, 2037970062, 
        1514790577, 1463996600, 1080017571, 1297403050, 
        -621329940, -671330331, -1058972162, -840281097, 
        -287606328, -472877119, -187865638, -104436781, 
        -1297141340, -1079754835, -1464259146, -1515052097, 
        -2038232704, -1954019447, -1667951214, -1851909221, 
        172466556, 122466165, 273792366, 492483431, 
        1047239000, 861968209, 612205898, 695634755, 
        1646252340, 1863638845, 2013908262, 1963115311, 
        1446242576, 1530455833, 1277555970, 1093597963, 
        1636604631, 1820824798, 2073724613, 1989249228, 
        1436590835, 1487645946, 1337376481, 1119727848, 
        164948639, 81781910, 331544205, 516552836, 
        1039717051, 821288114, 669961897, 719700128, 
        -1321436601, -1137216434, -1423284651, -1507760036, 
        -2062531997, -2011476886, -1626972559, -1844621192, 
        -647755249, -730921978, -1015933411, -830924780, 
        -314035669, -532464606, -144822727, -95084496, 
        -1224610662, -1173691757, -1390940024, -1608712575, 
        -2094148418, -1910056265, -1724135252, -1808742747, 
        -547775278, -766340389, -984645440, -935031095, 
        -344611594, -427906305, -245122844, -60246291, 
        1739656202, 1790575107, 2108100632, 1890328081, 
        1402811438, 1586903591, 1233856572, 1149249077, 
        266959938, 48394827, 369057872, 418672217, 
        1002783846, 919489135, 567498868, 752375421, 
        209336225, 24197544, 376187827, 459744698, 
        945164165, 895287692, 574624663, 793451934, 
        1679968233, 1764313568, 2117360635, 1933530610, 
        1343127501, 1560637892, 1243112415, 1192455638, 
        -590686415, -775825096, -958608605, -875051734, 
        -387518699, -437395172, -219090169, -262898, 
        -1265457287, -1181111952, -1367032981, -1550863006, 
        -2134991011, -1917480620, -1700232369, -1750889146
    };
    
    const int sm_U4[256] =
    {
        0, 151849742, 303699484, 454499602, 
        607398968, 758720310, 908999204, 1059270954, 
        1214797936, 1097159550, 1517440620, 1400849762, 
        1817998408, 1699839814, 2118541908, 2001430874, 
        -1865371424, -1713521682, -2100648196, -1949848078, 
        -1260086056, -1108764714, -1493267772, -1342996022, 
        -658970480, -776608866, -895287668, -1011878526, 
        -57883480, -176042074, -292105548, -409216582, 
        1002142683, 850817237, 698445255, 548169417, 
        529487843, 377642221, 227885567, 77089521, 
        1943217067, 2061379749, 1640576439, 1757691577, 
        1474760595, 1592394909, 1174215055, 1290801793, 
        -1418998981, -1570324427, -1183720153, -1333995991, 
        -1889540349, -2041385971, -1656360673, -1807156719, 
        -486304949, -368142267, -249985705, -132870567, 
        -952647821, -835013507, -718427793, -601841055, 
        1986918061, 2137062819, 1685577905, 1836772287, 
        1381620373, 1532285339, 1078185097, 1229899655, 
        1040559837, 923313619, 740276417, 621982671, 
        439452389, 322734571, 137073913, 19308535, 
        -423803315, -273658557, -190361519, -39167137, 
        -1031181707, -880516741, -795640727, -643926169, 
        -1361764803, -1479011021, -1127282655, -1245576401, 
        -1964953083, -2081670901, -1728371687, -1846137065, 
        1305906550, 1155237496, 1607244650, 1455525988, 
        1776460110, 1626319424, 2079897426, 1928707164, 
        96392454, 213114376, 396673818, 514443284, 
        562755902, 679998000, 865136418, 983426092, 
        -586793578, -737462632, -820237430, -971956092, 
        -114159186, -264299872, -349698126, -500888388, 
        -1787927066, -1671205144, -2022411270, -1904641804, 
        -1319482914, -1202240816, -1556062270, -1437772596, 
        -321194175, -438830001, -20913827, -137500077, 
        -923870343, -1042034569, -621490843, -738605461, 
        -1531793615, -1379949505, -1230456531, -1079659997, 
        -2138668279, -1987344377, -1835231979, -1684955621, 
        2081048481, 1963412655, 1846563261, 1729977011, 
        1480485785, 1362321559, 1243905413, 1126790795, 
        878845905, 1030690015, 645401037, 796197571, 
        274084841, 425408743, 38544885, 188821243, 
        -681472870, -563312748, -981755258, -864644728, 
        -212492126, -94852180, -514869570, -398279248, 
        -1626745622, -1778065436, -1928084746, -2078357000, 
        -1153566510, -1305414692, -1457000754, -1607801408, 
        1202797690, 1320957812, 1437280870, 1554391400, 
        1669664834, 1787304780, 1906247262, 2022837584, 
        265905162, 114585348, 499347990, 349075736, 
        736970802, 585122620, 972512814, 821712160, 
        -1699282452, -1816524062, -2001922064, -2120213250, 
        -1098699308, -1215420710, -1399243832, -1517014842, 
        -757114468, -606973294, -1060810880, -909622130, 
        -152341084, -1671510, -453942344, -302225226, 
        174567692, 57326082, 410887952, 292596766, 
        777231668, 660510266, 1011452712, 893681702, 
        1108339068, 1258480242, 1343618912, 1494807662, 
        1715193156, 1865862730, 1948373848, 2100090966, 
        -1593017801, -1476300487, -1290376149, -1172609243, 
        -2059905521, -1942659839, -1759363053, -1641067747, 
        -379313593, -529979063, -75615141, -227328171, 
        -850391425, -1000536719, -548792221, -699985043, 
        836553431, 953270745, 600235211, 718002117, 
        367585007, 484830689, 133361907, 251657213, 
        2041877159, 1891211689, 1806599355, 1654886325, 
        1568718495, 1418573201, 1335535747, 1184342925
    };
    
    const char sm_rcon[30] =
    {
        1, 2, 4, 8, 16, 32, 
        64, -128, 27, 54, 108, -40, 
        -85, 77, -102, 47, 94, -68, 
        99, -58, -105, 53, 106, -44, 
        -77, 125, -6, -17, -59, -111
    };
    
    const int sm_shifts[3][4][2] =
    {
        { {0, 0}, {1, 3}, {2, 2}, {3, 1} },
        { {0, 0}, {1, 5}, {2, 4}, {3, 3} },
        { {0, 0}, {1, 7}, {3, 5}, {4, 4} }
    };
    
    //Error Messages
    char const* sm_szErrorMsg1 = "Object not Initialized";
    char const* sm_szErrorMsg2 = "Data not multiple of Block Size";
    
    //Null chain
    char const* sm_chain0 = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
    
    //Auxiliary Function
    void Xor(char* buff, char const* chain)
    {
        if(false==m_bKeyInit)
        {
            printf("Error in Xor function\n");
            exit(1);
        }
        for(int i=0; i<m_blockSize; i++)
            *(buff++) ^= *(chain++);    
    }
    
    
    //Expand a user-supplied key material into a session key.
    // key        - The 128/192/256-bit user-key to use.
    // chain      - initial chain block for CBC and CFB modes.
    // keylength  - 16, 24 or 32 bytes
    // blockSize  - The block size in bytes of this Rijndael (16, 24 or 32 bytes).
    void MakeKey(char const* key, char const* chain, int keylength, int blockSize)
    {
        if(NULL == key)
        {
            printf("Error in MakeKey 1\n");
            exit(1);
        }   
        if(!(16==keylength || 24==keylength || 32==keylength))
        {
            printf("Error in MakeKey 2\n");
            exit(1);
        }   
        if(!(16==blockSize || 24==blockSize || 32==blockSize))
        {
            printf("Error in MakeKey 3\n");
            exit(1);
        }
        m_keylength = keylength;
        m_blockSize = blockSize;
        //Initialize the chain
        memcpy(m_chain0, chain, m_blockSize);
        memcpy(m_chain, chain, m_blockSize);
        //Calculate Number of Rounds
        switch(m_keylength)
        {
            case 16:
                m_iROUNDS = (m_blockSize == 16) ? 10 : (m_blockSize == 24 ? 12 : 14);
                break;
            case 24:
                m_iROUNDS = (m_blockSize != 32) ? 12 : 14;
                break;
    
            default: // 32 bytes = 256 bits
                m_iROUNDS = 14;
        }
        int BC = m_blockSize / 4;
        int i, j;
        for(i=0; i<=m_iROUNDS; i++)
        {
            for(j=0; j<BC; j++)
                m_Ke[i][j] = 0;
        }
        for(i=0; i<=m_iROUNDS; i++)
        {
            for(j=0; j<BC; j++)
                m_Kd[i][j] = 0;
        }
        int ROUND_KEY_COUNT = (m_iROUNDS + 1) * BC;
        int KC = m_keylength/4;
        //Copy user material bytes into temporary ints
        int* pi = tk;
        char const* pc = key;
        for(i=0; i<KC; i++)
        {
            *pi = (unsigned char)*(pc++) << 24;
            *pi |= (unsigned char)*(pc++) << 16;
            *pi |= (unsigned char)*(pc++) << 8;
            *(pi++) |= (unsigned char)*(pc++);
        }
        //Copy values into round key arrays
        int t = 0;
        for(j=0; (j<KC)&&(t<ROUND_KEY_COUNT); j++,t++)
        {
            m_Ke[t/BC][t%BC] = tk[j];
            m_Kd[m_iROUNDS - (t/BC)][t%BC] = tk[j];
        }
        int tt, rconpointer = 0;
        while(t < ROUND_KEY_COUNT)
        {
            //Extrapolate using phi (the round key evolution function)
            tt = tk[KC-1];
            tk[0] ^= (sm_S[(tt >> 16) & 0xFF] & 0xFF) << 24 ^
                (sm_S[(tt >>  8) & 0xFF] & 0xFF) << 16 ^
                (sm_S[ tt & 0xFF] & 0xFF) <<  8 ^
                (sm_S[(tt >> 24) & 0xFF] & 0xFF) ^
                (sm_rcon[rconpointer++]  & 0xFF) << 24;
            if(KC != 8)
                for(i=1, j=0; i<KC;)
                    tk[i++] ^= tk[j++];
            else
            {
                for(i=1, j=0; i<KC/2; )
                    tk[i++] ^= tk[j++];
                tt = tk[KC/2-1];
                tk[KC/2] ^= (sm_S[ tt & 0xFF] & 0xFF) ^
                    (sm_S[(tt >>  8) & 0xFF] & 0xFF) <<  8 ^
                    (sm_S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^
                    (sm_S[(tt >> 24) & 0xFF] & 0xFF) << 24;
                for(j = KC/2, i=j+1; i<KC; )
                    tk[i++] ^= tk[j++];
            }
            //Copy values into round key arrays
            for(j=0; (j<KC) && (t<ROUND_KEY_COUNT); j++, t++)
            {
                m_Ke[t/BC][t%BC] = tk[j];
                m_Kd[m_iROUNDS - (t/BC)][t%BC] = tk[j];
            }
        }
        //Inverse MixColumn where needed
        for(int r=1; r<m_iROUNDS; r++)
            for(j=0; j<BC; j++)
            {
                tt = m_Kd[r][j];
                m_Kd[r][j] = sm_U1[(tt >> 24) & 0xFF] ^
                    sm_U2[(tt >> 16) & 0xFF] ^
                    sm_U3[(tt >>  8) & 0xFF] ^
                    sm_U4[tt & 0xFF];
            }
        m_bKeyInit = true;
    }
    
    //Convenience method to encrypt exactly one block of plaintext, assuming
    //Rijndael's default block size (128-bit).
    // in         - The plaintext
    // result     - The ciphertext generated from a plaintext using the key
    void DefEncryptBlock(char const* in, char* result)
    {
        if(false==m_bKeyInit)
        {
            printf("Error in DefEncryptBlock\n");
            exit(1);
        }
        int* Ker = m_Ke[0];
        int t0 = ((unsigned char)*(in++) << 24);
        t0 |= ((unsigned char)*(in++) << 16);
        t0 |= ((unsigned char)*(in++) << 8);
        (t0 |= (unsigned char)*(in++)) ^= Ker[0];
        int t1 = ((unsigned char)*(in++) << 24);
        t1 |= ((unsigned char)*(in++) << 16);
        t1 |= ((unsigned char)*(in++) << 8);
        (t1 |= (unsigned char)*(in++)) ^= Ker[1];
        int t2 = ((unsigned char)*(in++) << 24);
        t2 |= ((unsigned char)*(in++) << 16);
        t2 |= ((unsigned char)*(in++) << 8);
        (t2 |= (unsigned char)*(in++)) ^= Ker[2];
        int t3 = ((unsigned char)*(in++) << 24);
        t3 |= ((unsigned char)*(in++) << 16);
        t3 |= ((unsigned char)*(in++) << 8);
        (t3 |= (unsigned char)*(in++)) ^= Ker[3];
        int a0, a1, a2, a3;
        //Apply Round Transforms
        for (int r = 1; r < m_iROUNDS; r++)
        {
            Ker = m_Ke[r];
            a0 = (sm_T1[(t0 >> 24) & 0xFF] ^
                sm_T2[(t1 >> 16) & 0xFF] ^
                sm_T3[(t2 >>  8) & 0xFF] ^
                sm_T4[t3 & 0xFF]) ^ Ker[0];
            a1 = (sm_T1[(t1 >> 24) & 0xFF] ^
                sm_T2[(t2 >> 16) & 0xFF] ^
                sm_T3[(t3 >>  8) & 0xFF] ^
                sm_T4[t0 & 0xFF]) ^ Ker[1];
            a2 = (sm_T1[(t2 >> 24) & 0xFF] ^
                sm_T2[(t3 >> 16) & 0xFF] ^
                sm_T3[(t0 >>  8) & 0xFF] ^
                sm_T4[t1 & 0xFF]) ^ Ker[2];
            a3 = (sm_T1[(t3 >> 24) & 0xFF] ^
                sm_T2[(t0 >> 16) & 0xFF] ^
                sm_T3[(t1 >>  8) & 0xFF] ^
                sm_T4[t2 & 0xFF]) ^ Ker[3];
            t0 = a0;
            t1 = a1;
            t2 = a2;
            t3 = a3;
        }
        //Last Round is special
        Ker = m_Ke[m_iROUNDS];
        int tt = Ker[0];
        result[0] = sm_S[(t0 >> 24) & 0xFF] ^ (tt >> 24);
        result[1] = sm_S[(t1 >> 16) & 0xFF] ^ (tt >> 16);
        result[2] = sm_S[(t2 >>  8) & 0xFF] ^ (tt >>  8);
        result[3] = sm_S[t3 & 0xFF] ^ tt;
        tt = Ker[1];
        result[4] = sm_S[(t1 >> 24) & 0xFF] ^ (tt >> 24);
        result[5] = sm_S[(t2 >> 16) & 0xFF] ^ (tt >> 16);
        result[6] = sm_S[(t3 >>  8) & 0xFF] ^ (tt >>  8);
        result[7] = sm_S[t0 & 0xFF] ^ tt;
        tt = Ker[2];
        result[8] = sm_S[(t2 >> 24) & 0xFF] ^ (tt >> 24);
        result[9] = sm_S[(t3 >> 16) & 0xFF] ^ (tt >> 16);
        result[10] = sm_S[(t0 >>  8) & 0xFF] ^ (tt >>  8);
        result[11] = sm_S[t1 & 0xFF] ^ tt;
        tt = Ker[3];
        result[12] = sm_S[(t3 >> 24) & 0xFF] ^ (tt >> 24);
        result[13] = sm_S[(t0 >> 16) & 0xFF] ^ (tt >> 16);
        result[14] = sm_S[(t1 >>  8) & 0xFF] ^ (tt >>  8);
        result[15] = sm_S[t2 & 0xFF] ^ tt;
    }
    
    //Convenience method to decrypt exactly one block of plaintext, assuming
    //Rijndael's default block size (128-bit).
    // in         - The ciphertext.
    // result     - The plaintext generated from a ciphertext using the session key.
    void DefDecryptBlock(char const* in, char* result)
    {
        if(false==m_bKeyInit)
        {
            printf("Error in DefDecryptBlock\n");
            exit(1);
        }
        int* Kdr = m_Kd[0];
        int t0 = ((unsigned char)*(in++) << 24);
        t0 = t0 | ((unsigned char)*(in++) << 16);
        t0 |= ((unsigned char)*(in++) << 8);
        (t0 |= (unsigned char)*(in++)) ^= Kdr[0];
        int t1 = ((unsigned char)*(in++) << 24);
        t1 |= ((unsigned char)*(in++) << 16);
        t1 |= ((unsigned char)*(in++) << 8);
        (t1 |= (unsigned char)*(in++)) ^= Kdr[1];
        int t2 = ((unsigned char)*(in++) << 24);
        t2 |= ((unsigned char)*(in++) << 16);
        t2 |= ((unsigned char)*(in++) << 8);
        (t2 |= (unsigned char)*(in++)) ^= Kdr[2];
        int t3 = ((unsigned char)*(in++) << 24);
        t3 |= ((unsigned char)*(in++) << 16);
        t3 |= ((unsigned char)*(in++) << 8);
        (t3 |= (unsigned char)*(in++)) ^= Kdr[3];
        int a0, a1, a2, a3;
        for(int r = 1; r < m_iROUNDS; r++) // apply round transforms
        {
            Kdr = m_Kd[r];
            a0 = (sm_T5[(t0 >> 24) & 0xFF] ^
                sm_T6[(t3 >> 16) & 0xFF] ^
                sm_T7[(t2 >>  8) & 0xFF] ^
                sm_T8[ t1        & 0xFF] ) ^ Kdr[0];
            a1 = (sm_T5[(t1 >> 24) & 0xFF] ^
                sm_T6[(t0 >> 16) & 0xFF] ^
                sm_T7[(t3 >>  8) & 0xFF] ^
                sm_T8[ t2        & 0xFF] ) ^ Kdr[1];
            a2 = (sm_T5[(t2 >> 24) & 0xFF] ^
                sm_T6[(t1 >> 16) & 0xFF] ^
                sm_T7[(t0 >>  8) & 0xFF] ^
                sm_T8[ t3        & 0xFF] ) ^ Kdr[2];
            a3 = (sm_T5[(t3 >> 24) & 0xFF] ^
                sm_T6[(t2 >> 16) & 0xFF] ^
                sm_T7[(t1 >>  8) & 0xFF] ^
                sm_T8[ t0        & 0xFF] ) ^ Kdr[3];
            t0 = a0;
            t1 = a1;
            t2 = a2;
            t3 = a3;
        }
        //Last Round is special
        Kdr = m_Kd[m_iROUNDS];
        int tt = Kdr[0];
        result[ 0] = sm_Si[(t0 >> 24) & 0xFF] ^ (tt >> 24);
        result[ 1] = sm_Si[(t3 >> 16) & 0xFF] ^ (tt >> 16);
        result[ 2] = sm_Si[(t2 >>  8) & 0xFF] ^ (tt >>  8);
        result[ 3] = sm_Si[ t1 & 0xFF] ^ tt;
        tt = Kdr[1];
        result[ 4] = sm_Si[(t1 >> 24) & 0xFF] ^ (tt >> 24);
        result[ 5] = sm_Si[(t0 >> 16) & 0xFF] ^ (tt >> 16);
        result[ 6] = sm_Si[(t3 >>  8) & 0xFF] ^ (tt >>  8);
        result[ 7] = sm_Si[ t2 & 0xFF] ^ tt;
        tt = Kdr[2];
        result[ 8] = sm_Si[(t2 >> 24) & 0xFF] ^ (tt >> 24);
        result[ 9] = sm_Si[(t1 >> 16) & 0xFF] ^ (tt >> 16);
        result[10] = sm_Si[(t0 >>  8) & 0xFF] ^ (tt >>  8);
        result[11] = sm_Si[ t3 & 0xFF] ^ tt;
        tt = Kdr[3];
        result[12] = sm_Si[(t3 >> 24) & 0xFF] ^ (tt >> 24);
        result[13] = sm_Si[(t2 >> 16) & 0xFF] ^ (tt >> 16);
        result[14] = sm_Si[(t1 >>  8) & 0xFF] ^ (tt >>  8);
        result[15] = sm_Si[ t0 & 0xFF] ^ tt;
    }
    
    //Encrypt exactly one block of plaintext.
    // in           - The plaintext.
    // result       - The ciphertext generated from a plaintext using the key.
    void EncryptBlock(char const* in, char* result)
    {
        if(false==m_bKeyInit)
        {
            printf("Error in EncryptBlock\n");
            exit(1);
        }
        if(DEFAULT_BLOCK_SIZE == m_blockSize)
        {
            DefEncryptBlock(in, result);
            return;
        }
        int BC = m_blockSize / 4;
        int SC = (BC == 4) ? 0 : (BC == 6 ? 1 : 2);
        int s1 = sm_shifts[SC][1][0];
        int s2 = sm_shifts[SC][2][0];
        int s3 = sm_shifts[SC][3][0];
        //Temporary Work Arrays
        int i;
        int tt;
        int* pi = t;
        for(i=0; i<BC; i++)
        {
            *pi = ((unsigned char)*(in++) << 24);
            *pi |= ((unsigned char)*(in++) << 16);
            *pi |= ((unsigned char)*(in++) << 8);
            (*(pi++) |= (unsigned char)*(in++)) ^= m_Ke[0][i];
        }
        //Apply Round Transforms
        for(int r=1; r<m_iROUNDS; r++)
        {
            for(i=0; i<BC; i++)
                a[i] = (sm_T1[(t[i] >> 24) & 0xFF] ^
                sm_T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^
                sm_T3[(t[(i + s2) % BC] >>  8) & 0xFF] ^
                sm_T4[ t[(i + s3) % BC] & 0xFF] ) ^ m_Ke[r][i];
            memcpy(t, a, 4*BC);
        }
        int j;
        //Last Round is Special
        for(i=0,j=0; i<BC; i++)
        {
            tt = m_Ke[m_iROUNDS][i];
            result[j++] = sm_S[(t[i] >> 24) & 0xFF] ^ (tt >> 24);
            result[j++] = sm_S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16);
            result[j++] = sm_S[(t[(i + s2) % BC] >>  8) & 0xFF] ^ (tt >>  8);
            result[j++] = sm_S[ t[(i + s3) % BC] & 0xFF] ^ tt;
        }
    }
    
    //Decrypt exactly one block of ciphertext.
    // in         - The ciphertext.
    // result     - The plaintext generated from a ciphertext using the session key.
    void DecryptBlock(char const* in, char* result)
    {
        if(false==m_bKeyInit)
        {
            printf("Error in DecryptBlock\n");
            exit(1);
        }   
        if(DEFAULT_BLOCK_SIZE == m_blockSize)
        {
            DefDecryptBlock(in, result);
            return;
        }
        int BC = m_blockSize / 4;
        int SC = BC == 4 ? 0 : (BC == 6 ? 1 : 2);
        int s1 = sm_shifts[SC][1][1];
        int s2 = sm_shifts[SC][2][1];
        int s3 = sm_shifts[SC][3][1];
        //Temporary Work Arrays
        int i;
        int tt;
        int* pi = t;
        for(i=0; i<BC; i++)
        {
            *pi = ((unsigned char)*(in++) << 24);
            *pi |= ((unsigned char)*(in++) << 16);
            *pi |= ((unsigned char)*(in++) << 8);
            (*(pi++) |= (unsigned char)*(in++)) ^= m_Kd[0][i];
        }
        //Apply Round Transforms
        for(int r=1; r<m_iROUNDS; r++)
        {
            for(i=0; i<BC; i++)
                a[i] = (sm_T5[(t[i] >> 24) & 0xFF] ^
                sm_T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^
                sm_T7[(t[(i + s2) % BC] >>  8) & 0xFF] ^
                sm_T8[ t[(i + s3) % BC] & 0xFF]) ^ m_Kd[r][i];
            memcpy(t, a, 4*BC);
        }
        int j;
        //Last Round is Special
        for(i=0,j=0; i<BC; i++)
        {
            tt = m_Kd[m_iROUNDS][i];
            result[j++] = sm_Si[(t[i] >> 24) & 0xFF] ^ (tt >> 24);
            result[j++] = sm_Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16);
            result[j++] = sm_Si[(t[(i + s2) % BC] >>  8) & 0xFF] ^ (tt >>  8);
            result[j++] = sm_Si[ t[(i + s3) % BC] & 0xFF] ^ tt;
        }
    }
    
    void Encrypt(char const* in, char* result, size_t n, int iMode)
    {
        if(false==m_bKeyInit)
        {
            printf("Error in Encrypt 1\n");
            exit(1);
        }   
        //n should be > 0 and multiple of m_blockSize
        if(0==n || n%m_blockSize!=0)
        {
            printf("Error in Encrypt 2\n");
            exit(1);
        }
        int i;
        char const* pin;
        char* presult;
        if(CBC == iMode) //CBC mode, using the Chain
        {
            for(i=0,pin=in,presult=result; i<n/m_blockSize; i++)
            {
                Xor(m_chain, pin);
                EncryptBlock(m_chain, presult);
                memcpy(m_chain, presult, m_blockSize);
                pin += m_blockSize;
                presult += m_blockSize;
            }
        }
        else if(CFB == iMode) //CFB mode, using the Chain
        {
            for(i=0,pin=in,presult=result; i<n/m_blockSize; i++)
            {
                EncryptBlock(m_chain, presult);
                Xor(presult, pin);
                memcpy(m_chain, presult, m_blockSize);
                pin += m_blockSize;
                presult += m_blockSize;
            }
        }
        else //ECB mode, not using the Chain
        {
            for(i=0,pin=in,presult=result; i<n/m_blockSize; i++)
            {
                EncryptBlock(pin, presult);
                pin += m_blockSize;
                presult += m_blockSize;
            }
        }
    }
    
    void Decrypt(char const* in, char* result, size_t n, int iMode)
    {
        if(false==m_bKeyInit)
        {
            printf("Error in Decrypt 1\n");
            exit(1);
        }   
    
        //n should be > 0 and multiple of m_blockSize
        if(0==n || n%m_blockSize!=0)
        {
            printf("Error in Decrypt 2\n");
            exit(1);
        }   
        int i;
        char const* pin;
        char* presult;
        if(CBC == iMode) //CBC mode, using the Chain
        {
            for(i=0,pin=in,presult=result; i<n/m_blockSize; i++)
            {
                DecryptBlock(pin, presult);
                Xor(presult, m_chain);
                memcpy(m_chain, pin, m_blockSize);              
                pin += m_blockSize;
                presult += m_blockSize;
            }
        }
        else if(CFB == iMode) //CFB mode, using the Chain, not using Decrypt()
        {
            for(i=0,pin=in,presult=result; i<n/m_blockSize; i++)
            {
                EncryptBlock(m_chain, presult);
                //memcpy(presult, pin, m_blockSize);
                Xor(presult, pin);
                memcpy(m_chain, pin, m_blockSize);
                pin += m_blockSize;
                presult += m_blockSize;
            }
        }
        else //ECB mode, not using the Chain
        {
            for(i=0,pin=in,presult=result; i<n/m_blockSize; i++)
            {
                DecryptBlock(pin, presult);
                pin += m_blockSize;
                presult += m_blockSize;
            }
        }
    }
    Code:
    // Module name: Rijndael.h
    	//Operation Modes
    	//The Electronic Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB) modes
    	//are implemented.
    	//In ECB mode if the same block is encrypted twice with the same key, the resulting
    	//ciphertext blocks are the same.
    	//In CBC Mode a ciphertext block is obtained by first xoring the
    	//plaintext block with the previous ciphertext block, and encrypting the resulting value.
    	//In CFB mode a ciphertext block is obtained by encrypting the previous ciphertext block
    	//and xoring the resulting value with the plaintext.
    	enum { ECB=0, CBC=1, CFB=2 };
    	enum { DEFAULT_BLOCK_SIZE=16 };
    	enum { MAX_BLOCK_SIZE=32, MAX_ROUNDS=14, MAX_KC=8, MAX_BC=8 };
    	//Expand a user-supplied key material into a session key.
    	// key        - The 128/192/256-bit user-key to use.
    	// chain      - initial chain block for CBC and CFB modes.
    	// keylength  - 16, 24 or 32 bytes
    	// blockSize  - The block size in bytes of this Rijndael (16, 24 or 32 bytes).
    	void MakeKey(char const* key, char const* chain, int keylength=DEFAULT_BLOCK_SIZE, int blockSize=DEFAULT_BLOCK_SIZE);
    	//Convenience method to encrypt exactly one block of plaintext, assuming
    	//Rijndael's default block size (128-bit).
    	// in         - The plaintext
    	// result     - The ciphertext generated from a plaintext using the key
    	void DefEncryptBlock(char const* in, char* result);
    	//Convenience method to decrypt exactly one block of plaintext, assuming
    	//Rijndael's default block size (128-bit).
    	// in         - The ciphertext.
    	// result     - The plaintext generated from a ciphertext using the session key.
    	void DefDecryptBlock(char const* in, char* result);
    	//Encrypt exactly one block of plaintext.
    	// in           - The plaintext.
        // result       - The ciphertext generated from a plaintext using the key.
        void EncryptBlock(char const* in, char* result);
    	//Decrypt exactly one block of ciphertext.
    	// in         - The ciphertext.
    	// result     - The plaintext generated from a ciphertext using the session key.
    	void DecryptBlock(char const* in, char* result);
    	void Encrypt(char const* in, char* result, size_t n, int iMode=ECB);
    	void Decrypt(char const* in, char* result, size_t n, int iMode=ECB);
    	//Key Initialization Flag
    	bool m_bKeyInit;
    	//Encryption (m_Ke) round key
    	int m_Ke[MAX_ROUNDS+1][MAX_BC];
    	//Decryption (m_Kd) round key
        int m_Kd[MAX_ROUNDS+1][MAX_BC];
    	//Key Length
    	int m_keylength;
    	//Block Size
    	int	m_blockSize;
    	//Number of Rounds
    	int m_iROUNDS;
    	//Chain Block
    	char m_chain0[MAX_BLOCK_SIZE];
    	char m_chain[MAX_BLOCK_SIZE];
    	//Auxiliary private use buffers
    	int tk[MAX_KC];
    	int a[MAX_BC];
    	int t[MAX_BC];
    Code:
    // Module name: test.cpp
    // Compile: cl.exe test.cpp rijndael.cpp
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    extern const int sm_alog;
    extern const int sm_log;
    extern char const* sm_szErrorMsg1;
    extern  bool m_bKeyInit;
    extern  int m_keylength;
    extern  int m_blockSize;
    extern  int m_iROUNDS;
    extern  char m_chain[32];
    extern  char m_chain0[32];
    extern  void MakeKey(char const* key, char const* chain, int keylength, int blockSize);
    extern void EncryptBlock(char const* in, char* result);
    extern  void DecryptBlock(char const* in, char* result);
    extern  void Encrypt(char const* in, char* result, size_t n, int iMode);
    extern  void Decrypt(char const* in, char* result, size_t n, int iMode);
    
    enum { ECB=0, CBC=1, CFB=2 };
    
    //Function to convert unsigned char to string of length 2
    void Char2Hex(unsigned char ch, char* szHex)
    {
        unsigned char byte[2];
        byte[0] = ch/16;
        byte[1] = ch%16;
        for(int i=0; i<2; i++)
        {
            if(byte[i] >= 0 && byte[i] <= 9)
                szHex[i] = '0' + byte[i];
            else
                szHex[i] = 'A' + byte[i] - 10;
        }
        szHex[2] = 0;
    }
    
    //Function to convert string of length 2 to unsigned char
    void Hex2Char(char const* szHex, unsigned char& rch)
    {
        rch = 0;
        for(int i=0; i<2; i++)
        {
            if(*(szHex + i) >='0' && *(szHex + i) <= '9')
                rch = (rch << 4) + (*(szHex + i) - '0');
            else if(*(szHex + i) >='A' && *(szHex + i) <= 'F')
                rch = (rch << 4) + (*(szHex + i) - 'A' + 10);
            else
                break;
        }
    }    
    
    //Function to convert string of unsigned chars to string of chars
    void CharStr2HexStr(unsigned char const* pucCharStr, char* pszHexStr, int iSize)
    {
        int i;
        char szHex[3];
        pszHexStr[0] = 0;
        for(i=0; i<iSize; i++)
        {
            Char2Hex(pucCharStr[i], szHex);
            strcat(pszHexStr, szHex);
        }
    }
    
    //Function to convert string of chars to string of unsigned chars
    void HexStr2CharStr(char const* pszHexStr, unsigned char* pucCharStr, int iSize)
    {
        int i;
        unsigned char ch;
        for(i=0; i<iSize; i++)
        {
            Hex2Char(pszHexStr+2*i, ch);
            pucCharStr[i] = ch;
        }
    }
    
    int main(void)
    {
        char szHex[99] = {0};
        MakeKey("1234567890123456","\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 16);
        char szDataIn1[81] = "0xFF-0xE3-0x22-0xDE-0x57-0xF7-0x89-0xE6-0x55-0xE7-0x0D-0xA3-0x34-0x4F-0xDD-0x42";
        char szDataIn[49] = {0};
        char szDataOut[81] = {0};
        strcpy(szDataIn, szDataIn1);
        Encrypt(szDataIn, szDataOut, 80, ECB);
        CharStr2HexStr((unsigned char*)szDataOut, szHex, 16);
        printf("HEX = %s\n", szHex);
        Decrypt(szDataOut, szDataIn, 80, ECB);
        printf("%s\n",szDataIn);
    return 0;
    }
    Last edited by BobS0327; 10-14-2006 at 08:44 AM.

  5. #5
    Registered User
    Join Date
    Oct 2006
    Posts
    8
    Hi BobS0327.

    First I want to say my thanking.

    So i could not use your code. Could you explain me the below code. How can i plaintext data in the below code?

    Code:
    /**
     * rijndael-alg-fst.c
     *
     * @version 3.0 (December 2000)
     *
     * Optimised ANSI C code for the Rijndael cipher (now AES)
     *
     * @author Vincent Rijmen <[email protected]>
     * @author Antoon Bosselaers <[email protected]>
     * @author Paulo Barreto <[email protected]>
     *
     * This code is hereby placed in the public domain.
     *
     * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    #include <assert.h>
    #include <stdlib.h>
    
    #include "rijndael-alg-fst.h"
    
    /*
    Te0[x] = S [x].[02, 01, 01, 03];
    Te1[x] = S [x].[03, 02, 01, 01];
    Te2[x] = S [x].[01, 03, 02, 01];
    Te3[x] = S [x].[01, 01, 03, 02];
    Te4[x] = S [x].[01, 01, 01, 01];
    
    Td0[x] = Si[x].[0e, 09, 0d, 0b];
    Td1[x] = Si[x].[0b, 0e, 09, 0d];
    Td2[x] = Si[x].[0d, 0b, 0e, 09];
    Td3[x] = Si[x].[09, 0d, 0b, 0e];
    Td4[x] = Si[x].[01, 01, 01, 01];
    */
    
    static const u32 Te0[256] = {
        0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
        0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
        0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
        0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
        0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
        0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
        0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
        0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
        0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
        0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
        0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
        0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
        0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
        0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
        0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
        0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
        0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
        0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
        0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
        0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
        0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
        0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
        0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
        0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
        0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
        0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
        0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
        0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
        0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
        0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
        0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
        0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
        0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
        0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
        0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
        0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
        0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
        0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
        0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
        0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
        0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
        0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
        0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
        0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
        0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
        0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
        0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
        0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
        0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
        0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
        0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
        0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
        0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
        0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
        0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
        0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
        0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
        0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
        0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
        0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
        0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
        0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
        0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
        0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
    };
    static const u32 Te1[256] = {
        0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
        0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
        0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
        0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
        0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
        0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
        0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
        0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
        0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
        0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
        0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
        0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
        0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
        0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
        0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
        0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
        0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
        0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
        0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
        0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
        0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
        0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
        0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
        0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
        0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
        0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
        0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
        0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
        0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
        0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
        0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
        0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
        0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
        0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
        0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
        0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
        0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
        0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
        0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
        0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
        0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
        0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
        0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
        0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
        0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
        0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
        0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
        0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
        0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
        0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
        0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
        0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
        0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
        0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
        0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
        0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
        0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
        0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
        0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
        0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
        0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
        0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
        0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
        0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
    };
    static const u32 Te2[256] = {
        0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
        0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
        0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
        0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
        0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
        0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
        0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
        0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
        0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
        0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
        0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
        0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
        0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
        0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
        0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
        0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
        0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
        0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
        0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
        0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
        0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
        0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
        0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
        0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
        0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
        0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
        0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
        0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
        0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
        0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
        0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
        0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
        0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
        0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
        0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
        0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
        0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
        0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
        0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
        0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
        0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
        0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
        0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
        0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
        0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
        0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
        0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
        0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
        0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
        0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
        0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
        0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
        0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
        0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
        0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
        0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
        0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
        0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
        0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
        0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
        0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
        0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
        0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
        0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
    };
    static const u32 Te3[256] = {
    
        0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
        0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
        0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
        0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
        0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
        0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
        0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
        0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
        0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
        0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
        0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
        0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
        0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
        0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
        0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
        0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
        0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
        0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
        0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
        0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
        0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
        0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
        0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
        0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
        0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
        0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
        0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
        0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
        0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
        0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
        0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
        0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
        0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
        0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
        0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
        0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
        0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
        0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
        0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
        0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
        0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
        0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
        0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
        0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
        0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
        0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
        0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
        0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
        0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
        0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
        0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
        0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
        0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
        0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
        0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
        0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
        0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
        0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
        0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
        0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
        0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
        0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
        0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
        0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
    };
    static const u32 Te4[256] = {
        0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
        0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
        0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
        0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
        0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
        0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
        0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
        0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
        0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
        0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
        0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
        0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
        0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
        0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
        0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
        0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
        0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
        0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
        0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
        0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
        0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
        0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
        0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
        0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
        0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
        0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
        0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
        0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
        0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
        0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
        0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
        0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
        0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
        0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
        0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
        0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
        0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
        0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
        0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
        0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
        0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
        0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
        0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
        0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
        0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
        0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
        0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
        0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
        0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
        0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
        0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
        0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
        0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
        0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
        0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
        0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
        0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
        0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
        0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
        0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
        0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
        0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
        0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
        0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
    };
    static const u32 Td0[256] = {
        0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
        0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
        0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
        0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
        0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
        0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
        0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
        0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
        0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
        0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
        0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
        0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
        0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
        0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
        0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
        0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
        0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
        0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
        0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
        0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
        0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
        0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
        0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
        0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
        0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
        0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
        0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
        0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
        0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
        0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
        0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
        0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
        0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
        0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
        0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
        0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
        0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
        0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
        0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
        0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
        0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
        0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
        0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
        0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
        0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
        0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
        0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
        0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
        0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
        0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
        0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
        0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
        0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
        0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
        0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
        0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
        0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
        0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
        0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
        0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
        0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
        0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
        0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
        0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
    };
    static const u32 Td1[256] = {
        0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
        0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
        0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
        0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
        0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
        0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
        0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
        0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
        0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
        0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
        0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
        0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
        0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
        0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
        0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
        0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
        0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
        0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
        0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
        0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
        0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
        0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
        0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
        0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
        0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
        0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
        0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
        0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
        0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
        0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
        0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
        0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
        0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
        0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
        0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
        0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
        0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
        0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
        0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
        0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
        0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
        0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
        0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
        0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
        0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
        0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
        0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
        0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
        0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
        0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
        0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
        0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
        0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
        0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
        0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
        0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
        0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
        0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
        0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
        0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
        0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
        0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
        0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
        0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
    };
    static const u32 Td2[256] = {
        0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
        0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
        0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
        0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
        0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
        0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
        0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
        0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
        0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
        0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
        0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
        0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
        0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
        0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
        0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
        0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
        0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
        0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
        0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
        0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
    
        0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
        0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
        0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
        0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
        0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
        0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
        0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
        0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
        0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
        0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
        0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
        0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
        0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
        0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
        0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
        0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
        0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
        0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
        0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
        0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
        0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
        0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
        0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
        0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
        0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
        0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
        0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
        0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
        0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
        0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
        0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
        0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
        0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
        0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
        0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
        0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
        0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
        0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
        0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
        0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
        0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
        0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
        0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
        0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
    };
    static const u32 Td3[256] = {
        0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
        0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
        0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
        0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
        0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
        0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
        0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
        0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
        0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
        0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
        0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
        0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
        0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
        0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
        0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
        0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
        0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
        0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
        0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
        0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
        0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
        0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
        0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
        0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
        0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
        0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
        0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
        0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
        0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
        0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
        0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
        0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
        0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
        0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
        0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
        0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
        0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
        0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
        0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
        0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
        0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
        0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
        0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
        0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
        0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
        0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
        0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
        0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
        0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
        0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
        0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
        0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
        0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
        0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
        0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
        0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
        0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
        0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
        0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
        0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
        0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
        0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
        0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
        0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
    };
    static const u32 Td4[256] = {
        0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
        0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
        0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
        0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
        0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
        0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
        0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
        0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
        0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
        0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
        0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
        0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
        0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
        0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
        0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
        0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
        0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
        0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
        0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
        0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
        0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
        0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
        0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
        0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
        0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
        0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
        0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
        0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
        0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
        0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
        0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
        0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
        0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
        0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
        0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
        0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
        0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
        0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
        0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
        0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
        0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
        0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
        0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
        0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
        0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
        0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
        0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
        0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
        0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
        0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
        0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
        0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
        0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
        0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
        0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
        0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
        0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
        0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
        0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
        0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
        0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
        0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
        0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
        0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
    };
    static const u32 rcon[] = {
    	0x01000000, 0x02000000, 0x04000000, 0x08000000,
    	0x10000000, 0x20000000, 0x40000000, 0x80000000,
    	0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
    };
    
    #define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
    
    #ifdef _MSC_VER
    #define GETU32(p) SWAP(*((u32 *)(p)))
    #define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
    #else
    #define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
    #define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
    #endif
    
    /**
     * Expand the cipher key into the encryption key schedule.
     *
     * @return	the number of rounds for the given cipher key size.
     */
    int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
       	int i = 0;
    	u32 temp;
    
    	rk[0] = GETU32(cipherKey     );
    	rk[1] = GETU32(cipherKey +  4);
    	rk[2] = GETU32(cipherKey +  8);
    	rk[3] = GETU32(cipherKey + 12);
    	if (keyBits == 128) {
    		for (;;) {
    			temp  = rk[3];
    			rk[4] = rk[0] ^
    				(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
    				(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
    				(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
    				(Te4[(temp >> 24)       ] & 0x000000ff) ^
    				rcon[i];
    			rk[5] = rk[1] ^ rk[4];
    			rk[6] = rk[2] ^ rk[5];
    			rk[7] = rk[3] ^ rk[6];
    			if (++i == 10) {
    				return 10;
    			}
    			rk += 4;
    		}
    	}
    	rk[4] = GETU32(cipherKey + 16);
    	rk[5] = GETU32(cipherKey + 20);
    	if (keyBits == 192) {
    		for (;;) {
    			temp = rk[ 5];
    			rk[ 6] = rk[ 0] ^
    				(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
    				(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
    				(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
    				(Te4[(temp >> 24)       ] & 0x000000ff) ^
    				rcon[i];
    			rk[ 7] = rk[ 1] ^ rk[ 6];
    			rk[ 8] = rk[ 2] ^ rk[ 7];
    			rk[ 9] = rk[ 3] ^ rk[ 8];
    			if (++i == 8) {
    				return 12;
    			}
    			rk[10] = rk[ 4] ^ rk[ 9];
    			rk[11] = rk[ 5] ^ rk[10];
    			rk += 6;
    		}
    	}
    	rk[6] = GETU32(cipherKey + 24);
    	rk[7] = GETU32(cipherKey + 28);
    	if (keyBits == 256) {
            for (;;) {
            	temp = rk[ 7];
            	rk[ 8] = rk[ 0] ^
            		(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
            		(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
            		(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
            		(Te4[(temp >> 24)       ] & 0x000000ff) ^
            		rcon[i];
            	rk[ 9] = rk[ 1] ^ rk[ 8];
            	rk[10] = rk[ 2] ^ rk[ 9];
            	rk[11] = rk[ 3] ^ rk[10];
    			if (++i == 7) {
    				return 14;
    			}
            	temp = rk[11];
            	rk[12] = rk[ 4] ^
            		(Te4[(temp >> 24)       ] & 0xff000000) ^
            		(Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
            		(Te4[(temp >>  8) & 0xff] & 0x0000ff00) ^
            		(Te4[(temp      ) & 0xff] & 0x000000ff);
            	rk[13] = rk[ 5] ^ rk[12];
            	rk[14] = rk[ 6] ^ rk[13];
            	rk[15] = rk[ 7] ^ rk[14];
    
    			rk += 8;
            }
    	}
    	return 0;
    }
    
    /**
     * Expand the cipher key into the decryption key schedule.
     *
     * @return	the number of rounds for the given cipher key size.
     */
    int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
    	int Nr, i, j;
    	u32 temp;
    
    	/* expand the cipher key: */
    	Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
    	/* invert the order of the round keys: */
    	for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
    		temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
    		temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
    		temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
    		temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
    	}
    	/* apply the inverse MixColumn transform to all round keys but the first and the last: */
    	for (i = 1; i < Nr; i++) {
    		rk += 4;
    		rk[0] =
    			Td0[Te4[(rk[0] >> 24)       ] & 0xff] ^
    			Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
    			Td2[Te4[(rk[0] >>  8) & 0xff] & 0xff] ^
    			Td3[Te4[(rk[0]      ) & 0xff] & 0xff];
    		rk[1] =
    			Td0[Te4[(rk[1] >> 24)       ] & 0xff] ^
    			Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
    			Td2[Te4[(rk[1] >>  8) & 0xff] & 0xff] ^
    			Td3[Te4[(rk[1]      ) & 0xff] & 0xff];
    		rk[2] =
    			Td0[Te4[(rk[2] >> 24)       ] & 0xff] ^
    			Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
    			Td2[Te4[(rk[2] >>  8) & 0xff] & 0xff] ^
    			Td3[Te4[(rk[2]      ) & 0xff] & 0xff];
    		rk[3] =
    			Td0[Te4[(rk[3] >> 24)       ] & 0xff] ^
    			Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
    			Td2[Te4[(rk[3] >>  8) & 0xff] & 0xff] ^
    			Td3[Te4[(rk[3]      ) & 0xff] & 0xff];
    	}
    	return Nr;
    }
    
    void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) {
    	u32 s0, s1, s2, s3, t0, t1, t2, t3;
    #ifndef FULL_UNROLL
        int r;
    #endif /* ?FULL_UNROLL */
    
        /*
    	 * map byte array block to cipher state
    	 * and add initial round key:
    	 */
    	s0 = GETU32(pt     ) ^ rk[0];
    	s1 = GETU32(pt +  4) ^ rk[1];
    	s2 = GETU32(pt +  8) ^ rk[2];
    	s3 = GETU32(pt + 12) ^ rk[3];
    #ifdef FULL_UNROLL
        /* round 1: */
       	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
       	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
       	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
       	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
       	/* round 2: */
       	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
       	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
       	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
       	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
        /* round 3: */
       	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
       	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
       	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
       	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
       	/* round 4: */
       	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
       	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
       	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
       	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
        /* round 5: */
       	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
       	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
       	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
       	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
       	/* round 6: */
       	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
       	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
       	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
       	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
        /* round 7: */
       	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
       	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
       	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
       	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
       	/* round 8: */
       	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
       	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
       	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
       	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
        /* round 9: */
       	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
       	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
       	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
       	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
        if (Nr > 10) {
            /* round 10: */
            s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
            s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
            s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
            s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
            /* round 11: */
            t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
            t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
            t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
            t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
            if (Nr > 12) {
                /* round 12: */
                s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
                s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
                s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
                s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
                /* round 13: */
                t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
                t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
                t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
                t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
            }
        }
        rk += Nr << 2;
    #else  /* !FULL_UNROLL */
        /*
    	 * Nr - 1 full rounds:
    	 */
        r = Nr >> 1;
        for (;;) {
            t0 =
                Te0[(s0 >> 24)       ] ^
                Te1[(s1 >> 16) & 0xff] ^
                Te2[(s2 >>  8) & 0xff] ^
                Te3[(s3      ) & 0xff] ^
                rk[4];
            t1 =
                Te0[(s1 >> 24)       ] ^
                Te1[(s2 >> 16) & 0xff] ^
                Te2[(s3 >>  8) & 0xff] ^
                Te3[(s0      ) & 0xff] ^
                rk[5];
            t2 =
                Te0[(s2 >> 24)       ] ^
                Te1[(s3 >> 16) & 0xff] ^
                Te2[(s0 >>  8) & 0xff] ^
                Te3[(s1      ) & 0xff] ^
                rk[6];
            t3 =
                Te0[(s3 >> 24)       ] ^
                Te1[(s0 >> 16) & 0xff] ^
                Te2[(s1 >>  8) & 0xff] ^
                Te3[(s2      ) & 0xff] ^
                rk[7];
    
            rk += 8;
            if (--r == 0) {
                break;
            }
    
            s0 =
                Te0[(t0 >> 24)       ] ^
                Te1[(t1 >> 16) & 0xff] ^
                Te2[(t2 >>  8) & 0xff] ^
                Te3[(t3      ) & 0xff] ^
                rk[0];
            s1 =
                Te0[(t1 >> 24)       ] ^
                Te1[(t2 >> 16) & 0xff] ^
                Te2[(t3 >>  8) & 0xff] ^
                Te3[(t0      ) & 0xff] ^
                rk[1];
            s2 =
                Te0[(t2 >> 24)       ] ^
                Te1[(t3 >> 16) & 0xff] ^
                Te2[(t0 >>  8) & 0xff] ^
                Te3[(t1      ) & 0xff] ^
                rk[2];
            s3 =
                Te0[(t3 >> 24)       ] ^
                Te1[(t0 >> 16) & 0xff] ^
                Te2[(t1 >>  8) & 0xff] ^
                Te3[(t2      ) & 0xff] ^
                rk[3];
        }
    #endif /* ?FULL_UNROLL */
        /*
    	 * apply last round and
    	 * map cipher state to byte array block:
    	 */
    	s0 =
    		(Te4[(t0 >> 24)       ] & 0xff000000) ^
    		(Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
    		(Te4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
    		(Te4[(t3      ) & 0xff] & 0x000000ff) ^
    		rk[0];
    	PUTU32(ct     , s0);
    	s1 =
    		(Te4[(t1 >> 24)       ] & 0xff000000) ^
    		(Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
    		(Te4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
    		(Te4[(t0      ) & 0xff] & 0x000000ff) ^
    		rk[1];
    	PUTU32(ct +  4, s1);
    	s2 =
    		(Te4[(t2 >> 24)       ] & 0xff000000) ^
    		(Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
    		(Te4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
    		(Te4[(t1      ) & 0xff] & 0x000000ff) ^
    		rk[2];
    	PUTU32(ct +  8, s2);
    	s3 =
    		(Te4[(t3 >> 24)       ] & 0xff000000) ^
    		(Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
    		(Te4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
    		(Te4[(t2      ) & 0xff] & 0x000000ff) ^
    		rk[3];
    	PUTU32(ct + 12, s3);
    }
    
    void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) {
    	u32 s0, s1, s2, s3, t0, t1, t2, t3;
    #ifndef FULL_UNROLL
        int r;
    #endif /* ?FULL_UNROLL */
    
        /*
    	 * map byte array block to cipher state
    	 * and add initial round key:
    	 */
        s0 = GETU32(ct     ) ^ rk[0];
        s1 = GETU32(ct +  4) ^ rk[1];
        s2 = GETU32(ct +  8) ^ rk[2];
        s3 = GETU32(ct + 12) ^ rk[3];
    #ifdef FULL_UNROLL
        /* round 1: */
        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
        /* round 2: */
        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
        /* round 3: */
        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
        /* round 4: */
        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
        /* round 5: */
        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
        /* round 6: */
        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
        /* round 7: */
        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
        /* round 8: */
        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
        /* round 9: */
        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
        if (Nr > 10) {
            /* round 10: */
            s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
            s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
            s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
            s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
            /* round 11: */
            t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
            t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
            t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
            t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
            if (Nr > 12) {
                /* round 12: */
                s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
                s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
                s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
                s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
                /* round 13: */
                t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
                t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
                t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
                t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
            }
        }
    	rk += Nr << 2;
    #else  /* !FULL_UNROLL */
        /*
         * Nr - 1 full rounds:
         */
        r = Nr >> 1;
        for (;;) {
            t0 =
                Td0[(s0 >> 24)       ] ^
                Td1[(s3 >> 16) & 0xff] ^
                Td2[(s2 >>  8) & 0xff] ^
                Td3[(s1      ) & 0xff] ^
                rk[4];
            t1 =
                Td0[(s1 >> 24)       ] ^
                Td1[(s0 >> 16) & 0xff] ^
                Td2[(s3 >>  8) & 0xff] ^
                Td3[(s2      ) & 0xff] ^
                rk[5];
            t2 =
                Td0[(s2 >> 24)       ] ^
                Td1[(s1 >> 16) & 0xff] ^
                Td2[(s0 >>  8) & 0xff] ^
                Td3[(s3      ) & 0xff] ^
                rk[6];
            t3 =
                Td0[(s3 >> 24)       ] ^
                Td1[(s2 >> 16) & 0xff] ^
                Td2[(s1 >>  8) & 0xff] ^
                Td3[(s0      ) & 0xff] ^
                rk[7];
    
            rk += 8;
            if (--r == 0) {
                break;
            }
    
            s0 =
                Td0[(t0 >> 24)       ] ^
                Td1[(t3 >> 16) & 0xff] ^
                Td2[(t2 >>  8) & 0xff] ^
                Td3[(t1      ) & 0xff] ^
                rk[0];
            s1 =
                Td0[(t1 >> 24)       ] ^
                Td1[(t0 >> 16) & 0xff] ^
                Td2[(t3 >>  8) & 0xff] ^
                Td3[(t2      ) & 0xff] ^
                rk[1];
            s2 =
                Td0[(t2 >> 24)       ] ^
                Td1[(t1 >> 16) & 0xff] ^
                Td2[(t0 >>  8) & 0xff] ^
                Td3[(t3      ) & 0xff] ^
                rk[2];
            s3 =
                Td0[(t3 >> 24)       ] ^
                Td1[(t2 >> 16) & 0xff] ^
                Td2[(t1 >>  8) & 0xff] ^
                Td3[(t0      ) & 0xff] ^
                rk[3];
        }
    #endif /* ?FULL_UNROLL */
        /*
    	 * apply last round and
    	 * map cipher state to byte array block:
    	 */
       	s0 =
       		(Td4[(t0 >> 24)       ] & 0xff000000) ^
       		(Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
       		(Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
       		(Td4[(t1      ) & 0xff] & 0x000000ff) ^
       		rk[0];
    	PUTU32(pt     , s0);
       	s1 =
       		(Td4[(t1 >> 24)       ] & 0xff000000) ^
       		(Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
       		(Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
       		(Td4[(t2      ) & 0xff] & 0x000000ff) ^
       		rk[1];
    	PUTU32(pt +  4, s1);
       	s2 =
       		(Td4[(t2 >> 24)       ] & 0xff000000) ^
       		(Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
       		(Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
       		(Td4[(t3      ) & 0xff] & 0x000000ff) ^
       		rk[2];
    	PUTU32(pt +  8, s2);
       	s3 =
       		(Td4[(t3 >> 24)       ] & 0xff000000) ^
       		(Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
       		(Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
       		(Td4[(t0      ) & 0xff] & 0x000000ff) ^
       		rk[3];
    	PUTU32(pt + 12, s3);
    }
    
    #ifdef INTERMEDIATE_VALUE_KAT
    
    void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) {
    	int r;
    	u32 s0, s1, s2, s3, t0, t1, t2, t3;
    
        /*
    	 * map byte array block to cipher state
    	 * and add initial round key:
    	 */
    	s0 = GETU32(block     ) ^ rk[0];
    	s1 = GETU32(block +  4) ^ rk[1];
    	s2 = GETU32(block +  8) ^ rk[2];
    	s3 = GETU32(block + 12) ^ rk[3];
        rk += 4;
    
        /*
    	 * Nr - 1 full rounds:
    	 */
    	for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) {
    		t0 =
    			Te0[(s0 >> 24)       ] ^
    			Te1[(s1 >> 16) & 0xff] ^
    			Te2[(s2 >>  8) & 0xff] ^
    			Te3[(s3      ) & 0xff] ^
    			rk[0];
    		t1 =
    			Te0[(s1 >> 24)       ] ^
    			Te1[(s2 >> 16) & 0xff] ^
    			Te2[(s3 >>  8) & 0xff] ^
    			Te3[(s0      ) & 0xff] ^
    			rk[1];
    		t2 =
    			Te0[(s2 >> 24)       ] ^
    			Te1[(s3 >> 16) & 0xff] ^
    			Te2[(s0 >>  8) & 0xff] ^
    			Te3[(s1      ) & 0xff] ^
    			rk[2];
    		t3 =
    			Te0[(s3 >> 24)       ] ^
    			Te1[(s0 >> 16) & 0xff] ^
    			Te2[(s1 >>  8) & 0xff] ^
    			Te3[(s2      ) & 0xff] ^
    			rk[3];
    
    		s0 = t0;
    		s1 = t1;
    		s2 = t2;
    		s3 = t3;
    		rk += 4;
    
        }
    
        /*
    	 * apply last round and
    	 * map cipher state to byte array block:
    	 */
    	if (rounds == Nr) {
        	t0 =
        		(Te4[(s0 >> 24)       ] & 0xff000000) ^
        		(Te4[(s1 >> 16) & 0xff] & 0x00ff0000) ^
        		(Te4[(s2 >>  8) & 0xff] & 0x0000ff00) ^
        		(Te4[(s3      ) & 0xff] & 0x000000ff) ^
        		rk[0];
        	t1 =
        		(Te4[(s1 >> 24)       ] & 0xff000000) ^
        		(Te4[(s2 >> 16) & 0xff] & 0x00ff0000) ^
        		(Te4[(s3 >>  8) & 0xff] & 0x0000ff00) ^
        		(Te4[(s0      ) & 0xff] & 0x000000ff) ^
        		rk[1];
        	t2 =
        		(Te4[(s2 >> 24)       ] & 0xff000000) ^
        		(Te4[(s3 >> 16) & 0xff] & 0x00ff0000) ^
        		(Te4[(s0 >>  8) & 0xff] & 0x0000ff00) ^
        		(Te4[(s1      ) & 0xff] & 0x000000ff) ^
        		rk[2];
        	t3 =
        		(Te4[(s3 >> 24)       ] & 0xff000000) ^
        		(Te4[(s0 >> 16) & 0xff] & 0x00ff0000) ^
        		(Te4[(s1 >>  8) & 0xff] & 0x0000ff00) ^
        		(Te4[(s2      ) & 0xff] & 0x000000ff) ^
        		rk[3];
    		
    		s0 = t0;
    		s1 = t1;
    		s2 = t2;
    		s3 = t3;
    	}
    
    	PUTU32(block     , s0);
    	PUTU32(block +  4, s1);
    	PUTU32(block +  8, s2);
    	PUTU32(block + 12, s3);
    }
    
    void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) {
    	int r;
    	u32 s0, s1, s2, s3, t0, t1, t2, t3;
    
        /*
    	 * map byte array block to cipher state
    	 * and add initial round key:
    	 */
    	s0 = GETU32(block     ) ^ rk[0];
    	s1 = GETU32(block +  4) ^ rk[1];
    	s2 = GETU32(block +  8) ^ rk[2];
    	s3 = GETU32(block + 12) ^ rk[3];
        rk += 4;
    
        /*
    	 * Nr - 1 full rounds:
    	 */
    	for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) {
    		t0 =
    			Td0[(s0 >> 24)       ] ^
    			Td1[(s3 >> 16) & 0xff] ^
    			Td2[(s2 >>  8) & 0xff] ^
    			Td3[(s1      ) & 0xff] ^
    			rk[0];
    		t1 =
    			Td0[(s1 >> 24)       ] ^
    			Td1[(s0 >> 16) & 0xff] ^
    			Td2[(s3 >>  8) & 0xff] ^
    			Td3[(s2      ) & 0xff] ^
    			rk[1];
    		t2 =
    			Td0[(s2 >> 24)       ] ^
    			Td1[(s1 >> 16) & 0xff] ^
    			Td2[(s0 >>  8) & 0xff] ^
    			Td3[(s3      ) & 0xff] ^
    			rk[2];
    		t3 =
    			Td0[(s3 >> 24)       ] ^
    			Td1[(s2 >> 16) & 0xff] ^
    			Td2[(s1 >>  8) & 0xff] ^
    			Td3[(s0      ) & 0xff] ^
    			rk[3];
    
    		s0 = t0;
    		s1 = t1;
    		s2 = t2;
    		s3 = t3;
    		rk += 4;
    
        }
    
        /*
    	 * complete the last round and
    	 * map cipher state to byte array block:
    	 */
    	t0 =
    		(Td4[(s0 >> 24)       ] & 0xff000000) ^
    		(Td4[(s3 >> 16) & 0xff] & 0x00ff0000) ^
    		(Td4[(s2 >>  8) & 0xff] & 0x0000ff00) ^
    		(Td4[(s1      ) & 0xff] & 0x000000ff);
    	t1 =
    		(Td4[(s1 >> 24)       ] & 0xff000000) ^
    		(Td4[(s0 >> 16) & 0xff] & 0x00ff0000) ^
    		(Td4[(s3 >>  8) & 0xff] & 0x0000ff00) ^
    		(Td4[(s2      ) & 0xff] & 0x000000ff);
    	t2 =
    		(Td4[(s2 >> 24)       ] & 0xff000000) ^
    		(Td4[(s1 >> 16) & 0xff] & 0x00ff0000) ^
    		(Td4[(s0 >>  8) & 0xff] & 0x0000ff00) ^
    		(Td4[(s3      ) & 0xff] & 0x000000ff);
    	t3 =
    		(Td4[(s3 >> 24)       ] & 0xff000000) ^
    		(Td4[(s2 >> 16) & 0xff] & 0x00ff0000) ^
    		(Td4[(s1 >>  8) & 0xff] & 0x0000ff00) ^
    		(Td4[(s0      ) & 0xff] & 0x000000ff);
    
    	if (rounds == Nr) {
    	    t0 ^= rk[0];
    	    t1 ^= rk[1];
    	    t2 ^= rk[2];
    	    t3 ^= rk[3];
    	}
    
    	PUTU32(block     , t0);
    	PUTU32(block +  4, t1);
    	PUTU32(block +  8, t2);
    	PUTU32(block + 12, t3);
    }
    
    #endif /* INTERMEDIATE_VALUE_KAT */
    Code:
    /**
     * rijndael-alg-fst.h
     *
     * @version 3.0 (December 2000)
     *
     * Optimised ANSI C code for the Rijndael cipher (now AES)
     *
     * @author Vincent Rijmen <[email protected]>
     * @author Antoon Bosselaers <[email protected]>
     * @author Paulo Barreto <[email protected]>
     *
     * This code is hereby placed in the public domain.
     *
     * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    #ifndef __RIJNDAEL_ALG_FST_H
    #define __RIJNDAEL_ALG_FST_H
    
    #define MAXKC	(256/32)
    #define MAXKB	(256/8)
    #define MAXNR	14
    
    typedef unsigned char	u8;	
    typedef unsigned short	u16;	
    typedef unsigned int	u32;
    
    int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
    int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
    void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]);
    void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]);
    
    #ifdef INTERMEDIATE_VALUE_KAT
    void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds);
    void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds);
    #endif /* INTERMEDIATE_VALUE_KAT */
    
    #endif /* __RIJNDAEL_ALG_FST_H */




    Code:
    /**
     * rijndael-api-fst.c
     *
     * @version 2.9 (December 2000)
     *
     * Optimised ANSI C code for the Rijndael cipher (now AES)
     *
     * @author Vincent Rijmen <[email protected]>
     * @author Antoon Bosselaers <[email protected]>
     * @author Paulo Barreto <[email protected]>
     *
     * This code is hereby placed in the public domain.
     *
     * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     * Acknowledgements:
     *
     * We are deeply indebted to the following people for their bug reports,
     * fixes, and improvement suggestions to this implementation. Though we
     * tried to list all contributions, we apologise in advance for any
     * missing reference.
     *
     * Andrew Bales <[email protected]>
     * Markus Friedl <[email protected]>
     * John Skodon <[email protected]>
     */
    
    #include <assert.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include "rijndael-alg-fst.h"
    #include "rijndael-api-fst.h"
    
    int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) {
    	int i;
    	char *keyMat;
    	u8 cipherKey[MAXKB];
    	
    	if (key == NULL) {
    		return BAD_KEY_INSTANCE;
    	}
    
    	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
    		key->direction = direction;
    	} else {
    		return BAD_KEY_DIR;
    	}
    
    	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
    		key->keyLen = keyLen;
    	} else {
    		return BAD_KEY_MAT;
    	}
    
    	if (keyMaterial != NULL) {
    		strncpy(key->keyMaterial, keyMaterial, keyLen/4);
    	}
    
    	/* initialize key schedule: */
    	keyMat = key->keyMaterial;
     	for (i = 0; i < key->keyLen/8; i++) {
    		int t, v;
    
    		t = *keyMat++;
    		if ((t >= '0') && (t <= '9')) v = (t - '0') << 4;
    		else if ((t >= 'a') && (t <= 'f')) v = (t - 'a' + 10) << 4;
    		else if ((t >= 'A') && (t <= 'F')) v = (t - 'A' + 10) << 4;
    		else return BAD_KEY_MAT;
    		
    		t = *keyMat++;
    		if ((t >= '0') && (t <= '9')) v ^= (t - '0');
    		else if ((t >= 'a') && (t <= 'f')) v ^= (t - 'a' + 10);
    		else if ((t >= 'A') && (t <= 'F')) v ^= (t - 'A' + 10);
    		else return BAD_KEY_MAT;
    		
    		cipherKey[i] = (u8)v;
    	}
    	if (direction == DIR_ENCRYPT) {
    		key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
    	} else {
    		key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
    	}
    	rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
    	return TRUE;
    }
    
    int cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
    	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
    		cipher->mode = mode;
    	} else {
    		return BAD_CIPHER_MODE;
    	}
    	if (IV != NULL) {
    		int i;
     		for (i = 0; i < MAX_IV_SIZE; i++) {
    			int t, j;
    
    			t = IV[2*i];
    			if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
    			else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
    			else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
    			else return BAD_CIPHER_INSTANCE;
    		
    			t = IV[2*i+1];
    			if ((t >= '0') && (t <= '9')) j ^= (t - '0');
    			else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
    			else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
    			else return BAD_CIPHER_INSTANCE;
    			
    			cipher->IV[i] = (u8)j;
    		}
    	} else {
    		memset(cipher->IV, 0, MAX_IV_SIZE);
    	}
    	return TRUE;
    }
    
    int blockEncrypt(cipherInstance *cipher, keyInstance *key,
    		BYTE *input, int inputLen, BYTE *outBuffer) {
    	int i, k, t, numBlocks;
    	u8 block[16], *iv;
    
    	if (cipher == NULL ||
    		key == NULL ||
    		key->direction == DIR_DECRYPT) {
    		return BAD_CIPHER_STATE;
    	}
    	if (input == NULL || inputLen <= 0) {
    		return 0; /* nothing to do */
    	}
    
    	numBlocks = inputLen/128;
    	
    	switch (cipher->mode) {
    	case MODE_ECB:
    		for (i = numBlocks; i > 0; i--) {
    			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
    			input += 16;
    			outBuffer += 16;
    		}
    		break;
    		
    	case MODE_CBC:
    		iv = cipher->IV;
    		for (i = numBlocks; i > 0; i--) {
    			((u32*)block)[0] = ((u32*)input)[0] ^ ((u32*)iv)[0];
    			((u32*)block)[1] = ((u32*)input)[1] ^ ((u32*)iv)[1];
    			((u32*)block)[2] = ((u32*)input)[2] ^ ((u32*)iv)[2];
    			((u32*)block)[3] = ((u32*)input)[3] ^ ((u32*)iv)[3];
    			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
    			iv = outBuffer;
    			input += 16;
    			outBuffer += 16;
    		}
    		break;
    
        case MODE_CFB1:
    		iv = cipher->IV;
            for (i = numBlocks; i > 0; i--) {
    			memcpy(outBuffer, input, 16);
                for (k = 0; k < 128; k++) {
    				rijndaelEncrypt(key->ek, key->Nr, iv, block);
                    outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
                    for (t = 0; t < 15; t++) {
                    	iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
                    }
                   	iv[15] = (iv[15] << 1) | ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
                }
                outBuffer += 16;
                input += 16;
            }
            break;
    
    	default:
    		return BAD_CIPHER_STATE;
    	}
    	
    	return 128*numBlocks;
    }
    
    /**
     * Encrypt data partitioned in octets, using RFC 2040-like padding.
     *
     * @param   input           data to be encrypted (octet sequence)
     * @param   inputOctets		input length in octets (not bits)
     * @param   outBuffer       encrypted output data
     *
     * @return	length in octets (not bits) of the encrypted output buffer.
     */
    int padEncrypt(cipherInstance *cipher, keyInstance *key,
    		BYTE *input, int inputOctets, BYTE *outBuffer) {
    	int i, numBlocks, padLen;
    	u8 block[16], *iv;
    
    	if (cipher == NULL ||
    		key == NULL ||
    		key->direction == DIR_DECRYPT) {
    		return BAD_CIPHER_STATE;
    	}
    	if (input == NULL || inputOctets <= 0) {
    		return 0; /* nothing to do */
    	}
    
    	numBlocks = inputOctets/16;
    
    	switch (cipher->mode) {
    	case MODE_ECB:
    		for (i = numBlocks; i > 0; i--) {
    			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
    			input += 16;
    			outBuffer += 16;
    		}
    		padLen = 16 - (inputOctets - 16*numBlocks);
    		assert(padLen > 0 && padLen <= 16);
    		memcpy(block, input, 16 - padLen);
    		memset(block + 16 - padLen, padLen, padLen);
    		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
    		break;
    
    	case MODE_CBC:
    		iv = cipher->IV;
    		for (i = numBlocks; i > 0; i--) {
    			((u32*)block)[0] = ((u32*)input)[0] ^ ((u32*)iv)[0];
    			((u32*)block)[1] = ((u32*)input)[1] ^ ((u32*)iv)[1];
    			((u32*)block)[2] = ((u32*)input)[2] ^ ((u32*)iv)[2];
    			((u32*)block)[3] = ((u32*)input)[3] ^ ((u32*)iv)[3];
    			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
    			iv = outBuffer;
    			input += 16;
    			outBuffer += 16;
    		}
    		padLen = 16 - (inputOctets - 16*numBlocks);
    		assert(padLen > 0 && padLen <= 16);
    		for (i = 0; i < 16 - padLen; i++) {
    			block[i] = input[i] ^ iv[i];
    		}
    		for (i = 16 - padLen; i < 16; i++) {
    			block[i] = (BYTE)padLen ^ iv[i];
    		}
    		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
    		break;
    
    	default:
    		return BAD_CIPHER_STATE;
    	}
    
    	return 16*(numBlocks + 1);
    }
    
    int blockDecrypt(cipherInstance *cipher, keyInstance *key,
    		BYTE *input, int inputLen, BYTE *outBuffer) {
    	int i, k, t, numBlocks;
    	u8 block[16], *iv;
    
    	if (cipher == NULL ||
    		key == NULL ||
    		cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT) {
    		return BAD_CIPHER_STATE;
    	}
    	if (input == NULL || inputLen <= 0) {
    		return 0; /* nothing to do */
    	}
    
    	numBlocks = inputLen/128;
    
    	switch (cipher->mode) {
    	case MODE_ECB:
    		for (i = numBlocks; i > 0; i--) {
    			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
    			input += 16;
    			outBuffer += 16;
    		}
    		break;
    		
    	case MODE_CBC:
    		iv = cipher->IV;
    		for (i = numBlocks; i > 0; i--) {
    			rijndaelDecrypt(key->rk, key->Nr, input, block);
    			((u32*)block)[0] ^= ((u32*)iv)[0];
    			((u32*)block)[1] ^= ((u32*)iv)[1];
    			((u32*)block)[2] ^= ((u32*)iv)[2];
    			((u32*)block)[3] ^= ((u32*)iv)[3];
    			memcpy(cipher->IV, input, 16);
    			memcpy(outBuffer, block, 16);
    			input += 16;
    			outBuffer += 16;
    		}
    		break;
    
        case MODE_CFB1:
    		iv = cipher->IV;
            for (i = numBlocks; i > 0; i--) {
    			memcpy(outBuffer, input, 16);
                for (k = 0; k < 128; k++) {
    				rijndaelEncrypt(key->ek, key->Nr, iv, block);
                    for (t = 0; t < 15; t++) {
                    	iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
                    }
                   	iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1);
                    outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
                }
                outBuffer += 16;
                input += 16;
            }
            break;
    
    	default:
    		return BAD_CIPHER_STATE;
    	}
    	
    	return 128*numBlocks;
    }
    
    int padDecrypt(cipherInstance *cipher, keyInstance *key,
    		BYTE *input, int inputOctets, BYTE *outBuffer) {
    	int i, numBlocks, padLen;
    	u8 block[16];
    
    	if (cipher == NULL ||
    		key == NULL ||
    		key->direction == DIR_ENCRYPT) {
    		return BAD_CIPHER_STATE;
    	}
    	if (input == NULL || inputOctets <= 0) {
    		return 0; /* nothing to do */
    	}
    	if (inputOctets % 16 != 0) {
    		return BAD_DATA;
    	}
    
    	numBlocks = inputOctets/16;
    
    	switch (cipher->mode) {
    	case MODE_ECB:
    		/* all blocks but last */
    		for (i = numBlocks - 1; i > 0; i--) {
    			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
    			input += 16;
    			outBuffer += 16;
    		}
    		/* last block */
    		rijndaelDecrypt(key->rk, key->Nr, input, block);
    		padLen = block[15];
    		if (padLen >= 16) {
    			return BAD_DATA;
    		}
    		for (i = 16 - padLen; i < 16; i++) {
    			if (block[i] != padLen) {
    				return BAD_DATA;
    			}
    		}
    		memcpy(outBuffer, block, 16 - padLen);
    		break;
    		
    	case MODE_CBC:
    		/* all blocks but last */
    		for (i = numBlocks - 1; i > 0; i--) {
    			rijndaelDecrypt(key->rk, key->Nr, input, block);
    			((u32*)block)[0] ^= ((u32*)cipher->IV)[0];
    			((u32*)block)[1] ^= ((u32*)cipher->IV)[1];
    			((u32*)block)[2] ^= ((u32*)cipher->IV)[2];
    			((u32*)block)[3] ^= ((u32*)cipher->IV)[3];
    			memcpy(cipher->IV, input, 16);
    			memcpy(outBuffer, block, 16);
    			input += 16;
    			outBuffer += 16;
    		}
    		/* last block */
    		rijndaelDecrypt(key->rk, key->Nr, input, block);
    		((u32*)block)[0] ^= ((u32*)cipher->IV)[0];
    		((u32*)block)[1] ^= ((u32*)cipher->IV)[1];
    		((u32*)block)[2] ^= ((u32*)cipher->IV)[2];
    		((u32*)block)[3] ^= ((u32*)cipher->IV)[3];
    		padLen = block[15];
    		if (padLen <= 0 || padLen > 16) {
    			return BAD_DATA;
    		}
    		for (i = 16 - padLen; i < 16; i++) {
    			if (block[i] != padLen) {
    				return BAD_DATA;
    			}
    		}
    		memcpy(outBuffer, block, 16 - padLen);
    		break;
    	
    	default:
    		return BAD_CIPHER_STATE;
    	}
    	
    	return 16*numBlocks - padLen;
    }
    
    #ifdef INTERMEDIATE_VALUE_KAT
    /**
     *	cipherUpdateRounds:
     *
     *	Encrypts/Decrypts exactly one full block a specified number of rounds.
     *	Only used in the Intermediate Value Known Answer Test.	
     *
     *	Returns:
     *		TRUE - on success
     *		BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
     */
    int cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
    		BYTE *input, int inputLen, BYTE *outBuffer, int rounds) {
    	u8 block[16];
    
    	if (cipher == NULL || key == NULL) {
    		return BAD_CIPHER_STATE;
    	}
    
    	memcpy(block, input, 16);
    
    	switch (key->direction) {
    	case DIR_ENCRYPT:
    		rijndaelEncryptRound(key->rk, key->Nr, block, rounds);
    		break;
    		
    	case DIR_DECRYPT:
    		rijndaelDecryptRound(key->rk, key->Nr, block, rounds);
    		break;
    		
    	default:
    		return BAD_KEY_DIR;
    	} 
    
    	memcpy(outBuffer, block, 16);
    	
    	return TRUE;
    }
    #endif /* INTERMEDIATE_VALUE_KAT */

    Code:
    /**
     * rijndael-api-fst.h
     *
     * @version 2.9 (December 2000)
     *
     * Optimised ANSI C code for the Rijndael cipher (now AES)
     *
     * @author Vincent Rijmen <[email protected]>
     * @author Antoon Bosselaers <[email protected]>
     * @author Paulo Barreto <[email protected]>
     *
     * This code is hereby placed in the public domain.
     *
     * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     * Acknowledgements:
     *
     * We are deeply indebted to the following people for their bug reports,
     * fixes, and improvement suggestions to this implementation. Though we
     * tried to list all contributions, we apologise in advance for any
     * missing reference.
     *
     * Andrew Bales <[email protected]>
     * Markus Friedl <[email protected]>
     * John Skodon <[email protected]>
     */
    
    #ifndef __RIJNDAEL_API_FST_H
    #define __RIJNDAEL_API_FST_H
    
    #include <stdio.h>
    #include "rijndael-alg-fst.h"
    
    /*  Generic Defines  */
    #define     DIR_ENCRYPT           0 /*  Are we encrpyting?  */
    #define     DIR_DECRYPT           1 /*  Are we decrpyting?  */
    #define     MODE_ECB              1 /*  Are we ciphering in ECB mode?   */
    #define     MODE_CBC              2 /*  Are we ciphering in CBC mode?   */
    #define     MODE_CFB1             3 /*  Are we ciphering in 1-bit CFB mode? */
    #define     TRUE                  1
    #define     FALSE                 0
    #define     BITSPERBLOCK        128 /* Default number of bits in a cipher block */
    
    /*  Error Codes  */
    #define     BAD_KEY_DIR          -1 /*  Key direction is invalid, e.g., unknown value */
    #define     BAD_KEY_MAT          -2 /*  Key material not of correct length */
    #define     BAD_KEY_INSTANCE     -3 /*  Key passed is not valid */
    #define     BAD_CIPHER_MODE      -4 /*  Params struct passed to cipherInit invalid */
    #define     BAD_CIPHER_STATE     -5 /*  Cipher in wrong state (e.g., not initialized) */
    #define     BAD_BLOCK_LENGTH     -6
    #define     BAD_CIPHER_INSTANCE  -7
    #define     BAD_DATA             -8 /*  Data contents are invalid, e.g., invalid padding */
    #define     BAD_OTHER            -9 /*  Unknown error */
    
    /*  Algorithm-specific Defines  */
    #define     MAX_KEY_SIZE         64 /* # of ASCII char's needed to represent a key */
    #define     MAX_IV_SIZE          16 /* # bytes needed to represent an IV  */
    
    /*  Typedefs  */
    
    typedef unsigned char   BYTE;
    
    /*  The structure for key information */
    typedef struct {
        BYTE  direction;                /* Key used for encrypting or decrypting? */
        int   keyLen;                   /* Length of the key  */
        char  keyMaterial[MAX_KEY_SIZE+1];  /* Raw key data in ASCII, e.g., user input or KAT values */
    	int   Nr;                       /* key-length-dependent number of rounds */
    	u32   rk[4*(MAXNR + 1)];        /* key schedule */
    	u32   ek[4*(MAXNR + 1)];        /* CFB1 key schedule (encryption only) */
    } keyInstance;
    
    /*  The structure for cipher information */
    typedef struct {                    /* changed order of the components */
        BYTE  mode;                     /* MODE_ECB, MODE_CBC, or MODE_CFB1 */
        BYTE  IV[MAX_IV_SIZE];          /* A possible Initialization Vector for ciphering */
    } cipherInstance;
    
    /*  Function prototypes  */
    
    int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial);
    
    int cipherInit(cipherInstance *cipher, BYTE mode, char *IV);
    
    int blockEncrypt(cipherInstance *cipher, keyInstance *key,
            BYTE *input, int inputLen, BYTE *outBuffer);
    
    int padEncrypt(cipherInstance *cipher, keyInstance *key,
    		BYTE *input, int inputOctets, BYTE *outBuffer);
    
    int blockDecrypt(cipherInstance *cipher, keyInstance *key,
            BYTE *input, int inputLen, BYTE *outBuffer);
    
    int padDecrypt(cipherInstance *cipher, keyInstance *key,
    		BYTE *input, int inputOctets, BYTE *outBuffer);
    
    #ifdef INTERMEDIATE_VALUE_KAT
    int cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
            BYTE *input, int inputLen, BYTE *outBuffer, int Rounds);
    #endif /* INTERMEDIATE_VALUE_KAT */
    
    #endif /* __RIJNDAEL_API_FST_H */




    Best regards...

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Do you have an actual question, or are you just going to keep flooding the board with other peoples code?

    Have you practiced using the code on your PC before making life harder and putting it on your embedded controller?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Oct 2006
    Posts
    8
    Of course, I have practiced two codes above, but I could not run them. And i don`t know how i can put plaintext data to code.

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    ./a.out

    Now run along.


    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    Oct 2006
    Posts
    8
    Quote Originally Posted by quzah
    ./a.out

    Now run along.


    Quzah.
    pardon? I couldn`t understand ./a.? What is ./a.?

  10. #10
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    Just how proficient in C are you? It would be very easy for anyone reasonably proficient in C to resolve all the syntactical issues needed to convert the above C++ hack into plain vanilla C. The C++ hack that I posted above came from my Rijndael class. Thus, the need for conversion. I did verify this code by using it to communicate with a networked security controller prior to posting it. So, it does work as a 128 bit Electronic Code Book (ECB) Rijndael implementation.

    I've also just converted the code to plain vanilla C and tested it to verify that it does work. I could be persuaded to email you the plain vanilla C but I just don't have the time nor the inclination to deal with a lot of noob questions such as how to input plaintext into the encryption function. In other words, the code is yours but I'm not available for any additional support and I don't want to clutter this thead with a another humongous post.

    BTW, your posting is missing at least one cipher function. ... It needs a lot of work.

    PM me with your email for the source code and be on your way.

    EDIT: FYI... to input plain text make the following change. I think you're confused by the string of hex values.
    Code:
    change
     char szDataIn1[81] = "0xFF-0xE3-0x22-0xDE-0x57-0xF7-0x89-0xE6-0x55-0xE7-0x0D-0xA3-0x34-0x4F-0xDD-0x42";
    to
      char szDataIn[33] = "Hello Gumit, How are you today??"; // plain text
    Last edited by BobS0327; 10-15-2006 at 08:14 PM.

  11. #11
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    How can i plaintext data in the below code?
    Code:
    //Module name test.c
    //Compile:
    //cl /DINTERMEDIATE_VALUE_KAT /DTRACE_KAT_MCT test.c rijndael-alg-fst.c rijndael-api-fst.c
    
    #include <stdio.h>
    #include <string.h>
    #include "rijndael-api-fst.h"
    
    int main(void) {
        u8 input[16];
        u8 output[16];
        int i, keyLength = 128;
        keyInstance keyInst;
        BYTE keyMaterial[320];
        cipherInstance cipherInst;
        memset(keyMaterial, 0, sizeof (keyMaterial));
        for (i = 0; i < keyLength/8; i++) {
            sprintf(&keyMaterial[2*i], "%02X", i);
        }
        sprintf(input, "Gumit was here!!");
        /* encryption */
        makeKey(&keyInst, DIR_ENCRYPT, keyLength, keyMaterial);
        cipherInit(&cipherInst, MODE_ECB, NULL);
        blockEncrypt(&cipherInst, &keyInst, input, 128, output);
        /* decryption: */   
        makeKey(&keyInst, DIR_DECRYPT, keyLength, keyMaterial);
        cipherInit(&cipherInst, MODE_ECB, NULL);
        memset(input, 0, sizeof input);
        blockDecrypt(&cipherInst, &keyInst, output, 128, input);
        for (i = 0; i < 16; i++)
            printf("%c",input[i]);
        printf("\n");
        return 0;
    }

  12. #12
    Registered User
    Join Date
    Oct 2006
    Posts
    8
    Quote Originally Posted by BobS0327
    Code:
    //Module name test.c
    //Compile:
    //cl /DINTERMEDIATE_VALUE_KAT /DTRACE_KAT_MCT test.c rijndael-alg-fst.c rijndael-api-fst.c
    
    #include <stdio.h>
    #include <string.h>
    #include "rijndael-api-fst.h"
    
    int main(void) {
        u8 input[16];
        u8 output[16];
        int i, keyLength = 128;
        keyInstance keyInst;
        BYTE keyMaterial[320];
        cipherInstance cipherInst;
        memset(keyMaterial, 0, sizeof (keyMaterial));
        for (i = 0; i < keyLength/8; i++) {
            sprintf(&keyMaterial[2*i], "%02X", i);
        }
        sprintf(input, "Gumit was here!!");
        /* encryption */
        makeKey(&keyInst, DIR_ENCRYPT, keyLength, keyMaterial);
        cipherInit(&cipherInst, MODE_ECB, NULL);
        blockEncrypt(&cipherInst, &keyInst, input, 128, output);
        /* decryption: */   
        makeKey(&keyInst, DIR_DECRYPT, keyLength, keyMaterial);
        cipherInit(&cipherInst, MODE_ECB, NULL);
        memset(input, 0, sizeof input);
        blockDecrypt(&cipherInst, &keyInst, output, 128, input);
        for (i = 0; i < 16; i++)
            printf("%c",input[i]);
        printf("\n");
        return 0;
    }
    Hi,
    first so thanks for your helps.
    i have a question;
    Is the test.c that my sent file or your code? Are they same?

    Best regards...

  13. #13
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    Is the test.c that my sent file or your code? Are they same?
    No, they are not the same. I have taken the author's test file named Rijndael-test-fst.c and removed all the unecessary functions etc. This test file was just their proof that their implementation of Rijndael was highly optimized by using test vectors. I used what I needed from their various testing methods to do the Rijndael encryption and decryption. In other words, test.c is the "bare bones" version of Rijndael-test.fst.c. You still have to compile test.c with the author's other two Rijndael files, Rijndael-alg-fst.c and rijndael-api-fst.c since I used their implementation in a "bare bones" fashion to do the encrypt/decrypt stuff.
    Last edited by BobS0327; 10-21-2006 at 07:33 PM.

  14. #14
    Registered User
    Join Date
    Oct 2006
    Posts
    8
    Hi,

    Finally I have worked the code, .

    But I have a problem . I am trying upload the code to ST72f63BU6 microcontrollers that has 1k RAM. When I try working the code, it gives me overflow error. I don`t think so, that it costs much storage.

    How can i solve this problem?

    Regards...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. AES SubBytes step
    By zxcv in forum Tech Board
    Replies: 7
    Last Post: 11-02-2010, 12:22 PM
  2. AES Encryption error code.
    By deevrielk in forum C++ Programming
    Replies: 1
    Last Post: 06-30-2008, 08:37 PM
  3. aes mix columns
    By zxcv in forum C Programming
    Replies: 8
    Last Post: 01-04-2008, 03:28 PM
  4. OpenSSL AES library documentation
    By kronixx in forum C Programming
    Replies: 1
    Last Post: 11-21-2005, 12:24 PM
  5. AES encryption limitation
    By willc0de4food in forum C Programming
    Replies: 2
    Last Post: 10-20-2005, 01:48 PM