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 Sun Mar 14 20:44:27 2004 for Crypto++ by doxygen 1.3.6-20040222