• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

rijndael.cpp

Go to the documentation of this file.
00001 // rijndael-alg-fst.c   v2.0   August '99
00002 // Optimised ANSI C code
00003 // authors: v1.0: Antoon Bosselaers
00004 //          v2.0: Vincent Rijmen
00005 
00006 
00007 /*
00008  *  taken from the 'aescrypt' project: www.sf.net/projects/aescrypt
00009  *  See LICENSE-EST for the license applicable to this file
00010  */
00011 
00012 
00013 // 14.Dec.2005 Cirilo:  Removed silly hex keys; keys are now effectively unsigned char.
00014 
00015 // KevinJ - TODO - What the hell is __UNUS?  It causes DevCPP not to compile.   I don't know what this is for so I'm taking it out entirely
00016 /*
00017 #if (defined(__GNUC__)  || defined(__GCCXML__))
00018 #define __UNUS  __attribute__((unused))
00019 #else
00020 */
00021 #define __UNUS
00022 //#endif
00023 
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include "Rijndael.h"
00028 
00029 // KevinJ - Added this to just generate a random initialization vector
00030 #include "Rand.h"
00031 
00032 #define SC      ((BC - 4) >> 1)
00033 
00034 #include "Rijndael-Boxes.h"
00035 
00036 static int ROUNDS;
00037 
00038 static word8 shifts[3][4][2] = {
00039   {
00040     {0, 0},
00041     {1, 3},
00042     {2, 2},
00043     {3, 1}
00044   },
00045    
00046   {
00047     {0, 0},
00048     {1, 5},
00049     {2, 4},
00050     {3, 3}
00051   },
00052    
00053   {
00054     {0, 0},
00055     {1, 7},
00056     {3, 5},
00057     {4, 4}
00058   }
00059 }; 
00060 
00061 word8 mul(word8 a, word8 b) {
00062    // multiply two elements of GF(2^m)
00063    // needed for MixColumn and InvMixColumn
00064    
00065         if (a && b)
00066                 return Alogtable[(Logtable[a] + Logtable[b])%255];
00067         else
00068                 return 0;
00069 }
00070 
00071 void KeyAddition(word8 a[4][4], word8 rk[4][4], word8 BC) {
00072         // XOR corresponding text input and round key input bytes
00073         int i, j;
00074         
00075         for(i = 0; i < BC; i++)
00076         for(j = 0; j < 4; j++)
00077                         a[i][j] ^= rk[i][j];
00078 }
00079 
00080 void ShiftRow(word8 a[4][4], word8 d, word8 BC) {
00081         // Row 0 remains unchanged
00082         // The other three rows are shifted a variable amount
00083         
00084         word8 tmp[4];
00085         int i, j;
00086         
00087         for(i = 1; i < 4; i++) {
00088                 for(j = 0; j < BC; j++)
00089                         tmp[j] = a[(j + shifts[SC][i][d]) % BC][i];
00090                 for(j = 0; j < BC; j++)
00091                         a[j][i] = tmp[j];
00092         }
00093 }
00094 
00095 void Substitution(word8 a[4][4], word8 box[256], word8 BC) {
00096         // Replace every byte of the input by the byte at that place
00097         // in the nonlinear S-box
00098         
00099         int i, j;
00100         
00101         for(i = 0; i < BC; i++)
00102                 for(j = 0; j < 4; j++)
00103                         a[i][j] = box[a[i][j]] ;
00104 }
00105    
00106 void MixColumn(word8 a[4][4], word8 BC) {
00107       // Mix the four bytes of every column in a linear way
00108         
00109         word8 b[4][4];
00110         int i, j;
00111                 
00112         for(j = 0; j < BC; j++)
00113                 for(i = 0; i < 4; i++)
00114                         b[j][i] = mul(2,a[j][i])
00115                                 ^ mul(3,a[j][(i + 1) % 4])
00116                                 ^ a[j][(i + 2) % 4]
00117                                 ^ a[j][(i + 3) % 4];
00118         for(i = 0; i < 4; i++)
00119                 for(j = 0; j < BC; j++)
00120                         a[j][i] = b[j][i];
00121 }
00122 
00123 void InvMixColumn(word8 a[4][4], word8 BC) {
00124   // Mix the four bytes of every column in a linear way
00125         // This is the opposite operation of Mixcolumn
00126         
00127         int j;
00128 
00129         for(j = 0; j < BC; j++)
00130                 *((word32*)a[j]) = *((word32*)U1[a[j][0]])
00131                                                                 ^ *((word32*)U2[a[j][1]])
00132                                                                 ^ *((word32*)U3[a[j][2]])
00133                                                                 ^ *((word32*)U4[a[j][3]]);
00134 
00135 
00136 }
00137 
00138 int rijndaelKeySched (word8 k[MAXKC][4], int keyBits __UNUS, word8 W[MAXROUNDS+1][4][4])
00139 {
00140 
00141         (void) keyBits;
00142         
00143         // Calculate the necessary round keys
00144         // The number of calculations depends on keyBits and blockBits
00145          
00146         int j, r, t, rconpointer = 0;
00147         word8 tk[MAXKC][4];
00148         int KC = ROUNDS - 6;
00149 
00150         for(j = KC-1; j >= 0; j--)
00151                 *((word32*)tk[j]) = *((word32*)k[j]);
00152         r = 0;
00153         t = 0;
00154         // copy values into round key array
00155         for(j = 0; (j < KC) && (r < (ROUNDS+1)); ) {
00156                 for (; (j < KC) && (t < 4); j++, t++)
00157                         *((word32*)W[r][t]) = *((word32*)tk[j]);
00158                 if (t == 4) {
00159                         r++;
00160                         t = 0;
00161                 }
00162         }
00163                 
00164         while (r < (ROUNDS+1)) { // while not enough round key material calculated
00165                 // calculate new values
00166                 tk[0][0] ^= S[tk[KC-1][1]];
00167                 tk[0][1] ^= S[tk[KC-1][2]];
00168                 tk[0][2] ^= S[tk[KC-1][3]];
00169                 tk[0][3] ^= S[tk[KC-1][0]];
00170                 tk[0][0] ^= rcon[rconpointer++];
00171 
00172                 if (KC != 8)
00173                         for(j = 1; j < KC; j++)
00174                                 *((word32*)tk[j]) ^= *((word32*)tk[j-1]);
00175                 else {
00176                         for(j = 1; j < KC/2; j++)
00177                                 *((word32*)tk[j]) ^= *((word32*)tk[j-1]);
00178                         tk[KC/2][0] ^= S[tk[KC/2 - 1][0]];
00179                         tk[KC/2][1] ^= S[tk[KC/2 - 1][1]];
00180                         tk[KC/2][2] ^= S[tk[KC/2 - 1][2]];
00181                         tk[KC/2][3] ^= S[tk[KC/2 - 1][3]];
00182                         for(j = KC/2 + 1; j < KC; j++)
00183                                 *((word32*)tk[j]) ^= *((word32*)tk[j-1]);
00184                 }
00185                 // copy values into round key array
00186                 for(j = 0; (j < KC) && (r < (ROUNDS+1)); ) {
00187                         for (; (j < KC) && (t < 4); j++, t++)
00188                                 *((word32*)W[r][t]) = *((word32*)tk[j]);
00189                         if (t == 4) {
00190                                 r++;
00191                                 t = 0;
00192                         }
00193                 }
00194         }               
00195 
00196         return 0;
00197 }
00198 
00199 int rijndaelKeyEnctoDec (int keyBits __UNUS, word8 W[MAXROUNDS+1][4][4])
00200 {
00201         (void) keyBits;
00202 
00203         int r;
00204 
00205         for (r = 1; r < ROUNDS; r++) {
00206                 InvMixColumn(W[r], 4);
00207         }
00208         return 0;
00209 }       
00210 
00211 int rijndaelEncrypt (word8 a[16], word8 b[16], word8 rk[MAXROUNDS+1][4][4])
00212 {
00213         // Encryption of one block. 
00214         
00215         int r;
00216    word8 temp[4][4];
00217 
00218     *((word32*)temp[0]) = *((word32*)a) ^ *((word32*)rk[0][0]);
00219     *((word32*)temp[1]) = *((word32*)(a+4)) ^ *((word32*)rk[0][1]);
00220     *((word32*)temp[2]) = *((word32*)(a+8)) ^ *((word32*)rk[0][2]);
00221     *((word32*)temp[3]) = *((word32*)(a+12)) ^ *((word32*)rk[0][3]);
00222     *((word32*)b) = *((word32*)T1[temp[0][0]])
00223            ^ *((word32*)T2[temp[1][1]])
00224            ^ *((word32*)T3[temp[2][2]]) 
00225            ^ *((word32*)T4[temp[3][3]]);
00226     *((word32*)(b+4)) = *((word32*)T1[temp[1][0]])
00227            ^ *((word32*)T2[temp[2][1]])
00228            ^ *((word32*)T3[temp[3][2]]) 
00229            ^ *((word32*)T4[temp[0][3]]);
00230     *((word32*)(b+8)) = *((word32*)T1[temp[2][0]])
00231            ^ *((word32*)T2[temp[3][1]])
00232            ^ *((word32*)T3[temp[0][2]]) 
00233            ^ *((word32*)T4[temp[1][3]]);
00234     *((word32*)(b+12)) = *((word32*)T1[temp[3][0]])
00235            ^ *((word32*)T2[temp[0][1]])
00236            ^ *((word32*)T3[temp[1][2]]) 
00237            ^ *((word32*)T4[temp[2][3]]);
00238    for(r = 1; r < ROUNDS-1; r++) {
00239                 *((word32*)temp[0]) = *((word32*)b) ^ *((word32*)rk[r][0]);
00240                 *((word32*)temp[1]) = *((word32*)(b+4)) ^ *((word32*)rk[r][1]);
00241                 *((word32*)temp[2]) = *((word32*)(b+8)) ^ *((word32*)rk[r][2]);
00242                 *((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[r][3]);
00243    *((word32*)b) = *((word32*)T1[temp[0][0]])
00244            ^ *((word32*)T2[temp[1][1]])
00245            ^ *((word32*)T3[temp[2][2]]) 
00246            ^ *((word32*)T4[temp[3][3]]);
00247    *((word32*)(b+4)) = *((word32*)T1[temp[1][0]])
00248            ^ *((word32*)T2[temp[2][1]])
00249            ^ *((word32*)T3[temp[3][2]]) 
00250            ^ *((word32*)T4[temp[0][3]]);
00251    *((word32*)(b+8)) = *((word32*)T1[temp[2][0]])
00252            ^ *((word32*)T2[temp[3][1]])
00253            ^ *((word32*)T3[temp[0][2]]) 
00254            ^ *((word32*)T4[temp[1][3]]);
00255    *((word32*)(b+12)) = *((word32*)T1[temp[3][0]])
00256            ^ *((word32*)T2[temp[0][1]])
00257            ^ *((word32*)T3[temp[1][2]]) 
00258            ^ *((word32*)T4[temp[2][3]]);
00259    }
00260    // last round is special   
00261         *((word32*)temp[0]) = *((word32*)b) ^ *((word32*)rk[ROUNDS-1][0]);
00262         *((word32*)temp[1]) = *((word32*)(b+4)) ^ *((word32*)rk[ROUNDS-1][1]);
00263         *((word32*)temp[2]) = *((word32*)(b+8)) ^ *((word32*)rk[ROUNDS-1][2]);
00264         *((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[ROUNDS-1][3]);
00265    b[0] = T1[temp[0][0]][1];
00266    b[1] = T1[temp[1][1]][1];
00267    b[2] = T1[temp[2][2]][1]; 
00268    b[3] = T1[temp[3][3]][1];
00269    b[4] = T1[temp[1][0]][1];
00270    b[5] = T1[temp[2][1]][1];
00271    b[6] = T1[temp[3][2]][1]; 
00272    b[7] = T1[temp[0][3]][1];
00273    b[8] = T1[temp[2][0]][1];
00274    b[9] = T1[temp[3][1]][1];
00275    b[10] = T1[temp[0][2]][1]; 
00276    b[11] = T1[temp[1][3]][1];
00277    b[12] = T1[temp[3][0]][1];
00278    b[13] = T1[temp[0][1]][1];
00279    b[14] = T1[temp[1][2]][1]; 
00280    b[15] = T1[temp[2][3]][1];
00281         *((word32*)b) ^= *((word32*)rk[ROUNDS][0]);
00282         *((word32*)(b+4)) ^= *((word32*)rk[ROUNDS][1]);
00283         *((word32*)(b+8)) ^= *((word32*)rk[ROUNDS][2]);
00284         *((word32*)(b+12)) ^= *((word32*)rk[ROUNDS][3]);
00285 
00286         return 0;
00287 }
00288 
00289 int rijndaelEncryptRound (word8 a[4][4], 
00290                 word8 rk[MAXROUNDS+1][4][4], int rounds)
00291 // Encrypt only a certain number of rounds.
00292 // Only used in the Intermediate Value Known Answer Test.
00293 
00294 {
00295         int r;
00296    word8 temp[4][4];
00297 
00298 
00299         // make number of rounds sane
00300         if (rounds > ROUNDS) rounds = ROUNDS;
00301 
00302         *((word32*)a[0]) = *((word32*)a[0]) ^ *((word32*)rk[0][0]);
00303         *((word32*)a[1]) = *((word32*)a[1]) ^ *((word32*)rk[0][1]);
00304         *((word32*)a[2]) = *((word32*)a[2]) ^ *((word32*)rk[0][2]);
00305         *((word32*)a[3]) = *((word32*)a[3]) ^ *((word32*)rk[0][3]);
00306 
00307         for(r = 1; (r <= rounds) && (r < ROUNDS); r++) {
00308                 *((word32*)temp[0]) = *((word32*)T1[a[0][0]])
00309            ^ *((word32*)T2[a[1][1]])
00310            ^ *((word32*)T3[a[2][2]]) 
00311            ^ *((word32*)T4[a[3][3]]);
00312                 *((word32*)temp[1]) = *((word32*)T1[a[1][0]])
00313            ^ *((word32*)T2[a[2][1]])
00314            ^ *((word32*)T3[a[3][2]]) 
00315            ^ *((word32*)T4[a[0][3]]);
00316                 *((word32*)temp[2]) = *((word32*)T1[a[2][0]])
00317            ^ *((word32*)T2[a[3][1]])
00318            ^ *((word32*)T3[a[0][2]]) 
00319            ^ *((word32*)T4[a[1][3]]);
00320                 *((word32*)temp[3]) = *((word32*)T1[a[3][0]])
00321            ^ *((word32*)T2[a[0][1]])
00322            ^ *((word32*)T3[a[1][2]]) 
00323            ^ *((word32*)T4[a[2][3]]);
00324                 *((word32*)a[0]) = *((word32*)temp[0]) ^ *((word32*)rk[r][0]);
00325                 *((word32*)a[1]) = *((word32*)temp[1]) ^ *((word32*)rk[r][1]);
00326                 *((word32*)a[2]) = *((word32*)temp[2]) ^ *((word32*)rk[r][2]);
00327                 *((word32*)a[3]) = *((word32*)temp[3]) ^ *((word32*)rk[r][3]);
00328    }
00329         if (rounds == ROUNDS) {
00330         // last round is special   
00331         temp[0][0] = T1[a[0][0]][1];
00332         temp[0][1] = T1[a[1][1]][1];
00333         temp[0][2] = T1[a[2][2]][1]; 
00334         temp[0][3] = T1[a[3][3]][1];
00335         temp[1][0] = T1[a[1][0]][1];
00336         temp[1][1] = T1[a[2][1]][1];
00337         temp[1][2] = T1[a[3][2]][1]; 
00338         temp[1][3] = T1[a[0][3]][1];
00339         temp[2][0] = T1[a[2][0]][1];
00340         temp[2][1] = T1[a[3][1]][1];
00341         temp[2][2] = T1[a[0][2]][1]; 
00342         temp[2][3] = T1[a[1][3]][1];
00343         temp[3][0] = T1[a[3][0]][1];
00344         temp[3][1] = T1[a[0][1]][1];
00345         temp[3][2] = T1[a[1][2]][1]; 
00346         temp[3][3] = T1[a[2][3]][1];
00347                 *((word32*)a[0]) = *((word32*)temp[0]) ^ *((word32*)rk[ROUNDS][0]);
00348                 *((word32*)a[1]) = *((word32*)temp[1]) ^ *((word32*)rk[ROUNDS][1]);
00349                 *((word32*)a[2]) = *((word32*)temp[2]) ^ *((word32*)rk[ROUNDS][2]);
00350                 *((word32*)a[3]) = *((word32*)temp[3]) ^ *((word32*)rk[ROUNDS][3]);
00351         }
00352 
00353         return 0;
00354 }   
00355 
00356 
00357 int rijndaelDecrypt (word8 a[16], word8 b[16], word8 rk[MAXROUNDS+1][4][4])
00358 {
00359         int r;
00360    word8 temp[4][4];
00361         
00362 
00363     *((word32*)temp[0]) = *((word32*)a) ^ *((word32*)rk[ROUNDS][0]);
00364     *((word32*)temp[1]) = *((word32*)(a+4)) ^ *((word32*)rk[ROUNDS][1]);
00365     *((word32*)temp[2]) = *((word32*)(a+8)) ^ *((word32*)rk[ROUNDS][2]);
00366     *((word32*)temp[3]) = *((word32*)(a+12)) ^ *((word32*)rk[ROUNDS][3]);
00367     *((word32*)b) = *((word32*)T5[temp[0][0]])
00368            ^ *((word32*)T6[temp[3][1]])
00369            ^ *((word32*)T7[temp[2][2]]) 
00370            ^ *((word32*)T8[temp[1][3]]);
00371    *((word32*)(b+4)) = *((word32*)T5[temp[1][0]])
00372            ^ *((word32*)T6[temp[0][1]])
00373            ^ *((word32*)T7[temp[3][2]]) 
00374            ^ *((word32*)T8[temp[2][3]]);
00375    *((word32*)(b+8)) = *((word32*)T5[temp[2][0]])
00376            ^ *((word32*)T6[temp[1][1]])
00377            ^ *((word32*)T7[temp[0][2]]) 
00378            ^ *((word32*)T8[temp[3][3]]);
00379    *((word32*)(b+12)) = *((word32*)T5[temp[3][0]])
00380            ^ *((word32*)T6[temp[2][1]])
00381            ^ *((word32*)T7[temp[1][2]]) 
00382            ^ *((word32*)T8[temp[0][3]]);
00383    for(r = ROUNDS-1; r > 1; r--) {
00384                 *((word32*)temp[0]) = *((word32*)b) ^ *((word32*)rk[r][0]);
00385                 *((word32*)temp[1]) = *((word32*)(b+4)) ^ *((word32*)rk[r][1]);
00386                 *((word32*)temp[2]) = *((word32*)(b+8)) ^ *((word32*)rk[r][2]);
00387                 *((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[r][3]);
00388                 *((word32*)b) = *((word32*)T5[temp[0][0]])
00389            ^ *((word32*)T6[temp[3][1]])
00390            ^ *((word32*)T7[temp[2][2]]) 
00391            ^ *((word32*)T8[temp[1][3]]);
00392                 *((word32*)(b+4)) = *((word32*)T5[temp[1][0]])
00393            ^ *((word32*)T6[temp[0][1]])
00394            ^ *((word32*)T7[temp[3][2]]) 
00395            ^ *((word32*)T8[temp[2][3]]);
00396                 *((word32*)(b+8)) = *((word32*)T5[temp[2][0]])
00397            ^ *((word32*)T6[temp[1][1]])
00398            ^ *((word32*)T7[temp[0][2]]) 
00399            ^ *((word32*)T8[temp[3][3]]);
00400                 *((word32*)(b+12)) = *((word32*)T5[temp[3][0]])
00401            ^ *((word32*)T6[temp[2][1]])
00402            ^ *((word32*)T7[temp[1][2]]) 
00403            ^ *((word32*)T8[temp[0][3]]);
00404    }
00405    // last round is special   
00406         *((word32*)temp[0]) = *((word32*)b) ^ *((word32*)rk[1][0]);
00407         *((word32*)temp[1]) = *((word32*)(b+4)) ^ *((word32*)rk[1][1]);
00408         *((word32*)temp[2]) = *((word32*)(b+8)) ^ *((word32*)rk[1][2]);
00409         *((word32*)temp[3]) = *((word32*)(b+12)) ^ *((word32*)rk[1][3]);
00410    b[0] = S5[temp[0][0]];
00411    b[1] = S5[temp[3][1]];
00412    b[2] = S5[temp[2][2]]; 
00413    b[3] = S5[temp[1][3]];
00414    b[4] = S5[temp[1][0]];
00415    b[5] = S5[temp[0][1]];
00416    b[6] = S5[temp[3][2]]; 
00417    b[7] = S5[temp[2][3]];
00418    b[8] = S5[temp[2][0]];
00419    b[9] = S5[temp[1][1]];
00420    b[10] = S5[temp[0][2]]; 
00421    b[11] = S5[temp[3][3]];
00422    b[12] = S5[temp[3][0]];
00423    b[13] = S5[temp[2][1]];
00424    b[14] = S5[temp[1][2]]; 
00425    b[15] = S5[temp[0][3]];
00426         *((word32*)b) ^= *((word32*)rk[0][0]);
00427         *((word32*)(b+4)) ^= *((word32*)rk[0][1]);
00428         *((word32*)(b+8)) ^= *((word32*)rk[0][2]);
00429         *((word32*)(b+12)) ^= *((word32*)rk[0][3]);
00430 
00431         return 0;
00432 }
00433 
00434 
00435 int rijndaelDecryptRound (word8 a[4][4],  
00436         word8 rk[MAXROUNDS+1][4][4], int rounds)
00437 // Decrypt only a certain number of rounds.
00438 // Only used in the Intermediate Value Known Answer Test.
00439 // Operations rearranged such that the intermediate values
00440 // of decryption correspond with the intermediate values
00441 // of encryption.
00442 
00443 {
00444         int r;
00445         
00446 
00447         // make number of rounds sane
00448         if (rounds > ROUNDS) rounds = ROUNDS;
00449 
00450         // First the special round:
00451         //   without InvMixColumn
00452         //   with extra KeyAddition
00453         
00454         KeyAddition(a,rk[ROUNDS],4);
00455         Substitution(a,Si,4);
00456         ShiftRow(a,1,4);              
00457         
00458         // ROUNDS-1 ordinary rounds
00459         
00460         for(r = ROUNDS-1; r > rounds; r--) {
00461                 KeyAddition(a,rk[r],4);
00462                 InvMixColumn(a,4);      
00463                 Substitution(a,Si,4);
00464                 ShiftRow(a,1,4);                
00465         }
00466         
00467         if (rounds == 0) {
00468                 // End with the extra key addition
00469                         
00470                 KeyAddition(a,rk[0],4);
00471         }    
00472 
00473         return 0;
00474 }
00475 
00476 /*** End Rijndael algorithm,  Begin the AES Interface ***/
00477 
00478 
00479 int makeKey(keyInstance *key, BYTE direction, int keyByteLen, char *keyMaterial)
00480 {
00481         word8 k[MAXKC][4];
00482         int i;
00483         int keyLen = keyByteLen*8;
00484         
00485         if (key == NULL) {
00486                 return BAD_KEY_INSTANCE;
00487         }
00488 
00489         if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
00490                 key->direction = direction;
00491         } else {
00492                 return BAD_KEY_DIR;
00493         }
00494 
00495         if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { 
00496                 key->keyLen = keyLen;
00497         } else {
00498                 return BAD_KEY_MAT;
00499         }
00500 
00501         if ( keyMaterial ) {
00502                 strncpy(key->keyMaterial, keyMaterial, keyByteLen);
00503         } else {
00504                 return BAD_KEY_MAT;
00505         }
00506 
00507         ROUNDS = keyLen/32 + 6;
00508 
00509         // initialize key schedule:
00510         for(i = 0; i < key->keyLen/8; i++) {
00511                 k[i / 4][i % 4] = (word8) key->keyMaterial[i]; 
00512         }
00513         rijndaelKeySched (k, key->keyLen, key->keySched);
00514         if (direction == DIR_DECRYPT)
00515                 rijndaelKeyEnctoDec (key->keyLen, key->keySched);
00516 
00517         return TRUE;
00518 }
00519 
00520 int cipherInit(cipherInstance *cipher, BYTE mode, char *IV)
00521 {
00522         int i;
00523         
00524         if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
00525                 cipher->mode = mode;
00526         } else {
00527                 return BAD_CIPHER_MODE;
00528         }
00529         
00530 
00531         if (IV != NULL) {
00532                 for(i = 0; i < 16; i++) cipher->IV[i] = IV[i];
00533         }
00534         else
00535         {
00536                 // KevinJ - Added this to just generate a random initialization vector
00537                 for(i = 0; i < 16; i++)
00538                         cipher->IV[i]=(BYTE)randomMT();
00539         }
00540 
00541         return TRUE;
00542 }
00543 
00544 
00545 int blockEncrypt(cipherInstance *cipher,
00546         keyInstance *key, BYTE *input, int inputByteLen, BYTE *outBuffer)
00547 {
00548         int i, k, numBlocks;
00549         word8 block[16], iv[4][4];
00550         int inputLen = inputByteLen*8;
00551 
00552         if (cipher == NULL ||
00553                 key == NULL ||
00554                 key->direction == DIR_DECRYPT) {
00555                 return BAD_CIPHER_STATE;
00556         }
00557         
00558 
00559         numBlocks = inputLen/128;
00560         
00561         switch (cipher->mode) {
00562         case MODE_ECB: 
00563                 for (i = numBlocks; i > 0; i--) {
00564                         
00565                         rijndaelEncrypt (input, outBuffer, key->keySched);
00566                         
00567                         input += 16;
00568                         outBuffer += 16;
00569                 }
00570                 break;
00571                 
00572         case MODE_CBC:
00573 #if STRICT_ALIGN 
00574                 memcpy(block,cipher->IV,16); 
00575 #else
00576                 *((word32*)block) =  *((word32*)(cipher->IV));
00577                 *((word32*)(block+4)) =  *((word32*)(cipher->IV+4));
00578                 *((word32*)(block+8)) =  *((word32*)(cipher->IV+8));
00579                 *((word32*)(block+12)) =  *((word32*)(cipher->IV+12));
00580 #endif
00581                 
00582                 for (i = numBlocks; i > 0; i--) {
00583                         *((word32*)block) ^= *((word32*)(input));
00584                         *((word32*)(block+4)) ^= *((word32*)(input+4));
00585                         *((word32*)(block+8)) ^= *((word32*)(input+8));
00586                         *((word32*)(block+12)) ^= *((word32*)(input+12));
00587 
00588                         rijndaelEncrypt (block, outBuffer, key->keySched);
00589                         
00590                         input += 16;
00591                         outBuffer += 16;
00592                 }
00593                 break;
00594         
00595         case MODE_CFB1:
00596 #if STRICT_ALIGN 
00597                 memcpy(iv,cipher->IV,16); 
00598 #else
00599                 *((word32*)iv[0]) = *((word32*)(cipher->IV));
00600                 *((word32*)iv[1]) = *((word32*)(cipher->IV+4));
00601                 *((word32*)iv[2]) = *((word32*)(cipher->IV+8));
00602                 *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
00603 #endif
00604                 for (i = numBlocks; i > 0; i--) {
00605                         for (k = 0; k < 128; k++) {
00606                                 *((word32*)block) = *((word32*)iv[0]);
00607                                 *((word32*)(block+4)) = *((word32*)iv[1]);
00608                                 *((word32*)(block+8)) = *((word32*)iv[2]);
00609                                 *((word32*)(block+12)) = *((word32*)iv[3]);
00610 
00611                                 rijndaelEncrypt (block, block, key->keySched);
00612                                 outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
00613                                 iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
00614                                 iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
00615                                 iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
00616                                 iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
00617                                 iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
00618                                 iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
00619                                 iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
00620                                 iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
00621                                 iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
00622                                 iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
00623                                 iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
00624                                 iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
00625                                 iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
00626                                 iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
00627                                 iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
00628                                 iv[3][3] = (word8)((iv[3][3] << 1) | (outBuffer[k/8] >> (7-(k&7))) & 1);
00629                         }
00630                 }
00631                 break;
00632         
00633         default:
00634                 return BAD_CIPHER_STATE;
00635         }
00636         
00637         return numBlocks*128;
00638 }
00639 
00640 int blockDecrypt(cipherInstance *cipher,
00641         keyInstance *key, BYTE *input, int inputByteLen, BYTE *outBuffer)
00642 {
00643         int i, k, numBlocks;
00644         word8 block[16], iv[4][4];
00645         int inputLen = inputByteLen*8;
00646 
00647         if (cipher == NULL ||
00648                 key == NULL ||
00649                 cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT) {
00650                 return BAD_CIPHER_STATE;
00651         }
00652         
00653 
00654         numBlocks = inputLen/128;
00655         
00656         switch (cipher->mode) {
00657         case MODE_ECB: 
00658                 for (i = numBlocks; i > 0; i--) { 
00659 
00660                         rijndaelDecrypt (input, outBuffer, key->keySched);
00661 
00662                         input += 16;
00663                         outBuffer += 16;
00664 
00665                 }
00666                 break;
00667                 
00668         case MODE_CBC:
00669                 // first block 
00670 
00671                 rijndaelDecrypt (input, block, key->keySched);
00672 #if STRICT_ALIGN
00673                 memcpy(outBuffer,cipher->IV,16); 
00674                 *((word32*)(outBuffer)) ^= *((word32*)block);
00675                 *((word32*)(outBuffer+4)) ^= *((word32*)(block+4));
00676                 *((word32*)(outBuffer+8)) ^= *((word32*)(block+8));
00677                 *((word32*)(outBuffer+12)) ^= *((word32*)(block+12));
00678 #else
00679                 *((word32*)(outBuffer)) = *((word32*)block) ^ *((word32*)(cipher->IV));
00680                 *((word32*)(outBuffer+4)) = *((word32*)(block+4)) ^ *((word32*)(cipher->IV+4));
00681                 *((word32*)(outBuffer+8)) = *((word32*)(block+8)) ^ *((word32*)(cipher->IV+8));
00682                 *((word32*)(outBuffer+12)) = *((word32*)(block+12)) ^ *((word32*)(cipher->IV+12));
00683 #endif
00684                 
00685                 // next blocks
00686                 for (i = numBlocks-1; i > 0; i--) { 
00687                 
00688                         rijndaelDecrypt (input, block, key->keySched);
00689                         
00690                         *((word32*)(outBuffer+16)) = *((word32*)block) ^
00691                                         *((word32*)(input-16));
00692                         *((word32*)(outBuffer+20)) = *((word32*)(block+4)) ^
00693                                         *((word32*)(input-12));
00694                         *((word32*)(outBuffer+24)) = *((word32*)(block+8)) ^
00695                                         *((word32*)(input-8));
00696                         *((word32*)(outBuffer+28)) = *((word32*)(block+12)) ^
00697                                         *((word32*)(input-4));
00698                         
00699                         input += 16;
00700                         outBuffer += 16;
00701                 }
00702                 break;
00703         
00704         case MODE_CFB1:
00705 #if STRICT_ALIGN 
00706                 memcpy(iv,cipher->IV,16); 
00707 #else
00708                 *((word32*)iv[0]) = *((word32*)(cipher->IV));
00709                 *((word32*)iv[1]) = *((word32*)(cipher->IV+4));
00710                 *((word32*)iv[2]) = *((word32*)(cipher->IV+8));
00711                 *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
00712 #endif
00713                 for (i = numBlocks; i > 0; i--) {
00714                         for (k = 0; k < 128; k++) {
00715                                 *((word32*)block) = *((word32*)iv[0]);
00716                                 *((word32*)(block+4)) = *((word32*)iv[1]);
00717                                 *((word32*)(block+8)) = *((word32*)iv[2]);
00718                                 *((word32*)(block+12)) = *((word32*)iv[3]);
00719 
00720                                 rijndaelEncrypt (block, block, key->keySched);
00721                                 iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
00722                                 iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
00723                                 iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
00724                                 iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
00725                                 iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
00726                                 iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
00727                                 iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
00728                                 iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
00729                                 iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
00730                                 iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
00731                                 iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
00732                                 iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
00733                                 iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
00734                                 iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
00735                                 iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
00736                                 iv[3][3] = (word8)((iv[3][3] << 1) | (input[k/8] >> (7-(k&7))) & 1);
00737                                 outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
00738                         }
00739                 }
00740                 break;
00741 
00742         default:
00743                 return BAD_CIPHER_STATE;
00744         }
00745         
00746         return numBlocks*128;
00747 }
00748 
00749 
00761 int cipherUpdateRounds(cipherInstance *cipher,
00762         keyInstance *key, BYTE *input, int inputLen __UNUS, BYTE *outBuffer, int rounds)
00763 {
00764         (void) inputLen;
00765 
00766         int j;
00767         word8 block[4][4];
00768 
00769         if (cipher == NULL ||
00770                 key == NULL) {
00771                 return BAD_CIPHER_STATE;
00772         }
00773 
00774         for (j = 3; j >= 0; j--) {
00775                 // parse input stream into rectangular array
00776                 *((word32*)block[j]) = *((word32*)(input+4*j));
00777         }
00778 
00779         switch (key->direction) {
00780         case DIR_ENCRYPT:
00781                 rijndaelEncryptRound (block, key->keySched, rounds);
00782         break;
00783                 
00784         case DIR_DECRYPT:
00785                 rijndaelDecryptRound (block, key->keySched, rounds);
00786         break;
00787                 
00788         default: return BAD_KEY_DIR;
00789         } 
00790 
00791         for (j = 3; j >= 0; j--) {
00792                 // parse rectangular array into output ciphertext bytes
00793                 *((word32*)(outBuffer+4*j)) = *((word32*)block[j]);
00794         }
00795         
00796         return TRUE;
00797 }

Generated on Thu Sep 30 2010 01:27:28 for RakNet by  doxygen 1.7.1