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 Fri Aug 13 09:56:54 2004 for Crypto++ by doxygen 1.3.7