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