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
201#ifndef HIDE_AES_TABLES_MAIN
202
203int
204main(void) {
205  int i;
206
207  aes_init_sbox();
208  aes_compute_inv_tables();
209
210#if TABLES_32BIT
211  printf("uint32_t U0 = {");
212  for (i=0; i < 256; i++) {
213    if ((i % 4) == 0)
214      printf("\n");
215    printf("0x%0x, ", U0[i]);
216  }
217  printf("\n}\n");
218
219 printf("uint32_t U1 = {");
220  for (i=0; i < 256; i++) {
221    if ((i % 4) == 0)
222      printf("\n");
223    printf("0x%x, ", U1[i]);
224  }
225  printf("\n}\n");
226
227 printf("uint32_t U2 = {");
228  for (i=0; i < 256; i++) {
229    if ((i % 4) == 0)
230      printf("\n");
231    printf("0x%x, ", U2[i]);
232  }
233  printf("\n}\n");
234
235 printf("uint32_t U3 = {");
236  for (i=0; i < 256; i++) {
237    if ((i % 4) == 0)
238      printf("\n");
239    printf("0x%x, ", U3[i]);
240  }
241  printf("\n}\n");
242
243 printf("uint32_t U4 = {");
244 for (i=0; i < 256; i++) {
245    if ((i % 4) == 0)
246      printf("\n");
247    printf("0x%x, ", U4[i]);
248  }
249  printf("\n}\n");
250
251#else
252
253  printf("uint32_t U0 = {");
254  for (i=0; i < 256; i++) {
255    if ((i % 4) == 0)
256      printf("\n");
257    printf("0x%lx, ", U0[i]);
258  }
259  printf("\n}\n");
260
261 printf("uint32_t U1 = {");
262  for (i=0; i < 256; i++) {
263    if ((i % 4) == 0)
264      printf("\n");
265    printf("0x%lx, ", U1[i]);
266  }
267  printf("\n}\n");
268
269 printf("uint32_t U2 = {");
270  for (i=0; i < 256; i++) {
271    if ((i % 4) == 0)
272      printf("\n");
273    printf("0x%lx, ", U2[i]);
274  }
275  printf("\n}\n");
276
277 printf("uint32_t U3 = {");
278  for (i=0; i < 256; i++) {
279    if ((i % 4) == 0)
280      printf("\n");
281    printf("0x%lx, ", U3[i]);
282  }
283  printf("\n}\n");
284
285 printf("uint32_t U4 = {");
286 for (i=0; i < 256; i++) {
287    if ((i % 4) == 0)
288      printf("\n");
289    printf("0x%lx, ", U4[i]);
290  }
291  printf("\n}\n");
292
293
294#endif /* TABLES_32BIT */
295
296
297#if AES_INVERSE_TEST
298  /*
299   * test that aes_encrypt and aes_decrypt are actually
300   * inverses of each other
301   */
302
303  printf("aes inverse test: ");
304  if (aes_test_inverse() == err_status_ok)
305    printf("passed\n");
306  else {
307    printf("failed\n");
308    exit(1);
309  }
310#endif
311
312  return 0;
313}
314
315#endif // HIDE_AES_TABLES_MAIN
316
317#if AES_INVERSE_TEST
318
319err_status_t
320aes_test_inverse(void) {
321  v128_t x, y;
322  aes_expanded_key_t expanded_key, decrypt_key;
323  uint8_t plaintext[16] = {
324    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
325    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
326  };
327  uint8_t key[16] = {
328    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
329    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
330  };
331  v128_t k;
332  v128_set_to_zero(&x);
333
334  v128_copy_octet_string(&k, key);
335  v128_copy_octet_string(&x, plaintext);
336  aes_expand_encryption_key(k, expanded_key);
337  aes_expand_decryption_key(k, decrypt_key);
338  aes_encrypt(&x, expanded_key);
339  aes_decrypt(&x, decrypt_key);
340
341  /* compare to expected value then report */
342  v128_copy_octet_string(&y, plaintext);
343
344  if (v128_is_eq(&x, &y))
345    return err_status_ok;
346  return err_status_algo_fail;
347
348}
349
350#endif
351