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