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