OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / user / unrar / rijndael.cpp
1 /**************************************************************************
2  * This code is based on Szymon Stefanek AES implementation:              *
3  * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael-cpplib.tar.gz *
4  *                                                                        *
5  * Dynamic tables generation is based on the Brian Gladman work:          *
6  * http://fp.gladman.plus.com/cryptography_technology/rijndael            *
7  **************************************************************************/
8 #include "rar.hpp"
9
10 const int uKeyLenInBytes=16, m_uRounds=10;
11
12 static byte S[256],S5[256],rcon[30];
13 static byte T1[256][4],T2[256][4],T3[256][4],T4[256][4];
14 static byte T5[256][4],T6[256][4],T7[256][4],T8[256][4];
15 static byte U1[256][4],U2[256][4],U3[256][4],U4[256][4];
16
17
18 inline void Xor128(byte *dest,const byte *arg1,const byte *arg2)
19 {
20 #if defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
21   ((uint32*)dest)[0]=((uint32*)arg1)[0]^((uint32*)arg2)[0];
22   ((uint32*)dest)[1]=((uint32*)arg1)[1]^((uint32*)arg2)[1];
23   ((uint32*)dest)[2]=((uint32*)arg1)[2]^((uint32*)arg2)[2];
24   ((uint32*)dest)[3]=((uint32*)arg1)[3]^((uint32*)arg2)[3];
25 #else
26   for (int I=0;I<16;I++)
27     dest[I]=arg1[I]^arg2[I];
28 #endif
29 }
30
31
32 inline void Xor128(byte *dest,const byte *arg1,const byte *arg2,
33                    const byte *arg3,const byte *arg4)
34 {
35 #if defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
36   (*(uint32*)dest)=(*(uint32*)arg1)^(*(uint32*)arg2)^(*(uint32*)arg3)^(*(uint32*)arg4);
37 #else
38   for (int I=0;I<4;I++)
39     dest[I]=arg1[I]^arg2[I]^arg3[I]^arg4[I];
40 #endif
41 }
42
43
44 inline void Copy128(byte *dest,const byte *src)
45 {
46 #if defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
47   ((uint32*)dest)[0]=((uint32*)src)[0];
48   ((uint32*)dest)[1]=((uint32*)src)[1];
49   ((uint32*)dest)[2]=((uint32*)src)[2];
50   ((uint32*)dest)[3]=((uint32*)src)[3];
51 #else
52   for (int I=0;I<16;I++)
53     dest[I]=src[I];
54 #endif
55 }
56
57
58 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59 // API
60 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
61
62 Rijndael::Rijndael()
63 {
64   if (S[0]==0)
65     GenerateTables();
66 }
67
68
69 void Rijndael::init(Direction dir,const byte * key,byte * initVector)
70 {
71   m_direction = dir;
72
73   byte keyMatrix[_MAX_KEY_COLUMNS][4];
74
75   for(uint i = 0;i < uKeyLenInBytes;i++)
76     keyMatrix[i >> 2][i & 3] = key[i]; 
77
78   for(int i = 0;i < MAX_IV_SIZE;i++)
79     m_initVector[i] = initVector[i];
80
81   keySched(keyMatrix);
82
83   if(m_direction == Decrypt)
84     keyEncToDec();
85 }
86
87
88   
89 int Rijndael::blockDecrypt(const byte *input, int inputLen, byte *outBuffer)
90 {
91   if (input == 0 || inputLen <= 0)
92     return 0;
93
94   byte block[16], iv[4][4];
95   memcpy(iv,m_initVector,16); 
96
97   int numBlocks=inputLen/16;
98   for (int i = numBlocks; i > 0; i--)
99   {
100     decrypt(input, block);
101     Xor128(block,block,(byte*)iv);
102 #if STRICT_ALIGN
103     memcpy(iv, input, 16);
104     memcpy(outBuf, block, 16);
105 #else
106     Copy128((byte*)iv,input);
107     Copy128(outBuffer,block);
108 #endif
109     input += 16;
110     outBuffer += 16;
111   }
112
113   memcpy(m_initVector,iv,16);
114   
115   return 16*numBlocks;
116 }
117
118
119 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
120 // ALGORITHM
121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
122
123
124 void Rijndael::keySched(byte key[_MAX_KEY_COLUMNS][4])
125 {
126   int j,rconpointer = 0;
127
128   // Calculate the necessary round keys
129   // The number of calculations depends on keyBits and blockBits
130   int uKeyColumns = m_uRounds - 6;
131
132   byte tempKey[_MAX_KEY_COLUMNS][4];
133
134   // Copy the input key to the temporary key matrix
135
136   memcpy(tempKey,key,sizeof(tempKey));
137
138   int r = 0;
139   int t = 0;
140
141   // copy values into round key array
142   for(j = 0;(j < uKeyColumns) && (r <= m_uRounds); )
143   {
144     for(;(j < uKeyColumns) && (t < 4); j++, t++)
145       for (int k=0;k<4;k++)
146         m_expandedKey[r][t][k]=tempKey[j][k];
147
148     if(t == 4)
149     {
150       r++;
151       t = 0;
152     }
153   }
154     
155   while(r <= m_uRounds)
156   {
157     tempKey[0][0] ^= S[tempKey[uKeyColumns-1][1]];
158     tempKey[0][1] ^= S[tempKey[uKeyColumns-1][2]];
159     tempKey[0][2] ^= S[tempKey[uKeyColumns-1][3]];
160     tempKey[0][3] ^= S[tempKey[uKeyColumns-1][0]];
161     tempKey[0][0] ^= rcon[rconpointer++];
162
163     if (uKeyColumns != 8)
164       for(j = 1; j < uKeyColumns; j++)
165         for (int k=0;k<4;k++)
166           tempKey[j][k] ^= tempKey[j-1][k];
167     else
168     {
169       for(j = 1; j < uKeyColumns/2; j++)
170         for (int k=0;k<4;k++)
171           tempKey[j][k] ^= tempKey[j-1][k];
172
173       tempKey[uKeyColumns/2][0] ^= S[tempKey[uKeyColumns/2 - 1][0]];
174       tempKey[uKeyColumns/2][1] ^= S[tempKey[uKeyColumns/2 - 1][1]];
175       tempKey[uKeyColumns/2][2] ^= S[tempKey[uKeyColumns/2 - 1][2]];
176       tempKey[uKeyColumns/2][3] ^= S[tempKey[uKeyColumns/2 - 1][3]];
177       for(j = uKeyColumns/2 + 1; j < uKeyColumns; j++)
178         for (int k=0;k<4;k++)
179           tempKey[j][k] ^= tempKey[j-1][k];
180     }
181     for(j = 0; (j < uKeyColumns) && (r <= m_uRounds); )
182     {
183       for(; (j < uKeyColumns) && (t < 4); j++, t++)
184         for (int k=0;k<4;k++)
185           m_expandedKey[r][t][k] = tempKey[j][k];
186       if(t == 4)
187       {
188         r++;
189         t = 0;
190       }
191     }
192   }   
193 }
194
195 void Rijndael::keyEncToDec()
196 {
197   for(int r = 1; r < m_uRounds; r++)
198   {
199     byte n_expandedKey[4][4];
200     for (int i=0;i<4;i++)
201       for (int j=0;j<4;j++)
202       {
203         byte *w=m_expandedKey[r][j];
204         n_expandedKey[j][i]=U1[w[0]][i]^U2[w[1]][i]^U3[w[2]][i]^U4[w[3]][i];
205       }
206     memcpy(m_expandedKey[r],n_expandedKey,sizeof(m_expandedKey[0]));
207   }
208
209
210
211 void Rijndael::decrypt(const byte a[16], byte b[16])
212 {
213   int r;
214   byte temp[4][4];
215   
216   Xor128((byte*)temp,(byte*)a,(byte*)m_expandedKey[m_uRounds]);
217
218   Xor128(b,   T5[temp[0][0]],T6[temp[3][1]],T7[temp[2][2]],T8[temp[1][3]]);
219   Xor128(b+4, T5[temp[1][0]],T6[temp[0][1]],T7[temp[3][2]],T8[temp[2][3]]);
220   Xor128(b+8, T5[temp[2][0]],T6[temp[1][1]],T7[temp[0][2]],T8[temp[3][3]]);
221   Xor128(b+12,T5[temp[3][0]],T6[temp[2][1]],T7[temp[1][2]],T8[temp[0][3]]);
222
223   for(r = m_uRounds-1; r > 1; r--)
224   {
225     Xor128((byte*)temp,(byte*)b,(byte*)m_expandedKey[r]);
226     Xor128(b,   T5[temp[0][0]],T6[temp[3][1]],T7[temp[2][2]],T8[temp[1][3]]);
227     Xor128(b+4, T5[temp[1][0]],T6[temp[0][1]],T7[temp[3][2]],T8[temp[2][3]]);
228     Xor128(b+8, T5[temp[2][0]],T6[temp[1][1]],T7[temp[0][2]],T8[temp[3][3]]);
229     Xor128(b+12,T5[temp[3][0]],T6[temp[2][1]],T7[temp[1][2]],T8[temp[0][3]]);
230   }
231  
232   Xor128((byte*)temp,(byte*)b,(byte*)m_expandedKey[1]);
233   b[ 0] = S5[temp[0][0]];
234   b[ 1] = S5[temp[3][1]];
235   b[ 2] = S5[temp[2][2]];
236   b[ 3] = S5[temp[1][3]];
237   b[ 4] = S5[temp[1][0]];
238   b[ 5] = S5[temp[0][1]];
239   b[ 6] = S5[temp[3][2]];
240   b[ 7] = S5[temp[2][3]];
241   b[ 8] = S5[temp[2][0]];
242   b[ 9] = S5[temp[1][1]];
243   b[10] = S5[temp[0][2]];
244   b[11] = S5[temp[3][3]];
245   b[12] = S5[temp[3][0]];
246   b[13] = S5[temp[2][1]];
247   b[14] = S5[temp[1][2]];
248   b[15] = S5[temp[0][3]];
249   Xor128((byte*)b,(byte*)b,(byte*)m_expandedKey[0]);
250 }
251
252 #define ff_poly 0x011b
253 #define ff_hi   0x80
254
255 #define FFinv(x)    ((x) ? pow[255 - log[x]]: 0)
256
257 #define FFmul02(x) (x ? pow[log[x] + 0x19] : 0)
258 #define FFmul03(x) (x ? pow[log[x] + 0x01] : 0)
259 #define FFmul09(x) (x ? pow[log[x] + 0xc7] : 0)
260 #define FFmul0b(x) (x ? pow[log[x] + 0x68] : 0)
261 #define FFmul0d(x) (x ? pow[log[x] + 0xee] : 0)
262 #define FFmul0e(x) (x ? pow[log[x] + 0xdf] : 0)
263 #define fwd_affine(x) \
264     (w = (uint)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), (byte)(0x63^(w^(w>>8))))
265
266 #define inv_affine(x) \
267     (w = (uint)x, w = (w<<1)^(w<<3)^(w<<6), (byte)(0x05^(w^(w>>8))))
268
269 void Rijndael::GenerateTables()
270 {
271   unsigned char pow[512],log[256];
272   int i = 0, w = 1; 
273   do
274   {   
275     pow[i] = (byte)w;
276     pow[i + 255] = (byte)w;
277     log[w] = (byte)i++;
278     w ^=  (w << 1) ^ (w & ff_hi ? ff_poly : 0);
279   } while (w != 1);
280  
281   for (int i = 0,w = 1; i < sizeof(rcon)/sizeof(rcon[0]); i++)
282   {
283     rcon[i] = w;
284     w = (w << 1) ^ (w & ff_hi ? ff_poly : 0);
285   }
286   for(int i = 0; i < 256; ++i)
287   {   
288     unsigned char b=S[i]=fwd_affine(FFinv((byte)i));
289     T1[i][1]=T1[i][2]=T2[i][2]=T2[i][3]=T3[i][0]=T3[i][3]=T4[i][0]=T4[i][1]=b;
290     T1[i][0]=T2[i][1]=T3[i][2]=T4[i][3]=FFmul02(b);
291     T1[i][3]=T2[i][0]=T3[i][1]=T4[i][2]=FFmul03(b);
292     S5[i] = b = FFinv(inv_affine((byte)i));
293     U1[b][3]=U2[b][0]=U3[b][1]=U4[b][2]=T5[i][3]=T6[i][0]=T7[i][1]=T8[i][2]=FFmul0b(b);
294     U1[b][1]=U2[b][2]=U3[b][3]=U4[b][0]=T5[i][1]=T6[i][2]=T7[i][3]=T8[i][0]=FFmul09(b);
295     U1[b][2]=U2[b][3]=U3[b][0]=U4[b][1]=T5[i][2]=T6[i][3]=T7[i][0]=T8[i][1]=FFmul0d(b);
296     U1[b][0]=U2[b][1]=U3[b][2]=U4[b][3]=T5[i][0]=T6[i][1]=T7[i][2]=T8[i][3]=FFmul0e(b);
297   }
298 }