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

Generated on Fri Aug 13 09:56:54 2004 for Crypto++ by doxygen 1.3.7