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