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 #include "rijndael.h"
00033 #include "misc.h"
00034 
00035 NAMESPACE_BEGIN(CryptoPP)
00036 
00037 void Rijndael::Base::UncheckedSetKey(CipherDir dir, const byte *userKey, unsigned int keylen)
00038 {
00039         AssertValidKeyLength(keylen);
00040 
00041         m_rounds = keylen/4 + 6;
00042         m_key.New(4*(m_rounds+1));
00043 
00044         word32 temp, *rk = m_key;
00045         unsigned int i=0;
00046 
00047         GetUserKey(BIG_ENDIAN_ORDER, rk, keylen/4, userKey, keylen);
00048 
00049         switch(keylen)
00050         {
00051         case 16:
00052                 while (true)
00053                 {
00054                         temp  = rk[3];
00055                         rk[4] = rk[0] ^
00056                                 (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
00057                                 (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
00058                                 (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
00059                                 (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
00060                                 rcon[i];
00061                         rk[5] = rk[1] ^ rk[4];
00062                         rk[6] = rk[2] ^ rk[5];
00063                         rk[7] = rk[3] ^ rk[6];
00064                         if (++i == 10)
00065                                 break;
00066                         rk += 4;
00067                 }
00068                 break;
00069 
00070         case 24:
00071                 while (true)    // for (;;) here triggers a bug in VC60 SP4 w/ Processor Pack
00072                 {
00073                         temp = rk[ 5];
00074                         rk[ 6] = rk[ 0] ^
00075                                 (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
00076                                 (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
00077                                 (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
00078                                 (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
00079                                 rcon[i];
00080                         rk[ 7] = rk[ 1] ^ rk[ 6];
00081                         rk[ 8] = rk[ 2] ^ rk[ 7];
00082                         rk[ 9] = rk[ 3] ^ rk[ 8];
00083                         if (++i == 8)
00084                                 break;
00085                         rk[10] = rk[ 4] ^ rk[ 9];
00086                         rk[11] = rk[ 5] ^ rk[10];
00087                         rk += 6;
00088                 }
00089                 break;
00090 
00091         case 32:
00092         while (true)
00093                 {
00094                 temp = rk[ 7];
00095                 rk[ 8] = rk[ 0] ^
00096                         (Te4[GETBYTE(temp, 2)] & 0xff000000) ^
00097                         (Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
00098                         (Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
00099                         (Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
00100                         rcon[i];
00101                 rk[ 9] = rk[ 1] ^ rk[ 8];
00102                 rk[10] = rk[ 2] ^ rk[ 9];
00103                 rk[11] = rk[ 3] ^ rk[10];
00104                         if (++i == 7)
00105                                 break;
00106                 temp = rk[11];
00107                 rk[12] = rk[ 4] ^
00108                         (Te4[GETBYTE(temp, 3)] & 0xff000000) ^
00109                         (Te4[GETBYTE(temp, 2)] & 0x00ff0000) ^
00110                         (Te4[GETBYTE(temp, 1)] & 0x0000ff00) ^
00111                         (Te4[GETBYTE(temp, 0)] & 0x000000ff);
00112                 rk[13] = rk[ 5] ^ rk[12];
00113                 rk[14] = rk[ 6] ^ rk[13];
00114                 rk[15] = rk[ 7] ^ rk[14];
00115 
00116                         rk += 8;
00117         }
00118                 break;
00119         }
00120 
00121         if (dir == DECRYPTION)
00122         {
00123                 unsigned int i, j;
00124                 rk = m_key;
00125 
00126                 /* invert the order of the round keys: */
00127                 for (i = 0, j = 4*m_rounds; i < j; i += 4, j -= 4) {
00128                         temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
00129                         temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
00130                         temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
00131                         temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
00132                 }
00133                 /* apply the inverse MixColumn transform to all round keys but the first and the last: */
00134                 for (i = 1; i < m_rounds; i++) {
00135                         rk += 4;
00136                         rk[0] =
00137                                 Td0[Te4[GETBYTE(rk[0], 3)] & 0xff] ^
00138                                 Td1[Te4[GETBYTE(rk[0], 2)] & 0xff] ^
00139                                 Td2[Te4[GETBYTE(rk[0], 1)] & 0xff] ^
00140                                 Td3[Te4[GETBYTE(rk[0], 0)] & 0xff];
00141                         rk[1] =
00142                                 Td0[Te4[GETBYTE(rk[1], 3)] & 0xff] ^
00143                                 Td1[Te4[GETBYTE(rk[1], 2)] & 0xff] ^
00144                                 Td2[Te4[GETBYTE(rk[1], 1)] & 0xff] ^
00145                                 Td3[Te4[GETBYTE(rk[1], 0)] & 0xff];
00146                         rk[2] =
00147                                 Td0[Te4[GETBYTE(rk[2], 3)] & 0xff] ^
00148                                 Td1[Te4[GETBYTE(rk[2], 2)] & 0xff] ^
00149                                 Td2[Te4[GETBYTE(rk[2], 1)] & 0xff] ^
00150                                 Td3[Te4[GETBYTE(rk[2], 0)] & 0xff];
00151                         rk[3] =
00152                                 Td0[Te4[GETBYTE(rk[3], 3)] & 0xff] ^
00153                                 Td1[Te4[GETBYTE(rk[3], 2)] & 0xff] ^
00154                                 Td2[Te4[GETBYTE(rk[3], 1)] & 0xff] ^
00155                                 Td3[Te4[GETBYTE(rk[3], 0)] & 0xff];
00156                 }
00157         }
00158 }
00159 
00160 typedef BlockGetAndPut<word32, BigEndian> Block;
00161 
00162 void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
00163 {
00164         word32 s0, s1, s2, s3, t0, t1, t2, t3;
00165         const word32 *rk = m_key;
00166 
00167     /*
00168          * map byte array block to cipher state
00169          * and add initial round key:
00170          */
00171         Block::Get(inBlock)(s0)(s1)(s2)(s3);
00172         s0 ^= rk[0];
00173         s1 ^= rk[1];
00174         s2 ^= rk[2];
00175         s3 ^= rk[3];
00176     /*
00177          * Nr - 1 full rounds:
00178          */
00179     unsigned int r = m_rounds >> 1;
00180     for (;;) {
00181         t0 =
00182             Te0[GETBYTE(s0, 3)] ^
00183             Te1[GETBYTE(s1, 2)] ^
00184             Te2[GETBYTE(s2, 1)] ^
00185             Te3[GETBYTE(s3, 0)] ^
00186             rk[4];
00187         t1 =
00188             Te0[GETBYTE(s1, 3)] ^
00189             Te1[GETBYTE(s2, 2)] ^
00190             Te2[GETBYTE(s3, 1)] ^
00191             Te3[GETBYTE(s0, 0)] ^
00192             rk[5];
00193         t2 =
00194             Te0[GETBYTE(s2, 3)] ^
00195             Te1[GETBYTE(s3, 2)] ^
00196             Te2[GETBYTE(s0, 1)] ^
00197             Te3[GETBYTE(s1, 0)] ^
00198             rk[6];
00199         t3 =
00200             Te0[GETBYTE(s3, 3)] ^
00201             Te1[GETBYTE(s0, 2)] ^
00202             Te2[GETBYTE(s1, 1)] ^
00203             Te3[GETBYTE(s2, 0)] ^
00204             rk[7];
00205 
00206         rk += 8;
00207         if (--r == 0) {
00208             break;
00209         }
00210 
00211         s0 =
00212             Te0[GETBYTE(t0, 3)] ^
00213             Te1[GETBYTE(t1, 2)] ^
00214             Te2[GETBYTE(t2, 1)] ^
00215             Te3[GETBYTE(t3, 0)] ^
00216             rk[0];
00217         s1 =
00218             Te0[GETBYTE(t1, 3)] ^
00219             Te1[GETBYTE(t2, 2)] ^
00220             Te2[GETBYTE(t3, 1)] ^
00221             Te3[GETBYTE(t0, 0)] ^
00222             rk[1];
00223         s2 =
00224             Te0[GETBYTE(t2, 3)] ^
00225             Te1[GETBYTE(t3, 2)] ^
00226             Te2[GETBYTE(t0, 1)] ^
00227             Te3[GETBYTE(t1, 0)] ^
00228             rk[2];
00229         s3 =
00230             Te0[GETBYTE(t3, 3)] ^
00231             Te1[GETBYTE(t0, 2)] ^
00232             Te2[GETBYTE(t1, 1)] ^
00233             Te3[GETBYTE(t2, 0)] ^
00234             rk[3];
00235     }
00236     /*
00237          * apply last round and
00238          * map cipher state to byte array block:
00239          */
00240 
00241         s0 =
00242                 (Te4[GETBYTE(t0, 3)] & 0xff000000) ^
00243                 (Te4[GETBYTE(t1, 2)] & 0x00ff0000) ^
00244                 (Te4[GETBYTE(t2, 1)] & 0x0000ff00) ^
00245                 (Te4[GETBYTE(t3, 0)] & 0x000000ff) ^
00246                 rk[0];
00247         s1 =
00248                 (Te4[GETBYTE(t1, 3)] & 0xff000000) ^
00249                 (Te4[GETBYTE(t2, 2)] & 0x00ff0000) ^
00250                 (Te4[GETBYTE(t3, 1)] & 0x0000ff00) ^
00251                 (Te4[GETBYTE(t0, 0)] & 0x000000ff) ^
00252                 rk[1];
00253         s2 =
00254                 (Te4[GETBYTE(t2, 3)] & 0xff000000) ^
00255                 (Te4[GETBYTE(t3, 2)] & 0x00ff0000) ^
00256                 (Te4[GETBYTE(t0, 1)] & 0x0000ff00) ^
00257                 (Te4[GETBYTE(t1, 0)] & 0x000000ff) ^
00258                 rk[2];
00259         s3 =
00260                 (Te4[GETBYTE(t3, 3)] & 0xff000000) ^
00261                 (Te4[GETBYTE(t0, 2)] & 0x00ff0000) ^
00262                 (Te4[GETBYTE(t1, 1)] & 0x0000ff00) ^
00263                 (Te4[GETBYTE(t2, 0)] & 0x000000ff) ^
00264                 rk[3];
00265 
00266         Block::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3);
00267 }
00268 
00269 void Rijndael::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
00270 {
00271         word32 s0, s1, s2, s3, t0, t1, t2, t3;
00272     const word32 *rk = m_key;
00273 
00274     /*
00275          * map byte array block to cipher state
00276          * and add initial round key:
00277          */
00278         Block::Get(inBlock)(s0)(s1)(s2)(s3);
00279         s0 ^= rk[0];
00280         s1 ^= rk[1];
00281         s2 ^= rk[2];
00282         s3 ^= rk[3];
00283     /*
00284      * Nr - 1 full rounds:
00285      */
00286     unsigned int r = m_rounds >> 1;
00287     for (;;) {
00288         t0 =
00289             Td0[GETBYTE(s0, 3)] ^
00290             Td1[GETBYTE(s3, 2)] ^
00291             Td2[GETBYTE(s2, 1)] ^
00292             Td3[GETBYTE(s1, 0)] ^
00293             rk[4];
00294         t1 =
00295             Td0[GETBYTE(s1, 3)] ^
00296             Td1[GETBYTE(s0, 2)] ^
00297             Td2[GETBYTE(s3, 1)] ^
00298             Td3[GETBYTE(s2, 0)] ^
00299             rk[5];
00300         t2 =
00301             Td0[GETBYTE(s2, 3)] ^
00302             Td1[GETBYTE(s1, 2)] ^
00303             Td2[GETBYTE(s0, 1)] ^
00304             Td3[GETBYTE(s3, 0)] ^
00305             rk[6];
00306         t3 =
00307             Td0[GETBYTE(s3, 3)] ^
00308             Td1[GETBYTE(s2, 2)] ^
00309             Td2[GETBYTE(s1, 1)] ^
00310             Td3[GETBYTE(s0, 0)] ^
00311             rk[7];
00312 
00313         rk += 8;
00314         if (--r == 0) {
00315             break;
00316         }
00317 
00318         s0 =
00319             Td0[GETBYTE(t0, 3)] ^
00320             Td1[GETBYTE(t3, 2)] ^
00321             Td2[GETBYTE(t2, 1)] ^
00322             Td3[GETBYTE(t1, 0)] ^
00323             rk[0];
00324         s1 =
00325             Td0[GETBYTE(t1, 3)] ^
00326             Td1[GETBYTE(t0, 2)] ^
00327             Td2[GETBYTE(t3, 1)] ^
00328             Td3[GETBYTE(t2, 0)] ^
00329             rk[1];
00330         s2 =
00331             Td0[GETBYTE(t2, 3)] ^
00332             Td1[GETBYTE(t1, 2)] ^
00333             Td2[GETBYTE(t0, 1)] ^
00334             Td3[GETBYTE(t3, 0)] ^
00335             rk[2];
00336         s3 =
00337             Td0[GETBYTE(t3, 3)] ^
00338             Td1[GETBYTE(t2, 2)] ^
00339             Td2[GETBYTE(t1, 1)] ^
00340             Td3[GETBYTE(t0, 0)] ^
00341             rk[3];
00342     }
00343     /*
00344          * apply last round and
00345          * map cipher state to byte array block:
00346          */
00347         s0 =
00348                 (Td4[GETBYTE(t0, 3)] & 0xff000000) ^
00349                 (Td4[GETBYTE(t3, 2)] & 0x00ff0000) ^
00350                 (Td4[GETBYTE(t2, 1)] & 0x0000ff00) ^
00351                 (Td4[GETBYTE(t1, 0)] & 0x000000ff) ^
00352                 rk[0];
00353         s1 =
00354                 (Td4[GETBYTE(t1, 3)] & 0xff000000) ^
00355                 (Td4[GETBYTE(t0, 2)] & 0x00ff0000) ^
00356                 (Td4[GETBYTE(t3, 1)] & 0x0000ff00) ^
00357                 (Td4[GETBYTE(t2, 0)] & 0x000000ff) ^
00358                 rk[1];
00359         s2 =
00360                 (Td4[GETBYTE(t2, 3)] & 0xff000000) ^
00361                 (Td4[GETBYTE(t1, 2)] & 0x00ff0000) ^
00362                 (Td4[GETBYTE(t0, 1)] & 0x0000ff00) ^
00363                 (Td4[GETBYTE(t3, 0)] & 0x000000ff) ^
00364                 rk[2];
00365         s3 =
00366                 (Td4[GETBYTE(t3, 3)] & 0xff000000) ^
00367                 (Td4[GETBYTE(t2, 2)] & 0x00ff0000) ^
00368                 (Td4[GETBYTE(t1, 1)] & 0x0000ff00) ^
00369                 (Td4[GETBYTE(t0, 0)] & 0x000000ff) ^
00370                 rk[3];
00371 
00372         Block::Put(xorBlock, outBlock)(s0)(s1)(s2)(s3);
00373 }
00374 
00375 NAMESPACE_END

Generated on Mon Apr 19 18:12:32 2004 for Crypto++ by doxygen 1.3.6-20040222