summaryrefslogtreecommitdiff
path: root/aes.c
diff options
context:
space:
mode:
authorStefan Esser2010-02-21 11:44:54 +0100
committerStefan Esser2010-02-21 11:44:54 +0100
commit36dbfacbe64697d959f524e537b15b73c090d898 (patch)
treef1c7ce1409b0e7765fc72d550546967fcf0f9717 /aes.c
Inital commit
Diffstat (limited to 'aes.c')
-rw-r--r--aes.c382
1 files changed, 382 insertions, 0 deletions
diff --git a/aes.c b/aes.c
new file mode 100644
index 0000000..f8804da
--- /dev/null
+++ b/aes.c
@@ -0,0 +1,382 @@
1/* Rijndael Block Cipher - rijndael.c
2
3 Written by Mike Scott 21st April 1999
4 mike@compapp.dcu.ie
5 An alternative faster version is implemented in MIRACL
6 ftp://ftp.computing.dcu.ie/pub/crypto/miracl.zip
7
8 Copyright (c) 1999 Mike Scott
9
10 Simply compile and run, e.g.
11
12 cl /O2 rijndael.c (Microsoft C)
13 bcc32 /O2 rijndael.c (Borland C)
14 gcc -O2 rijndael.c -o rijndael (Gnu C)
15
16 Compiles and runs fine as a C++ program also.
17
18 See rijndael documentation. The code follows the documentation as closely
19 as possible, and where possible uses the same function and variable names.
20
21 Permission for free direct or derivative use is granted subject
22 to compliance with any conditions that the originators of the
23 algorithm place on its exploitation.
24
25 Inspiration from Brian Gladman's implementation is acknowledged.
26
27 Written for clarity, rather than speed.
28 Assumes long is 32 bit quantity.
29 Full implementation.
30 Endian indifferent.
31*/
32
33#include "php.h"
34#include "php_suhosin.h"
35
36/* rotates x one bit to the left */
37
38#define ROTL(x) (((x)>>7)|((x)<<1))
39
40/* Rotates 32-bit word left by 1, 2 or 3 byte */
41
42#define ROTL8(x) (((x)<<8)|((x)>>24))
43#define ROTL16(x) (((x)<<16)|((x)>>16))
44#define ROTL24(x) (((x)<<24)|((x)>>8))
45
46/* Fixed Data */
47
48static BYTE InCo[4]={0xB,0xD,0x9,0xE}; /* Inverse Coefficients */
49
50static BYTE fbsub[256];
51static BYTE rbsub[256];
52static BYTE ptab[256],ltab[256];
53static WORD ftable[256];
54static WORD rtable[256];
55static WORD rco[30];
56
57/* Parameter-dependent data */
58
59static int Nk,Nb,Nr;
60
61static WORD pack(BYTE *b)
62{ /* pack bytes into a 32-bit Word */
63 return ((WORD)b[3]<<24)|((WORD)b[2]<<16)|((WORD)b[1]<<8)|(WORD)b[0];
64}
65
66static void unpack(WORD a,BYTE *b)
67{ /* unpack bytes from a word */
68 b[0]=(BYTE)a;
69 b[1]=(BYTE)(a>>8);
70 b[2]=(BYTE)(a>>16);
71 b[3]=(BYTE)(a>>24);
72}
73
74static BYTE xtime(BYTE a)
75{
76 BYTE b;
77 if (a&0x80) b=0x1B;
78 else b=0;
79 a<<=1;
80 a^=b;
81 return a;
82}
83
84static BYTE bmul(BYTE x,BYTE y)
85{ /* x.y= AntiLog(Log(x) + Log(y)) */
86 if (x && y) return ptab[(ltab[x]+ltab[y])%255];
87 else return 0;
88}
89
90static WORD SubByte(WORD a)
91{
92 BYTE b[4];
93 unpack(a,b);
94 b[0]=fbsub[b[0]];
95 b[1]=fbsub[b[1]];
96 b[2]=fbsub[b[2]];
97 b[3]=fbsub[b[3]];
98 return pack(b);
99}
100
101static BYTE product(WORD x,WORD y)
102{ /* dot product of two 4-byte arrays */
103 BYTE xb[4],yb[4];
104 unpack(x,xb);
105 unpack(y,yb);
106 return bmul(xb[0],yb[0])^bmul(xb[1],yb[1])^bmul(xb[2],yb[2])^bmul(xb[3],yb[3]);
107}
108
109static WORD InvMixCol(WORD x)
110{ /* matrix Multiplication */
111 WORD y,m;
112 BYTE b[4];
113
114 m=pack(InCo);
115 b[3]=product(m,x);
116 m=ROTL24(m);
117 b[2]=product(m,x);
118 m=ROTL24(m);
119 b[1]=product(m,x);
120 m=ROTL24(m);
121 b[0]=product(m,x);
122 y=pack(b);
123 return y;
124}
125
126static BYTE ByteSub(BYTE x)
127{
128 BYTE y=ptab[255-ltab[x]]; /* multiplicative inverse */
129 x=y; x=ROTL(x);
130 y^=x; x=ROTL(x);
131 y^=x; x=ROTL(x);
132 y^=x; x=ROTL(x);
133 y^=x; y^=0x63;
134 return y;
135}
136
137void suhosin_aes_gentables()
138{ /* generate tables */
139 int i;
140 BYTE y,b[4];
141
142 /* use 3 as primitive root to generate power and log tables */
143
144 ltab[0]=0;
145 ptab[0]=1; ltab[1]=0;
146 ptab[1]=3; ltab[3]=1;
147 for (i=2;i<256;i++)
148 {
149 ptab[i]=ptab[i-1]^xtime(ptab[i-1]);
150 ltab[ptab[i]]=i;
151 }
152
153 /* affine transformation:- each bit is xored with itself shifted one bit */
154
155 fbsub[0]=0x63;
156 rbsub[0x63]=0;
157 for (i=1;i<256;i++)
158 {
159 y=ByteSub((BYTE)i);
160 fbsub[i]=y; rbsub[y]=i;
161 }
162
163 for (i=0,y=1;i<30;i++)
164 {
165 rco[i]=y;
166 y=xtime(y);
167 }
168
169 /* calculate forward and reverse tables */
170 for (i=0;i<256;i++)
171 {
172 y=fbsub[i];
173 b[3]=y^xtime(y); b[2]=y;
174 b[1]=y; b[0]=xtime(y);
175 ftable[i]=pack(b);
176
177 y=rbsub[i];
178 b[3]=bmul(InCo[0],y); b[2]=bmul(InCo[1],y);
179 b[1]=bmul(InCo[2],y); b[0]=bmul(InCo[3],y);
180 rtable[i]=pack(b);
181 }
182}
183
184void suhosin_aes_gkey(int nb,int nk,char *key TSRMLS_DC)
185{ /* blocksize=32*nb bits. Key=32*nk bits */
186 /* currently nb,bk = 4, 6 or 8 */
187 /* key comes as 4*Nk bytes */
188 /* Key Scheduler. Create expanded encryption key */
189 int i,j,k,m,N;
190 int C1,C2,C3;
191 WORD CipherKey[8];
192
193 Nb=nb; Nk=nk;
194
195 /* Nr is number of rounds */
196 if (Nb>=Nk) Nr=6+Nb;
197 else Nr=6+Nk;
198
199 C1=1;
200 if (Nb<8) { C2=2; C3=3; }
201 else { C2=3; C3=4; }
202
203 /* pre-calculate forward and reverse increments */
204 for (m=j=0;j<nb;j++,m+=3)
205 {
206 SUHOSIN_G(fi)[m]=(j+C1)%nb;
207 SUHOSIN_G(fi)[m+1]=(j+C2)%nb;
208 SUHOSIN_G(fi)[m+2]=(j+C3)%nb;
209 SUHOSIN_G(ri)[m]=(nb+j-C1)%nb;
210 SUHOSIN_G(ri)[m+1]=(nb+j-C2)%nb;
211 SUHOSIN_G(ri)[m+2]=(nb+j-C3)%nb;
212 }
213
214 N=Nb*(Nr+1);
215
216 for (i=j=0;i<Nk;i++,j+=4)
217 {
218 CipherKey[i]=pack((BYTE *)&key[j]);
219 }
220 for (i=0;i<Nk;i++) SUHOSIN_G(fkey)[i]=CipherKey[i];
221 for (j=Nk,k=0;j<N;j+=Nk,k++)
222 {
223 SUHOSIN_G(fkey)[j]=SUHOSIN_G(fkey)[j-Nk]^SubByte(ROTL24(SUHOSIN_G(fkey)[j-1]))^rco[k];
224 if (Nk<=6)
225 {
226 for (i=1;i<Nk && (i+j)<N;i++)
227 SUHOSIN_G(fkey)[i+j]=SUHOSIN_G(fkey)[i+j-Nk]^SUHOSIN_G(fkey)[i+j-1];
228 }
229 else
230 {
231 for (i=1;i<4 &&(i+j)<N;i++)
232 SUHOSIN_G(fkey)[i+j]=SUHOSIN_G(fkey)[i+j-Nk]^SUHOSIN_G(fkey)[i+j-1];
233 if ((j+4)<N) SUHOSIN_G(fkey)[j+4]=SUHOSIN_G(fkey)[j+4-Nk]^SubByte(SUHOSIN_G(fkey)[j+3]);
234 for (i=5;i<Nk && (i+j)<N;i++)
235 SUHOSIN_G(fkey)[i+j]=SUHOSIN_G(fkey)[i+j-Nk]^SUHOSIN_G(fkey)[i+j-1];
236 }
237
238 }
239
240 /* now for the expanded decrypt key in reverse order */
241
242 for (j=0;j<Nb;j++) SUHOSIN_G(rkey)[j+N-Nb]=SUHOSIN_G(fkey)[j];
243 for (i=Nb;i<N-Nb;i+=Nb)
244 {
245 k=N-Nb-i;
246 for (j=0;j<Nb;j++) SUHOSIN_G(rkey)[k+j]=InvMixCol(SUHOSIN_G(fkey)[i+j]);
247 }
248 for (j=N-Nb;j<N;j++) SUHOSIN_G(rkey)[j-N+Nb]=SUHOSIN_G(fkey)[j];
249}
250
251
252/* There is an obvious time/space trade-off possible here. *
253 * Instead of just one ftable[], I could have 4, the other *
254 * 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */
255
256void suhosin_aes_encrypt(char *buff TSRMLS_DC)
257{
258 int i,j,k,m;
259 WORD a[8],b[8],*x,*y,*t;
260
261 for (i=j=0;i<Nb;i++,j+=4)
262 {
263 a[i]=pack((BYTE *)&buff[j]);
264 a[i]^=SUHOSIN_G(fkey)[i];
265 }
266 k=Nb;
267 x=a; y=b;
268
269/* State alternates between a and b */
270 for (i=1;i<Nr;i++)
271 { /* Nr is number of rounds. May be odd. */
272
273/* if Nb is fixed - unroll this next
274 loop and hard-code in the values of fi[] */
275
276 for (m=j=0;j<Nb;j++,m+=3)
277 { /* deal with each 32-bit element of the State */
278 /* This is the time-critical bit */
279 y[j]=SUHOSIN_G(fkey)[k++]^ftable[(BYTE)x[j]]^
280 ROTL8(ftable[(BYTE)(x[SUHOSIN_G(fi)[m]]>>8)])^
281 ROTL16(ftable[(BYTE)(x[SUHOSIN_G(fi)[m+1]]>>16)])^
282 ROTL24(ftable[x[SUHOSIN_G(fi)[m+2]]>>24]);
283 }
284 t=x; x=y; y=t; /* swap pointers */
285 }
286
287/* Last Round - unroll if possible */
288 for (m=j=0;j<Nb;j++,m+=3)
289 {
290 y[j]=SUHOSIN_G(fkey)[k++]^(WORD)fbsub[(BYTE)x[j]]^
291 ROTL8((WORD)fbsub[(BYTE)(x[SUHOSIN_G(fi)[m]]>>8)])^
292 ROTL16((WORD)fbsub[(BYTE)(x[SUHOSIN_G(fi)[m+1]]>>16)])^
293 ROTL24((WORD)fbsub[x[SUHOSIN_G(fi)[m+2]]>>24]);
294 }
295 for (i=j=0;i<Nb;i++,j+=4)
296 {
297 unpack(y[i],(BYTE *)&buff[j]);
298 x[i]=y[i]=0; /* clean up stack */
299 }
300 return;
301}
302
303void suhosin_aes_decrypt(char *buff TSRMLS_DC)
304{
305 int i,j,k,m;
306 WORD a[8],b[8],*x,*y,*t;
307
308 for (i=j=0;i<Nb;i++,j+=4)
309 {
310 a[i]=pack((BYTE *)&buff[j]);
311 a[i]^=SUHOSIN_G(rkey)[i];
312 }
313 k=Nb;
314 x=a; y=b;
315
316/* State alternates between a and b */
317 for (i=1;i<Nr;i++)
318 { /* Nr is number of rounds. May be odd. */
319
320/* if Nb is fixed - unroll this next
321 loop and hard-code in the values of ri[] */
322
323 for (m=j=0;j<Nb;j++,m+=3)
324 { /* This is the time-critical bit */
325 y[j]=SUHOSIN_G(rkey)[k++]^rtable[(BYTE)x[j]]^
326 ROTL8(rtable[(BYTE)(x[SUHOSIN_G(ri)[m]]>>8)])^
327 ROTL16(rtable[(BYTE)(x[SUHOSIN_G(ri)[m+1]]>>16)])^
328 ROTL24(rtable[x[SUHOSIN_G(ri)[m+2]]>>24]);
329 }
330 t=x; x=y; y=t; /* swap pointers */
331 }
332
333/* Last Round - unroll if possible */
334 for (m=j=0;j<Nb;j++,m+=3)
335 {
336 y[j]=SUHOSIN_G(rkey)[k++]^(WORD)rbsub[(BYTE)x[j]]^
337 ROTL8((WORD)rbsub[(BYTE)(x[SUHOSIN_G(ri)[m]]>>8)])^
338 ROTL16((WORD)rbsub[(BYTE)(x[SUHOSIN_G(ri)[m+1]]>>16)])^
339 ROTL24((WORD)rbsub[x[SUHOSIN_G(ri)[m+2]]>>24]);
340 }
341 for (i=j=0;i<Nb;i++,j+=4)
342 {
343 unpack(y[i],(BYTE *)&buff[j]);
344 x[i]=y[i]=0; /* clean up stack */
345 }
346 return;
347}
348
349
350/*
351static int main()
352{
353 int i,nb,nk;
354 char key[32];
355 char block[32];
356
357 gentables();
358
359 for (i=0;i<32;i++) key[i]=0;
360 key[0]=1;
361 for (i=0;i<32;i++) block[i]=i;
362
363 for (nb=4;nb<=8;nb+=2)
364 for (nk=4;nk<=8;nk+=2)
365 {
366 printf("\nBlock Size= %d bits, Key Size= %d bits\n",nb*32,nk*32);
367 gkey(nb,nk,key);
368 printf("Plain= ");
369 for (i=0;i<nb*4;i++) printf("%02x",block[i]);
370 printf("\n");
371 encrypt(block);
372 printf("Encrypt= ");
373 for (i=0;i<nb*4;i++) printf("%02x",(unsigned char)block[i]);
374 printf("\n");
375 decrypt(block);
376 printf("Decrypt= ");
377 for (i=0;i<nb*4;i++) printf("%02x",block[i]);
378 printf("\n");
379 }
380 return 0;
381}
382*/