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

modes.cpp

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

Generated on Sat Aug 28 17:24:56 2004 for Crypto++ by doxygen 1.3.8