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

Generated on Tue Aug 16 08:38:42 2005 for Crypto++ by  doxygen 1.3.9.1