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

Generated on Sat Dec 23 02:07:08 2006 for Crypto++ by  doxygen 1.5.1-p1