1/* rijndael - An implementation of the Rijndael cipher.
2 * Copyright (C) 2000, 2001 Rafael R. Sevilla <sevillar@team.ph.inter.net>
3 *
4 * Currently maintained by brian d foy, <bdfoy@cpan.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#include "rijndael.h"
22#include <stdlib.h>
23#include <string.h>
24#include <stdio.h>
25
26#if 0
27
28static void
29print_block(UINT8 *block)
30{
31  int i;
32
33  for (i=0; i<RIJNDAEL_BLOCKSIZE; i++)
34    printf("%02x", block[i]);
35  printf("\n");
36}
37#endif
38
39/* These tables combine both the S-boxes and the mixcolumn transformation, so
40   that we can perform a round's encryption or by means of four table lookups
41   and four XOR's per column of state.  They were generated by the
42   makertbls.pl script. */
43UINT32 dtbl[] = {
44  0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6,
45  0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,
46  0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
47  0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec,
48  0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
49  0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,
50  0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45,
51  0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b,
52  0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
53  0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
54  0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9,
55  0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
56  0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d,
57  0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f,
58  0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
59  0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea,
60  0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34,
61  0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
62  0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d,
63  0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
64  0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1,
65  0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6,
66  0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972,
67  0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
68  0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
69  0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511,
70  0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,
71  0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b,
72  0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05,
73  0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
74  0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142,
75  0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf,
76  0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
77  0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e,
78  0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
79  0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
80  0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3,
81  0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b,
82  0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
83  0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
84  0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14,
85  0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,
86  0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4,
87  0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2,
88  0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
89  0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949,
90  0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf,
91  0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
92  0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c,
93  0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
94  0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
95  0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f,
96  0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc,
97  0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c,
98  0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
99  0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27,
100  0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
101  0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433,
102  0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9,
103  0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
104  0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a,
105  0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,
106  0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
107  0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c,
108};
109
110UINT32 itbl[] = {
111  0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a,
112  0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b,
113  0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5,
114  0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5,
115  0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
116  0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b,
117  0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295,
118  0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e,
119  0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927,
120  0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
121  0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362,
122  0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9,
123  0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52,
124  0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566,
125  0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
126  0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed,
127  0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e,
128  0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4,
129  0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4,
130  0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
131  0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d,
132  0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060,
133  0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967,
134  0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879,
135  0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
136  0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c,
137  0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36,
138  0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624,
139  0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b,
140  0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
141  0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12,
142  0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14,
143  0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3,
144  0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b,
145  0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
146  0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684,
147  0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7,
148  0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177,
149  0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947,
150  0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
151  0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498,
152  0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f,
153  0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54,
154  0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382,
155  0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
156  0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb,
157  0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83,
158  0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef,
159  0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029,
160  0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
161  0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733,
162  0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117,
163  0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4,
164  0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546,
165  0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
166  0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d,
167  0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb,
168  0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a,
169  0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773,
170  0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
171  0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2,
172  0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff,
173  0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664,
174  0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0,
175};
176
177
178/* Needed only for the key schedule and for final rounds */
179UINT8 sbox[256] = {
180  99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 171,
181  118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 156, 164,
182  114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 229, 241, 113,
183  216,  49,  21,  4, 199,  35, 195,  24, 150,   5, 154,   7,  18, 128, 226,
184  235,  39, 178, 117,  9, 131,  44,  26,  27, 110,  90, 160,  82,  59, 214,
185  179,  41, 227,  47, 132, 83, 209,   0, 237,  32, 252, 177,  91, 106, 203,
186  190,  57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,  69,
187  249,   2, 127,  80,  60, 159, 168, 81, 163,  64, 143, 146, 157,  56, 245,
188  188, 182, 218,  33,  16, 255, 243, 210, 205,  12,  19, 236,  95, 151,  68,
189  23, 196, 167, 126,  61, 100,  93,  25, 115, 96, 129,  79, 220,  34,  42,
190  144, 136,  70, 238, 184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,
191  6,  36,  92, 194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109,
192  141, 213,  78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,
193  46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62,
194  181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158, 225,
195  248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,  40, 223,
196  140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 176,  84, 187,
197  22,
198};
199
200UINT8 isbox[256] = {
201  82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 215,
202  251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 196, 222,
203  233, 203, 84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 149,  11,  66,
204  250, 195,  78,  8,  46, 161, 102,  40, 217,  36, 178, 118,  91, 162,  73,
205  109, 139, 209,  37, 114, 248, 246, 100, 134, 104, 152,  22, 212, 164,  92,
206  204,  93, 101, 182, 146, 108, 112,  72,  80, 253, 237, 185, 218,  94,  21,
207  70,  87, 167, 141, 157, 132, 144, 216, 171,   0, 140, 188, 211,  10, 247,
208  228,  88,   5, 184, 179,  69,   6, 208,  44,  30, 143, 202,  63,  15,   2,
209  193, 175, 189,   3,   1,  19, 138, 107,  58, 145,  17,  65,  79, 103, 220,
210  234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116,  34, 231, 173,
211  53, 133, 226, 249,  55, 232,  28, 117, 223, 110,  71, 241,  26, 113,  29,
212  41, 197, 137, 111, 183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75,
213  198, 210, 121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,
214  51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,  96,  81,
215  127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239, 160,
216  224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 153,  97,
217  23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99,  85,  33,  12,
218  125,
219};
220
221/* Used only by the key schedule */
222UINT8 Logtable[256] = {
223  0,   0,  25,   1,  50,   2,  26, 198,  75, 199,  27, 104,  51, 238, 223,  3,
224  100,   4, 224,  14,  52, 141, 129, 239,  76, 113,   8, 200, 248, 105,  28,
225  193, 125, 194,  29, 181, 249, 185,  39, 106,  77, 228, 166, 114, 154, 201,
226  9, 120, 101,  47, 138,   5,  33,  15, 225,  36,  18, 240, 130,  69,  53,
227  147, 218, 142, 150, 143, 219, 189,  54, 208, 206, 148,  19,  92, 210, 241,
228  64,  70, 131,  56, 102, 221, 253,  48, 191,   6, 139,  98, 179,  37, 226,
229  152,  34, 136, 145,  16, 126, 110,  72, 195, 163, 182,  30,  66,  58, 107,
230  40,  84, 250, 133,  61, 186, 43, 121,  10,  21, 155, 159,  94, 202,  78,
231  212, 172, 229, 243, 115, 167,  87, 175,  88, 168,  80, 244, 234, 214, 116,
232  79, 174, 233, 213, 231, 230, 173, 232, 44, 215, 117, 122, 235,  22,  11,
233  245,  89, 203,  95, 176, 156, 169,  81, 160, 127,  12, 246, 111,  23, 196,
234  73, 236, 216,  67,  31,  45, 164, 118, 123, 183, 204, 187,  62,  90, 251,
235  96, 177, 134,  59,  82, 161, 108, 170,  85,  41, 157, 151, 178, 135, 144,
236  97, 190, 220, 252, 188, 149, 207, 205,  55,  63,  91, 209, 83,  57, 132,
237  60,  65, 162, 109,  71,  20,  42, 158,  93,  86, 242, 211, 171, 68,  17,
238  146, 217,  35,  32,  46, 137, 180, 124, 184,  38, 119, 153, 227, 165, 103,
239  74, 237, 222, 197,  49, 254,  24,  13,  99, 140, 128, 192, 247, 112,   7,
240};
241
242UINT8 Alogtable[256] = {
243  1,   3,   5,  15,  17,  51,  85, 255,  26,  46, 114, 150, 161, 248,  19,
244  53, 95, 225,  56,  72, 216, 115, 149, 164, 247,   2,   6,  10,  30,  34,
245  102, 170, 229,  52,  92, 228,  55,  89, 235,  38, 106, 190, 217, 112, 144,
246  171, 230,  49,  83, 245,   4,  12,  20,  60,  68, 204,  79, 209, 104, 184,
247  211, 110, 178, 205,  76, 212, 103, 169, 224,  59,  77, 215,  98, 166, 241,
248  8,  24,  40, 120, 136, 131, 158, 185, 208, 107, 189, 220, 127, 129, 152,
249  179, 206,  73, 219, 118, 154, 181, 196,  87, 249,  16,  48,  80, 240,  11,
250  29,  39, 105, 187, 214,  97, 163, 254,  25,  43, 125, 135, 146, 173, 236,
251  47, 113, 147, 174, 233,  32,  96, 160, 251,  22,  58,  78, 210, 109, 183,
252  194,  93, 231,  50,  86, 250,  21,  63,  65, 195,  94, 226,  61,  71, 201,
253  64, 192,  91, 237,  44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172,
254  239,  42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193,  88,
255  232,  35, 101, 175, 234,  37, 111, 177, 200,  67, 197,  84, 252,  31,  33,
256  99, 165, 244,   7,   9,  27,  45, 119, 153, 176, 203,  70, 202,  69, 207,
257  74, 222, 121, 139, 134, 145, 168, 227,  62,  66, 198,  81, 243,  14,  18,
258  54,  90, 238,  41, 123, 141, 140, 143, 138, 133, 148, 167, 242,  13,  23,
259  57,  75, 221, 124, 132, 151, 162, 253,  28,  36, 108, 180, 199,  82, 246, 1,
260};
261
262#define ROTBYTE(x) (((x) >> 8) | (((x) & 0xff) << 24))
263#define ROTRBYTE(x) (((x) << 8) | (((x) >> 24) & 0xff))
264#define SUBBYTE(x, box) (((box)[((x) & 0xff)]) | \
265                        ((box)[(((x) >> 8) & 0xff)] << 8) | \
266                        ((box)[(((x) >> 16) & 0xff)] << 16) | \
267                        ((box)[(((x) >> 24) & 0xff)] << 24))
268
269static UINT8
270xtime(UINT8 a)
271{
272  UINT8 b;
273
274  b = (a & 0x80) ? 0x1b : 0;
275  a<<=1;
276  a^=b;
277  return(a);
278}
279
280static UINT8
281mul(UINT8 a, UINT8 b)
282{
283  if (a && b) return Alogtable[(Logtable[a] + Logtable[b])%255];
284  else return 0;
285}
286
287static void
288inv_mix_column(UINT32 *a, UINT32 *b)
289{
290  UINT8 c[4][4];
291  int i, j;
292
293  for(j = 0; j < 4; j++) {
294    for(i = 0; i < 4; i++) {
295      c[j][i] = mul(0xe, (a[j] >> i*8) & 0xff)
296	^ mul(0xb, (a[j] >> ((i+1)%4)*8) & 0xff)
297	^ mul(0xd, (a[j] >> ((i+2)%4)*8) & 0xff)
298	^ mul(0x9, (a[j] >> ((i+3)%4)*8) & 0xff);
299    }
300  }
301  for(i = 0; i < 4; i++) {
302    b[i] = 0;
303    for(j = 0; j < 4; j++)
304      b[i] |= c[i][j] << (j*8);
305  }
306}
307
308void
309rijndael_setup(RIJNDAEL_context *ctx, size_t keysize, const UINT8 *key)
310{
311  int nk, nr, i, lastkey;
312  UINT32 temp, rcon;
313
314  /* Truncate keysizes to the valid key sizes provided by Rijndael */
315  if (keysize >= 32) {
316    nk = 8;
317    nr = 14;
318  } else if (keysize >= 24) {
319    nk = 6;
320    nr = 12;
321  } else {			/* must be 16 or more */
322    nk = 4;
323    nr = 10;
324  }
325
326  lastkey = (RIJNDAEL_BLOCKSIZE/4) * (nr + 1);
327  ctx->nrounds = nr;
328  rcon = 1;
329  for (i=0; i<nk; i++) {
330    ctx->keys[i] = key[i*4] + (key[i*4+1]<<8) + (key[i*4+2]<<16) +
331      (key[i*4+3]<<24);
332  }
333
334  for (i=nk; i<lastkey; i++) {
335    temp = ctx->keys[i-1];
336    if (i % nk == 0) {
337      temp = SUBBYTE(ROTBYTE(temp), sbox) ^ rcon;
338      rcon = (UINT32)xtime((UINT8)rcon&0xff);
339    } else if (nk > 6 && (i%nk) == 4) {
340      temp = SUBBYTE(temp, sbox);
341    }
342    ctx->keys[i] = ctx->keys[i-nk] ^ temp;
343  }
344  /* Generate the inverse keys */
345  for (i=0; i<4; i++) {
346    ctx->ikeys[i] = ctx->keys[i];
347    ctx->ikeys[lastkey-4 + i] = ctx->keys[lastkey-4 + i];
348  }
349  for (i=4; i<lastkey-4; i+=4)
350    inv_mix_column(&(ctx->keys[i]), &(ctx->ikeys[i]));
351}
352
353/* Key addition that also packs every byte in the key to a word rep. */
354static void
355key_addition_8to32(const UINT8 *txt, UINT32 *keys, UINT32 *out)
356{
357  const UINT8 *ptr;
358  int i, j;
359  UINT32 val;
360
361  ptr = txt;
362  for (i=0; i<4; i++) {
363    val = 0;
364    for (j=0; j<4; j++)
365      val |= (*ptr++ << 8*j);
366    out[i] = keys[i]^val;
367  }
368}
369
370static void
371key_addition32(const UINT32 *txt, UINT32 *keys, UINT32 *out)
372{
373  int i;
374
375  for (i=0; i<4; i++)
376    out[i] = keys[i] ^ txt[i];
377}
378
379static void
380key_addition32to8(const UINT32 *txt, UINT32 *keys, UINT8 *out)
381{
382  UINT8 *ptr;
383  int i, j;
384  UINT32 val;
385
386  ptr = out;
387  for (i=0; i<4; i++) {
388    val = txt[i] ^ keys[i];
389    for (j=0; j<4; j++)
390      *ptr++ = (val >> 8*j) & 0xff;
391  }
392}
393
394static int idx[4][4] = {
395  { 0, 1, 2, 3 },
396  { 1, 2, 3, 0 },
397  { 2, 3, 0, 1 },
398  { 3, 0, 1, 2 } };
399
400void
401rijndael_encrypt(RIJNDAEL_context *ctx,
402		 const UINT8 *plaintext,
403		 UINT8 *ciphertext)
404{
405  int r, j;
406  UINT32 wtxt[4], t[4];		/* working ciphertext */
407  UINT32 e;
408
409  key_addition_8to32(plaintext, &(ctx->keys[0]), wtxt);
410  for (r=1; r<ctx->nrounds; r++) {
411    for (j=0; j<4; j++) {
412      t[j] = dtbl[wtxt[j] & 0xff] ^
413	ROTRBYTE(dtbl[(wtxt[idx[1][j]] >> 8) & 0xff]^
414		 ROTRBYTE(dtbl[(wtxt[idx[2][j]] >> 16) & 0xff] ^
415			  ROTRBYTE(dtbl[(wtxt[idx[3][j]] >> 24) & 0xff])));
416    }
417    key_addition32(t, &(ctx->keys[r*4]), wtxt);
418  }
419  /* last round is special: there is no mixcolumn, so we can't use the big
420     tables. */
421  for (j=0; j<4; j++) {
422    e = wtxt[j] & 0xff;
423    e |= (wtxt[idx[1][j]]) & (0xff  << 8 );
424    e |= (wtxt[idx[2][j]]) & (0xff  << 16);
425    e |= (wtxt[idx[3][j]]) & (0xffU << 24);
426    t[j] = e;
427  }
428  for (j=0; j<4; j++)
429    t[j] = SUBBYTE(t[j], sbox);
430  key_addition32to8(t, &(ctx->keys[4*ctx->nrounds]), ciphertext);
431}
432
433static int iidx[4][4] = {
434  { 0, 1, 2, 3 },
435  { 3, 0, 1, 2 },
436  { 2, 3, 0, 1 },
437  { 1, 2, 3, 0 } };
438
439void
440rijndael_decrypt(RIJNDAEL_context *ctx,
441		 const UINT8 *ciphertext,
442		 UINT8 *plaintext)
443{
444  int r, j;
445  UINT32 wtxt[4], t[4];		/* working ciphertext */
446  UINT32 e;
447
448  key_addition_8to32(ciphertext, &(ctx->ikeys[4*ctx->nrounds]), wtxt);
449  for (r=ctx->nrounds-1; r> 0;  r--) {
450    for (j=0; j<4; j++) {
451      t[j] = itbl[wtxt[j] & 0xff] ^
452	ROTRBYTE(itbl[(wtxt[iidx[1][j]] >> 8) & 0xff]^
453		 ROTRBYTE(itbl[(wtxt[iidx[2][j]] >> 16) & 0xff] ^
454			  ROTRBYTE(itbl[(wtxt[iidx[3][j]] >> 24) & 0xff])));
455    }
456    key_addition32(t, &(ctx->ikeys[r*4]), wtxt);
457  }
458  /* last round is special: there is no mixcolumn, so we can't use the big
459     tables. */
460  for (j=0; j<4; j++) {
461    e = wtxt[j] & 0xff;
462    e |= (wtxt[iidx[1][j]]) & (0xff  << 8);
463    e |= (wtxt[iidx[2][j]]) & (0xff  << 16);
464    e |= (wtxt[iidx[3][j]]) & (0xffU << 24);
465    t[j] = e;
466  }
467  for (j=0; j<4; j++)
468    t[j] = SUBBYTE(t[j], isbox);
469  key_addition32to8(t, &(ctx->ikeys[0]), plaintext);
470}
471
472void
473block_encrypt(RIJNDAEL_context *ctx, UINT8 *input, int inputlen,
474		   UINT8 *output, UINT8 *iv)
475{
476  int i, j, nblocks, carry_flg;
477  UINT8 block[RIJNDAEL_BLOCKSIZE], block2[RIJNDAEL_BLOCKSIZE], oldptxt;
478
479  nblocks = inputlen / RIJNDAEL_BLOCKSIZE;
480
481  switch (ctx->mode) {
482  case MODE_ECB:		/* electronic code book */
483    for (i = 0; i<nblocks; i++) {
484      rijndael_encrypt(ctx, &input[RIJNDAEL_BLOCKSIZE*i],
485		       &output[RIJNDAEL_BLOCKSIZE*i]);
486    }
487    break;
488  case MODE_CBC:		/* Cipher block chaining */
489    /* set initial value */
490    memcpy(block, iv, RIJNDAEL_BLOCKSIZE);
491    for (i=0; i< nblocks; i++) {
492      for (j=0; j<RIJNDAEL_BLOCKSIZE; j++)
493	block[j] ^= input[i*RIJNDAEL_BLOCKSIZE + j] & 0xff;
494      rijndael_encrypt(ctx, block, block);
495      memcpy(&output[RIJNDAEL_BLOCKSIZE*i], block, RIJNDAEL_BLOCKSIZE);
496    }
497    break;
498  case MODE_CFB:		/* 128-bit cipher feedback */
499    memcpy(block, iv, RIJNDAEL_BLOCKSIZE);
500    for (i=0; i<nblocks; i++) {
501      rijndael_encrypt(ctx, block, block);
502      for (j=0; j<RIJNDAEL_BLOCKSIZE; j++)
503	block[j] ^= input[i*RIJNDAEL_BLOCKSIZE + j];
504      memcpy(&output[RIJNDAEL_BLOCKSIZE*i], block, RIJNDAEL_BLOCKSIZE);
505    }
506    break;
507  case MODE_OFB:		/* 128-bit output feedback */
508    memcpy(block, iv, RIJNDAEL_BLOCKSIZE);
509    for (i=0; i<nblocks; i++) {
510      rijndael_encrypt(ctx, block, block);
511      for (j=0; j<RIJNDAEL_BLOCKSIZE; j++) {
512	output[RIJNDAEL_BLOCKSIZE*i + j] = block[j] ^
513	  input[RIJNDAEL_BLOCKSIZE*i + j];
514      }
515    }
516    break;
517  case MODE_CTR:		/* counter */
518    memcpy(block, iv, RIJNDAEL_BLOCKSIZE);
519    for (i=0; i<nblocks; i++) {
520      rijndael_encrypt(ctx, block, block2);
521      for (j=0; j<RIJNDAEL_BLOCKSIZE; j++) {
522	output[RIJNDAEL_BLOCKSIZE*i + j] = block2[j] ^
523	  input[RIJNDAEL_BLOCKSIZE*i + j];
524      }
525      block[RIJNDAEL_BLOCKSIZE-1]++;
526      carry_flg = block[RIJNDAEL_BLOCKSIZE-1] != 0 ? 0 : 1;
527      for (j=RIJNDAEL_BLOCKSIZE-2; j>=0; j--) {
528	if (carry_flg) {
529	  block[j]++;
530          carry_flg = block[j] != 0 ? 0 : 1;
531        } else
532	  break;
533      }
534    }
535    break;
536  default:
537    break;
538  }
539}
540
541void
542block_decrypt(RIJNDAEL_context *ctx, UINT8 *input, int inputlen,
543		   UINT8 *output, UINT8 *iv)
544{
545  int i, j, nblocks, carry_flg;
546  UINT8 block[RIJNDAEL_BLOCKSIZE], block2[RIJNDAEL_BLOCKSIZE];
547
548  nblocks = inputlen / RIJNDAEL_BLOCKSIZE;
549  switch (ctx->mode) {
550  case MODE_ECB:
551    for (i = 0; i<nblocks; i++) {
552      rijndael_decrypt(ctx, &input[RIJNDAEL_BLOCKSIZE*i],
553		       &output[RIJNDAEL_BLOCKSIZE*i]);
554    }
555    break;
556  case MODE_CBC:
557    /* first block */
558    rijndael_decrypt(ctx, input, block);
559    /* XOR the block with the IV to get the output */
560    for (i=0; i<RIJNDAEL_BLOCKSIZE; i++)
561      output[i] = block[i] ^ iv[i];
562    for (i=1; i<nblocks; i++) {
563      rijndael_decrypt(ctx, &input[i*RIJNDAEL_BLOCKSIZE], block);
564      for (j=0; j<RIJNDAEL_BLOCKSIZE; j++) {
565	output[i*RIJNDAEL_BLOCKSIZE + j] = block[j] ^
566	  input[(i-1)*RIJNDAEL_BLOCKSIZE + j];
567      }
568    }
569    break;
570  case MODE_CFB:		/* 128-bit cipher feedback */
571    memcpy(block, iv, RIJNDAEL_BLOCKSIZE);
572    for (i=0; i<nblocks; i++) {
573      rijndael_encrypt(ctx, block, block); /* ENCRYPT is right! */
574      for (j=0; j<RIJNDAEL_BLOCKSIZE; j++) {
575	output[RIJNDAEL_BLOCKSIZE*i + j] = block[j] ^
576	  input[RIJNDAEL_BLOCKSIZE*i + j];
577      }
578      memcpy(block, &input[RIJNDAEL_BLOCKSIZE*i], RIJNDAEL_BLOCKSIZE);
579    }
580    break;
581  case MODE_OFB:		/* 128-bit output feedback */
582    /* this is exactly the same as encryption in OFB...in fact you can use
583       the encryption in OFB mode to decrypt! */
584    memcpy(block, iv, RIJNDAEL_BLOCKSIZE);
585    for (i=0; i<nblocks; i++) {
586      rijndael_encrypt(ctx, block, block);
587      for (j=0; j<RIJNDAEL_BLOCKSIZE; j++) {
588	output[RIJNDAEL_BLOCKSIZE*i + j] = block[j] ^
589	  input[RIJNDAEL_BLOCKSIZE*i + j];
590      }
591    }
592    break;
593  case MODE_CTR:		/* counter */
594    memcpy(block, iv, RIJNDAEL_BLOCKSIZE);
595    for (i=0; i<nblocks; i++) {
596      rijndael_encrypt(ctx, block, block2);
597      for (j=0; j<RIJNDAEL_BLOCKSIZE; j++) {
598	output[RIJNDAEL_BLOCKSIZE*i + j] = block2[j] ^
599	  input[RIJNDAEL_BLOCKSIZE*i + j];
600      }
601      block[RIJNDAEL_BLOCKSIZE-1]++;
602      carry_flg = block[RIJNDAEL_BLOCKSIZE-1] != 0 ? 0 : 1;
603      for (j=RIJNDAEL_BLOCKSIZE-2; j>=0; j--) {
604	if (carry_flg) {
605	  block[j]++;
606          carry_flg = block[j] != 0 ? 0 : 1;
607        } else
608	  break;
609      }
610    }
611    break;
612  default:
613    break;
614  }
615}
616
617