1 /* rijndael-alg-ref.c v2.0 August '99
2 * Reference ANSI C code
3 * authors: Paulo Barreto
4 * Vincent Rijmen
5 *
6 * This code is placed in the public domain.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11
12 #include "rijndael-alg-ref.h"
13
14 #define SC ((BC - 4) >> 1)
15
16 #include "boxes-ref.dat"
17
18 static word8 shifts[3][4][2] = {
19 { { 0, 0 },
20 { 1, 3 },
21 { 2, 2 },
22 { 3, 1 } },
23
24 { { 0, 0 },
25 { 1, 5 },
26 { 2, 4 },
27 { 3, 3 } },
28
29 { { 0, 0 },
30 { 1, 7 },
31 { 3, 5 },
32 { 4, 4 } }
33 };
34
35 word8 mul(word8, word8);
36 void KeyAddition(word8 [][], word8 [][], word8);
37 void Substitution(word8 [][], word8 box[], word8);
38 void ShiftRow(word8 [][], word8, word8);
39 void MixColumn(word8 [][], word8);
40 void InvMixColumn(word8 [][], word8);
41
mul(word8 a,word8 b)42 word8 mul(word8 a, word8 b) {
43 /* multiply two elements of GF(2^m)
44 * needed for MixColumn and InvMixColumn
45 */
46 if (a && b) return Alogtable[(Logtable[a] + Logtable[b])%255];
47 else return 0;
48 }
49
KeyAddition(word8 a[4][MAXBC],word8 rk[4][MAXBC],word8 BC)50 void KeyAddition(word8 a[4][MAXBC], word8 rk[4][MAXBC], word8 BC) {
51 /* Exor corresponding text input and round key input bytes
52 */
53 int i, j;
54
55 for(i = 0; i < 4; i++)
56 for(j = 0; j < BC; j++) a[i][j] ^= rk[i][j];
57 }
58
ShiftRow(word8 a[4][MAXBC],word8 d,word8 BC)59 void ShiftRow(word8 a[4][MAXBC], word8 d, word8 BC) {
60 /* Row 0 remains unchanged
61 * The other three rows are shifted a variable amount
62 */
63 word8 tmp[MAXBC];
64 int i, j;
65
66 for(i = 1; i < 4; i++) {
67 for(j = 0; j < BC; j++) tmp[j] = a[i][(j + shifts[SC][i][d]) % BC];
68 for(j = 0; j < BC; j++) a[i][j] = tmp[j];
69 }
70 }
71
Substitution(word8 a[4][MAXBC],word8 box[256],word8 BC)72 void Substitution(word8 a[4][MAXBC], word8 box[256], word8 BC) {
73 /* Replace every byte of the input by the byte at that place
74 * in the nonlinear S-box
75 */
76 int i, j;
77
78 for(i = 0; i < 4; i++)
79 for(j = 0; j < BC; j++) a[i][j] = box[a[i][j]] ;
80 }
81
MixColumn(word8 a[4][MAXBC],word8 BC)82 void MixColumn(word8 a[4][MAXBC], word8 BC) {
83 /* Mix the four bytes of every column in a linear way
84 */
85 word8 b[4][MAXBC];
86 int i, j;
87
88 for(j = 0; j < BC; j++)
89 for(i = 0; i < 4; i++)
90 b[i][j] = mul(2,a[i][j])
91 ^ mul(3,a[(i + 1) % 4][j])
92 ^ a[(i + 2) % 4][j]
93 ^ a[(i + 3) % 4][j];
94 for(i = 0; i < 4; i++)
95 for(j = 0; j < BC; j++) a[i][j] = b[i][j];
96 }
97
InvMixColumn(word8 a[4][MAXBC],word8 BC)98 void InvMixColumn(word8 a[4][MAXBC], word8 BC) {
99 /* Mix the four bytes of every column in a linear way
100 * This is the opposite operation of Mixcolumn
101 */
102 word8 b[4][MAXBC];
103 int i, j;
104
105 for(j = 0; j < BC; j++)
106 for(i = 0; i < 4; i++)
107 b[i][j] = mul(0xe,a[i][j])
108 ^ mul(0xb,a[(i + 1) % 4][j])
109 ^ mul(0xd,a[(i + 2) % 4][j])
110 ^ mul(0x9,a[(i + 3) % 4][j]);
111 for(i = 0; i < 4; i++)
112 for(j = 0; j < BC; j++) a[i][j] = b[i][j];
113 }
114
rijndaelKeySched(word8 k[4][MAXKC],int keyBits,int blockBits,word8 W[MAXROUNDS+1][4][MAXBC])115 int rijndaelKeySched (word8 k[4][MAXKC], int keyBits, int blockBits, word8 W[MAXROUNDS+1][4][MAXBC]) {
116 /* Calculate the necessary round keys
117 * The number of calculations depends on keyBits and blockBits
118 */
119 int KC, BC, ROUNDS;
120 int i, j, t, rconpointer = 0;
121 word8 tk[4][MAXKC];
122
123 switch (keyBits) {
124 case 128: KC = 4; break;
125 case 192: KC = 6; break;
126 case 256: KC = 8; break;
127 default : return (-1);
128 }
129
130 switch (blockBits) {
131 case 128: BC = 4; break;
132 case 192: BC = 6; break;
133 case 256: BC = 8; break;
134 default : return (-2);
135 }
136
137 switch (keyBits >= blockBits ? keyBits : blockBits) {
138 case 128: ROUNDS = 10; break;
139 case 192: ROUNDS = 12; break;
140 case 256: ROUNDS = 14; break;
141 default : return (-3); /* this cannot happen */
142 }
143
144
145 for(j = 0; j < KC; j++)
146 for(i = 0; i < 4; i++)
147 tk[i][j] = k[i][j];
148 t = 0;
149 /* copy values into round key array */
150 for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++)
151 for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j];
152
153 while (t < (ROUNDS+1)*BC) { /* while not enough round key material calculated */
154 /* calculate new values */
155 for(i = 0; i < 4; i++)
156 tk[i][0] ^= S[tk[(i+1)%4][KC-1]];
157 tk[0][0] ^= rcon[rconpointer++];
158
159 if (KC != 8)
160 for(j = 1; j < KC; j++)
161 for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1];
162 else {
163 for(j = 1; j < KC/2; j++)
164 for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1];
165 for(i = 0; i < 4; i++) tk[i][KC/2] ^= S[tk[i][KC/2 - 1]];
166 for(j = KC/2 + 1; j < KC; j++)
167 for(i = 0; i < 4; i++) tk[i][j] ^= tk[i][j-1];
168 }
169 /* copy values into round key array */
170 for(j = 0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++)
171 for(i = 0; i < 4; i++) W[t / BC][i][t % BC] = tk[i][j];
172 }
173
174 return 0;
175 }
176
rijndaelEncrypt(word8 a[4][MAXBC],int keyBits,int blockBits,word8 rk[MAXROUNDS+1][4][MAXBC])177 int rijndaelEncrypt (word8 a[4][MAXBC], int keyBits, int blockBits, word8 rk[MAXROUNDS+1][4][MAXBC])
178 {
179 /* Encryption of one block.
180 */
181 int r, BC, ROUNDS;
182
183 switch (blockBits) {
184 case 128: BC = 4; break;
185 case 192: BC = 6; break;
186 case 256: BC = 8; break;
187 default : return (-2);
188 }
189
190 switch (keyBits >= blockBits ? keyBits : blockBits) {
191 case 128: ROUNDS = 10; break;
192 case 192: ROUNDS = 12; break;
193 case 256: ROUNDS = 14; break;
194 default : return (-3); /* this cannot happen */
195 }
196
197 /* begin with a key addition
198 */
199 KeyAddition(a,rk[0],BC);
200
201 /* ROUNDS-1 ordinary rounds
202 */
203 for(r = 1; r < ROUNDS; r++) {
204 Substitution(a,S,BC);
205 ShiftRow(a,0,BC);
206 MixColumn(a,BC);
207 KeyAddition(a,rk[r],BC);
208 }
209
210 /* Last round is special: there is no MixColumn
211 */
212 Substitution(a,S,BC);
213 ShiftRow(a,0,BC);
214 KeyAddition(a,rk[ROUNDS],BC);
215
216 return 0;
217 }
218
219
220
rijndaelEncryptRound(word8 a[4][MAXBC],int keyBits,int blockBits,word8 rk[MAXROUNDS+1][4][MAXBC],int rounds)221 int rijndaelEncryptRound (word8 a[4][MAXBC], int keyBits, int blockBits,
222 word8 rk[MAXROUNDS+1][4][MAXBC], int rounds)
223 /* Encrypt only a certain number of rounds.
224 * Only used in the Intermediate Value Known Answer Test.
225 */
226 {
227 int r, BC, ROUNDS;
228
229 switch (blockBits) {
230 case 128: BC = 4; break;
231 case 192: BC = 6; break;
232 case 256: BC = 8; break;
233 default : return (-2);
234 }
235
236 switch (keyBits >= blockBits ? keyBits : blockBits) {
237 case 128: ROUNDS = 10; break;
238 case 192: ROUNDS = 12; break;
239 case 256: ROUNDS = 14; break;
240 default : return (-3); /* this cannot happen */
241 }
242
243 /* make number of rounds sane */
244 if (rounds > ROUNDS) rounds = ROUNDS;
245
246 /* begin with a key addition
247 */
248 KeyAddition(a,rk[0],BC);
249
250 /* at most ROUNDS-1 ordinary rounds
251 */
252 for(r = 1; (r <= rounds) && (r < ROUNDS); r++) {
253 Substitution(a,S,BC);
254 ShiftRow(a,0,BC);
255 MixColumn(a,BC);
256 KeyAddition(a,rk[r],BC);
257 }
258
259 /* if necessary, do the last, special, round:
260 */
261 if (rounds == ROUNDS) {
262 Substitution(a,S,BC);
263 ShiftRow(a,0,BC);
264 KeyAddition(a,rk[ROUNDS],BC);
265 }
266
267 return 0;
268 }
269
270
rijndaelDecrypt(word8 a[4][MAXBC],int keyBits,int blockBits,word8 rk[MAXROUNDS+1][4][MAXBC])271 int rijndaelDecrypt (word8 a[4][MAXBC], int keyBits, int blockBits, word8 rk[MAXROUNDS+1][4][MAXBC])
272 {
273 int r, BC, ROUNDS;
274
275 switch (blockBits) {
276 case 128: BC = 4; break;
277 case 192: BC = 6; break;
278 case 256: BC = 8; break;
279 default : return (-2);
280 }
281
282 switch (keyBits >= blockBits ? keyBits : blockBits) {
283 case 128: ROUNDS = 10; break;
284 case 192: ROUNDS = 12; break;
285 case 256: ROUNDS = 14; break;
286 default : return (-3); /* this cannot happen */
287 }
288
289 /* To decrypt: apply the inverse operations of the encrypt routine,
290 * in opposite order
291 *
292 * (KeyAddition is an involution: it 's equal to its inverse)
293 * (the inverse of Substitution with table S is Substitution with the inverse table of S)
294 * (the inverse of Shiftrow is Shiftrow over a suitable distance)
295 */
296
297 /* First the special round:
298 * without InvMixColumn
299 * with extra KeyAddition
300 */
301 KeyAddition(a,rk[ROUNDS],BC);
302 Substitution(a,Si,BC);
303 ShiftRow(a,1,BC);
304
305 /* ROUNDS-1 ordinary rounds
306 */
307 for(r = ROUNDS-1; r > 0; r--) {
308 KeyAddition(a,rk[r],BC);
309 InvMixColumn(a,BC);
310 Substitution(a,Si,BC);
311 ShiftRow(a,1,BC);
312 }
313
314 /* End with the extra key addition
315 */
316
317 KeyAddition(a,rk[0],BC);
318
319 return 0;
320 }
321
322
rijndaelDecryptRound(word8 a[4][MAXBC],int keyBits,int blockBits,word8 rk[MAXROUNDS+1][4][MAXBC],int rounds)323 int rijndaelDecryptRound (word8 a[4][MAXBC], int keyBits, int blockBits,
324 word8 rk[MAXROUNDS+1][4][MAXBC], int rounds)
325 /* Decrypt only a certain number of rounds.
326 * Only used in the Intermediate Value Known Answer Test.
327 * Operations rearranged such that the intermediate values
328 * of decryption correspond with the intermediate values
329 * of encryption.
330 */
331 {
332 int r, BC, ROUNDS;
333
334 switch (blockBits) {
335 case 128: BC = 4; break;
336 case 192: BC = 6; break;
337 case 256: BC = 8; break;
338 default : return (-2);
339 }
340
341 switch (keyBits >= blockBits ? keyBits : blockBits) {
342 case 128: ROUNDS = 10; break;
343 case 192: ROUNDS = 12; break;
344 case 256: ROUNDS = 14; break;
345 default : return (-3); /* this cannot happen */
346 }
347
348
349 /* make number of rounds sane */
350 if (rounds > ROUNDS) rounds = ROUNDS;
351
352 /* First the special round:
353 * without InvMixColumn
354 * with extra KeyAddition
355 */
356 KeyAddition(a,rk[ROUNDS],BC);
357 Substitution(a,Si,BC);
358 ShiftRow(a,1,BC);
359
360 /* ROUNDS-1 ordinary rounds
361 */
362 for(r = ROUNDS-1; r > rounds; r--) {
363 KeyAddition(a,rk[r],BC);
364 InvMixColumn(a,BC);
365 Substitution(a,Si,BC);
366 ShiftRow(a,1,BC);
367 }
368
369 if (rounds == 0) {
370 /* End with the extra key addition
371 */
372 KeyAddition(a,rk[0],BC);
373 }
374
375 return 0;
376 }
377
378
379
380