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