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