1/*
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
347