• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
50 unsigned char aes_sbox[256];
51 
52 unsigned char aes_inv_sbox[256];
53 
54 uint32_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 
68 uint8_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 
75 uint8_t b = 99;
76 
77 
78 void
aes_init_sbox(void)79 aes_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 
91 void
aes_compute_tables(void)92 aes_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 
139 uint32_t U0[256], U1[256], U2[256], U3[256], U4[256];
140 
141 extern uint8_t aes_inv_sbox[256];
142 
143 void
aes_compute_inv_tables(void)144 aes_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 
196 err_status_t
197 aes_test_inverse(void);
198 
199 #define TABLES_32BIT 1
200 
201 #ifndef HIDE_AES_TABLES_MAIN
202 
203 int
main(void)204 main(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 
319 err_status_t
aes_test_inverse(void)320 aes_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