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 CTR_ModePolicy::SeekToIteration(lword iterationCount)
00028 {
00029         int carry=0;
00030         for (int i=BlockSize()-1; i>=0; i--)
00031         {
00032                 unsigned int sum = m_register[i] + byte(iterationCount) + carry;
00033                 m_counterArray[i] = (byte) sum;
00034                 carry = sum >> 8;
00035                 iterationCount >>= 8;
00036         }
00037 }
00038 
00039 inline void CTR_ModePolicy::ProcessMultipleBlocks(byte *output, const byte *input, size_t n)
00040 {
00041         unsigned int s = BlockSize(), j = 0;
00042         for (unsigned int i=1; i<n; i++, j+=s)
00043                 IncrementCounterByOne(m_counterArray + j + s, m_counterArray + j, s);
00044         m_cipher->ProcessAndXorMultipleBlocks(m_counterArray, input, output, n);
00045         IncrementCounterByOne(m_counterArray, m_counterArray + s*(n-1), s);
00046 }
00047 
00048 void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
00049 {
00050         assert(m_cipher->IsForwardTransformation());    // CTR mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
00051         unsigned int maxBlocks = m_cipher->OptimalNumberOfParallelBlocks();
00052         if (maxBlocks == 1)
00053         {
00054                 unsigned int sizeIncrement = BlockSize();
00055                 while (iterationCount)
00056                 {
00057                         m_cipher->ProcessAndXorBlock(m_counterArray, input, output);
00058                         IncrementCounterByOne(m_counterArray, sizeIncrement);
00059                         output += sizeIncrement;
00060                         input += sizeIncrement;
00061                         iterationCount -= 1;
00062                 }
00063         }
00064         else
00065         {
00066                 unsigned int sizeIncrement = maxBlocks * BlockSize();
00067                 while (iterationCount >= maxBlocks)
00068                 {
00069                         ProcessMultipleBlocks(output, input, maxBlocks);
00070                         output += sizeIncrement;
00071                         input += sizeIncrement;
00072                         iterationCount -= maxBlocks;
00073                 }
00074                 if (iterationCount > 0)
00075                         ProcessMultipleBlocks(output, input, iterationCount);
00076         }
00077 }
00078 
00079 void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv)
00080 {
00081         unsigned int s = BlockSize();
00082         CopyOrZero(m_register, iv, s);
00083         m_counterArray.New(s * m_cipher->OptimalNumberOfParallelBlocks());
00084         CopyOrZero(m_counterArray, iv, s);
00085 }
00086 
00087 void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
00088 {
00089         m_cipher->SetKey(key, length, params);
00090         ResizeBuffers();
00091         if (IsResynchronizable())
00092                 Resynchronize(GetIVAndThrowIfInvalid(params));
00093 }
00094 
00095 void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inString, size_t length)
00096 {
00097         if (!length)
00098                 return;
00099 
00100         unsigned int s = BlockSize();
00101         assert(length % s == 0);
00102 
00103         if (!RequireAlignedInput() || IsAlignedOn(inString, m_cipher->BlockAlignment()))
00104                 ProcessBlocks(outString, inString, length / s);
00105         else
00106         {
00107                 do
00108                 {
00109                         memcpy(m_buffer, inString, s);
00110                         ProcessBlocks(outString, m_buffer, 1);
00111                         inString += s;
00112                         outString += s;
00113                         length -= s;
00114                 } while (length > 0);
00115         }
00116 }
00117 
00118 void CBC_Encryption::ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks)
00119 {
00120         unsigned int blockSize = BlockSize();
00121         xorbuf(m_register, inString, blockSize);
00122         while (--numberOfBlocks)
00123         {
00124                 m_cipher->ProcessBlock(m_register, outString);
00125                 inString += blockSize;
00126                 xorbuf(m_register, inString, outString, blockSize);
00127                 outString += blockSize;
00128         }
00129         m_cipher->ProcessBlock(m_register);
00130         memcpy(outString, m_register, blockSize);
00131 }
00132 
00133 void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00134 {
00135         if (length <= BlockSize())
00136         {
00137                 if (!m_stolenIV)
00138                         throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing");
00139 
00140                 // steal from IV
00141                 memcpy(outString, m_register, length);
00142                 outString = m_stolenIV;
00143         }
00144         else
00145         {
00146                 // steal from next to last block
00147                 xorbuf(m_register, inString, BlockSize());
00148                 m_cipher->ProcessBlock(m_register);
00149                 inString += BlockSize();
00150                 length -= BlockSize();
00151                 memcpy(outString+BlockSize(), m_register, length);
00152         }
00153 
00154         // output last full ciphertext block
00155         xorbuf(m_register, inString, length);
00156         m_cipher->ProcessBlock(m_register);
00157         memcpy(outString, m_register, BlockSize());
00158 }
00159 
00160 void CBC_Decryption::ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks)
00161 {
00162         unsigned int blockSize = BlockSize();
00163         do
00164         {
00165                 memcpy(m_temp, inString, blockSize);    // make copy in case we're doing in place decryption
00166                 m_cipher->ProcessAndXorBlock(m_temp, m_register, outString);
00167                 m_register.swap(m_temp);
00168                 inString += blockSize;
00169                 outString += blockSize;
00170         } while (--numberOfBlocks);
00171 }
00172 
00173 void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00174 {
00175         const byte *pn, *pn1;
00176         bool stealIV = length <= BlockSize();
00177 
00178         if (stealIV)
00179         {
00180                 pn = inString;
00181                 pn1 = m_register;
00182         }
00183         else
00184         {
00185                 pn = inString + BlockSize();
00186                 pn1 = inString;
00187                 length -= BlockSize();
00188         }
00189 
00190         // decrypt last partial plaintext block
00191         memcpy(m_temp, pn1, BlockSize());
00192         m_cipher->ProcessBlock(m_temp);
00193         xorbuf(m_temp, pn, length);
00194 
00195         if (stealIV)
00196                 memcpy(outString, m_temp, length);
00197         else
00198         {
00199                 memcpy(outString+BlockSize(), m_temp, length);
00200                 // decrypt next to last plaintext block
00201                 memcpy(m_temp, pn, length);
00202                 m_cipher->ProcessBlock(m_temp);
00203                 xorbuf(outString, m_temp, m_register, BlockSize());
00204         }
00205 }
00206 
00207 NAMESPACE_END
00208 
00209 #endif

Generated on Fri Jun 1 11:11:22 2007 for Crypto++ by  doxygen 1.5.2