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