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 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 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 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 int 202 main(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 315 err_status_t 316 aes_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