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 memcpy_s(m_register, m_register.size(), iv, BlockSize());
00060 TransformRegister();
00061 }
00062
00063 void CFB_ModePolicy::SetFeedbackSize(unsigned int feedbackSize)
00064 {
00065 if (feedbackSize > BlockSize())
00066 throw InvalidArgument("CFB_Mode: invalid feedback size");
00067 m_feedbackSize = feedbackSize ? feedbackSize : BlockSize();
00068 }
00069
00070 void CFB_ModePolicy::ResizeBuffers()
00071 {
00072 CipherModeBase::ResizeBuffers();
00073 m_temp.New(BlockSize());
00074 }
00075
00076 void OFB_ModePolicy::WriteKeystream(byte *keystreamBuffer, size_t iterationCount)
00077 {
00078 assert(m_cipher->IsForwardTransformation());
00079 unsigned int s = BlockSize();
00080 m_cipher->ProcessBlock(m_register, keystreamBuffer);
00081 if (iterationCount > 1)
00082 m_cipher->AdvancedProcessBlocks(keystreamBuffer, NULL, keystreamBuffer+s, s*(iterationCount-1), 0);
00083 memcpy(m_register, keystreamBuffer+s*(iterationCount-1), s);
00084 }
00085
00086 void OFB_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
00087 {
00088 CopyOrZero(m_register, iv, length);
00089 }
00090
00091 void CTR_ModePolicy::SeekToIteration(lword iterationCount)
00092 {
00093 int carry=0;
00094 for (int i=BlockSize()-1; i>=0; i--)
00095 {
00096 unsigned int sum = m_register[i] + byte(iterationCount) + carry;
00097 m_counterArray[i] = (byte) sum;
00098 carry = sum >> 8;
00099 iterationCount >>= 8;
00100 }
00101 }
00102
00103 void CTR_ModePolicy::IncrementCounterBy256()
00104 {
00105 IncrementCounterByOne(m_counterArray, BlockSize()-1);
00106 }
00107
00108 void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
00109 {
00110 assert(m_cipher->IsForwardTransformation());
00111 unsigned int s = BlockSize();
00112 unsigned int inputIncrement = input ? s : 0;
00113
00114 while (iterationCount)
00115 {
00116 byte lsb = m_counterArray[s-1];
00117 size_t blocks = UnsignedMin(iterationCount, 256U-lsb);
00118 m_cipher->AdvancedProcessBlocks(m_counterArray, input, output, blocks*s, BlockTransformation::BT_InBlockIsCounter);
00119 if ((m_counterArray[s-1] = lsb + (byte)blocks) == 0)
00120 IncrementCounterBy256();
00121
00122 output += blocks*s;
00123 input += blocks*inputIncrement;
00124 iterationCount -= blocks;
00125 }
00126 }
00127
00128 void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
00129 {
00130 assert(length == BlockSize());
00131 CopyOrZero(m_register, iv, length);
00132 m_counterArray = m_register;
00133 }
00134
00135 void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
00136 {
00137 m_cipher->SetKey(key, length, params);
00138 ResizeBuffers();
00139 if (IsResynchronizable())
00140 {
00141 size_t ivLength;
00142 const byte *iv = GetIVAndThrowIfInvalid(params, ivLength);
00143 Resynchronize(iv, (int)ivLength);
00144 }
00145 }
00146
00147 void ECB_OneWay::ProcessData(byte *outString, const byte *inString, size_t length)
00148 {
00149 assert(length%BlockSize()==0);
00150 m_cipher->AdvancedProcessBlocks(inString, NULL, outString, length, 0);
00151 }
00152
00153 void CBC_Encryption::ProcessData(byte *outString, const byte *inString, size_t length)
00154 {
00155 if (!length)
00156 return;
00157 assert(length%BlockSize()==0);
00158
00159 unsigned int blockSize = BlockSize();
00160 m_cipher->AdvancedProcessBlocks(inString, m_register, outString, blockSize, BlockTransformation::BT_XorInput);
00161 if (length > blockSize)
00162 m_cipher->AdvancedProcessBlocks(inString+blockSize, outString, outString+blockSize, length-blockSize, BlockTransformation::BT_XorInput);
00163 memcpy(m_register, outString + length - blockSize, blockSize);
00164 }
00165
00166 void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00167 {
00168 if (length <= BlockSize())
00169 {
00170 if (!m_stolenIV)
00171 throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing");
00172
00173
00174 memcpy(outString, m_register, length);
00175 outString = m_stolenIV;
00176 }
00177 else
00178 {
00179
00180 xorbuf(m_register, inString, BlockSize());
00181 m_cipher->ProcessBlock(m_register);
00182 inString += BlockSize();
00183 length -= BlockSize();
00184 memcpy(outString+BlockSize(), m_register, length);
00185 }
00186
00187
00188 xorbuf(m_register, inString, length);
00189 m_cipher->ProcessBlock(m_register);
00190 memcpy(outString, m_register, BlockSize());
00191 }
00192
00193 void CBC_Decryption::ProcessData(byte *outString, const byte *inString, size_t length)
00194 {
00195 if (!length)
00196 return;
00197 assert(length%BlockSize()==0);
00198
00199 unsigned int blockSize = BlockSize();
00200 memcpy(m_temp, inString+length-blockSize, blockSize);
00201 if (length > blockSize)
00202 m_cipher->AdvancedProcessBlocks(inString+blockSize, inString, outString+blockSize, length-blockSize, BlockTransformation::BT_ReverseDirection);
00203 m_cipher->ProcessAndXorBlock(inString, m_register, outString);
00204 m_register.swap(m_temp);
00205 }
00206
00207 void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00208 {
00209 const byte *pn, *pn1;
00210 bool stealIV = length <= BlockSize();
00211
00212 if (stealIV)
00213 {
00214 pn = inString;
00215 pn1 = m_register;
00216 }
00217 else
00218 {
00219 pn = inString + BlockSize();
00220 pn1 = inString;
00221 length -= BlockSize();
00222 }
00223
00224
00225 memcpy(m_temp, pn1, BlockSize());
00226 m_cipher->ProcessBlock(m_temp);
00227 xorbuf(m_temp, pn, length);
00228
00229 if (stealIV)
00230 memcpy(outString, m_temp, length);
00231 else
00232 {
00233 memcpy(outString+BlockSize(), m_temp, length);
00234
00235 memcpy(m_temp, pn, length);
00236 m_cipher->ProcessBlock(m_temp);
00237 xorbuf(outString, m_temp, m_register, BlockSize());
00238 }
00239 }
00240
00241 NAMESPACE_END
00242
00243 #endif