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 CTR_ModePolicy::SeekToIteration(lword iterationCount)
00028 {
00029 int carry=0;
00030 for (int i=BlockSize()-1; i>=0; i--)
00031 {
00032 unsigned int sum = m_register[i] + byte(iterationCount) + carry;
00033 m_counterArray[i] = (byte) sum;
00034 carry = sum >> 8;
00035 iterationCount >>= 8;
00036 }
00037 }
00038
00039 inline void CTR_ModePolicy::ProcessMultipleBlocks(byte *output, const byte *input, size_t n)
00040 {
00041 unsigned int s = BlockSize(), j = 0;
00042 for (unsigned int i=1; i<n; i++, j+=s)
00043 IncrementCounterByOne(m_counterArray + j + s, m_counterArray + j, s);
00044 m_cipher->ProcessAndXorMultipleBlocks(m_counterArray, input, output, n);
00045 IncrementCounterByOne(m_counterArray, m_counterArray + s*(n-1), s);
00046 }
00047
00048 void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
00049 {
00050 assert(m_cipher->IsForwardTransformation());
00051 unsigned int maxBlocks = m_cipher->OptimalNumberOfParallelBlocks();
00052 if (maxBlocks == 1)
00053 {
00054 unsigned int sizeIncrement = BlockSize();
00055 while (iterationCount)
00056 {
00057 m_cipher->ProcessAndXorBlock(m_counterArray, input, output);
00058 IncrementCounterByOne(m_counterArray, sizeIncrement);
00059 output += sizeIncrement;
00060 input += sizeIncrement;
00061 iterationCount -= 1;
00062 }
00063 }
00064 else
00065 {
00066 unsigned int sizeIncrement = maxBlocks * BlockSize();
00067 while (iterationCount >= maxBlocks)
00068 {
00069 ProcessMultipleBlocks(output, input, maxBlocks);
00070 output += sizeIncrement;
00071 input += sizeIncrement;
00072 iterationCount -= maxBlocks;
00073 }
00074 if (iterationCount > 0)
00075 ProcessMultipleBlocks(output, input, iterationCount);
00076 }
00077 }
00078
00079 void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv)
00080 {
00081 unsigned int s = BlockSize();
00082 CopyOrZero(m_register, iv, s);
00083 m_counterArray.New(s * m_cipher->OptimalNumberOfParallelBlocks());
00084 CopyOrZero(m_counterArray, iv, s);
00085 }
00086
00087 void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
00088 {
00089 m_cipher->SetKey(key, length, params);
00090 ResizeBuffers();
00091 if (IsResynchronizable())
00092 Resynchronize(GetIVAndThrowIfInvalid(params));
00093 }
00094
00095 void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inString, size_t length)
00096 {
00097 if (!length)
00098 return;
00099
00100 unsigned int s = BlockSize();
00101 assert(length % s == 0);
00102
00103 if (!RequireAlignedInput() || IsAlignedOn(inString, m_cipher->BlockAlignment()))
00104 ProcessBlocks(outString, inString, length / s);
00105 else
00106 {
00107 do
00108 {
00109 memcpy(m_buffer, inString, s);
00110 ProcessBlocks(outString, m_buffer, 1);
00111 inString += s;
00112 outString += s;
00113 length -= s;
00114 } while (length > 0);
00115 }
00116 }
00117
00118 void CBC_Encryption::ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks)
00119 {
00120 unsigned int blockSize = BlockSize();
00121 xorbuf(m_register, inString, blockSize);
00122 while (--numberOfBlocks)
00123 {
00124 m_cipher->ProcessBlock(m_register, outString);
00125 inString += blockSize;
00126 xorbuf(m_register, inString, outString, blockSize);
00127 outString += blockSize;
00128 }
00129 m_cipher->ProcessBlock(m_register);
00130 memcpy(outString, m_register, blockSize);
00131 }
00132
00133 void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00134 {
00135 if (length <= BlockSize())
00136 {
00137 if (!m_stolenIV)
00138 throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing");
00139
00140
00141 memcpy(outString, m_register, length);
00142 outString = m_stolenIV;
00143 }
00144 else
00145 {
00146
00147 xorbuf(m_register, inString, BlockSize());
00148 m_cipher->ProcessBlock(m_register);
00149 inString += BlockSize();
00150 length -= BlockSize();
00151 memcpy(outString+BlockSize(), m_register, length);
00152 }
00153
00154
00155 xorbuf(m_register, inString, length);
00156 m_cipher->ProcessBlock(m_register);
00157 memcpy(outString, m_register, BlockSize());
00158 }
00159
00160 void CBC_Decryption::ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks)
00161 {
00162 unsigned int blockSize = BlockSize();
00163 do
00164 {
00165 memcpy(m_temp, inString, blockSize);
00166 m_cipher->ProcessAndXorBlock(m_temp, m_register, outString);
00167 m_register.swap(m_temp);
00168 inString += blockSize;
00169 outString += blockSize;
00170 } while (--numberOfBlocks);
00171 }
00172
00173 void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
00174 {
00175 const byte *pn, *pn1;
00176 bool stealIV = length <= BlockSize();
00177
00178 if (stealIV)
00179 {
00180 pn = inString;
00181 pn1 = m_register;
00182 }
00183 else
00184 {
00185 pn = inString + BlockSize();
00186 pn1 = inString;
00187 length -= BlockSize();
00188 }
00189
00190
00191 memcpy(m_temp, pn1, BlockSize());
00192 m_cipher->ProcessBlock(m_temp);
00193 xorbuf(m_temp, pn, length);
00194
00195 if (stealIV)
00196 memcpy(outString, m_temp, length);
00197 else
00198 {
00199 memcpy(outString+BlockSize(), m_temp, length);
00200
00201 memcpy(m_temp, pn, length);
00202 m_cipher->ProcessBlock(m_temp);
00203 xorbuf(outString, m_temp, m_register, BlockSize());
00204 }
00205 }
00206
00207 NAMESPACE_END
00208
00209 #endif