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

Generated on Tue Jul 8 23:34:20 2003 for Crypto++ by doxygen 1.3.2