- Main Page
- Namespaces
- Classes
- Files

- File List
- 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 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