• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • 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 CFB_ModePolicy::Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount)
00028 {
00029         assert(m_cipher->IsForwardTransformation());    // CFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
00030         assert(m_feedbackSize == BlockSize());
00031 
00032         unsigned int s = BlockSize();
00033         if (dir == ENCRYPTION)
00034         {
00035                 m_cipher->ProcessAndXorBlock(m_register, input, output);
00036                 m_cipher->AdvancedProcessBlocks(output, input+s, output+s, (iterationCount-1)*s, 0);
00037                 memcpy(m_register, output+(iterationCount-1)*s, s);
00038         }
00039         else
00040         {
00041                 memcpy(m_temp, input+(iterationCount-1)*s, s);  // make copy first in case of in-place decryption
00042                 m_cipher->AdvancedProcessBlocks(input, input+s, output+s, (iterationCount-1)*s, BlockTransformation::BT_ReverseDirection);
00043                 m_cipher->ProcessAndXorBlock(m_register, input, output);
00044                 memcpy(m_register, m_temp, s);
00045         }
00046 }
00047 
00048 void CFB_ModePolicy::TransformRegister()
00049 {
00050         assert(m_cipher->IsForwardTransformation());    // CFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
00051         m_cipher->ProcessBlock(m_register, m_temp);
00052         unsigned int updateSize = BlockSize()-m_feedbackSize;
00053         memmove_s(m_register, m_register.size(), m_register+m_feedbackSize, updateSize);
00054         memcpy_s(m_register+updateSize, m_register.size()-updateSize, m_temp, m_feedbackSize);
00055 }
00056 
00057 void CFB_ModePolicy::CipherResynchronize(const byte *iv, size_t length)
00058 {
00059         assert(length == BlockSize());
00060         CopyOrZero(m_register, iv, length);
00061         TransformRegister();
00062 }
00063 
00064 void CFB_ModePolicy::SetFeedbackSize(unsigned int feedbackSize)
00065 {
00066         if (feedbackSize > BlockSize())
00067                 throw InvalidArgument("CFB_Mode: invalid feedback size");
00068         m_feedbackSize = feedbackSize ? feedbackSize : BlockSize();
00069 }
00070 
00071 void CFB_ModePolicy::ResizeBuffers()
00072 {
00073         CipherModeBase::ResizeBuffers();
00074         m_temp.New(BlockSize());
00075 }
00076 
00077 void OFB_ModePolicy::WriteKeystream(byte *keystreamBuffer, size_t iterationCount)
00078 {
00079         assert(m_cipher->IsForwardTransformation());    // OFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
00080         unsigned int s = BlockSize();
00081         m_cipher->ProcessBlock(m_register, keystreamBuffer);
00082         if (iterationCount > 1)
00083                 m_cipher->AdvancedProcessBlocks(keystreamBuffer, NULL, keystreamBuffer+s, s*(iterationCount-1), 0);
00084         memcpy(m_register, keystreamBuffer+s*(iterationCount-1), s);
00085 }
00086 
00087 void OFB_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
00088 {
00089         assert(length == BlockSize());
00090         CopyOrZero(m_register, iv, length);
00091 }
00092 
00093 void CTR_ModePolicy::SeekToIteration(lword iterationCount)
00094 {
00095         int carry=0;
00096         for (int i=BlockSize()-1; i>=0; i--)
00097         {
00098                 unsigned int sum = m_register[i] + byte(iterationCount) + carry;
00099                 m_counterArray[i] = (byte) sum;
00100                 carry = sum >> 8;
00101                 iterationCount >>= 8;
00102         }
00103 }
00104 
00105 void CTR_ModePolicy::IncrementCounterBy256()
00106 {
00107         IncrementCounterByOne(m_counterArray, BlockSize()-1);
00108 }
00109 
00110 void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
00111 {
00112         assert(m_cipher->IsForwardTransformation());    // CTR mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
00113         unsigned int s = BlockSize();
00114         unsigned int inputIncrement = input ? s : 0;
00115 
00116         while (iterationCount)
00117         {
00118                 byte lsb = m_counterArray[s-1];
00119                 size_t blocks = UnsignedMin(iterationCount, 256U-lsb);
00120                 m_cipher->AdvancedProcessBlocks(m_counterArray, input, output, blocks*s, BlockTransformation::BT_InBlockIsCounter|BlockTransformation::BT_AllowParallel);
00121                 if ((m_counterArray[s-1] = lsb + (byte)blocks) == 0)
00122                         IncrementCounterBy256();
00123 
00124                 output += blocks*s;
00125                 input += blocks*inputIncrement;
00126                 iterationCount -= blocks;
00127         }
00128 }
00129 
00130 void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
00131 {
00132         assert(length == BlockSize());
00133         CopyOrZero(m_register, iv, length);
00134         m_counterArray = m_register;
00135 }
00136 
00137 void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
00138 {
00139         m_cipher->SetKey(key, length, params);
00140         ResizeBuffers();
00141         if (IsResynchronizable())
00142         {
00143                 size_t ivLength;
00144                 const byte *iv = GetIVAndThrowIfInvalid(params, ivLength);
00145                 Resynchronize(iv, (int)ivLength);
00146         }
00147 }
00148 
00149 void ECB_OneWay::ProcessData(byte *outString, const byte *inString, size_t length)
00150 {
00151         assert(length%BlockSize()==0);
00152         m_cipher->AdvancedProcessBlocks(inString, NULL, outString, length, BlockTransformation::BT_AllowParallel);
00153 }
00154 
00155 void CBC_Encryption::ProcessData(byte *outString, const byte *inString, size_t length)
00156 {
00157         if (!length)
00158                 return;
00159         assert(length%BlockSize()==0);
00160 
00161         unsigned int blockSize = BlockSize();
00162         m_cipher->AdvancedProcessBlocks(inString, m_register, outString, blockSize, BlockTransformation::BT_XorInput);
00163         if (length > blockSize)
00164                 m_cipher->AdvancedProcessBlocks(inString+blockSize, outString, outString+blockSize, length-blockSize, BlockTransformation::BT_XorInput);
00165         memcpy(m_register, outString + length - blockSize, blockSize);
00166 }
00167 
00168 void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00169 {
00170         if (length <= BlockSize())
00171         {
00172                 if (!m_stolenIV)
00173                         throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing");
00174 
00175                 // steal from IV
00176                 memcpy(outString, m_register, length);
00177                 outString = m_stolenIV;
00178         }
00179         else
00180         {
00181                 // steal from next to last block
00182                 xorbuf(m_register, inString, BlockSize());
00183                 m_cipher->ProcessBlock(m_register);
00184                 inString += BlockSize();
00185                 length -= BlockSize();
00186                 memcpy(outString+BlockSize(), m_register, length);
00187         }
00188 
00189         // output last full ciphertext block
00190         xorbuf(m_register, inString, length);
00191         m_cipher->ProcessBlock(m_register);
00192         memcpy(outString, m_register, BlockSize());
00193 }
00194 
00195 void CBC_Decryption::ProcessData(byte *outString, const byte *inString, size_t length)
00196 {
00197         if (!length)
00198                 return;
00199         assert(length%BlockSize()==0);
00200 
00201         unsigned int blockSize = BlockSize();
00202         memcpy(m_temp, inString+length-blockSize, blockSize);   // save copy now in case of in-place decryption
00203         if (length > blockSize)
00204                 m_cipher->AdvancedProcessBlocks(inString+blockSize, inString, outString+blockSize, length-blockSize, BlockTransformation::BT_ReverseDirection|BlockTransformation::BT_AllowParallel);
00205         m_cipher->ProcessAndXorBlock(inString, m_register, outString);
00206         m_register.swap(m_temp);
00207 }
00208 
00209 void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00210 {
00211         const byte *pn, *pn1;
00212         bool stealIV = length <= BlockSize();
00213 
00214         if (stealIV)
00215         {
00216                 pn = inString;
00217                 pn1 = m_register;
00218         }
00219         else
00220         {
00221                 pn = inString + BlockSize();
00222                 pn1 = inString;
00223                 length -= BlockSize();
00224         }
00225 
00226         // decrypt last partial plaintext block
00227         memcpy(m_temp, pn1, BlockSize());
00228         m_cipher->ProcessBlock(m_temp);
00229         xorbuf(m_temp, pn, length);
00230 
00231         if (stealIV)
00232                 memcpy(outString, m_temp, length);
00233         else
00234         {
00235                 memcpy(outString+BlockSize(), m_temp, length);
00236                 // decrypt next to last plaintext block
00237                 memcpy(m_temp, pn, length);
00238                 m_cipher->ProcessBlock(m_temp);
00239                 xorbuf(outString, m_temp, m_register, BlockSize());
00240         }
00241 }
00242 
00243 NAMESPACE_END
00244 
00245 #endif

Generated on Mon Aug 9 2010 15:56:35 for Crypto++ by  doxygen 1.7.1