MakingThings
  • Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

aes.c

00001 /*********************************************************************************
00002 
00003  Copyright 2006-2008 MakingThings
00004 
00005  Licensed under the Apache License, 
00006  Version 2.0 (the "License"); you may not use this file except in compliance 
00007  with the License. You may obtain a copy of the License at
00008 
00009  http://www.apache.org/licenses/LICENSE-2.0 
00010  
00011  Unless required by applicable law or agreed to in writing, software distributed
00012  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
00013  CONDITIONS OF ANY KIND, either express or implied. See the License for
00014  the specific language governing permissions and limitations under the License.
00015 
00016 *********************************************************************************/
00017 
00018 #include "aes.h"
00019 #include <string.h>
00020 
00021 static int Aes_SetupEncrypt( unsigned long* rk, const unsigned char* key, int keybits);
00022 static int Aes_SetupDecrypt( unsigned long *rk, const unsigned char *key, int keybits);
00023 static void Aes_DoEncrypt( const unsigned long *rk, int nrounds, 
00024   const unsigned char plaintext[16], unsigned char ciphertext[16]);
00025 static void Aes_DoDecrypt( const unsigned long *rk, int nrounds,
00026   const unsigned char ciphertext[16], unsigned char plaintext[16]);
00027 
00028 #define FULL_UNROLL
00029 
00030 typedef unsigned long u32;
00031 typedef unsigned char u8;
00032 
00033 /** \defgroup aes AES (Advanced Encryption Standard)
00034   Encrypt and decrypt data using AES.
00035 
00036   AES is a block cipher adopted for use by the NSA (US government agency).  According to Wikipedia,
00037   "This marks the first time the public has had access to a cipher approved by the NSA for
00038   top secret information."  Pretty cool, right?  This is a good way to send info privately
00039   from your Make Controller over the network, to a web server for example.
00040 
00041   AES requires that both sides of communication have access to the same key.  So both your Make 
00042   Controller, and whatever other device it's communicating with need to know about the same 
00043   password so they can decrypt data that has been encrypted by the other.
00044 
00045   There are several different flavors of AES.  There are two main ways in which AES libraries
00046   differ:
00047   - the way they chain blocks
00048   - the way they pad data
00049 
00050   This library uses ECB (Electronic Code Book) chaining, and pads data with a character 
00051   that corresponds to the number of bytes needed to pad to 16.  Check the Wikipedia article
00052   for an explanation - http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
00053 
00054   The lookup tables used in this library will use somewhere between 8 and 13 kB of program space, 
00055   depending on the compiler optimization you use.  Memory usage is pretty minimal.
00056 
00057   Code is used and adapted from Philip J. Erdelsky - see http://www.efgh.com/software/rijndael.htm
00058   for the original.
00059 
00060   \ingroup Libraries
00061   @{
00062 */
00063 
00064 static const u32 Te0[256] =
00065 {
00066   0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
00067   0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
00068   0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
00069   0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
00070   0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
00071   0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
00072   0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
00073   0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
00074   0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
00075   0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
00076   0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
00077   0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
00078   0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
00079   0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
00080   0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
00081   0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
00082   0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
00083   0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
00084   0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
00085   0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
00086   0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
00087   0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
00088   0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
00089   0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
00090   0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
00091   0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
00092   0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
00093   0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
00094   0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
00095   0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
00096   0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
00097   0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
00098   0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
00099   0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
00100   0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
00101   0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
00102   0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
00103   0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
00104   0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
00105   0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
00106   0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
00107   0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
00108   0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
00109   0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
00110   0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
00111   0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
00112   0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
00113   0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
00114   0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
00115   0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
00116   0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
00117   0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
00118   0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
00119   0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
00120   0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
00121   0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
00122   0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
00123   0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
00124   0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
00125   0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
00126   0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
00127   0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
00128   0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
00129   0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
00130 };
00131 
00132 static const u32 Te1[256] =
00133 {
00134   0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
00135   0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
00136   0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
00137   0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
00138   0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
00139   0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
00140   0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
00141   0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
00142   0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
00143   0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
00144   0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
00145   0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
00146   0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
00147   0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
00148   0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
00149   0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
00150   0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
00151   0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
00152   0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
00153   0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
00154   0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
00155   0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
00156   0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
00157   0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
00158   0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
00159   0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
00160   0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
00161   0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
00162   0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
00163   0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
00164   0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
00165   0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
00166   0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
00167   0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
00168   0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
00169   0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
00170   0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
00171   0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
00172   0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
00173   0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
00174   0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
00175   0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
00176   0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
00177   0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
00178   0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
00179   0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
00180   0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
00181   0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
00182   0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
00183   0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
00184   0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
00185   0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
00186   0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
00187   0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
00188   0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
00189   0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
00190   0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
00191   0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
00192   0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
00193   0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
00194   0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
00195   0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
00196   0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
00197   0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
00198 };
00199 
00200 static const u32 Te2[256] =
00201 {
00202   0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
00203   0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
00204   0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
00205   0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
00206   0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
00207   0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
00208   0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
00209   0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
00210   0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
00211   0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
00212   0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
00213   0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
00214   0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
00215   0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
00216   0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
00217   0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
00218   0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
00219   0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
00220   0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
00221   0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
00222   0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
00223   0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
00224   0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
00225   0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
00226   0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
00227   0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
00228   0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
00229   0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
00230   0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
00231   0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
00232   0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
00233   0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
00234   0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
00235   0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
00236   0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
00237   0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
00238   0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
00239   0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
00240   0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
00241   0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
00242   0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
00243   0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
00244   0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
00245   0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
00246   0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
00247   0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
00248   0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
00249   0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
00250   0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
00251   0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
00252   0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
00253   0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
00254   0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
00255   0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
00256   0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
00257   0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
00258   0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
00259   0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
00260   0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
00261   0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
00262   0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
00263   0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
00264   0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
00265   0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
00266 };
00267 
00268 static const u32 Te3[256] =
00269 {
00270   0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
00271   0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
00272   0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
00273   0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
00274   0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
00275   0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
00276   0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
00277   0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
00278   0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
00279   0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
00280   0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
00281   0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
00282   0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
00283   0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
00284   0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
00285   0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
00286   0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
00287   0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
00288   0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
00289   0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
00290   0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
00291   0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
00292   0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
00293   0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
00294   0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
00295   0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
00296   0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
00297   0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
00298   0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
00299   0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
00300   0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
00301   0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
00302   0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
00303   0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
00304   0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
00305   0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
00306   0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
00307   0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
00308   0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
00309   0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
00310   0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
00311   0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
00312   0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
00313   0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
00314   0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
00315   0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
00316   0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
00317   0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
00318   0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
00319   0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
00320   0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
00321   0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
00322   0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
00323   0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
00324   0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
00325   0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
00326   0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
00327   0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
00328   0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
00329   0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
00330   0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
00331   0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
00332   0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
00333   0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
00334 };
00335 
00336 static const u32 Te4[256] =
00337 {
00338   0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
00339   0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
00340   0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
00341   0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
00342   0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
00343   0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
00344   0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
00345   0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
00346   0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
00347   0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
00348   0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
00349   0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
00350   0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
00351   0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
00352   0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
00353   0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
00354   0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
00355   0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
00356   0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
00357   0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
00358   0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
00359   0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
00360   0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
00361   0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
00362   0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
00363   0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
00364   0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
00365   0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
00366   0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
00367   0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
00368   0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
00369   0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
00370   0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
00371   0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
00372   0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
00373   0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
00374   0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
00375   0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
00376   0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
00377   0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
00378   0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
00379   0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
00380   0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
00381   0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
00382   0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
00383   0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
00384   0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
00385   0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
00386   0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
00387   0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
00388   0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
00389   0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
00390   0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
00391   0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
00392   0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
00393   0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
00394   0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
00395   0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
00396   0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
00397   0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
00398   0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
00399   0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
00400   0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
00401   0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
00402 };
00403 
00404 static const u32 Td0[256] =
00405 {
00406   0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
00407   0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
00408   0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
00409   0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
00410   0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
00411   0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
00412   0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
00413   0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
00414   0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
00415   0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
00416   0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
00417   0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
00418   0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
00419   0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
00420   0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
00421   0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
00422   0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
00423   0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
00424   0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
00425   0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
00426   0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
00427   0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
00428   0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
00429   0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
00430   0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
00431   0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
00432   0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
00433   0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
00434   0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
00435   0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
00436   0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
00437   0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
00438   0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
00439   0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
00440   0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
00441   0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
00442   0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
00443   0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
00444   0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
00445   0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
00446   0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
00447   0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
00448   0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
00449   0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
00450   0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
00451   0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
00452   0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
00453   0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
00454   0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
00455   0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
00456   0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
00457   0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
00458   0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
00459   0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
00460   0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
00461   0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
00462   0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
00463   0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
00464   0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
00465   0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
00466   0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
00467   0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
00468   0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
00469   0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
00470 };
00471 
00472 static const u32 Td1[256] =
00473 {
00474   0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
00475   0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
00476   0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
00477   0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
00478   0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
00479   0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
00480   0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
00481   0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
00482   0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
00483   0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
00484   0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
00485   0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
00486   0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
00487   0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
00488   0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
00489   0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
00490   0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
00491   0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
00492   0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
00493   0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
00494   0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
00495   0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
00496   0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
00497   0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
00498   0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
00499   0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
00500   0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
00501   0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
00502   0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
00503   0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
00504   0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
00505   0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
00506   0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
00507   0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
00508   0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
00509   0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
00510   0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
00511   0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
00512   0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
00513   0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
00514   0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
00515   0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
00516   0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
00517   0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
00518   0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
00519   0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
00520   0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
00521   0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
00522   0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
00523   0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
00524   0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
00525   0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
00526   0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
00527   0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
00528   0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
00529   0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
00530   0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
00531   0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
00532   0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
00533   0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
00534   0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
00535   0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
00536   0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
00537   0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
00538 };
00539 
00540 static const u32 Td2[256] =
00541 {
00542   0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
00543   0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
00544   0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
00545   0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
00546   0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
00547   0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
00548   0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
00549   0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
00550   0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
00551   0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
00552   0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
00553   0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
00554   0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
00555   0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
00556   0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
00557   0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
00558   0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
00559   0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
00560   0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
00561   0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
00562   0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
00563   0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
00564   0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
00565   0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
00566   0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
00567   0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
00568   0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
00569   0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
00570   0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
00571   0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
00572   0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
00573   0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
00574   0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
00575   0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
00576   0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
00577   0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
00578   0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
00579   0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
00580   0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
00581   0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
00582   0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
00583   0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
00584   0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
00585   0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
00586   0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
00587   0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
00588   0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
00589   0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
00590   0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
00591   0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
00592   0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
00593   0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
00594   0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
00595   0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
00596   0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
00597   0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
00598   0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
00599   0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
00600   0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
00601   0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
00602   0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
00603   0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
00604   0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
00605   0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
00606 };
00607 
00608 static const u32 Td3[256] =
00609 {
00610   0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
00611   0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
00612   0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
00613   0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
00614   0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
00615   0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
00616   0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
00617   0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
00618   0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
00619   0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
00620   0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
00621   0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
00622   0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
00623   0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
00624   0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
00625   0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
00626   0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
00627   0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
00628   0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
00629   0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
00630   0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
00631   0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
00632   0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
00633   0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
00634   0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
00635   0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
00636   0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
00637   0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
00638   0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
00639   0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
00640   0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
00641   0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
00642   0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
00643   0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
00644   0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
00645   0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
00646   0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
00647   0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
00648   0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
00649   0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
00650   0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
00651   0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
00652   0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
00653   0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
00654   0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
00655   0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
00656   0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
00657   0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
00658   0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
00659   0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
00660   0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
00661   0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
00662   0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
00663   0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
00664   0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
00665   0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
00666   0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
00667   0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
00668   0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
00669   0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
00670   0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
00671   0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
00672   0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
00673   0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
00674 };
00675 
00676 static const u32 Td4[256] =
00677 {
00678   0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
00679   0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
00680   0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
00681   0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
00682   0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
00683   0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
00684   0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
00685   0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
00686   0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
00687   0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
00688   0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
00689   0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
00690   0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
00691   0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
00692   0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
00693   0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
00694   0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
00695   0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
00696   0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
00697   0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
00698   0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
00699   0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
00700   0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
00701   0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
00702   0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
00703   0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
00704   0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
00705   0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
00706   0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
00707   0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
00708   0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
00709   0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
00710   0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
00711   0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
00712   0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
00713   0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
00714   0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
00715   0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
00716   0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
00717   0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
00718   0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
00719   0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
00720   0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
00721   0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
00722   0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
00723   0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
00724   0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
00725   0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
00726   0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
00727   0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
00728   0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
00729   0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
00730   0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
00731   0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
00732   0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
00733   0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
00734   0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
00735   0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
00736   0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
00737   0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
00738   0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
00739   0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
00740   0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
00741   0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
00742 };
00743 
00744 static const u32 rcon[] =
00745 {
00746   0x01000000, 0x02000000, 0x04000000, 0x08000000,
00747   0x10000000, 0x20000000, 0x40000000, 0x80000000,
00748   0x1B000000, 0x36000000,
00749   /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
00750 };
00751 
00752 #define GETU32(plaintext) (((u32)(plaintext)[0] << 24) ^ \
00753                     ((u32)(plaintext)[1] << 16) ^ \
00754                     ((u32)(plaintext)[2] <<  8) ^ \
00755                     ((u32)(plaintext)[3]))
00756 
00757 #define PUTU32(ciphertext, st) { (ciphertext)[0] = (u8)((st) >> 24); \
00758                          (ciphertext)[1] = (u8)((st) >> 16); \
00759                          (ciphertext)[2] = (u8)((st) >>  8); \
00760                          (ciphertext)[3] = (u8)(st); }
00761 
00762 /*
00763  * Expand the cipher key into the encryption key schedule.
00764  *
00765  * @return the number of rounds for the given cipher key size.
00766  */
00767 // static
00768 int Aes_SetupEncrypt(u32 *rk, const u8 *key, int keybits)
00769 {
00770   int i = 0;
00771   u32 temp;
00772 
00773   rk[0] = GETU32(key     );
00774   rk[1] = GETU32(key +  4);
00775   rk[2] = GETU32(key +  8);
00776   rk[3] = GETU32(key + 12);
00777   if (keybits == 128)
00778   {
00779     for (;;)
00780     {
00781       temp  = rk[3];
00782       rk[4] = rk[0] ^
00783         (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
00784         (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
00785         (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
00786         (Te4[(temp >> 24)       ] & 0x000000ff) ^
00787         rcon[i];
00788       rk[5] = rk[1] ^ rk[4];
00789       rk[6] = rk[2] ^ rk[5];
00790       rk[7] = rk[3] ^ rk[6];
00791       if (++i == 10)
00792         return 10;
00793       rk += 4;
00794     }
00795   }
00796   rk[4] = GETU32(key + 16);
00797   rk[5] = GETU32(key + 20);
00798   if (keybits == 192)
00799   {
00800     for (;;)
00801     {
00802       temp = rk[ 5];
00803       rk[ 6] = rk[ 0] ^
00804         (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
00805         (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
00806         (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
00807         (Te4[(temp >> 24)       ] & 0x000000ff) ^
00808         rcon[i];
00809       rk[ 7] = rk[ 1] ^ rk[ 6];
00810       rk[ 8] = rk[ 2] ^ rk[ 7];
00811       rk[ 9] = rk[ 3] ^ rk[ 8];
00812       if (++i == 8)
00813         return 12;
00814       rk[10] = rk[ 4] ^ rk[ 9];
00815       rk[11] = rk[ 5] ^ rk[10];
00816       rk += 6;
00817     }
00818   }
00819   rk[6] = GETU32(key + 24);
00820   rk[7] = GETU32(key + 28);
00821   if (keybits == 256)
00822   {
00823     for (;;)
00824     {
00825       temp = rk[ 7];
00826       rk[ 8] = rk[ 0] ^
00827         (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
00828         (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
00829         (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
00830         (Te4[(temp >> 24)       ] & 0x000000ff) ^
00831         rcon[i];
00832       rk[ 9] = rk[ 1] ^ rk[ 8];
00833       rk[10] = rk[ 2] ^ rk[ 9];
00834       rk[11] = rk[ 3] ^ rk[10];
00835       if (++i == 7)
00836         return 14;
00837       temp = rk[11];
00838       rk[12] = rk[ 4] ^
00839         (Te4[(temp >> 24)       ] & 0xff000000) ^
00840         (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
00841         (Te4[(temp >>  8) & 0xff] & 0x0000ff00) ^
00842         (Te4[(temp      ) & 0xff] & 0x000000ff);
00843       rk[13] = rk[ 5] ^ rk[12];
00844       rk[14] = rk[ 6] ^ rk[13];
00845       rk[15] = rk[ 7] ^ rk[14];
00846       rk += 8;
00847     }
00848   }
00849   return 0;
00850 }
00851 
00852 /*
00853  * Expand the cipher key into the decryption key schedule.
00854  *
00855  * @return the number of rounds for the given cipher key size.
00856  */
00857 // static
00858 int Aes_SetupDecrypt(u32 *rk, const u8 *key, int keybits)
00859 {
00860   int nrounds, i, j;
00861   u32 temp;
00862 
00863   /* expand the cipher key: */
00864   nrounds = Aes_SetupEncrypt(rk, key, keybits);
00865   /* invert the order of the round keys: */
00866   for (i = 0, j = 4*nrounds; i < j; i += 4, j -= 4)
00867   {
00868     temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
00869     temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
00870     temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
00871     temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
00872   }
00873   /* apply the inverse MixColumn transform to all round keys but the first and the last: */
00874   for (i = 1; i < nrounds; i++)
00875   {
00876     rk += 4;
00877     rk[0] =
00878       Td0[Te4[(rk[0] >> 24)       ] & 0xff] ^
00879       Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
00880       Td2[Te4[(rk[0] >>  8) & 0xff] & 0xff] ^
00881       Td3[Te4[(rk[0]      ) & 0xff] & 0xff];
00882     rk[1] =
00883       Td0[Te4[(rk[1] >> 24)       ] & 0xff] ^
00884       Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
00885       Td2[Te4[(rk[1] >>  8) & 0xff] & 0xff] ^
00886       Td3[Te4[(rk[1]      ) & 0xff] & 0xff];
00887     rk[2] =
00888       Td0[Te4[(rk[2] >> 24)       ] & 0xff] ^
00889       Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
00890       Td2[Te4[(rk[2] >>  8) & 0xff] & 0xff] ^
00891       Td3[Te4[(rk[2]      ) & 0xff] & 0xff];
00892     rk[3] =
00893       Td0[Te4[(rk[3] >> 24)       ] & 0xff] ^
00894       Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
00895       Td2[Te4[(rk[3] >>  8) & 0xff] & 0xff] ^
00896       Td3[Te4[(rk[3]      ) & 0xff] & 0xff];
00897   }
00898   return nrounds;
00899 }
00900 
00901 /*
00902  * Expand the cipher key into the decryption key schedule.
00903  *
00904  * @return the number of rounds for the given cipher key size.
00905  */
00906 void Aes_DoEncrypt(const u32 *rk, int nrounds, const u8 plaintext[16],
00907   u8 ciphertext[16])
00908 {
00909   u32 s0, s1, s2, s3, t0, t1, t2, t3;
00910   #ifndef FULL_UNROLL
00911     int r;
00912   #endif /* ?FULL_UNROLL */
00913   /*
00914    * map byte array block to cipher state
00915    * and add initial round key:
00916   */
00917   s0 = GETU32(plaintext     ) ^ rk[0];
00918   s1 = GETU32(plaintext +  4) ^ rk[1];
00919   s2 = GETU32(plaintext +  8) ^ rk[2];
00920   s3 = GETU32(plaintext + 12) ^ rk[3];
00921   #ifdef FULL_UNROLL
00922     /* round 1: */
00923     t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
00924     t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
00925     t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
00926     t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
00927     /* round 2: */
00928     s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
00929     s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
00930     s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
00931     s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
00932     /* round 3: */
00933     t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
00934     t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
00935     t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
00936     t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
00937     /* round 4: */
00938     s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
00939     s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
00940     s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
00941     s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
00942     /* round 5: */
00943     t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
00944     t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
00945     t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
00946     t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
00947     /* round 6: */
00948     s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
00949     s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
00950     s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
00951     s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
00952     /* round 7: */
00953     t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
00954     t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
00955     t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
00956     t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
00957     /* round 8: */
00958     s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
00959     s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
00960     s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
00961     s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
00962     /* round 9: */
00963     t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
00964     t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
00965     t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
00966     t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
00967     if (nrounds > 10)
00968     {
00969       /* round 10: */
00970       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
00971       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
00972       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
00973       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
00974       /* round 11: */
00975       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
00976       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
00977       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
00978       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
00979       if (nrounds > 12)
00980       {
00981         /* round 12: */
00982         s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
00983         s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
00984         s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
00985         s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
00986         /* round 13: */
00987         t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
00988         t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
00989         t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
00990         t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
00991       }
00992     }
00993     rk += nrounds << 2;
00994   #else  /* !FULL_UNROLL */
00995     /*
00996     * nrounds - 1 full rounds:
00997     */
00998     r = nrounds >> 1;
00999     for (;;)
01000     {
01001       t0 =
01002         Te0[(s0 >> 24)       ] ^
01003         Te1[(s1 >> 16) & 0xff] ^
01004         Te2[(s2 >>  8) & 0xff] ^
01005         Te3[(s3      ) & 0xff] ^
01006         rk[4];
01007       t1 =
01008         Te0[(s1 >> 24)       ] ^
01009         Te1[(s2 >> 16) & 0xff] ^
01010         Te2[(s3 >>  8) & 0xff] ^
01011         Te3[(s0      ) & 0xff] ^
01012         rk[5];
01013       t2 =
01014         Te0[(s2 >> 24)       ] ^
01015         Te1[(s3 >> 16) & 0xff] ^
01016         Te2[(s0 >>  8) & 0xff] ^
01017         Te3[(s1      ) & 0xff] ^
01018         rk[6];
01019       t3 =
01020         Te0[(s3 >> 24)       ] ^
01021         Te1[(s0 >> 16) & 0xff] ^
01022         Te2[(s1 >>  8) & 0xff] ^
01023         Te3[(s2      ) & 0xff] ^
01024         rk[7];
01025         rk += 8;
01026         if (--r == 0)
01027             break;
01028       s0 =
01029         Te0[(t0 >> 24)       ] ^
01030         Te1[(t1 >> 16) & 0xff] ^
01031         Te2[(t2 >>  8) & 0xff] ^
01032         Te3[(t3      ) & 0xff] ^
01033         rk[0];
01034       s1 =
01035         Te0[(t1 >> 24)       ] ^
01036         Te1[(t2 >> 16) & 0xff] ^
01037         Te2[(t3 >>  8) & 0xff] ^
01038         Te3[(t0      ) & 0xff] ^
01039         rk[1];
01040       s2 =
01041         Te0[(t2 >> 24)       ] ^
01042         Te1[(t3 >> 16) & 0xff] ^
01043         Te2[(t0 >>  8) & 0xff] ^
01044         Te3[(t1      ) & 0xff] ^
01045         rk[2];
01046       s3 =
01047         Te0[(t3 >> 24)       ] ^
01048         Te1[(t0 >> 16) & 0xff] ^
01049         Te2[(t1 >>  8) & 0xff] ^
01050         Te3[(t2      ) & 0xff] ^
01051         rk[3];
01052      }
01053  #endif /* ?FULL_UNROLL */
01054   /*
01055   * apply last round and
01056   * map cipher state to byte array block:
01057   */
01058   s0 =
01059     (Te4[(t0 >> 24)       ] & 0xff000000) ^
01060     (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
01061     (Te4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
01062     (Te4[(t3      ) & 0xff] & 0x000000ff) ^
01063     rk[0];
01064   PUTU32(ciphertext     , s0);
01065   s1 =
01066     (Te4[(t1 >> 24)       ] & 0xff000000) ^
01067     (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
01068     (Te4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
01069     (Te4[(t0      ) & 0xff] & 0x000000ff) ^
01070     rk[1];
01071   PUTU32(ciphertext +  4, s1);
01072   s2 =
01073     (Te4[(t2 >> 24)       ] & 0xff000000) ^
01074     (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
01075     (Te4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
01076     (Te4[(t1      ) & 0xff] & 0x000000ff) ^
01077     rk[2];
01078   PUTU32(ciphertext +  8, s2);
01079   s3 =
01080     (Te4[(t3 >> 24)       ] & 0xff000000) ^
01081     (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
01082     (Te4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
01083     (Te4[(t2      ) & 0xff] & 0x000000ff) ^
01084     rk[3];
01085   PUTU32(ciphertext + 12, s3);
01086 }
01087 
01088 // static
01089 void Aes_DoDecrypt(const u32 *rk, int nrounds, const u8 ciphertext[16],
01090   u8 plaintext[16])
01091 {
01092   u32 s0, s1, s2, s3, t0, t1, t2, t3;
01093   #ifndef FULL_UNROLL
01094     int r;
01095   #endif /* ?FULL_UNROLL */
01096 
01097   /*
01098   * map byte array block to cipher state
01099   * and add initial round key:
01100   */
01101     s0 = GETU32(ciphertext     ) ^ rk[0];
01102     s1 = GETU32(ciphertext +  4) ^ rk[1];
01103     s2 = GETU32(ciphertext +  8) ^ rk[2];
01104     s3 = GETU32(ciphertext + 12) ^ rk[3];
01105   #ifdef FULL_UNROLL
01106     /* round 1: */
01107     t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
01108     t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
01109     t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
01110     t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
01111     /* round 2: */
01112     s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
01113     s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
01114     s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
01115     s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
01116     /* round 3: */
01117     t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
01118     t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
01119     t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
01120     t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
01121     /* round 4: */
01122     s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
01123     s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
01124     s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
01125     s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
01126     /* round 5: */
01127     t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
01128     t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
01129     t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
01130     t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
01131     /* round 6: */
01132     s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
01133     s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
01134     s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
01135     s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
01136     /* round 7: */
01137     t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
01138     t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
01139     t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
01140     t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
01141     /* round 8: */
01142     s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
01143     s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
01144     s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
01145     s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
01146     /* round 9: */
01147     t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
01148     t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
01149     t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
01150     t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
01151     if (nrounds > 10)
01152     {
01153       /* round 10: */
01154       s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
01155       s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
01156       s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
01157       s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
01158       /* round 11: */
01159       t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
01160       t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
01161       t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
01162       t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
01163       if (nrounds > 12)
01164       {
01165         /* round 12: */
01166         s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
01167         s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
01168         s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
01169         s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
01170         /* round 13: */
01171         t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
01172         t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
01173         t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
01174         t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
01175       }
01176     }
01177     rk += nrounds << 2;
01178   #else  /* !FULL_UNROLL */
01179     /*
01180     * nrounds - 1 full rounds:
01181     */
01182     r = nrounds >> 1;
01183     for (;;)
01184     {
01185       t0 =
01186         Td0[(s0 >> 24)       ] ^
01187         Td1[(s3 >> 16) & 0xff] ^
01188         Td2[(s2 >>  8) & 0xff] ^
01189         Td3[(s1      ) & 0xff] ^
01190         rk[4];
01191       t1 =
01192         Td0[(s1 >> 24)       ] ^
01193         Td1[(s0 >> 16) & 0xff] ^
01194         Td2[(s3 >>  8) & 0xff] ^
01195         Td3[(s2      ) & 0xff] ^
01196         rk[5];
01197       t2 =
01198         Td0[(s2 >> 24)       ] ^
01199         Td1[(s1 >> 16) & 0xff] ^
01200         Td2[(s0 >>  8) & 0xff] ^
01201         Td3[(s3      ) & 0xff] ^
01202         rk[6];
01203       t3 =
01204         Td0[(s3 >> 24)       ] ^
01205         Td1[(s2 >> 16) & 0xff] ^
01206         Td2[(s1 >>  8) & 0xff] ^
01207         Td3[(s0      ) & 0xff] ^
01208         rk[7];
01209       rk += 8;
01210       if (--r == 0)
01211           break;
01212       s0 =
01213         Td0[(t0 >> 24)       ] ^
01214         Td1[(t3 >> 16) & 0xff] ^
01215         Td2[(t2 >>  8) & 0xff] ^
01216         Td3[(t1      ) & 0xff] ^
01217         rk[0];
01218       s1 =
01219         Td0[(t1 >> 24)       ] ^
01220         Td1[(t0 >> 16) & 0xff] ^
01221         Td2[(t3 >>  8) & 0xff] ^
01222         Td3[(t2      ) & 0xff] ^
01223         rk[1];
01224       s2 =
01225         Td0[(t2 >> 24)       ] ^
01226         Td1[(t1 >> 16) & 0xff] ^
01227         Td2[(t0 >>  8) & 0xff] ^
01228         Td3[(t3      ) & 0xff] ^
01229         rk[2];
01230       s3 =
01231         Td0[(t3 >> 24)       ] ^
01232         Td1[(t2 >> 16) & 0xff] ^
01233         Td2[(t1 >>  8) & 0xff] ^
01234         Td3[(t0      ) & 0xff] ^
01235         rk[3];
01236     }
01237   #endif /* ?FULL_UNROLL */
01238   /*
01239   * apply last round and
01240   * map cipher state to byte array block:
01241   */
01242   s0 =
01243     (Td4[(t0 >> 24)       ] & 0xff000000) ^
01244     (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
01245     (Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
01246     (Td4[(t1      ) & 0xff] & 0x000000ff) ^
01247     rk[0];
01248   PUTU32(plaintext     , s0);
01249   s1 =
01250     (Td4[(t1 >> 24)       ] & 0xff000000) ^
01251     (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
01252     (Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
01253     (Td4[(t2      ) & 0xff] & 0x000000ff) ^
01254     rk[1];
01255   PUTU32(plaintext +  4, s1);
01256   s2 =
01257     (Td4[(t2 >> 24)       ] & 0xff000000) ^
01258     (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
01259     (Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
01260     (Td4[(t3      ) & 0xff] & 0x000000ff) ^
01261     rk[2];
01262   PUTU32(plaintext +  8, s2);
01263   s3 =
01264     (Td4[(t3 >> 24)       ] & 0xff000000) ^
01265     (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
01266     (Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
01267     (Td4[(t0      ) & 0xff] & 0x000000ff) ^
01268     rk[3];
01269   PUTU32(plaintext + 12, s3);
01270 }
01271 
01272 #define KEYLENGTH(keybits) ((keybits)/8)
01273 #define RKLENGTH(keybits)  ((keybits)/8+28)
01274 #define NROUNDS(keybits)   ((keybits)/32+6)
01275 
01276 #define KEYBITS 128
01277 #define BLOCK_SIZE 16
01278 
01279 /**
01280   Ecrypt a block of data using AES.
01281 
01282   @param output A pointer to the buffer into which the encrypted data will be written.
01283   @param outlen The maximum number of bytes to write into the output buffer.
01284   @param input A pointer to the data to be encrypted.
01285   @param inlen The number of bytes of data to encrypt.
01286   @param password The password, or key, used to encrypt the data.  Must be 16 bytes long.
01287   @return The number of bytes encrypted, or -1 on failure.
01288 
01289   \par Example
01290   \code
01291   #define BUFF_SIZE 256
01292   unsigned char cipherbuf[BUFF_SIZE]; // the buffer that will be written into
01293   unsigned char plaintext[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // the text to encrypt
01294   unsigned char secret[] = "A SECRET PASSWORD"; // 16 bytes long
01295   int written = Aes_Encrypt(cipherbuf, BUFF_SIZE, plaintext, 26, secret);
01296   \endcode
01297 */
01298 int Aes_Encrypt(unsigned char* output, int outlen, unsigned char* input, int inlen, unsigned char* password)
01299 {
01300   unsigned long rk[RKLENGTH(KEYBITS)];
01301   unsigned char key[KEYLENGTH(KEYBITS)];
01302   int nrounds;
01303   int totalout = outlen;
01304 
01305   memcpy(key, password, BLOCK_SIZE); // gotta be 16 coming in
01306 
01307   nrounds = Aes_SetupEncrypt(rk, key, KEYBITS); // initialize the encrypt buffer
01308   while(inlen)
01309   {
01310     unsigned char plaintext[BLOCK_SIZE];
01311     unsigned char ciphertext[BLOCK_SIZE];
01312     unsigned int j;
01313     // grab bytes from the input and stuff them in plaintext
01314     for(j = 0; j < BLOCK_SIZE; j++)
01315     {
01316       if(inlen)
01317       {
01318         plaintext[j] = *input++;
01319         inlen--;
01320       }
01321       else
01322         break;
01323     }
01324 
01325     char c = BLOCK_SIZE - j; // pad with the character that corresponds to how many bytes we need to pad
01326     unsigned int orig_block_size = j;
01327     for (; j < BLOCK_SIZE; j++) // if we didn't get 16 bytes, pad plaintext
01328       plaintext[j] = c;
01329     Aes_DoEncrypt(rk, nrounds, plaintext, ciphertext);
01330     if(outlen < BLOCK_SIZE) // not enough room to write out
01331       return -1;
01332     memcpy(output, ciphertext, BLOCK_SIZE);
01333     output += BLOCK_SIZE;
01334     outlen -= BLOCK_SIZE;
01335 
01336     if(orig_block_size == BLOCK_SIZE && inlen == 0) // the last chunk was 16 bytes.  encrypt another round so we know how to decrypt the padding
01337     {
01338       memset(plaintext, BLOCK_SIZE, BLOCK_SIZE); // pad 16 bytes with the value 16
01339       Aes_DoEncrypt(rk, nrounds, plaintext, ciphertext);
01340       if(outlen < BLOCK_SIZE) // not enough room to write out
01341         return -1;
01342       memcpy(output, ciphertext, BLOCK_SIZE);
01343       output += BLOCK_SIZE;
01344       outlen -= BLOCK_SIZE;
01345     }
01346   }
01347   return totalout - outlen;
01348 }
01349 
01350 /**
01351   Decrypt a block of AES encrypted data.
01352 
01353   @param output A pointer to the buffer into which the decrypted data will be written.
01354   @param outlen The maximum number of bytes of data to write into the output buffer.
01355   @param input A pointer to the encrypted block to be decrytped.
01356   @param inlen The number of bytes to be decrypted.
01357   @param password The password, or key, used to encrypt the data.  Must be 16 bytes long.
01358   @return The number of bytes written, or -1 on failure.
01359 
01360   \par Example
01361   \code
01362   // first encrypt some data, then decrypt it and make sure we get out what we put in
01363   unsigned char cipherbuf[256];
01364   unsigned char plainbuf[256];
01365   unsigned char plaintext[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // our plaintext to encrypt
01366   unsigned char secret[] = "A SECRET PASSWORD"; // 16 bytes long
01367 
01368   int written = Aes_Encrypt(cipherbuf, 256, plaintext, 26, secret);
01369   written = Aes_Decrypt(plainbuf, 256, cipherbuf, written, secret);
01370   // we now have our original plaintext in plainbuf
01371   \endcode
01372 */
01373 int Aes_Decrypt(unsigned char* output, int outlen, unsigned char* input, int inlen, unsigned char* password)
01374 {
01375   unsigned long rk[RKLENGTH(KEYBITS)];
01376   unsigned char key[KEYLENGTH(KEYBITS)];
01377   int nrounds;
01378   int totalout = outlen;
01379 
01380   memcpy(key, password, BLOCK_SIZE); // gotta be 16 coming in
01381   
01382   nrounds = Aes_SetupDecrypt(rk, key, KEYBITS);
01383   while(inlen)
01384   {
01385     unsigned char plaintext[BLOCK_SIZE];
01386     unsigned char ciphertext[BLOCK_SIZE];
01387 
01388     if(inlen < BLOCK_SIZE) // the ciphered text should be in 16 byte chunks
01389       return -1;
01390     memcpy(ciphertext, input, BLOCK_SIZE); // stuff a block from input in ciphertext
01391     input += BLOCK_SIZE;
01392     inlen -= BLOCK_SIZE;
01393     Aes_DoDecrypt(rk, nrounds, ciphertext, plaintext);
01394     if(inlen < BLOCK_SIZE) // we're on our last block.  check the padding to determine the size of the original data
01395     {
01396       int padlen = plaintext[BLOCK_SIZE-1]; // look at the last byte
01397       if(padlen < 1 || padlen > 16) // check for bogus padlen
01398         return -1;
01399       int datalen = BLOCK_SIZE - padlen;
01400       if(outlen < datalen) // not enough room to write out
01401         return -1;
01402       memcpy(output, plaintext, datalen); // stuff only data (no padding) into the output
01403       outlen -= datalen;
01404     }
01405     else // proceed as normal
01406     {
01407       if(outlen < BLOCK_SIZE) // not enough room to write out
01408         return -1;
01409       memcpy(output, plaintext, BLOCK_SIZE); // stuff a decrypted block into the output
01410       output += BLOCK_SIZE;
01411       outlen -= BLOCK_SIZE;
01412     }
01413   }
01414   return totalout - outlen;
01415 }
01416 
01417 /** @}
01418 */
01419 
01420 
01421 
01422 
01423 
01424 

The Make Controller Kit is an open source project maintained by MakingThings.
MakingThings code is released under the Apache 2.0 license.
Bug tracker, development wiki and status can be found at http://dev.makingthings.com.
This document was last updated on 18 May 2009.