00001
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());
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);
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());
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());
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());
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 ¶ms)
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
00176 memcpy(outString, m_register, length);
00177 outString = m_stolenIV;
00178 }
00179 else
00180 {
00181
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
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);
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
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
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