<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>Crypto++: rijndael.cpp Source File</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.3.7 --> <div class="qindex"><a class="qindex" href="index.html">Main Page</a> | <a class="qindex" href="namespaces.html">Namespace List</a> | <a class="qindex" href="hierarchy.html">Class Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical List</a> | <a class="qindex" href="annotated.html">Class List</a> | <a class="qindex" href="files.html">File List</a> | <a class="qindex" href="namespacemembers.html">Namespace Members</a> | <a class="qindex" href="functions.html">Class Members</a> | <a class="qindex" href="globals.html">File Members</a></div> <h1>rijndael.cpp</h1><pre class="fragment"><div>00001 <span class="comment">// rijndael.cpp - modified by Chris Morgan <cmorgan@wpi.edu></span> 00002 <span class="comment">// and Wei Dai from Paulo Baretto's Rijndael implementation</span> 00003 <span class="comment">// The original code and all modifications are in the public domain.</span> 00004 00005 <span class="comment">// This is the original introductory comment:</span> 00006 <span class="comment"></span> 00007 <span class="comment">/**</span> 00008 <span class="comment"> * version 3.0 (December 2000)</span> 00009 <span class="comment"> *</span> 00010 <span class="comment"> * Optimised ANSI C code for the Rijndael cipher (now AES)</span> 00011 <span class="comment"> *</span> 00012 <span class="comment"> * author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be></span> 00013 <span class="comment"> * author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be></span> 00014 <span class="comment"> * author Paulo Barreto <paulo.barreto@terra.com.br></span> 00015 <span class="comment"> *</span> 00016 <span class="comment"> * This code is hereby placed in the public domain.</span> 00017 <span class="comment"> *</span> 00018 <span class="comment"> * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS</span> 00019 <span class="comment"> * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED</span> 00020 <span class="comment"> * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE</span> 00021 <span class="comment"> * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE</span> 00022 <span class="comment"> * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR</span> 00023 <span class="comment"> * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF</span> 00024 <span class="comment"> * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR</span> 00025 <span class="comment"> * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,</span> 00026 <span class="comment"> * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE</span> 00027 <span class="comment"> * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,</span> 00028 <span class="comment"> * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span> 00029 <span class="comment"> */</span> 00030 00031 <span class="preprocessor">#include "pch.h"</span> 00032 00033 <span class="preprocessor">#ifndef CRYPTOPP_IMPORTS</span> 00034 <span class="preprocessor"></span> 00035 <span class="preprocessor">#include "<a class="code" href="rijndael_8h.html">rijndael.h</a>"</span> 00036 <span class="preprocessor">#include "misc.h"</span> 00037 00038 NAMESPACE_BEGIN(CryptoPP) 00039 00040 void <a class="code" href="class_rijndael.html">Rijndael</a>::Base::UncheckedSetKey(CipherDir dir, const byte *userKey, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> 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 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i=0; 00049 00050 GetUserKey(BIG_ENDIAN_ORDER, rk, keylen/4, userKey, keylen); 00051 00052 <span class="keywordflow">switch</span>(keylen) 00053 { 00054 <span class="keywordflow">case</span> 16: 00055 <span class="keywordflow">while</span> (<span class="keyword">true</span>) 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 <span class="keywordflow">if</span> (++i == 10) 00068 <span class="keywordflow">break</span>; 00069 rk += 4; 00070 } 00071 <span class="keywordflow">break</span>; 00072 00073 <span class="keywordflow">case</span> 24: 00074 <span class="keywordflow">while</span> (<span class="keyword">true</span>) <span class="comment">// for (;;) here triggers a bug in VC60 SP4 w/ Processor Pack</span> 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 <span class="keywordflow">if</span> (++i == 8) 00087 <span class="keywordflow">break</span>; 00088 rk[10] = rk[ 4] ^ rk[ 9]; 00089 rk[11] = rk[ 5] ^ rk[10]; 00090 rk += 6; 00091 } 00092 <span class="keywordflow">break</span>; 00093 00094 <span class="keywordflow">case</span> 32: 00095 <span class="keywordflow">while</span> (<span class="keyword">true</span>) 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 <span class="keywordflow">if</span> (++i == 7) 00108 <span class="keywordflow">break</span>; 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 <span class="keywordflow">break</span>; 00122 } 00123 00124 <span class="keywordflow">if</span> (dir == DECRYPTION) 00125 { 00126 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i, j; 00127 rk = m_key; 00128 00129 <span class="comment">/* invert the order of the round keys: */</span> 00130 <span class="keywordflow">for</span> (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 <span class="comment">/* apply the inverse MixColumn transform to all round keys but the first and the last: */</span> 00137 <span class="keywordflow">for</span> (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 <span class="keyword">typedef</span> BlockGetAndPut<word32, BigEndian> Block; 00164 00165 <span class="keywordtype">void</span> Rijndael::Enc::ProcessAndXorBlock(<span class="keyword">const</span> byte *inBlock, <span class="keyword">const</span> byte *xorBlock, byte *outBlock)<span class="keyword"> const</span> 00166 <span class="keyword"></span>{ 00167 word32 s0, s1, s2, s3, t0, t1, t2, t3; 00168 <span class="keyword">const</span> word32 *rk = m_key; 00169 00170 <span class="comment">/*</span> 00171 <span class="comment"> * map byte array block to cipher state</span> 00172 <span class="comment"> * and add initial round key:</span> 00173 <span class="comment"> */</span> 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 <span class="comment">/*</span> 00180 <span class="comment"> * Nr - 1 full rounds:</span> 00181 <span class="comment"> */</span> 00182 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> r = m_rounds >> 1; 00183 <span class="keywordflow">for</span> (;;) { 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 <span class="keywordflow">if</span> (--r == 0) { 00211 <span class="keywordflow">break</span>; 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 <span class="comment">/*</span> 00240 <span class="comment"> * apply last round and</span> 00241 <span class="comment"> * map cipher state to byte array block:</span> 00242 <span class="comment"> */</span> 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 <span class="keywordtype">void</span> Rijndael::Dec::ProcessAndXorBlock(<span class="keyword">const</span> byte *inBlock, <span class="keyword">const</span> byte *xorBlock, byte *outBlock)<span class="keyword"> const</span> 00273 <span class="keyword"></span>{ 00274 word32 s0, s1, s2, s3, t0, t1, t2, t3; 00275 <span class="keyword">const</span> word32 *rk = m_key; 00276 00277 <span class="comment">/*</span> 00278 <span class="comment"> * map byte array block to cipher state</span> 00279 <span class="comment"> * and add initial round key:</span> 00280 <span class="comment"> */</span> 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 <span class="comment">/*</span> 00287 <span class="comment"> * Nr - 1 full rounds:</span> 00288 <span class="comment"> */</span> 00289 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> r = m_rounds >> 1; 00290 <span class="keywordflow">for</span> (;;) { 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 <span class="keywordflow">if</span> (--r == 0) { 00318 <span class="keywordflow">break</span>; 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 <span class="comment">/*</span> 00347 <span class="comment"> * apply last round and</span> 00348 <span class="comment"> * map cipher state to byte array block:</span> 00349 <span class="comment"> */</span> 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 <span class="preprocessor">#endif</span> </div></pre><hr size="1"><address style="align: right;"><small>Generated on Sun Nov 7 08:23:58 2004 for Crypto++ by <a href="http://www.doxygen.org/index.html"> <img src="doxygen.png" alt="doxygen" align="middle" border=0 ></a> 1.3.7 </small></address> </body> </html>