Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

rijndael.cpp

00001 // rijndael.cpp - modified by Chris Morgan <cmorgan@wpi.edu>
00002 // and Wei Dai from Paulo Baretto's Rijndael implementation
00003 // The original code and all modifications are in the public domain.
00004 
00005 // This is the original introductory comment:
00006 
00007 /**
00008  * version 3.0 (December 2000)
00009  *
00010  * Optimised ANSI C code for the Rijndael cipher (now AES)
00011  *
00012  * author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
00013  * author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
00014  * author Paulo Barreto <paulo.barreto@terra.com.br>
00015  *
00016  * This code is hereby placed in the public domain.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
00019  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
00022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
00025  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00027  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00028  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  */
00030 
00031 #include "pch.h"
00032 
00033 #ifndef CRYPTOPP_IMPORTS
00034 
00035 #include "rijndael.h"
00036 #include "misc.h"
00037 
00038 NAMESPACE_BEGIN(CryptoPP)
00039 
00040 void Rijndael::Base::UncheckedSetKey(CipherDir dir, const byte *userKey, unsigned int keylen)
00041 {
00042         AssertValidKeyLength(keylen);
00043 
00044         m_rounds = keylen/4 + 6;
00045         m_key.New(4*(m_rounds+1));
00046 
00047         word32 temp, *rk = m_key;
00048         unsigned int i=0;
00049 
00050         GetUserKey(BIG_ENDIAN_ORDER, rk, keylen/4, userKey, keylen);
00051 
00052         switch(keylen)
00053         {
00054         case 16:
00055                 while (true)
00056                 {
00057                         temp  = rk[3];
00058                         rk[4] = rk[0] ^
00059                                 (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
00060                                 (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
00061                                 (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
00062                                 (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
00063                                 rcon[i];
00064                         rk[5] = rk[1] ^ rk[4];
00065                         rk[6] = rk[2] ^ rk[5];
00066                         rk[7] = rk[3] ^ rk[6];
00067                         if (++i == 10)
00068                                 break;
00069                         rk += 4;
00070                 }
00071                 break;
00072 
00073         case 24:
00074                 while (true)    // for (;;) here triggers a bug in VC60 SP4 w/ Processor Pack
00075                 {
00076                         temp = rk[ 5];
00077                         rk[ 6] = rk[ 0] ^
00078                                 (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
00079                                 (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
00080                                 (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
00081                                 (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
00082                                 rcon[i];
00083                         rk[ 7] = rk[ 1] ^ rk[ 6];
00084                         rk[ 8] = rk[ 2] ^ rk[ 7];
00085                         rk[ 9] = rk[ 3] ^ rk[ 8];
00086                         if (++i == 8)
00087                                 break;
00088                         rk[10] = rk[ 4] ^ rk[ 9];
00089                         rk[11] = rk[ 5] ^ rk[10];
00090                         rk += 6;
00091                 }
00092                 break;
00093 
00094         case 32:
00095         while (true)
00096                 {
00097                 temp = rk[ 7];
00098                 rk[ 8] = rk[ 0] ^
00099                         (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
00100                         (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
00101                         (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
00102                         (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
00103                         rcon[i];
00104                 rk[ 9] = rk[ 1] ^ rk[ 8];
00105                 rk[10] = rk[ 2] ^ rk[ 9];
00106                 rk[11] = rk[ 3] ^ rk[10];
00107                         if (++i == 7)
00108                                 break;
00109                 temp = rk[11];
00110                 rk[12] = rk[ 4] ^
00111                         (Te4[GETBYTE(temp, 3)] & 0xff000000) ^
00112                         (Te4[GETBYTE(temp, 2)] & 0x00ff0000) ^
00113                         (Te4[GETBYTE(temp, 1)] & 0x0000ff00) ^
00114                         (Te4[GETBYTE(temp, 0)] & 0x000000ff);
00115                 rk[13] = rk[ 5] ^ rk[12];
00116                 rk[14] = rk[ 6] ^ rk[13];
00117                 rk[15] = rk[ 7] ^ rk[14];
00118 
00119                         rk += 8;
00120         }
00121                 break;
00122         }
00123 
00124         if (dir == DECRYPTION)
00125         {
00126                 unsigned int i, j;
00127                 rk = m_key;
00128 
00129                 /* invert the order of the round keys: */
00130                 for (i = 0, j = 4*m_rounds; i < j; i += 4, j -= 4) {
00131                         temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
00132                         temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
00133                         temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
00134                         temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
00135                 }
00136                 /* apply the inverse MixColumn transform to all round keys but the first and the last: */
00137                 for (i = 1; i < m_rounds; i++) {
00138                         rk += 4;
00139                         rk[0] =
00140                                 Td0[Te4[GETBYTE(rk[0], 3)] & 0xff] ^
00141                                 Td1[Te4[GETBYTE(rk[0], 2)] & 0xff] ^
00142                                 Td2[Te4[GETBYTE(rk[0], 1)] & 0xff] ^
00143                                 Td3[Te4[GETBYTE(rk[0], 0)] & 0xff];
00144                         rk[1] =
00145                                 Td0[Te4[GETBYTE(rk[1], 3)] & 0xff] ^
00146                                 Td1[Te4[GETBYTE(rk[1], 2)] & 0xff] ^
00147                                 Td2[Te4[GETBYTE(rk[1], 1)] & 0xff] ^
00148                                 Td3[Te4[GETBYTE(rk[1], 0)] & 0xff];
00149                         rk[2] =
00150                                 Td0[Te4[GETBYTE(rk[2], 3)] & 0xff] ^
00151                                 Td1[Te4[GETBYTE(rk[2], 2)] & 0xff] ^
00152                                 Td2[Te4[GETBYTE(rk[2], 1)] & 0xff] ^
00153                                 Td3[Te4[GETBYTE(rk[2], 0)] & 0xff];
00154                         rk[3] =
00155                                 Td0[Te4[GETBYTE(rk[3], 3)] & 0xff] ^
00156                                 Td1[Te4[GETBYTE(rk[3], 2)] & 0xff] ^
00157                                 Td2[Te4[GETBYTE(rk[3], 1)] & 0xff] ^
00158                                 Td3[Te4[GETBYTE(rk[3], 0)] & 0xff];
00159                 }
00160         }
00161 }
00162 
00163 typedef BlockGetAndPut<word32, BigEndian> Block;
00164 
00165 void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
00166 {
00167         word32 s0, s1, s2, s3, t0, t1, t2, t3;
00168         const word32 *rk = m_key;
00169 
00170     /*
00171          * map byte array block to cipher state
00172          * and add initial round key:
00173          */
00174         Block::Get(inBlock)(s0)(s1)(s2)(s3);
00175         s0 ^= rk[0];
00176         s1 ^= rk[1];
00177         s2 ^= rk[2];
00178         s3 ^= rk[3];
00179     /*
00180          * Nr - 1 full rounds:
00181          */
00182     unsigned int r = m_rounds >> 1;
00183     for (;;) {
00184         t0 =
00185             Te0[GETBYTE(s0, 3)] ^
00186             Te1[GETBYTE(s1, 2)] ^
00187             Te2[GETBYTE(s2, 1)] ^
00188             Te3[GETBYTE(s3, 0)] ^
00189             rk[4];
00190         t1 =
00191             Te0[GETBYTE(s1, 3)] ^
00192             Te1[GETBYTE(s2, 2)] ^
00193             Te2[GETBYTE(s3, 1)] ^
00194             Te3[GETBYTE(s0, 0)] ^
00195             rk[5];
00196         t2 =
00197             Te0[GETBYTE(s2, 3)] ^
00198             Te1[GETBYTE(s3, 2)] ^
00199             Te2[GETBYTE(s0, 1)] ^
00200             Te3[GETBYTE(s1, 0)] ^
00201             rk[6];
00202         t3 =
00203             Te0[GETBYTE(s3, 3)] ^
00204             Te1[GETBYTE(s0, 2)] ^
00205             Te2[GETBYTE(s1, 1)] ^
00206             Te3[GETBYTE(s2, 0)] ^
00207             rk[7];
00208 
00209         rk += 8;
00210         if (--r == 0) {
00211             break;
00212         }
00213 
00214         s0 =
00215             Te0[GETBYTE(t0, 3)] ^
00216             Te1[GETBYTE(t1, 2)] ^
00217             Te2[GETBYTE(t2, 1)] ^
00218             Te3[GETBYTE(t3, 0)] ^
00219             rk[0];
00220         s1 =
00221             Te0[GETBYTE(t1, 3)] ^
00222             Te1[GETBYTE(t2, 2)] ^
00223             Te2[GETBYTE(t3, 1)] ^
00224             Te3[GETBYTE(t0, 0)] ^
00225             rk[1];
00226         s2 =
00227             Te0[GETBYTE(t2, 3)] ^
00228             Te1[GETBYTE(t3, 2)] ^
00229             Te2[GETBYTE(t0, 1)] ^
00230             Te3[GETBYTE(t1, 0)] ^
00231             rk[2];
00232         s3 =
00233             Te0[GETBYTE(t3, 3)] ^
00234             Te1[GETBYTE(t0, 2)] ^
00235             Te2[GETBYTE(t1, 1)] ^
00236             Te3[GETBYTE(t2, 0)] ^
00237             rk[3];
00238     }
00239     /*
00240          * apply last round and
00241          * map cipher state to byte array block:
00242          */
00243 
00244         s0 =
00245                 (Te4[GETBYTE(t0, 3)] & 0xff000000) ^
00246                 (Te4[GETBYTE(t1, 2)] & 0x00ff0000) ^
00247                 (Te4[GETBYTE(t2, 1)] & 0x0000ff00) ^
00248                 (Te4[GETBYTE(t3, 0)] & 0x000000ff) ^
00249                 rk[0];
00250         s1 =
00251                 (Te4[GETBYTE(t1, 3)] & 0xff000000) ^
00252                 (Te4[GETBYTE(t2, 2)] & 0x00ff0000) ^
00253                 (Te4[GETBYTE(t3, 1)] & 0x0000ff00) ^
00254                 (Te4[GETBYTE(t0, 0)] & 0x000000ff) ^
00255                 rk[1];
00256         s2 =
00257                 (Te4[GETBYTE(t2, 3)] & 0xff000000) ^
00258                 (Te4[GETBYTE(t3, 2)] & 0x00ff0000) ^
00259                 (Te4[GETBYTE(t0, 1)] & 0x0000ff00) ^
00260                 (Te4[GETBYTE(t1, 0)] & 0x000000ff) ^
00261                 rk[2];
00262         s3 =
00263                 (Te4[GETBYTE(t3, 3)] & 0xff000000) ^
00264                 (Te4[GETBYTE(t0, 2)] & 0x00ff0000) ^
00265                 (Te4[GETBYTE(t1, 1)] & 0x0000ff00) ^
00266                 (Te4[GETBYTE(t2, 0)] & 0x000000ff) ^
00267                 rk[3];
00268 
00269         Block::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3);
00270 }
00271 
00272 void Rijndael::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
00273 {
00274         word32 s0, s1, s2, s3, t0, t1, t2, t3;
00275     const word32 *rk = m_key;
00276 
00277     /*
00278          * map byte array block to cipher state
00279          * and add initial round key:
00280          */
00281         Block::Get(inBlock)(s0)(s1)(s2)(s3);
00282         s0 ^= rk[0];
00283         s1 ^= rk[1];
00284         s2 ^= rk[2];
00285         s3 ^= rk[3];
00286     /*
00287      * Nr - 1 full rounds:
00288      */
00289     unsigned int r = m_rounds >> 1;
00290     for (;;) {
00291         t0 =
00292             Td0[GETBYTE(s0, 3)] ^
00293             Td1[GETBYTE(s3, 2)] ^
00294             Td2[GETBYTE(s2, 1)] ^
00295             Td3[GETBYTE(s1, 0)] ^
00296             rk[4];
00297         t1 =
00298             Td0[GETBYTE(s1, 3)] ^
00299             Td1[GETBYTE(s0, 2)] ^
00300             Td2[GETBYTE(s3, 1)] ^
00301             Td3[GETBYTE(s2, 0)] ^
00302             rk[5];
00303         t2 =
00304             Td0[GETBYTE(s2, 3)] ^
00305             Td1[GETBYTE(s1, 2)] ^
00306             Td2[GETBYTE(s0, 1)] ^
00307             Td3[GETBYTE(s3, 0)] ^
00308             rk[6];
00309         t3 =
00310             Td0[GETBYTE(s3, 3)] ^
00311             Td1[GETBYTE(s2, 2)] ^
00312             Td2[GETBYTE(s1, 1)] ^
00313             Td3[GETBYTE(s0, 0)] ^
00314             rk[7];
00315 
00316         rk += 8;
00317         if (--r == 0) {
00318             break;
00319         }
00320 
00321         s0 =
00322             Td0[GETBYTE(t0, 3)] ^
00323             Td1[GETBYTE(t3, 2)] ^
00324             Td2[GETBYTE(t2, 1)] ^
00325             Td3[GETBYTE(t1, 0)] ^
00326             rk[0];
00327         s1 =
00328             Td0[GETBYTE(t1, 3)] ^
00329             Td1[GETBYTE(t0, 2)] ^
00330             Td2[GETBYTE(t3, 1)] ^
00331             Td3[GETBYTE(t2, 0)] ^
00332             rk[1];
00333         s2 =
00334             Td0[GETBYTE(t2, 3)] ^
00335             Td1[GETBYTE(t1, 2)] ^
00336             Td2[GETBYTE(t0, 1)] ^
00337             Td3[GETBYTE(t3, 0)] ^
00338             rk[2];
00339         s3 =
00340             Td0[GETBYTE(t3, 3)] ^
00341             Td1[GETBYTE(t2, 2)] ^
00342             Td2[GETBYTE(t1, 1)] ^
00343             Td3[GETBYTE(t0, 0)] ^
00344             rk[3];
00345     }
00346     /*
00347          * apply last round and
00348          * map cipher state to byte array block:
00349          */
00350         s0 =
00351                 (Td4[GETBYTE(t0, 3)] & 0xff000000) ^
00352                 (Td4[GETBYTE(t3, 2)] & 0x00ff0000) ^
00353                 (Td4[GETBYTE(t2, 1)] & 0x0000ff00) ^
00354                 (Td4[GETBYTE(t1, 0)] & 0x000000ff) ^
00355                 rk[0];
00356         s1 =
00357                 (Td4[GETBYTE(t1, 3)] & 0xff000000) ^
00358                 (Td4[GETBYTE(t0, 2)] & 0x00ff0000) ^
00359                 (Td4[GETBYTE(t3, 1)] & 0x0000ff00) ^
00360                 (Td4[GETBYTE(t2, 0)] & 0x000000ff) ^
00361                 rk[1];
00362         s2 =
00363                 (Td4[GETBYTE(t2, 3)] & 0xff000000) ^
00364                 (Td4[GETBYTE(t1, 2)] & 0x00ff0000) ^
00365                 (Td4[GETBYTE(t0, 1)] & 0x0000ff00) ^
00366                 (Td4[GETBYTE(t3, 0)] & 0x000000ff) ^
00367                 rk[2];
00368         s3 =
00369                 (Td4[GETBYTE(t3, 3)] & 0xff000000) ^
00370                 (Td4[GETBYTE(t2, 2)] & 0x00ff0000) ^
00371                 (Td4[GETBYTE(t1, 1)] & 0x0000ff00) ^
00372                 (Td4[GETBYTE(t0, 0)] & 0x000000ff) ^
00373                 rk[3];
00374 
00375         Block::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3);
00376 }
00377 
00378 NAMESPACE_END
00379 
00380 #endif

Generated on Wed Nov 17 21:26:09 2004 for Crypto++ by  doxygen 1.3.9.1