blob: b2bc1d78d1ab45e295a0b57a667068b42b216dc9 [file] [log] [blame]
Benny Prijono8a0ab282008-01-23 20:17:42 +00001/*
2 * aes_tables.c
3 *
4 * generate tables for the AES cipher
5 *
6 * David A. McGrew
7 * Cisco Systems, Inc.
8 */
9/*
10 *
11 * Copyright(c) 2001-2006 Cisco Systems, Inc.
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials provided
24 * with the distribution.
25 *
26 * Neither the name of the Cisco Systems, Inc. nor the names of its
27 * contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
41 * OF THE POSSIBILITY OF SUCH DAMAGE.
42 *
43 */
44
45#include <stdio.h>
46#include "gf2_8.h"
47#include "crypto_math.h"
48
49
50unsigned char aes_sbox[256];
51
52unsigned char aes_inv_sbox[256];
53
54uint32_t T0[256], T1[256], T2[256], T3[256], T4[256];
55
56
57#define AES_INVERSE_TEST 0 /* set to 1 to test forward/backwards aes */
58
59/* functions for precomputing AES values */
60
61/*
62 * A[] is the 8 x 8 binary matrix (represented as an array of columns,
63 * where each column is an octet) which defines the affine
64 * transformation used in the AES substitution table (Section
65 * 4.2.1 of the spec).
66 */
67
68uint8_t A[8] = { 31, 62, 124, 248, 241, 227, 199, 143 };
69
70/*
71 * b is the 8 bit vector (represented as an octet) used in the affine
72 * transform described above.
73 */
74
75uint8_t b = 99;
76
77
78void
79aes_init_sbox(void) {
80 unsigned int i;
81 uint8_t x;
82
83 for (i=0; i < 256; i++) {
84 x = gf2_8_compute_inverse((gf2_8)i);
85 x = A_times_x_plus_b(A, x, b);
86 aes_sbox[i] = x;
87 aes_inv_sbox[x] = i;
88 }
89}
90
91void
92aes_compute_tables(void) {
93 int i;
94 uint32_t x1, x2, x3;
95 v32_t tmp;
96
97 /* initialize substitution table */
98 aes_init_sbox();
99
100 /* combine sbox with linear operations to form 8-bit to 32-bit tables */
101 for (i=0; i < 256; i++) {
102 x1 = aes_sbox[i];
103 x2 = gf2_8_shift(x1);
104 x3 = x2 ^ x1;
105
106 tmp.v8[0] = x2;
107 tmp.v8[1] = x1;
108 tmp.v8[2] = x1;
109 tmp.v8[3] = x3;
110 T0[i] = tmp.value;
111
112 tmp.v8[0] = x3;
113 tmp.v8[1] = x2;
114 tmp.v8[2] = x1;
115 tmp.v8[3] = x1;
116 T1[i] = tmp.value;
117
118 tmp.v8[0] = x1;
119 tmp.v8[1] = x3;
120 tmp.v8[2] = x2;
121 tmp.v8[3] = x1;
122 T2[i] = tmp.value;
123
124 tmp.v8[0] = x1;
125 tmp.v8[1] = x1;
126 tmp.v8[2] = x3;
127 tmp.v8[3] = x2;
128 T3[i] = tmp.value;
129
130 }
131}
132
133
134/*
135 * the tables U0, U1, U2, U3 implement the aes operations invSubBytes,
136 * invMixColumns, and invShiftRows
137 */
138
139uint32_t U0[256], U1[256], U2[256], U3[256], U4[256];
140
141extern uint8_t aes_inv_sbox[256];
142
143void
144aes_compute_inv_tables(void) {
145 int i;
146 uint8_t x, xe, x9, xd, xb;
147 v32_t tmp;
148
149 /* combine sbox with linear operations to form 8-bit to 32-bit tables */
150 for (i=0; i < 256; i++) {
151 x = aes_inv_sbox[i];
152
153 xe = gf2_8_multiply(0x0e, x);
154 x9 = gf2_8_multiply(0x09, x);
155 xd = gf2_8_multiply(0x0d, x);
156 xb = gf2_8_multiply(0x0b, x);
157
158 tmp.v8[0] = xe;
159 tmp.v8[1] = x9;
160 tmp.v8[2] = xd;
161 tmp.v8[3] = xb;
162 U0[i] = tmp.value;
163
164 tmp.v8[0] = xb;
165 tmp.v8[1] = xe;
166 tmp.v8[2] = x9;
167 tmp.v8[3] = xd;
168 U1[i] = tmp.value;
169
170 tmp.v8[0] = xd;
171 tmp.v8[1] = xb;
172 tmp.v8[2] = xe;
173 tmp.v8[3] = x9;
174 U2[i] = tmp.value;
175
176 tmp.v8[0] = x9;
177 tmp.v8[1] = xd;
178 tmp.v8[2] = xb;
179 tmp.v8[3] = xe;
180 U3[i] = tmp.value;
181
182 tmp.v8[0] = tmp.v8[1] = tmp.v8[2] = tmp.v8[3] = x;
183 U4[i] = tmp.value;
184 }
185}
186
187
188/*
189 * aes_test_inverse() returns err_status_ok if aes
190 * encryption and decryption are true inverses of each other, and
191 * returns err_status_algo_fail otherwise
192 */
193
194#include "err.h"
195
196err_status_t
197aes_test_inverse(void);
198
199#define TABLES_32BIT 1
200
201int
202main(void) {
203 int i;
204
205 aes_init_sbox();
206 aes_compute_inv_tables();
207
208#if TABLES_32BIT
209 printf("uint32_t U0 = {");
210 for (i=0; i < 256; i++) {
211 if ((i % 4) == 0)
212 printf("\n");
213 printf("0x%0x, ", U0[i]);
214 }
215 printf("\n}\n");
216
217 printf("uint32_t U1 = {");
218 for (i=0; i < 256; i++) {
219 if ((i % 4) == 0)
220 printf("\n");
221 printf("0x%x, ", U1[i]);
222 }
223 printf("\n}\n");
224
225 printf("uint32_t U2 = {");
226 for (i=0; i < 256; i++) {
227 if ((i % 4) == 0)
228 printf("\n");
229 printf("0x%x, ", U2[i]);
230 }
231 printf("\n}\n");
232
233 printf("uint32_t U3 = {");
234 for (i=0; i < 256; i++) {
235 if ((i % 4) == 0)
236 printf("\n");
237 printf("0x%x, ", U3[i]);
238 }
239 printf("\n}\n");
240
241 printf("uint32_t U4 = {");
242 for (i=0; i < 256; i++) {
243 if ((i % 4) == 0)
244 printf("\n");
245 printf("0x%x, ", U4[i]);
246 }
247 printf("\n}\n");
248
249#else
250
251 printf("uint32_t U0 = {");
252 for (i=0; i < 256; i++) {
253 if ((i % 4) == 0)
254 printf("\n");
255 printf("0x%lx, ", U0[i]);
256 }
257 printf("\n}\n");
258
259 printf("uint32_t U1 = {");
260 for (i=0; i < 256; i++) {
261 if ((i % 4) == 0)
262 printf("\n");
263 printf("0x%lx, ", U1[i]);
264 }
265 printf("\n}\n");
266
267 printf("uint32_t U2 = {");
268 for (i=0; i < 256; i++) {
269 if ((i % 4) == 0)
270 printf("\n");
271 printf("0x%lx, ", U2[i]);
272 }
273 printf("\n}\n");
274
275 printf("uint32_t U3 = {");
276 for (i=0; i < 256; i++) {
277 if ((i % 4) == 0)
278 printf("\n");
279 printf("0x%lx, ", U3[i]);
280 }
281 printf("\n}\n");
282
283 printf("uint32_t U4 = {");
284 for (i=0; i < 256; i++) {
285 if ((i % 4) == 0)
286 printf("\n");
287 printf("0x%lx, ", U4[i]);
288 }
289 printf("\n}\n");
290
291
292#endif /* TABLES_32BIT */
293
294
295#if AES_INVERSE_TEST
296 /*
297 * test that aes_encrypt and aes_decrypt are actually
298 * inverses of each other
299 */
300
301 printf("aes inverse test: ");
302 if (aes_test_inverse() == err_status_ok)
303 printf("passed\n");
304 else {
305 printf("failed\n");
306 exit(1);
307 }
308#endif
309
310 return 0;
311}
312
313#if AES_INVERSE_TEST
314
315err_status_t
316aes_test_inverse(void) {
317 v128_t x, y;
318 aes_expanded_key_t expanded_key, decrypt_key;
319 uint8_t plaintext[16] = {
320 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
321 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
322 };
323 uint8_t key[16] = {
324 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
325 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
326 };
327 v128_t k;
328 v128_set_to_zero(&x);
329
330 v128_copy_octet_string(&k, key);
331 v128_copy_octet_string(&x, plaintext);
332 aes_expand_encryption_key(k, expanded_key);
333 aes_expand_decryption_key(k, decrypt_key);
334 aes_encrypt(&x, expanded_key);
335 aes_decrypt(&x, decrypt_key);
336
337 /* compare to expected value then report */
338 v128_copy_octet_string(&y, plaintext);
339
340 if (v128_is_eq(&x, &y))
341 return err_status_ok;
342 return err_status_algo_fail;
343
344}
345
346#endif