]>
Commit | Line | Data |
---|---|---|
dfe89252 | 1 | /* |
2 | * rijndael-alg-fst.c v2.4 April '2000 | |
3 | * rijndael-alg-api.c v2.4 April '2000 | |
4 | * | |
5 | * Optimised ANSI C code | |
6 | * | |
7 | * authors: v1.0: Antoon Bosselaers | |
8 | * v2.0: Vincent Rijmen, K.U.Leuven | |
9 | * v2.3: Paulo Barreto | |
10 | * v2.4: Vincent Rijmen, K.U.Leuven | |
11 | * | |
12 | * This code is placed in the public domain. | |
13 | */ | |
14 | ||
15 | #include <stdio.h> | |
16 | #include <stdlib.h> | |
17 | #include <assert.h> | |
94ec8c6b | 18 | |
6bcf7caa | 19 | #include "config.h" |
94ec8c6b | 20 | #include "rijndael.h" |
dfe89252 | 21 | #include "rijndael_boxes.h" |
94ec8c6b | 22 | |
dfe89252 | 23 | int |
24 | rijndael_keysched(u_int8_t k[RIJNDAEL_MAXKC][4], | |
25 | u_int8_t W[RIJNDAEL_MAXROUNDS+1][4][4], int ROUNDS) | |
94ec8c6b | 26 | { |
dfe89252 | 27 | /* Calculate the necessary round keys |
28 | * The number of calculations depends on keyBits and blockBits | |
29 | */ | |
30 | int j, r, t, rconpointer = 0; | |
31 | u_int8_t tk[RIJNDAEL_MAXKC][4]; | |
32 | int KC = ROUNDS - 6; | |
33 | ||
34 | for (j = KC-1; j >= 0; j--) { | |
35 | *((u_int32_t*)tk[j]) = *((u_int32_t*)k[j]); | |
94ec8c6b | 36 | } |
dfe89252 | 37 | r = 0; |
38 | t = 0; | |
39 | /* copy values into round key array */ | |
40 | for (j = 0; (j < KC) && (r < ROUNDS + 1); ) { | |
41 | for (; (j < KC) && (t < 4); j++, t++) { | |
42 | *((u_int32_t*)W[r][t]) = *((u_int32_t*)tk[j]); | |
43 | } | |
44 | if (t == 4) { | |
45 | r++; | |
46 | t = 0; | |
94ec8c6b | 47 | } |
48 | } | |
dfe89252 | 49 | |
50 | while (r < ROUNDS + 1) { /* while not enough round key material calculated */ | |
51 | /* calculate new values */ | |
52 | tk[0][0] ^= S[tk[KC-1][1]]; | |
53 | tk[0][1] ^= S[tk[KC-1][2]]; | |
54 | tk[0][2] ^= S[tk[KC-1][3]]; | |
55 | tk[0][3] ^= S[tk[KC-1][0]]; | |
56 | tk[0][0] ^= rcon[rconpointer++]; | |
57 | ||
58 | if (KC != 8) { | |
59 | for (j = 1; j < KC; j++) { | |
60 | *((u_int32_t*)tk[j]) ^= *((u_int32_t*)tk[j-1]); | |
61 | } | |
62 | } else { | |
63 | for (j = 1; j < KC/2; j++) { | |
64 | *((u_int32_t*)tk[j]) ^= *((u_int32_t*)tk[j-1]); | |
65 | } | |
66 | tk[KC/2][0] ^= S[tk[KC/2 - 1][0]]; | |
67 | tk[KC/2][1] ^= S[tk[KC/2 - 1][1]]; | |
68 | tk[KC/2][2] ^= S[tk[KC/2 - 1][2]]; | |
69 | tk[KC/2][3] ^= S[tk[KC/2 - 1][3]]; | |
70 | for (j = KC/2 + 1; j < KC; j++) { | |
71 | *((u_int32_t*)tk[j]) ^= *((u_int32_t*)tk[j-1]); | |
72 | } | |
73 | } | |
74 | /* copy values into round key array */ | |
75 | for (j = 0; (j < KC) && (r < ROUNDS + 1); ) { | |
76 | for (; (j < KC) && (t < 4); j++, t++) { | |
77 | *((u_int32_t*)W[r][t]) = *((u_int32_t*)tk[j]); | |
78 | } | |
79 | if (t == 4) { | |
80 | r++; | |
81 | t = 0; | |
82 | } | |
83 | } | |
84 | } | |
85 | return 0; | |
9ea53ba5 | 86 | } |
94ec8c6b | 87 | |
dfe89252 | 88 | int |
89 | rijndael_key_enc_to_dec(u_int8_t W[RIJNDAEL_MAXROUNDS+1][4][4], int ROUNDS) | |
90 | { | |
91 | int r; | |
92 | u_int8_t *w; | |
93 | ||
94 | for (r = 1; r < ROUNDS; r++) { | |
95 | w = W[r][0]; | |
96 | *((u_int32_t*)w) = *((u_int32_t*)U1[w[0]]) | |
97 | ^ *((u_int32_t*)U2[w[1]]) | |
98 | ^ *((u_int32_t*)U3[w[2]]) | |
99 | ^ *((u_int32_t*)U4[w[3]]); | |
100 | ||
101 | w = W[r][1]; | |
102 | *((u_int32_t*)w) = *((u_int32_t*)U1[w[0]]) | |
103 | ^ *((u_int32_t*)U2[w[1]]) | |
104 | ^ *((u_int32_t*)U3[w[2]]) | |
105 | ^ *((u_int32_t*)U4[w[3]]); | |
106 | ||
107 | w = W[r][2]; | |
108 | *((u_int32_t*)w) = *((u_int32_t*)U1[w[0]]) | |
109 | ^ *((u_int32_t*)U2[w[1]]) | |
110 | ^ *((u_int32_t*)U3[w[2]]) | |
111 | ^ *((u_int32_t*)U4[w[3]]); | |
112 | ||
113 | w = W[r][3]; | |
114 | *((u_int32_t*)w) = *((u_int32_t*)U1[w[0]]) | |
115 | ^ *((u_int32_t*)U2[w[1]]) | |
116 | ^ *((u_int32_t*)U3[w[2]]) | |
117 | ^ *((u_int32_t*)U4[w[3]]); | |
94ec8c6b | 118 | } |
dfe89252 | 119 | return 0; |
120 | } | |
121 | ||
122 | /** | |
123 | * Encrypt a single block. | |
124 | */ | |
125 | int | |
126 | rijndael_encrypt(rijndael_key *key, u_int8_t a[16], u_int8_t b[16]) | |
127 | { | |
128 | u_int8_t (*rk)[4][4] = key->keySched; | |
129 | int ROUNDS = key->ROUNDS; | |
130 | int r; | |
131 | u_int8_t temp[4][4]; | |
132 | ||
133 | *((u_int32_t*)temp[0]) = *((u_int32_t*)(a )) ^ *((u_int32_t*)rk[0][0]); | |
134 | *((u_int32_t*)temp[1]) = *((u_int32_t*)(a+ 4)) ^ *((u_int32_t*)rk[0][1]); | |
135 | *((u_int32_t*)temp[2]) = *((u_int32_t*)(a+ 8)) ^ *((u_int32_t*)rk[0][2]); | |
136 | *((u_int32_t*)temp[3]) = *((u_int32_t*)(a+12)) ^ *((u_int32_t*)rk[0][3]); | |
137 | *((u_int32_t*)(b )) = *((u_int32_t*)T1[temp[0][0]]) | |
138 | ^ *((u_int32_t*)T2[temp[1][1]]) | |
139 | ^ *((u_int32_t*)T3[temp[2][2]]) | |
140 | ^ *((u_int32_t*)T4[temp[3][3]]); | |
141 | *((u_int32_t*)(b + 4)) = *((u_int32_t*)T1[temp[1][0]]) | |
142 | ^ *((u_int32_t*)T2[temp[2][1]]) | |
143 | ^ *((u_int32_t*)T3[temp[3][2]]) | |
144 | ^ *((u_int32_t*)T4[temp[0][3]]); | |
145 | *((u_int32_t*)(b + 8)) = *((u_int32_t*)T1[temp[2][0]]) | |
146 | ^ *((u_int32_t*)T2[temp[3][1]]) | |
147 | ^ *((u_int32_t*)T3[temp[0][2]]) | |
148 | ^ *((u_int32_t*)T4[temp[1][3]]); | |
149 | *((u_int32_t*)(b +12)) = *((u_int32_t*)T1[temp[3][0]]) | |
150 | ^ *((u_int32_t*)T2[temp[0][1]]) | |
151 | ^ *((u_int32_t*)T3[temp[1][2]]) | |
152 | ^ *((u_int32_t*)T4[temp[2][3]]); | |
153 | for (r = 1; r < ROUNDS-1; r++) { | |
154 | *((u_int32_t*)temp[0]) = *((u_int32_t*)(b )) ^ *((u_int32_t*)rk[r][0]); | |
155 | *((u_int32_t*)temp[1]) = *((u_int32_t*)(b+ 4)) ^ *((u_int32_t*)rk[r][1]); | |
156 | *((u_int32_t*)temp[2]) = *((u_int32_t*)(b+ 8)) ^ *((u_int32_t*)rk[r][2]); | |
157 | *((u_int32_t*)temp[3]) = *((u_int32_t*)(b+12)) ^ *((u_int32_t*)rk[r][3]); | |
158 | ||
159 | *((u_int32_t*)(b )) = *((u_int32_t*)T1[temp[0][0]]) | |
160 | ^ *((u_int32_t*)T2[temp[1][1]]) | |
161 | ^ *((u_int32_t*)T3[temp[2][2]]) | |
162 | ^ *((u_int32_t*)T4[temp[3][3]]); | |
163 | *((u_int32_t*)(b + 4)) = *((u_int32_t*)T1[temp[1][0]]) | |
164 | ^ *((u_int32_t*)T2[temp[2][1]]) | |
165 | ^ *((u_int32_t*)T3[temp[3][2]]) | |
166 | ^ *((u_int32_t*)T4[temp[0][3]]); | |
167 | *((u_int32_t*)(b + 8)) = *((u_int32_t*)T1[temp[2][0]]) | |
168 | ^ *((u_int32_t*)T2[temp[3][1]]) | |
169 | ^ *((u_int32_t*)T3[temp[0][2]]) | |
170 | ^ *((u_int32_t*)T4[temp[1][3]]); | |
171 | *((u_int32_t*)(b +12)) = *((u_int32_t*)T1[temp[3][0]]) | |
172 | ^ *((u_int32_t*)T2[temp[0][1]]) | |
173 | ^ *((u_int32_t*)T3[temp[1][2]]) | |
174 | ^ *((u_int32_t*)T4[temp[2][3]]); | |
94ec8c6b | 175 | } |
dfe89252 | 176 | /* last round is special */ |
177 | *((u_int32_t*)temp[0]) = *((u_int32_t*)(b )) ^ *((u_int32_t*)rk[ROUNDS-1][0]); | |
178 | *((u_int32_t*)temp[1]) = *((u_int32_t*)(b+ 4)) ^ *((u_int32_t*)rk[ROUNDS-1][1]); | |
179 | *((u_int32_t*)temp[2]) = *((u_int32_t*)(b+ 8)) ^ *((u_int32_t*)rk[ROUNDS-1][2]); | |
180 | *((u_int32_t*)temp[3]) = *((u_int32_t*)(b+12)) ^ *((u_int32_t*)rk[ROUNDS-1][3]); | |
181 | b[ 0] = T1[temp[0][0]][1]; | |
182 | b[ 1] = T1[temp[1][1]][1]; | |
183 | b[ 2] = T1[temp[2][2]][1]; | |
184 | b[ 3] = T1[temp[3][3]][1]; | |
185 | b[ 4] = T1[temp[1][0]][1]; | |
186 | b[ 5] = T1[temp[2][1]][1]; | |
187 | b[ 6] = T1[temp[3][2]][1]; | |
188 | b[ 7] = T1[temp[0][3]][1]; | |
189 | b[ 8] = T1[temp[2][0]][1]; | |
190 | b[ 9] = T1[temp[3][1]][1]; | |
191 | b[10] = T1[temp[0][2]][1]; | |
192 | b[11] = T1[temp[1][3]][1]; | |
193 | b[12] = T1[temp[3][0]][1]; | |
194 | b[13] = T1[temp[0][1]][1]; | |
195 | b[14] = T1[temp[1][2]][1]; | |
196 | b[15] = T1[temp[2][3]][1]; | |
197 | *((u_int32_t*)(b )) ^= *((u_int32_t*)rk[ROUNDS][0]); | |
198 | *((u_int32_t*)(b+ 4)) ^= *((u_int32_t*)rk[ROUNDS][1]); | |
199 | *((u_int32_t*)(b+ 8)) ^= *((u_int32_t*)rk[ROUNDS][2]); | |
200 | *((u_int32_t*)(b+12)) ^= *((u_int32_t*)rk[ROUNDS][3]); | |
201 | ||
202 | return 0; | |
9ea53ba5 | 203 | } |
94ec8c6b | 204 | |
dfe89252 | 205 | /** |
206 | * Decrypt a single block. | |
207 | */ | |
208 | int | |
209 | rijndael_decrypt(rijndael_key *key, u_int8_t a[16], u_int8_t b[16]) | |
210 | { | |
211 | u_int8_t (*rk)[4][4] = key->keySched; | |
212 | int ROUNDS = key->ROUNDS; | |
213 | int r; | |
214 | u_int8_t temp[4][4]; | |
215 | ||
216 | *((u_int32_t*)temp[0]) = *((u_int32_t*)(a )) ^ *((u_int32_t*)rk[ROUNDS][0]); | |
217 | *((u_int32_t*)temp[1]) = *((u_int32_t*)(a+ 4)) ^ *((u_int32_t*)rk[ROUNDS][1]); | |
218 | *((u_int32_t*)temp[2]) = *((u_int32_t*)(a+ 8)) ^ *((u_int32_t*)rk[ROUNDS][2]); | |
219 | *((u_int32_t*)temp[3]) = *((u_int32_t*)(a+12)) ^ *((u_int32_t*)rk[ROUNDS][3]); | |
220 | ||
221 | *((u_int32_t*)(b )) = *((u_int32_t*)T5[temp[0][0]]) | |
222 | ^ *((u_int32_t*)T6[temp[3][1]]) | |
223 | ^ *((u_int32_t*)T7[temp[2][2]]) | |
224 | ^ *((u_int32_t*)T8[temp[1][3]]); | |
225 | *((u_int32_t*)(b+ 4)) = *((u_int32_t*)T5[temp[1][0]]) | |
226 | ^ *((u_int32_t*)T6[temp[0][1]]) | |
227 | ^ *((u_int32_t*)T7[temp[3][2]]) | |
228 | ^ *((u_int32_t*)T8[temp[2][3]]); | |
229 | *((u_int32_t*)(b+ 8)) = *((u_int32_t*)T5[temp[2][0]]) | |
230 | ^ *((u_int32_t*)T6[temp[1][1]]) | |
231 | ^ *((u_int32_t*)T7[temp[0][2]]) | |
232 | ^ *((u_int32_t*)T8[temp[3][3]]); | |
233 | *((u_int32_t*)(b+12)) = *((u_int32_t*)T5[temp[3][0]]) | |
234 | ^ *((u_int32_t*)T6[temp[2][1]]) | |
235 | ^ *((u_int32_t*)T7[temp[1][2]]) | |
236 | ^ *((u_int32_t*)T8[temp[0][3]]); | |
237 | for (r = ROUNDS-1; r > 1; r--) { | |
238 | *((u_int32_t*)temp[0]) = *((u_int32_t*)(b )) ^ *((u_int32_t*)rk[r][0]); | |
239 | *((u_int32_t*)temp[1]) = *((u_int32_t*)(b+ 4)) ^ *((u_int32_t*)rk[r][1]); | |
240 | *((u_int32_t*)temp[2]) = *((u_int32_t*)(b+ 8)) ^ *((u_int32_t*)rk[r][2]); | |
241 | *((u_int32_t*)temp[3]) = *((u_int32_t*)(b+12)) ^ *((u_int32_t*)rk[r][3]); | |
242 | *((u_int32_t*)(b )) = *((u_int32_t*)T5[temp[0][0]]) | |
243 | ^ *((u_int32_t*)T6[temp[3][1]]) | |
244 | ^ *((u_int32_t*)T7[temp[2][2]]) | |
245 | ^ *((u_int32_t*)T8[temp[1][3]]); | |
246 | *((u_int32_t*)(b+ 4)) = *((u_int32_t*)T5[temp[1][0]]) | |
247 | ^ *((u_int32_t*)T6[temp[0][1]]) | |
248 | ^ *((u_int32_t*)T7[temp[3][2]]) | |
249 | ^ *((u_int32_t*)T8[temp[2][3]]); | |
250 | *((u_int32_t*)(b+ 8)) = *((u_int32_t*)T5[temp[2][0]]) | |
251 | ^ *((u_int32_t*)T6[temp[1][1]]) | |
252 | ^ *((u_int32_t*)T7[temp[0][2]]) | |
253 | ^ *((u_int32_t*)T8[temp[3][3]]); | |
254 | *((u_int32_t*)(b+12)) = *((u_int32_t*)T5[temp[3][0]]) | |
255 | ^ *((u_int32_t*)T6[temp[2][1]]) | |
256 | ^ *((u_int32_t*)T7[temp[1][2]]) | |
257 | ^ *((u_int32_t*)T8[temp[0][3]]); | |
94ec8c6b | 258 | } |
dfe89252 | 259 | /* last round is special */ |
260 | *((u_int32_t*)temp[0]) = *((u_int32_t*)(b )) ^ *((u_int32_t*)rk[1][0]); | |
261 | *((u_int32_t*)temp[1]) = *((u_int32_t*)(b+ 4)) ^ *((u_int32_t*)rk[1][1]); | |
262 | *((u_int32_t*)temp[2]) = *((u_int32_t*)(b+ 8)) ^ *((u_int32_t*)rk[1][2]); | |
263 | *((u_int32_t*)temp[3]) = *((u_int32_t*)(b+12)) ^ *((u_int32_t*)rk[1][3]); | |
264 | b[ 0] = S5[temp[0][0]]; | |
265 | b[ 1] = S5[temp[3][1]]; | |
266 | b[ 2] = S5[temp[2][2]]; | |
267 | b[ 3] = S5[temp[1][3]]; | |
268 | b[ 4] = S5[temp[1][0]]; | |
269 | b[ 5] = S5[temp[0][1]]; | |
270 | b[ 6] = S5[temp[3][2]]; | |
271 | b[ 7] = S5[temp[2][3]]; | |
272 | b[ 8] = S5[temp[2][0]]; | |
273 | b[ 9] = S5[temp[1][1]]; | |
274 | b[10] = S5[temp[0][2]]; | |
275 | b[11] = S5[temp[3][3]]; | |
276 | b[12] = S5[temp[3][0]]; | |
277 | b[13] = S5[temp[2][1]]; | |
278 | b[14] = S5[temp[1][2]]; | |
279 | b[15] = S5[temp[0][3]]; | |
280 | *((u_int32_t*)(b )) ^= *((u_int32_t*)rk[0][0]); | |
281 | *((u_int32_t*)(b+ 4)) ^= *((u_int32_t*)rk[0][1]); | |
282 | *((u_int32_t*)(b+ 8)) ^= *((u_int32_t*)rk[0][2]); | |
283 | *((u_int32_t*)(b+12)) ^= *((u_int32_t*)rk[0][3]); | |
284 | ||
285 | return 0; | |
286 | } | |
94ec8c6b | 287 | |
dfe89252 | 288 | int |
289 | rijndael_makekey(rijndael_key *key, int direction, int keyLen, u_int8_t *keyMaterial) | |
290 | { | |
291 | u_int8_t k[RIJNDAEL_MAXKC][4]; | |
292 | int i; | |
293 | ||
294 | if (key == NULL) | |
295 | return -1; | |
296 | if ((direction != RIJNDAEL_ENCRYPT) && (direction != RIJNDAEL_DECRYPT)) | |
297 | return -1; | |
298 | if ((keyLen != 128) && (keyLen != 192) && (keyLen != 256)) | |
299 | return -1; | |
300 | ||
301 | key->ROUNDS = keyLen/32 + 6; | |
302 | ||
303 | /* initialize key schedule: */ | |
304 | for (i = 0; i < keyLen/8; i++) | |
305 | k[i >> 2][i & 3] = (u_int8_t)keyMaterial[i]; | |
306 | ||
307 | rijndael_keysched(k, key->keySched, key->ROUNDS); | |
308 | if (direction == RIJNDAEL_DECRYPT) | |
309 | rijndael_key_enc_to_dec(key->keySched, key->ROUNDS); | |
310 | return 0; | |
9ea53ba5 | 311 | } |