<!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++: modes.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>modes.cpp</h1><pre class="fragment"><div>00001 <span class="comment">// modes.cpp - written and placed in the public domain by Wei Dai</span> 00002 00003 <span class="preprocessor">#include "pch.h"</span> 00004 00005 <span class="preprocessor">#ifndef CRYPTOPP_IMPORTS</span> 00006 <span class="preprocessor"></span> 00007 <span class="preprocessor">#include "<a class="code" href="modes_8h.html">modes.h</a>"</span> 00008 00009 <span class="preprocessor">#ifndef NDEBUG</span> 00010 <span class="preprocessor"></span><span class="preprocessor">#include "<a class="code" href="des_8h.html">des.h</a>"</span> 00011 <span class="preprocessor">#endif</span> 00012 <span class="preprocessor"></span> 00013 NAMESPACE_BEGIN(CryptoPP) 00014 00015 #ifndef NDEBUG 00016 <span class="keywordtype">void</span> Modes_TestInstantiations() 00017 { 00018 <a class="code" href="struct_c_f_b___mode.html">CFB_Mode<DES></a>::Encryption m0; 00019 <a class="code" href="struct_c_f_b___mode.html">CFB_Mode<DES></a>::Decryption m1; 00020 <a class="code" href="struct_o_f_b___mode.html">OFB_Mode<DES></a>::Encryption m2; 00021 <a class="code" href="struct_c_t_r___mode.html">CTR_Mode<DES></a>::Encryption m3; 00022 <a class="code" href="struct_e_c_b___mode.html">ECB_Mode<DES></a>::Encryption m4; 00023 <a class="code" href="struct_c_b_c___mode.html">CBC_Mode<DES></a>::Encryption m5; 00024 } 00025 <span class="preprocessor">#endif</span> 00026 <span class="preprocessor"></span> 00027 <span class="keywordtype">void</span> CipherModeBase::SetKey(<span class="keyword">const</span> byte *key, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length, <span class="keyword">const</span> <a class="code" href="class_name_value_pairs.html">NameValuePairs</a> &params) 00028 { 00029 UncheckedSetKey(params, key, length, GetIVAndThrowIfInvalid(params)); <span class="comment">// the underlying cipher will check the key length</span> 00030 } 00031 00032 <span class="keywordtype">void</span> CipherModeBase::GetNextIV(byte *IV) 00033 { 00034 <span class="keywordflow">if</span> (!IsForwardTransformation()) 00035 <span class="keywordflow">throw</span> <a class="code" href="class_not_implemented.html">NotImplemented</a>(<span class="stringliteral">"CipherModeBase: GetNextIV() must be called on an encryption object"</span>); 00036 00037 m_cipher->ProcessBlock(m_register); 00038 memcpy(IV, m_register, <a class="code" href="namespace_name.html#a9">BlockSize</a>()); 00039 } 00040 00041 <span class="keywordtype">void</span> CTR_ModePolicy::SeekToIteration(lword iterationCount) 00042 { 00043 <span class="keywordtype">int</span> carry=0; 00044 <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i=<a class="code" href="namespace_name.html#a9">BlockSize</a>()-1; i>=0; i--) 00045 { 00046 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> sum = m_register[i] + byte(iterationCount) + carry; 00047 m_counterArray[i] = (byte) sum; 00048 carry = sum >> 8; 00049 iterationCount >>= 8; 00050 } 00051 } 00052 00053 <span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">void</span> IncrementCounterByOne(byte *inout, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> s) 00054 { 00055 <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i=s-1, carry=1; i>=0 && carry; i--) 00056 carry = !++inout[i]; 00057 } 00058 00059 <span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">void</span> IncrementCounterByOne(byte *output, <span class="keyword">const</span> byte *input, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> s) 00060 { 00061 <span class="keywordtype">int</span> i, carry; 00062 <span class="keywordflow">for</span> (i=s-1, carry=1; i>=0 && carry; i--) 00063 carry = !(output[i] = input[i]+1); 00064 memcpy(output, input, i+1); 00065 } 00066 00067 <span class="keywordtype">void</span> CTR_ModePolicy::GetNextIV(byte *IV) 00068 { 00069 IncrementCounterByOne(IV, m_counterArray, <a class="code" href="namespace_name.html#a9">BlockSize</a>()); 00070 } 00071 00072 <span class="keyword">inline</span> <span class="keywordtype">void</span> CTR_ModePolicy::ProcessMultipleBlocks(byte *output, <span class="keyword">const</span> byte *input, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> n) 00073 { 00074 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> s = <a class="code" href="namespace_name.html#a9">BlockSize</a>(), j = 0; 00075 <span class="keywordflow">for</span> (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i=1; i<n; i++, j+=s) 00076 IncrementCounterByOne(m_counterArray + j + s, m_counterArray + j, s); 00077 m_cipher->ProcessAndXorMultipleBlocks(m_counterArray, input, output, n); 00078 IncrementCounterByOne(m_counterArray, m_counterArray + s*(n-1), s); 00079 } 00080 00081 <span class="keywordtype">void</span> CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, <span class="keyword">const</span> byte *input, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> iterationCount) 00082 { 00083 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> maxBlocks = m_cipher->OptimalNumberOfParallelBlocks(); 00084 <span class="keywordflow">if</span> (maxBlocks == 1) 00085 { 00086 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> sizeIncrement = <a class="code" href="namespace_name.html#a9">BlockSize</a>(); 00087 <span class="keywordflow">while</span> (iterationCount) 00088 { 00089 m_cipher->ProcessAndXorBlock(m_counterArray, input, output); 00090 IncrementCounterByOne(m_counterArray, sizeIncrement); 00091 output += sizeIncrement; 00092 input += sizeIncrement; 00093 iterationCount -= 1; 00094 } 00095 } 00096 <span class="keywordflow">else</span> 00097 { 00098 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> sizeIncrement = maxBlocks * <a class="code" href="namespace_name.html#a9">BlockSize</a>(); 00099 <span class="keywordflow">while</span> (iterationCount >= maxBlocks) 00100 { 00101 ProcessMultipleBlocks(output, input, maxBlocks); 00102 output += sizeIncrement; 00103 input += sizeIncrement; 00104 iterationCount -= maxBlocks; 00105 } 00106 <span class="keywordflow">if</span> (iterationCount > 0) 00107 ProcessMultipleBlocks(output, input, iterationCount); 00108 } 00109 } 00110 00111 <span class="keywordtype">void</span> CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, <span class="keyword">const</span> byte *iv) 00112 { 00113 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> s = <a class="code" href="namespace_name.html#a9">BlockSize</a>(); 00114 CopyOrZero(m_register, iv, s); 00115 m_counterArray.New(s * m_cipher->OptimalNumberOfParallelBlocks()); 00116 CopyOrZero(m_counterArray, iv, s); 00117 } 00118 00119 <span class="keywordtype">void</span> BlockOrientedCipherModeBase::UncheckedSetKey(<span class="keyword">const</span> <a class="code" href="class_name_value_pairs.html">NameValuePairs</a> &params, <span class="keyword">const</span> byte *key, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length, <span class="keyword">const</span> byte *iv) 00120 { 00121 m_cipher->SetKey(key, length, params); 00122 ResizeBuffers(); 00123 <span class="keywordflow">if</span> (IsResynchronizable()) 00124 Resynchronize(iv); 00125 } 00126 00127 <span class="keywordtype">void</span> BlockOrientedCipherModeBase::ProcessData(byte *outString, <span class="keyword">const</span> byte *inString, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length) 00128 { 00129 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> s = <a class="code" href="namespace_name.html#a9">BlockSize</a>(); 00130 assert(length % s == 0); 00131 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> alignment = m_cipher->BlockAlignment(); 00132 <span class="keywordtype">bool</span> inputAlignmentOk = !RequireAlignedInput() || IsAlignedOn(inString, alignment); 00133 00134 <span class="keywordflow">if</span> (IsAlignedOn(outString, alignment)) 00135 { 00136 <span class="keywordflow">if</span> (inputAlignmentOk) 00137 ProcessBlocks(outString, inString, length / s); 00138 <span class="keywordflow">else</span> 00139 { 00140 memcpy(outString, inString, length); 00141 ProcessBlocks(outString, outString, length / s); 00142 } 00143 } 00144 <span class="keywordflow">else</span> 00145 { 00146 <span class="keywordflow">while</span> (length) 00147 { 00148 <span class="keywordflow">if</span> (inputAlignmentOk) 00149 ProcessBlocks(m_buffer, inString, 1); 00150 <span class="keywordflow">else</span> 00151 { 00152 memcpy(m_buffer, inString, s); 00153 ProcessBlocks(m_buffer, m_buffer, 1); 00154 } 00155 memcpy(outString, m_buffer, s); 00156 inString += s; 00157 outString += s; 00158 length -= s; 00159 } 00160 } 00161 } 00162 00163 <span class="keywordtype">void</span> CBC_Encryption::ProcessBlocks(byte *outString, <span class="keyword">const</span> byte *inString, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> numberOfBlocks) 00164 { 00165 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> blockSize = <a class="code" href="namespace_name.html#a9">BlockSize</a>(); 00166 <span class="keywordflow">while</span> (numberOfBlocks--) 00167 { 00168 xorbuf(m_register, inString, blockSize); 00169 m_cipher->ProcessBlock(m_register); 00170 memcpy(outString, m_register, blockSize); 00171 inString += blockSize; 00172 outString += blockSize; 00173 } 00174 } 00175 00176 <span class="keywordtype">void</span> CBC_CTS_Encryption::ProcessLastBlock(byte *outString, <span class="keyword">const</span> byte *inString, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length) 00177 { 00178 <span class="keywordflow">if</span> (length <= <a class="code" href="namespace_name.html#a9">BlockSize</a>()) 00179 { 00180 <span class="keywordflow">if</span> (!m_stolenIV) 00181 <span class="keywordflow">throw</span> <a class="code" href="class_invalid_argument.html">InvalidArgument</a>(<span class="stringliteral">"CBC_Encryption: message is too short for ciphertext stealing"</span>); 00182 00183 <span class="comment">// steal from IV</span> 00184 memcpy(outString, m_register, length); 00185 outString = m_stolenIV; 00186 } 00187 <span class="keywordflow">else</span> 00188 { 00189 <span class="comment">// steal from next to last block</span> 00190 xorbuf(m_register, inString, <a class="code" href="namespace_name.html#a9">BlockSize</a>()); 00191 m_cipher->ProcessBlock(m_register); 00192 inString += <a class="code" href="namespace_name.html#a9">BlockSize</a>(); 00193 length -= <a class="code" href="namespace_name.html#a9">BlockSize</a>(); 00194 memcpy(outString+<a class="code" href="namespace_name.html#a9">BlockSize</a>(), m_register, length); 00195 } 00196 00197 <span class="comment">// output last full ciphertext block</span> 00198 xorbuf(m_register, inString, length); 00199 m_cipher->ProcessBlock(m_register); 00200 memcpy(outString, m_register, <a class="code" href="namespace_name.html#a9">BlockSize</a>()); 00201 } 00202 00203 <span class="keywordtype">void</span> CBC_Decryption::ProcessBlocks(byte *outString, <span class="keyword">const</span> byte *inString, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> numberOfBlocks) 00204 { 00205 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> blockSize = <a class="code" href="namespace_name.html#a9">BlockSize</a>(); 00206 <span class="keywordflow">while</span> (numberOfBlocks--) 00207 { 00208 memcpy(m_temp, inString, blockSize); 00209 m_cipher->ProcessBlock(m_temp, outString); 00210 xorbuf(outString, m_register, blockSize); 00211 m_register.swap(m_temp); 00212 inString += blockSize; 00213 outString += blockSize; 00214 } 00215 } 00216 00217 <span class="keywordtype">void</span> CBC_CTS_Decryption::ProcessLastBlock(byte *outString, <span class="keyword">const</span> byte *inString, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length) 00218 { 00219 <span class="keyword">const</span> byte *pn, *pn1; 00220 <span class="keywordtype">bool</span> stealIV = length <= <a class="code" href="namespace_name.html#a9">BlockSize</a>(); 00221 00222 <span class="keywordflow">if</span> (stealIV) 00223 { 00224 pn = inString; 00225 pn1 = m_register; 00226 } 00227 <span class="keywordflow">else</span> 00228 { 00229 pn = inString + <a class="code" href="namespace_name.html#a9">BlockSize</a>(); 00230 pn1 = inString; 00231 length -= <a class="code" href="namespace_name.html#a9">BlockSize</a>(); 00232 } 00233 00234 <span class="comment">// decrypt last partial plaintext block</span> 00235 memcpy(m_temp, pn1, <a class="code" href="namespace_name.html#a9">BlockSize</a>()); 00236 m_cipher->ProcessBlock(m_temp); 00237 xorbuf(m_temp, pn, length); 00238 00239 <span class="keywordflow">if</span> (stealIV) 00240 memcpy(outString, m_temp, length); 00241 <span class="keywordflow">else</span> 00242 { 00243 memcpy(outString+<a class="code" href="namespace_name.html#a9">BlockSize</a>(), m_temp, length); 00244 <span class="comment">// decrypt next to last plaintext block</span> 00245 memcpy(m_temp, pn, length); 00246 m_cipher->ProcessBlock(m_temp); 00247 xorbuf(outString, m_temp, m_register, <a class="code" href="namespace_name.html#a9">BlockSize</a>()); 00248 } 00249 } 00250 00251 NAMESPACE_END 00252 00253 <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>