source: mainline/uspace/lib/crypto/aes.c@ 1dcc0b9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1dcc0b9 was 1dcc0b9, checked in by Jan Kolarik <kolarik@…>, 11 years ago

Scanning whole 2.4GHz spectrum, created supplicant for managing connection between device STA and AP, finished association process between STA and AP, handling 4way handshake protocol used for key management, written needed cryptographic algorithms (AES, SHA1, HMAC, PBKDF2) for CCMP protocol, data communication on OPEN/CCMP networks.

  • Property mode set to 100644
File size: 11.6 KB
Line 
1/*
2 * Copyright (c) 2015 Jan Kolarik
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file aes.c
30 *
31 * Implementation of AES algorithm.
32 *
33 * Based on FIPS 197.
34 */
35
36#include <stdio.h>
37#include <errno.h>
38#include <mem.h>
39
40#include "crypto.h"
41
42/* Number of elements in rows/columns in AES arrays. */
43#define ELEMS 4
44
45/* Number of elements (words) in cipher. */
46#define CIPHER_ELEMS 4
47
48/* Length of AES block. */
49#define BLOCK_LEN 16
50
51/* Number of iterations in AES algorithm. */
52#define ROUNDS 10
53
54/*
55 * Irreducible polynomial used in AES algorithm.
56 *
57 * NOTE: x^8 + x^4 + x^3 + x + 1.
58 */
59#define AES_IP 0x1B
60
61/* Precomputed values for AES sub_byte transformation. */
62static const uint8_t sub_byte_array[BLOCK_LEN][BLOCK_LEN] = {
63 {
64 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
65 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76
66 },
67 {
68 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
69 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0
70 },
71 {
72 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
73 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15
74 },
75 {
76 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
77 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75
78 },
79 {
80 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
81 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84
82 },
83 {
84 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
85 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf
86 },
87 {
88 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
89 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8
90 },
91 {
92 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
93 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2
94 },
95 {
96 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
97 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73
98 },
99 {
100 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
101 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb
102 },
103 {
104 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
105 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79
106 },
107 {
108 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
109 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08
110 },
111 {
112 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
113 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a
114 },
115 {
116 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
117 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e
118 },
119 {
120 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
121 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf
122 },
123 {
124 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
125 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
126 }
127};
128
129/* Precomputed values for AES inv_sub_byte transformation. */
130static uint8_t inv_sub_byte_array[BLOCK_LEN][BLOCK_LEN] = {
131 {
132 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
133 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
134 },
135 {
136 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
137 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
138 },
139 {
140 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
141 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
142 },
143 {
144 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
145 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
146 },
147 {
148 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
149 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
150 },
151 {
152 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
153 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
154 },
155 {
156 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
157 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
158 },
159 {
160 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
161 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
162 },
163 {
164 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
165 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
166 },
167 {
168 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
169 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
170 },
171 {
172 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
173 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
174 },
175 {
176 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
177 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
178 },
179 {
180 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
181 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
182 },
183 {
184 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
185 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
186 },
187 {
188 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
189 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
190 },
191 {
192 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
193 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
194 }
195};
196
197/* Precomputed values of powers of 2 in GF(2^8) left shifted by 24b. */
198static const uint32_t r_con_array[] = {
199 0x01000000, 0x02000000, 0x04000000, 0x08000000,
200 0x10000000, 0x20000000, 0x40000000, 0x80000000,
201 0x1B000000, 0x36000000
202};
203
204static uint8_t sub_byte(uint8_t byte, bool inv)
205{
206 uint8_t i = byte >> 4;
207 uint8_t j = byte & 0xF;
208
209 if(!inv) {
210 return sub_byte_array[i][j];
211 } else {
212 return inv_sub_byte_array[i][j];
213 }
214}
215
216static void sub_bytes(uint8_t state[ELEMS][ELEMS], bool inv)
217{
218 uint8_t val;
219
220 for(size_t i = 0; i < ELEMS; i++) {
221 for(size_t j = 0; j < ELEMS; j++) {
222 val = state[i][j];
223 state[i][j] = sub_byte(val, inv);
224 }
225 }
226}
227
228static void shift_rows(uint8_t state[ELEMS][ELEMS])
229{
230 uint8_t temp[ELEMS];
231
232 for(size_t i = 1; i < ELEMS; i++) {
233 memcpy(temp, state[i], i);
234 memcpy(state[i], state[i] + i, ELEMS - i);
235 memcpy(state[i] + ELEMS - i, temp, i);
236 }
237}
238
239static void inv_shift_rows(uint8_t state[ELEMS][ELEMS])
240{
241 uint8_t temp[ELEMS];
242
243 for(size_t i = 1; i < ELEMS; i++) {
244 memcpy(temp, state[i], ELEMS - i);
245 memcpy(state[i], state[i] + ELEMS - i, i);
246 memcpy(state[i] + i, temp, ELEMS - i);
247 }
248}
249
250static uint8_t galois_mult(uint8_t x, uint8_t y) {
251 uint8_t result = 0;
252 uint8_t F_bitH;
253
254 for(size_t i = 0; i < 8; i++) {
255 if (y & 1)
256 result ^= x;
257 F_bitH = (x & 0x80);
258 x <<= 1;
259 if (F_bitH)
260 x ^= AES_IP;
261 y >>= 1;
262 }
263
264 return result;
265}
266
267static void mix_columns(uint8_t state[ELEMS][ELEMS])
268{
269 uint8_t orig_state[ELEMS][ELEMS];
270 memcpy(orig_state, state, BLOCK_LEN);
271
272 for(size_t j = 0; j < ELEMS; j++) {
273 state[0][j] =
274 galois_mult(0x2, orig_state[0][j]) ^
275 galois_mult(0x3, orig_state[1][j]) ^
276 orig_state[2][j] ^
277 orig_state[3][j];
278 state[1][j] =
279 orig_state[0][j] ^
280 galois_mult(0x2, orig_state[1][j]) ^
281 galois_mult(0x3, orig_state[2][j]) ^
282 orig_state[3][j];
283 state[2][j] =
284 orig_state[0][j] ^
285 orig_state[1][j] ^
286 galois_mult(0x2, orig_state[2][j]) ^
287 galois_mult(0x3, orig_state[3][j]);
288 state[3][j] =
289 galois_mult(0x3, orig_state[0][j]) ^
290 orig_state[1][j] ^
291 orig_state[2][j] ^
292 galois_mult(0x2, orig_state[3][j]);
293 }
294}
295
296static void inv_mix_columns(uint8_t state[ELEMS][ELEMS])
297{
298 uint8_t orig_state[ELEMS][ELEMS];
299 memcpy(orig_state, state, BLOCK_LEN);
300
301 for(size_t j = 0; j < ELEMS; j++) {
302 state[0][j] =
303 galois_mult(0x0E, orig_state[0][j]) ^
304 galois_mult(0x0B, orig_state[1][j]) ^
305 galois_mult(0x0D, orig_state[2][j]) ^
306 galois_mult(0x09, orig_state[3][j]);
307 state[1][j] =
308 galois_mult(0x09, orig_state[0][j]) ^
309 galois_mult(0x0E, orig_state[1][j]) ^
310 galois_mult(0x0B, orig_state[2][j]) ^
311 galois_mult(0x0D, orig_state[3][j]);
312 state[2][j] =
313 galois_mult(0x0D, orig_state[0][j]) ^
314 galois_mult(0x09, orig_state[1][j]) ^
315 galois_mult(0x0E, orig_state[2][j]) ^
316 galois_mult(0x0B, orig_state[3][j]);
317 state[3][j] =
318 galois_mult(0x0B, orig_state[0][j]) ^
319 galois_mult(0x0D, orig_state[1][j]) ^
320 galois_mult(0x09, orig_state[2][j]) ^
321 galois_mult(0x0E, orig_state[3][j]);
322 }
323}
324
325static void add_round_key(uint8_t state[ELEMS][ELEMS], uint32_t *round_key)
326{
327 uint8_t byte_round;
328 uint8_t shift;
329 uint32_t mask = 0xFF;
330
331 for(size_t j = 0; j < ELEMS; j++) {
332 for(size_t i = 0; i < ELEMS; i++) {
333 shift = 24 - 8*i;
334 byte_round = (round_key[j] & (mask << shift)) >> shift;
335 state[i][j] = state[i][j] ^ byte_round;
336 }
337 }
338}
339
340static uint32_t sub_word(uint32_t word)
341{
342 uint32_t temp = word;
343 uint8_t *start = (uint8_t *) &temp;
344
345 for(size_t i = 0; i < 4; i++) {
346 *(start+i) = sub_byte(*(start+i), false);
347 }
348
349 return temp;
350}
351
352static uint32_t rot_word(uint32_t word)
353{
354 return (word << 8 | word >> 24);
355}
356
357static void key_expansion(uint8_t *key, uint32_t *key_exp)
358{
359 uint32_t temp;
360
361 for(size_t i = 0; i < CIPHER_ELEMS; i++) {
362 key_exp[i] =
363 (key[4*i] << 24) +
364 (key[4*i+1] << 16) +
365 (key[4*i+2] << 8) +
366 (key[4*i+3]);
367 }
368
369 for(size_t i = CIPHER_ELEMS; i < ELEMS * (ROUNDS + 1); i++) {
370 temp = key_exp[i-1];
371
372 if((i % CIPHER_ELEMS) == 0) {
373 temp = sub_word(rot_word(temp)) ^
374 r_con_array[i/CIPHER_ELEMS - 1];
375 }
376
377 key_exp[i] = key_exp[i - CIPHER_ELEMS] ^ temp;
378 }
379}
380
381int aes_encrypt(uint8_t *key, uint8_t *input, uint8_t *output)
382{
383 if(!key || !input)
384 return EINVAL;
385
386 if(!output)
387 return ENOMEM;
388
389 /* Create key expansion. */
390 uint32_t key_exp[ELEMS * (ROUNDS+1)];
391 key_expansion(key, key_exp);
392
393 /* Copy input into state array. */
394 uint8_t state[ELEMS][ELEMS];
395 for(size_t i = 0; i < ELEMS; i++) {
396 for(size_t j = 0; j < ELEMS; j++) {
397 state[i][j] = input[i + ELEMS*j];
398 }
399 }
400
401 /* Processing loop. */
402 add_round_key(state, key_exp);
403
404 for(size_t k = 1; k <= ROUNDS; k++) {
405 sub_bytes(state, false);
406 for(size_t i = 0; i < ELEMS; i++) {
407 for(size_t j = 0; j < ELEMS; j++) {
408 printf("STATE SUB %d %d : %x\n", i, j, state[i][j]);
409 }
410 }
411 shift_rows(state);
412 for(size_t i = 0; i < ELEMS; i++) {
413 for(size_t j = 0; j < ELEMS; j++) {
414 printf("STATE SHIFT %d %d : %x\n", i, j, state[i][j]);
415 }
416 }
417 if(k < ROUNDS)
418 mix_columns(state);
419 add_round_key(state, key_exp + k*ELEMS);
420 }
421
422 /* Copy state array into output. */
423 for(size_t i = 0; i < ELEMS; i++) {
424 for(size_t j = 0; j < ELEMS; j++) {
425 output[i + j*ELEMS] = state[i][j];
426 }
427 }
428
429 return EOK;
430}
431
432int aes_decrypt(uint8_t *key, uint8_t *input, uint8_t *output)
433{
434 if(!key || !input)
435 return EINVAL;
436
437 if(!output)
438 return ENOMEM;
439
440 /* Create key expansion. */
441 uint32_t key_exp[ELEMS * (ROUNDS+1)];
442 key_expansion(key, key_exp);
443
444 /* Copy input into state array. */
445 uint8_t state[ELEMS][ELEMS];
446 for(size_t i = 0; i < ELEMS; i++) {
447 for(size_t j = 0; j < ELEMS; j++) {
448 state[i][j] = input[i + ELEMS*j];
449 }
450 }
451
452 /* Processing loop. */
453 add_round_key(state, key_exp + ROUNDS*ELEMS);
454
455 for(int k = ROUNDS - 1; k >= 0; k--) {
456 inv_shift_rows(state);
457 sub_bytes(state, true);
458 add_round_key(state, key_exp + k*ELEMS);
459 if(k > 0)
460 inv_mix_columns(state);
461 }
462
463 /* Copy state array into output. */
464 for(size_t i = 0; i < ELEMS; i++) {
465 for(size_t j = 0; j < ELEMS; j++) {
466 output[i + j*ELEMS] = state[i][j];
467 }
468 }
469
470 return EOK;
471}
Note: See TracBrowser for help on using the repository browser.