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