xref: /reactos/sdk/lib/cryptlib/mvAesAlg.c (revision 84ccccab)
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 
16 MV_U8 mul1(MV_U8 aa, MV_U8 bb);
17 void KeyAddition(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC], MV_U8 BC);
18 void ShiftRow128Enc(MV_U8 a[4][MAXBC]);
19 void ShiftRow128Dec(MV_U8 a[4][MAXBC]);
20 void Substitution(MV_U8 a[4][MAXBC], MV_U8 box[256]);
21 void MixColumn(MV_U8 a[4][MAXBC], MV_U8 rk[4][MAXBC]);
22 void InvMixColumn(MV_U8 a[4][MAXBC]);
23 
24 
25 #define mul(aa, bb) (mask[bb] & Alogtable[aa + Logtable[bb]])
26 
27 MV_U8 mul1(MV_U8 aa, MV_U8 bb)
28 {
29     return mask[bb] & Alogtable[aa + Logtable[bb]];
30 }
31 
32 
33 void 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 
44 void 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 
88 void 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 
134 void 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 
144 void 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 
161 void 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 
179 int 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 
244 int 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 
277 int 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