/src/hostap/src/crypto/aes-internal-enc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * AES (Rijndael) cipher - encrypt |
3 | | * |
4 | | * Modifications to public domain implementation: |
5 | | * - cleanup |
6 | | * - use C pre-processor to make it easier to change S table access |
7 | | * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at |
8 | | * cost of reduced throughput (quite small difference on Pentium 4, |
9 | | * 10-25% when using -O1 or -O2 optimization) |
10 | | * |
11 | | * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> |
12 | | * |
13 | | * This software may be distributed under the terms of the BSD license. |
14 | | * See README for more details. |
15 | | */ |
16 | | |
17 | | #include "includes.h" |
18 | | |
19 | | #include "common.h" |
20 | | #include "crypto.h" |
21 | | #include "aes_i.h" |
22 | | |
23 | | static void rijndaelEncrypt(const u32 rk[], int Nr, const u8 pt[16], u8 ct[16]) |
24 | 0 | { |
25 | 0 | u32 s0, s1, s2, s3, t0, t1, t2, t3; |
26 | 0 | #ifndef FULL_UNROLL |
27 | 0 | int r; |
28 | 0 | #endif /* ?FULL_UNROLL */ |
29 | | |
30 | | /* |
31 | | * map byte array block to cipher state |
32 | | * and add initial round key: |
33 | | */ |
34 | 0 | s0 = GETU32(pt ) ^ rk[0]; |
35 | 0 | s1 = GETU32(pt + 4) ^ rk[1]; |
36 | 0 | s2 = GETU32(pt + 8) ^ rk[2]; |
37 | 0 | s3 = GETU32(pt + 12) ^ rk[3]; |
38 | |
|
39 | 0 | #define ROUND(i,d,s) \ |
40 | 0 | d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ |
41 | 0 | d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ |
42 | 0 | d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ |
43 | 0 | d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] |
44 | |
|
45 | | #ifdef FULL_UNROLL |
46 | | |
47 | | ROUND(1,t,s); |
48 | | ROUND(2,s,t); |
49 | | ROUND(3,t,s); |
50 | | ROUND(4,s,t); |
51 | | ROUND(5,t,s); |
52 | | ROUND(6,s,t); |
53 | | ROUND(7,t,s); |
54 | | ROUND(8,s,t); |
55 | | ROUND(9,t,s); |
56 | | if (Nr > 10) { |
57 | | ROUND(10,s,t); |
58 | | ROUND(11,t,s); |
59 | | if (Nr > 12) { |
60 | | ROUND(12,s,t); |
61 | | ROUND(13,t,s); |
62 | | } |
63 | | } |
64 | | |
65 | | rk += Nr << 2; |
66 | | |
67 | | #else /* !FULL_UNROLL */ |
68 | | |
69 | | /* Nr - 1 full rounds: */ |
70 | 0 | r = Nr >> 1; |
71 | 0 | for (;;) { |
72 | 0 | ROUND(1,t,s); |
73 | 0 | rk += 8; |
74 | 0 | if (--r == 0) |
75 | 0 | break; |
76 | 0 | ROUND(0,s,t); |
77 | 0 | } |
78 | |
|
79 | 0 | #endif /* ?FULL_UNROLL */ |
80 | |
|
81 | 0 | #undef ROUND |
82 | | |
83 | | /* |
84 | | * apply last round and |
85 | | * map cipher state to byte array block: |
86 | | */ |
87 | 0 | s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; |
88 | 0 | PUTU32(ct , s0); |
89 | 0 | s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; |
90 | 0 | PUTU32(ct + 4, s1); |
91 | 0 | s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; |
92 | 0 | PUTU32(ct + 8, s2); |
93 | 0 | s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; |
94 | 0 | PUTU32(ct + 12, s3); |
95 | 0 | } |
96 | | |
97 | | |
98 | | void * aes_encrypt_init(const u8 *key, size_t len) |
99 | 0 | { |
100 | 0 | u32 *rk; |
101 | 0 | int res; |
102 | |
|
103 | 0 | if (TEST_FAIL()) |
104 | 0 | return NULL; |
105 | | |
106 | 0 | rk = os_malloc(AES_PRIV_SIZE); |
107 | 0 | if (rk == NULL) |
108 | 0 | return NULL; |
109 | 0 | res = rijndaelKeySetupEnc(rk, key, len * 8); |
110 | 0 | if (res < 0) { |
111 | 0 | os_free(rk); |
112 | 0 | return NULL; |
113 | 0 | } |
114 | 0 | rk[AES_PRIV_NR_POS] = res; |
115 | 0 | return rk; |
116 | 0 | } |
117 | | |
118 | | |
119 | | int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) |
120 | 0 | { |
121 | 0 | u32 *rk = ctx; |
122 | 0 | rijndaelEncrypt(ctx, rk[AES_PRIV_NR_POS], plain, crypt); |
123 | 0 | return 0; |
124 | 0 | } |
125 | | |
126 | | |
127 | | void aes_encrypt_deinit(void *ctx) |
128 | 0 | { |
129 | 0 | os_memset(ctx, 0, AES_PRIV_SIZE); |
130 | 0 | os_free(ctx); |
131 | 0 | } |