00001
00002
00003 #include "pch.h"
00004
00005 #ifndef CRYPTOPP_IMPORTS
00006
00007 #include "modes.h"
00008 #include "misc.h"
00009
00010 #ifndef NDEBUG
00011 #include "des.h"
00012 #endif
00013
00014 NAMESPACE_BEGIN(CryptoPP)
00015
00016 #if !defined(NDEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
00017 void Modes_TestInstantiations()
00018 {
00019 CFB_Mode<DES>::Encryption m0;
00020 CFB_Mode<DES>::Decryption m1;
00021 OFB_Mode<DES>::Encryption m2;
00022 CTR_Mode<DES>::Encryption m3;
00023 ECB_Mode<DES>::Encryption m4;
00024 CBC_Mode<DES>::Encryption m5;
00025 }
00026 #endif
00027
00028
00029 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
00030 void CipherModeBase::ResizeBuffers()
00031 {
00032 m_register.New(m_cipher->BlockSize());
00033 }
00034 #endif
00035
00036 void CFB_ModePolicy::Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount)
00037 {
00038 assert(input);
00039 assert(output);
00040 assert(m_cipher->IsForwardTransformation());
00041 assert(m_feedbackSize == BlockSize());
00042
00043 const unsigned int s = BlockSize();
00044 if (dir == ENCRYPTION)
00045 {
00046 m_cipher->ProcessAndXorBlock(m_register, input, output);
00047 if (iterationCount > 1)
00048 m_cipher->AdvancedProcessBlocks(output, input+s, output+s, (iterationCount-1)*s, 0);
00049 memcpy(m_register, output+(iterationCount-1)*s, s);
00050 }
00051 else
00052 {
00053 memcpy(m_temp, input+(iterationCount-1)*s, s);
00054 if (iterationCount > 1)
00055 m_cipher->AdvancedProcessBlocks(input, input+s, output+s, (iterationCount-1)*s, BlockTransformation::BT_ReverseDirection);
00056 m_cipher->ProcessAndXorBlock(m_register, input, output);
00057 memcpy(m_register, m_temp, s);
00058 }
00059 }
00060
00061 void CFB_ModePolicy::TransformRegister()
00062 {
00063 assert(m_cipher->IsForwardTransformation());
00064 m_cipher->ProcessBlock(m_register, m_temp);
00065 unsigned int updateSize = BlockSize()-m_feedbackSize;
00066 memmove_s(m_register, m_register.size(), m_register+m_feedbackSize, updateSize);
00067 memcpy_s(m_register+updateSize, m_register.size()-updateSize, m_temp, m_feedbackSize);
00068 }
00069
00070 void CFB_ModePolicy::CipherResynchronize(const byte *iv, size_t length)
00071 {
00072 assert(length == BlockSize());
00073 CopyOrZero(m_register, iv, length);
00074 TransformRegister();
00075 }
00076
00077 void CFB_ModePolicy::SetFeedbackSize(unsigned int feedbackSize)
00078 {
00079 if (feedbackSize > BlockSize())
00080 throw InvalidArgument("CFB_Mode: invalid feedback size");
00081 m_feedbackSize = feedbackSize ? feedbackSize : BlockSize();
00082 }
00083
00084 void CFB_ModePolicy::ResizeBuffers()
00085 {
00086 CipherModeBase::ResizeBuffers();
00087 m_temp.New(BlockSize());
00088 }
00089
00090 void OFB_ModePolicy::WriteKeystream(byte *keystreamBuffer, size_t iterationCount)
00091 {
00092 assert(m_cipher->IsForwardTransformation());
00093 unsigned int s = BlockSize();
00094 m_cipher->ProcessBlock(m_register, keystreamBuffer);
00095 if (iterationCount > 1)
00096 m_cipher->AdvancedProcessBlocks(keystreamBuffer, NULL, keystreamBuffer+s, s*(iterationCount-1), 0);
00097 memcpy(m_register, keystreamBuffer+s*(iterationCount-1), s);
00098 }
00099
00100 void OFB_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
00101 {
00102 CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
00103 assert(length == BlockSize());
00104
00105 CopyOrZero(m_register, iv, length);
00106 }
00107
00108 void CTR_ModePolicy::SeekToIteration(lword iterationCount)
00109 {
00110 int carry=0;
00111 for (int i=BlockSize()-1; i>=0; i--)
00112 {
00113 unsigned int sum = m_register[i] + byte(iterationCount) + carry;
00114 m_counterArray[i] = (byte) sum;
00115 carry = sum >> 8;
00116 iterationCount >>= 8;
00117 }
00118 }
00119
00120 void CTR_ModePolicy::IncrementCounterBy256()
00121 {
00122 IncrementCounterByOne(m_counterArray, BlockSize()-1);
00123 }
00124
00125 void CTR_ModePolicy::OperateKeystream(KeystreamOperation , byte *output, const byte *input, size_t iterationCount)
00126 {
00127 assert(m_cipher->IsForwardTransformation());
00128 unsigned int s = BlockSize();
00129 unsigned int inputIncrement = input ? s : 0;
00130
00131 while (iterationCount)
00132 {
00133 byte lsb = m_counterArray[s-1];
00134 size_t blocks = UnsignedMin(iterationCount, 256U-lsb);
00135 m_cipher->AdvancedProcessBlocks(m_counterArray, input, output, blocks*s, BlockTransformation::BT_InBlockIsCounter|BlockTransformation::BT_AllowParallel);
00136 if ((m_counterArray[s-1] = lsb + (byte)blocks) == 0)
00137 IncrementCounterBy256();
00138
00139 output += blocks*s;
00140 input += blocks*inputIncrement;
00141 iterationCount -= blocks;
00142 }
00143 }
00144
00145 void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
00146 {
00147 CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
00148 assert(length == BlockSize());
00149
00150 CopyOrZero(m_register, iv, length);
00151 m_counterArray = m_register;
00152 }
00153
00154 void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
00155 {
00156 m_cipher->SetKey(key, length, params);
00157 ResizeBuffers();
00158 if (IsResynchronizable())
00159 {
00160 size_t ivLength;
00161 const byte *iv = GetIVAndThrowIfInvalid(params, ivLength);
00162 Resynchronize(iv, (int)ivLength);
00163 }
00164 }
00165
00166
00167 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
00168 void BlockOrientedCipherModeBase::ResizeBuffers()
00169 {
00170 CipherModeBase::ResizeBuffers();
00171 m_buffer.New(BlockSize());
00172 }
00173 #endif
00174
00175 void ECB_OneWay::ProcessData(byte *outString, const byte *inString, size_t length)
00176 {
00177 assert(length%BlockSize()==0);
00178 m_cipher->AdvancedProcessBlocks(inString, NULL, outString, length, BlockTransformation::BT_AllowParallel);
00179 }
00180
00181 void CBC_Encryption::ProcessData(byte *outString, const byte *inString, size_t length)
00182 {
00183 if (!length)
00184 return;
00185 assert(length%BlockSize()==0);
00186
00187 unsigned int blockSize = BlockSize();
00188 m_cipher->AdvancedProcessBlocks(inString, m_register, outString, blockSize, BlockTransformation::BT_XorInput);
00189 if (length > blockSize)
00190 m_cipher->AdvancedProcessBlocks(inString+blockSize, outString, outString+blockSize, length-blockSize, BlockTransformation::BT_XorInput);
00191 memcpy(m_register, outString + length - blockSize, blockSize);
00192 }
00193
00194 void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00195 {
00196 if (length <= BlockSize())
00197 {
00198 if (!m_stolenIV)
00199 throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing");
00200
00201
00202 memcpy(outString, m_register, length);
00203 outString = m_stolenIV;
00204 }
00205 else
00206 {
00207
00208 xorbuf(m_register, inString, BlockSize());
00209 m_cipher->ProcessBlock(m_register);
00210 inString += BlockSize();
00211 length -= BlockSize();
00212 memcpy(outString+BlockSize(), m_register, length);
00213 }
00214
00215
00216 xorbuf(m_register, inString, length);
00217 m_cipher->ProcessBlock(m_register);
00218 memcpy(outString, m_register, BlockSize());
00219 }
00220
00221
00222 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
00223 void CBC_Decryption::ResizeBuffers()
00224 {
00225 BlockOrientedCipherModeBase::ResizeBuffers();
00226 m_temp.New(BlockSize());
00227 }
00228 #endif
00229
00230 void CBC_Decryption::ProcessData(byte *outString, const byte *inString, size_t length)
00231 {
00232 if (!length)
00233 return;
00234 assert(length%BlockSize()==0);
00235
00236 unsigned int blockSize = BlockSize();
00237 memcpy(m_temp, inString+length-blockSize, blockSize);
00238 if (length > blockSize)
00239 m_cipher->AdvancedProcessBlocks(inString+blockSize, inString, outString+blockSize, length-blockSize, BlockTransformation::BT_ReverseDirection|BlockTransformation::BT_AllowParallel);
00240 m_cipher->ProcessAndXorBlock(inString, m_register, outString);
00241 m_register.swap(m_temp);
00242 }
00243
00244 void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00245 {
00246 const byte *pn, *pn1;
00247 bool stealIV = length <= BlockSize();
00248
00249 if (stealIV)
00250 {
00251 pn = inString;
00252 pn1 = m_register;
00253 }
00254 else
00255 {
00256 pn = inString + BlockSize();
00257 pn1 = inString;
00258 length -= BlockSize();
00259 }
00260
00261
00262 memcpy(m_temp, pn1, BlockSize());
00263 m_cipher->ProcessBlock(m_temp);
00264 xorbuf(m_temp, pn, length);
00265
00266 if (stealIV)
00267 memcpy(outString, m_temp, length);
00268 else
00269 {
00270 memcpy(outString+BlockSize(), m_temp, length);
00271
00272 memcpy(m_temp, pn, length);
00273 m_cipher->ProcessBlock(m_temp);
00274 xorbuf(outString, m_temp, m_register, BlockSize());
00275 }
00276 }
00277
00278 NAMESPACE_END
00279
00280 #endif